Add GL_KOS_texture_stride support
This commit is contained in:
parent
c94bfd7c9c
commit
8aa9a0ec43
@ -152,9 +152,11 @@ function(gen_sample sample)
|
||||
if(PLATFORM_DREAMCAST)
|
||||
if(EXISTS "${CMAKE_SOURCE_DIR}/samples/${sample}/romdisk")
|
||||
message("Generating romdisk for sample: ${sample}")
|
||||
file(GLOB_RECURSE ROMDISK_FILES "${ROMDISK_DIR}/*")
|
||||
add_custom_command(
|
||||
OUTPUT ${ROMDISK_IMG}
|
||||
COMMAND ${GENROMFS} -f ${ROMDISK_IMG} -d ${ROMDISK_DIR} -v
|
||||
DEPENDS ${ROMDISK_FILES}
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
@ -201,12 +203,14 @@ if(BUILD_SAMPLES)
|
||||
gen_sample(nehe04 samples/nehe04/main.c)
|
||||
gen_sample(nehe05 samples/nehe05/main.c)
|
||||
gen_sample(nehe06 samples/nehe06/main.c samples/loadbmp.c)
|
||||
gen_sample(nehe06_strided samples/nehe06_strided/main.c samples/loadbmp.c)
|
||||
gen_sample(nehe06_vq samples/nehe06_vq/main.c)
|
||||
gen_sample(nehe06_4444twid samples/nehe06_4444twid/main.c)
|
||||
gen_sample(nehe08 samples/nehe08/main.c samples/nehe08/pvr-texture.c)
|
||||
gen_sample(nehe10 samples/nehe10/main.c samples/loadbmp.c)
|
||||
gen_sample(nehe16 samples/nehe16/main.c samples/nehe16/pvr-texture.c)
|
||||
gen_sample(nehe20 samples/nehe20/main.c samples/loadbmp.c)
|
||||
gen_sample(nehe20_strided samples/nehe20_strided/main.c samples/loadbmp.c)
|
||||
gen_sample(ortho2d samples/ortho2d/main.c)
|
||||
gen_sample(paletted samples/paletted/main.c)
|
||||
gen_sample(paletted_pcx samples/paletted_pcx/main.c)
|
||||
|
||||
21
GL/draw.c
21
GL/draw.c
@ -751,6 +751,25 @@ GL_FORCE_INLINE void apply_poly_header(PolyHeader* header, GLboolean multiTextur
|
||||
*/
|
||||
}
|
||||
|
||||
GL_FORCE_INLINE void apply_strided_texture_uv_scale(SubmissionTarget* target) {
|
||||
TextureObject* texture = _glGetTexture0();
|
||||
|
||||
if(!texture || !texture->isStrided || !texture->pvrWidth || !texture->pvrHeight) {
|
||||
return;
|
||||
}
|
||||
|
||||
const float uScale = (float) texture->logicalWidth / (float) texture->pvrWidth;
|
||||
const float vScale = (float) texture->logicalHeight / (float) texture->pvrHeight;
|
||||
Vertex* it = _glSubmissionTargetStart(target);
|
||||
Vertex* end = _glSubmissionTargetEnd(target);
|
||||
|
||||
while(it < end) {
|
||||
it->uv[0] *= uScale;
|
||||
it->uv[1] *= vScale;
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
#define DEBUG_CLIPPING 0
|
||||
|
||||
|
||||
@ -842,6 +861,8 @@ GL_FORCE_INLINE void submitVertices(GLenum mode, GLsizei first, GLuint count, GL
|
||||
|
||||
_glTnlApplyEffects(target);
|
||||
|
||||
apply_strided_texture_uv_scale(target);
|
||||
|
||||
// /*
|
||||
// Now, if multitexturing is enabled, we want to send exactly the same vertices again, except:
|
||||
// - We want to enable blending, and send them to the TR list
|
||||
|
||||
@ -67,8 +67,10 @@ typedef enum GPUTextureFormat {
|
||||
GPU_TXRFMT_PAL8BPP = (6 << 27),
|
||||
GPU_TXRFMT_TWIDDLED = (0 << 26),
|
||||
GPU_TXRFMT_NONTWIDDLED = (1 << 26),
|
||||
GPU_TXRFMT_NOSTRIDE = (0 << 21),
|
||||
GPU_TXRFMT_STRIDE = (1 << 21)
|
||||
GPU_TXRFMT_POW2_STRIDE = (0 << 25),
|
||||
GPU_TXRFMT_NOSTRIDE = GPU_TXRFMT_POW2_STRIDE,
|
||||
GPU_TXRFMT_X32_STRIDE = (1 << 25),
|
||||
GPU_TXRFMT_STRIDE = GPU_TXRFMT_X32_STRIDE
|
||||
} GPUTextureFormat;
|
||||
|
||||
static inline uint32_t GPUPaletteSelect8BPP(uint32_t x) {
|
||||
@ -218,6 +220,10 @@ typedef struct {
|
||||
int width;
|
||||
int height;
|
||||
int format;
|
||||
int stride_width;
|
||||
float uv_scale_u;
|
||||
float uv_scale_v;
|
||||
int is_strided;
|
||||
void* base;
|
||||
} txr;
|
||||
struct {
|
||||
@ -232,6 +238,10 @@ typedef struct {
|
||||
int width;
|
||||
int height;
|
||||
int format;
|
||||
int stride_width;
|
||||
float uv_scale_u;
|
||||
float uv_scale_v;
|
||||
int is_strided;
|
||||
void* base;
|
||||
} txr2;
|
||||
} PolyContext;
|
||||
@ -245,7 +255,13 @@ typedef struct {
|
||||
uint32_t d2;
|
||||
uint32_t d3;
|
||||
uint32_t d4;
|
||||
uint8_t padding[32];
|
||||
struct {
|
||||
uint32_t texture_stride;
|
||||
float uv_scale_u;
|
||||
float uv_scale_v;
|
||||
uint8_t texture_is_strided;
|
||||
uint8_t padding[19];
|
||||
} meta;
|
||||
} PolyHeader;
|
||||
|
||||
enum GPUCommand {
|
||||
@ -384,6 +400,10 @@ static inline void CompilePolyHeader(PolyHeader *dst, const PolyContext *src) {
|
||||
|
||||
/* The base values for CMD */
|
||||
dst->cmd = GPU_CMD_POLYHDR;
|
||||
dst->meta.texture_is_strided = 0;
|
||||
dst->meta.texture_stride = 0;
|
||||
dst->meta.uv_scale_u = 1.0f;
|
||||
dst->meta.uv_scale_v = 1.0f;
|
||||
|
||||
/* Big hack! This enables texturing no matter what. If we disable texturing then
|
||||
* we lose offset color and the vertex format changes meaning we have to manipulate
|
||||
@ -448,6 +468,10 @@ static inline void CompilePolyHeader(PolyHeader *dst, const PolyContext *src) {
|
||||
/* Polygon mode 3 */
|
||||
dst->mode3 = (src->txr.mipmap << GPU_TA_PM3_MIPMAP_SHIFT) & GPU_TA_PM3_MIPMAP_MASK;
|
||||
dst->mode3 |= (src->txr.format << GPU_TA_PM3_TXRFMT_SHIFT) & GPU_TA_PM3_TXRFMT_MASK;
|
||||
dst->meta.texture_is_strided = src->txr.is_strided ? 1 : 0;
|
||||
dst->meta.texture_stride = src->txr.stride_width;
|
||||
dst->meta.uv_scale_u = src->txr.uv_scale_u;
|
||||
dst->meta.uv_scale_v = src->txr.uv_scale_v;
|
||||
|
||||
/* Convert the texture address */
|
||||
txr_base = (uint32_t) src->txr.base;
|
||||
|
||||
@ -87,6 +87,7 @@ GL_FORCE_INLINE void _glPerspectiveDivideVertex(Vertex* vertex, int count) {
|
||||
}
|
||||
|
||||
static uintptr_t sq_dest_addr = 0;
|
||||
static size_t CURRENT_TEXTURE_STRIDE = 0;
|
||||
|
||||
static inline void _glPushHeader(Vertex* v, size_t count) {
|
||||
TRACE();
|
||||
@ -195,6 +196,12 @@ void SceneListSubmit(Vertex* vertices, int n) {
|
||||
Vertex* v0 = vertices;
|
||||
for(int i = 0; i < n - 1; ++i, ++v0) {
|
||||
if(is_header(v0)) {
|
||||
PolyHeader* header = (PolyHeader*) v0;
|
||||
if(header->meta.texture_is_strided && header->meta.texture_stride != CURRENT_TEXTURE_STRIDE) {
|
||||
pvr_txr_set_stride(header->meta.texture_stride);
|
||||
CURRENT_TEXTURE_STRIDE = header->meta.texture_stride;
|
||||
}
|
||||
|
||||
_glPushHeader(v0, 1);
|
||||
visible_mask = 0;
|
||||
continue;
|
||||
@ -378,6 +385,7 @@ void SceneListSubmit(Vertex* vertices, int n) {
|
||||
}
|
||||
|
||||
void SceneBegin() {
|
||||
CURRENT_TEXTURE_STRIDE = 0;
|
||||
pvr_wait_ready();
|
||||
pvr_scene_begin();
|
||||
}
|
||||
|
||||
@ -128,8 +128,12 @@ typedef struct {
|
||||
GLboolean isPaletted;
|
||||
//50
|
||||
GLenum internalFormat;
|
||||
//54
|
||||
GLubyte padding[10]; // Pad to 64-bytes
|
||||
GLushort logicalWidth;
|
||||
GLushort logicalHeight;
|
||||
GLushort pvrWidth;
|
||||
GLushort pvrHeight;
|
||||
GLushort strideWidth;
|
||||
GLboolean isStrided;
|
||||
} __attribute__((aligned(32))) TextureObject;
|
||||
|
||||
typedef struct {
|
||||
|
||||
14
GL/state.c
14
GL/state.c
@ -409,8 +409,8 @@ void _glUpdatePVRTextureContext(PolyContext *context, GLshort textureUnit) {
|
||||
if(tx1->data) {
|
||||
context->txr.enable = GPU_TEXTURE_ENABLE;
|
||||
context->txr.filter = filter;
|
||||
context->txr.width = tx1->width;
|
||||
context->txr.height = tx1->height;
|
||||
context->txr.width = tx1->pvrWidth ? tx1->pvrWidth : tx1->width;
|
||||
context->txr.height = tx1->pvrHeight ? tx1->pvrHeight : tx1->height;
|
||||
context->txr.mipmap = enableMipmaps;
|
||||
context->txr.mipmap_bias = tx1->mipmap_bias;
|
||||
|
||||
@ -421,6 +421,14 @@ void _glUpdatePVRTextureContext(PolyContext *context, GLshort textureUnit) {
|
||||
}
|
||||
|
||||
context->txr.format = tx1->color;
|
||||
context->txr.is_strided = tx1->isStrided;
|
||||
context->txr.stride_width = tx1->strideWidth;
|
||||
context->txr.uv_scale_u = tx1->isStrided ? ((float) tx1->logicalWidth / (float) tx1->pvrWidth) : 1.0f;
|
||||
context->txr.uv_scale_v = tx1->isStrided ? ((float) tx1->logicalHeight / (float) tx1->pvrHeight) : 1.0f;
|
||||
|
||||
if(tx1->isStrided) {
|
||||
context->txr.format |= GPU_TXRFMT_X32_STRIDE;
|
||||
}
|
||||
|
||||
if(tx1->isPaletted) {
|
||||
if(_glIsSharedTexturePaletteEnabled()) {
|
||||
@ -1137,7 +1145,7 @@ const GLubyte *glGetString(GLenum name) {
|
||||
return (const GLubyte*) "1.2 (partial) - GLdc 1.1";
|
||||
|
||||
case GL_EXTENSIONS:
|
||||
return (const GLubyte*)"GL_ARB_framebuffer_object, GL_ARB_multitexture, GL_ARB_texture_rg, GL_OES_compressed_paletted_texture, GL_EXT_paletted_texture, GL_EXT_shared_texture_palette, GL_KOS_multiple_shared_palette, GL_ARB_vertex_array_bgra, GL_ARB_vertex_type_2_10_10_10_rev, GL_KOS_texture_memory_management, GL_ATI_meminfo";
|
||||
return (const GLubyte*)"GL_ARB_framebuffer_object, GL_ARB_multitexture, GL_ARB_texture_rg, GL_OES_compressed_paletted_texture, GL_EXT_paletted_texture, GL_EXT_shared_texture_palette, GL_KOS_multiple_shared_palette, GL_ARB_vertex_array_bgra, GL_ARB_vertex_type_2_10_10_10_rev, GL_KOS_texture_memory_management, GL_KOS_texture_stride, GL_ATI_meminfo";
|
||||
}
|
||||
|
||||
return (const GLubyte*) "GL_KOS_ERROR: ENUM Unsupported\n";
|
||||
|
||||
219
GL/texture.c
219
GL/texture.c
@ -42,6 +42,64 @@ static GLboolean TEXTURE_TWIDDLE_ENABLED = GL_FALSE;
|
||||
static void* ALLOC_BASE = NULL;
|
||||
static size_t ALLOC_SIZE = 0;
|
||||
|
||||
#define GL_KOS_MAX_STRIDE_WIDTH 992
|
||||
|
||||
static GLuint _glNextPowerOfTwo(GLuint v) {
|
||||
if(v <= 1) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
v--;
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
v |= v >> 16;
|
||||
return v + 1;
|
||||
}
|
||||
|
||||
static GLboolean _glIsTwiddledFormat(GLenum internalFormat) {
|
||||
return (
|
||||
internalFormat == GL_RGB565_TWID_KOS ||
|
||||
internalFormat == GL_ARGB4444_TWID_KOS ||
|
||||
internalFormat == GL_ARGB1555_TWID_KOS ||
|
||||
internalFormat == GL_COLOR_INDEX8_TWID_KOS ||
|
||||
internalFormat == GL_COLOR_INDEX4_TWID_KOS ||
|
||||
internalFormat == GL_COMPRESSED_RGB_565_VQ_TWID_KOS ||
|
||||
internalFormat == GL_COMPRESSED_ARGB_1555_VQ_TWID_KOS ||
|
||||
internalFormat == GL_COMPRESSED_ARGB_4444_VQ_TWID_KOS ||
|
||||
internalFormat == GL_COMPRESSED_RGB_565_VQ_MIPMAP_TWID_KOS ||
|
||||
internalFormat == GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_TWID_KOS ||
|
||||
internalFormat == GL_COMPRESSED_ARGB_4444_VQ_MIPMAP_TWID_KOS
|
||||
) ? GL_TRUE : GL_FALSE;
|
||||
}
|
||||
|
||||
static GLboolean _glIsCompressedFormat(GLenum internalFormat) {
|
||||
return (
|
||||
internalFormat == GL_COMPRESSED_RGB_565_VQ_KOS ||
|
||||
internalFormat == GL_COMPRESSED_ARGB_1555_VQ_KOS ||
|
||||
internalFormat == GL_COMPRESSED_ARGB_4444_VQ_KOS ||
|
||||
internalFormat == GL_COMPRESSED_RGB_565_VQ_TWID_KOS ||
|
||||
internalFormat == GL_COMPRESSED_ARGB_1555_VQ_TWID_KOS ||
|
||||
internalFormat == GL_COMPRESSED_ARGB_4444_VQ_TWID_KOS ||
|
||||
internalFormat == GL_COMPRESSED_RGB_565_VQ_MIPMAP_KOS ||
|
||||
internalFormat == GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_KOS ||
|
||||
internalFormat == GL_COMPRESSED_ARGB_4444_VQ_MIPMAP_KOS ||
|
||||
internalFormat == GL_COMPRESSED_RGB_565_VQ_MIPMAP_TWID_KOS ||
|
||||
internalFormat == GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_TWID_KOS ||
|
||||
internalFormat == GL_COMPRESSED_ARGB_4444_VQ_MIPMAP_TWID_KOS
|
||||
) ? GL_TRUE : GL_FALSE;
|
||||
}
|
||||
|
||||
static GLboolean _glIsPalettedFormat(GLenum internalFormat) {
|
||||
return (
|
||||
internalFormat == GL_COLOR_INDEX8_EXT ||
|
||||
internalFormat == GL_COLOR_INDEX4_EXT ||
|
||||
internalFormat == GL_COLOR_INDEX8_TWID_KOS ||
|
||||
internalFormat == GL_COLOR_INDEX4_TWID_KOS
|
||||
) ? GL_TRUE : GL_FALSE;
|
||||
}
|
||||
|
||||
static void calc_twiddle_factors(uint32_t w, uint32_t h, uint32_t* maskX, uint32_t* maskY) {
|
||||
*maskX = 0;
|
||||
*maskY = 0;
|
||||
@ -495,6 +553,10 @@ void _glResetSharedPalettes()
|
||||
static void _glInitializeTextureObject(TextureObject* txr, unsigned int id) {
|
||||
txr->index = id;
|
||||
txr->width = txr->height = 0;
|
||||
txr->logicalWidth = txr->logicalHeight = 0;
|
||||
txr->pvrWidth = txr->pvrHeight = 0;
|
||||
txr->strideWidth = 0;
|
||||
txr->isStrided = GL_FALSE;
|
||||
txr->mipmap = 0;
|
||||
txr->uv_wrap = 0;
|
||||
txr->env = GPU_TXRENV_MODULATEALPHA;
|
||||
@ -868,16 +930,28 @@ void APIENTRY glCompressedTexImage2DARB(GLenum target,
|
||||
|
||||
gl_assert(ACTIVE_TEXTURE < MAX_GLDC_TEXTURE_UNITS);
|
||||
TextureObject* active = TEXTURE_UNITS[ACTIVE_TEXTURE];
|
||||
GLuint original_id = active->index;
|
||||
|
||||
if(!active) {
|
||||
_glKosThrowError(GL_INVALID_OPERATION, __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if(active->strideWidth) {
|
||||
_glKosThrowError(GL_INVALID_OPERATION, __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
GLuint original_id = active->index;
|
||||
|
||||
/* Set the required mipmap count */
|
||||
active->width = width;
|
||||
active->height = height;
|
||||
active->logicalWidth = width;
|
||||
active->logicalHeight = height;
|
||||
active->pvrWidth = width;
|
||||
active->pvrHeight = height;
|
||||
active->strideWidth = 0;
|
||||
active->isStrided = GL_FALSE;
|
||||
active->internalFormat = internalFormat;
|
||||
active->color = _determinePVRFormat(internalFormat);
|
||||
active->mipmapCount = _glGetMipmapLevelCount(active);
|
||||
@ -1059,6 +1133,18 @@ static GLint _cleanInternalFormat(GLint internalFormat) {
|
||||
}
|
||||
}
|
||||
|
||||
static GLint _cleanInternalFormatForTexture(const TextureObject* txr, GLint internalFormat) {
|
||||
if(!txr || !txr->strideWidth) {
|
||||
return _cleanInternalFormat(internalFormat);
|
||||
}
|
||||
|
||||
GLboolean oldTwiddle = TEXTURE_TWIDDLE_ENABLED;
|
||||
TEXTURE_TWIDDLE_ENABLED = GL_FALSE;
|
||||
GLint ret = _cleanInternalFormat(internalFormat);
|
||||
TEXTURE_TWIDDLE_ENABLED = oldTwiddle;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static GLuint _determinePVRFormat(GLint internalFormat) {
|
||||
/* Given a cleaned internalFormat, return the Dreamcast format
|
||||
* that can hold it
|
||||
@ -1448,7 +1534,7 @@ static bool _glValidTextureSize(GLuint size) {
|
||||
}
|
||||
}
|
||||
|
||||
static bool _glTexImage2DValidate(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type) {
|
||||
static bool _glTexImage2DValidate(const TextureObject* txr, GLenum target, GLint level, GLint internalFormat, GLint cleanInternalFormat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type) {
|
||||
if(target != GL_TEXTURE_2D) {
|
||||
INFO_MSG("Target unsupported");
|
||||
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
||||
@ -1493,16 +1579,62 @@ static bool _glTexImage2DValidate(GLenum target, GLint level, GLint internalForm
|
||||
}
|
||||
}
|
||||
|
||||
if(_cleanInternalFormat(internalFormat) == -1) {
|
||||
if(cleanInternalFormat == -1) {
|
||||
INFO_MSG("Unsupported internal format");
|
||||
_glKosThrowError(GL_INVALID_VALUE, __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
GLboolean isStrided = (txr && txr->strideWidth) ? GL_TRUE : GL_FALSE;
|
||||
|
||||
if(isStrided) {
|
||||
if(level != 0) {
|
||||
INFO_MSG("Strided textures do not support mipmaps");
|
||||
_glKosThrowError(GL_INVALID_VALUE, __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(width != txr->strideWidth) {
|
||||
INFO_MSG("Strided texture width must match GL_TEXTURE_STRIDE_KOS");
|
||||
_glKosThrowError(GL_INVALID_VALUE, __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
if((txr->strideWidth % 32) != 0 || txr->strideWidth > GL_KOS_MAX_STRIDE_WIDTH) {
|
||||
INFO_MSG("Invalid strided texture width");
|
||||
_glKosThrowError(GL_INVALID_VALUE, __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(height <= 0) {
|
||||
INFO_MSG("Invalid strided texture height");
|
||||
_glKosThrowError(GL_INVALID_VALUE, __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(_glIsTwiddledFormat(cleanInternalFormat)) {
|
||||
INFO_MSG("Strided textures must use non-twiddled storage");
|
||||
_glKosThrowError(GL_INVALID_OPERATION, __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(_glIsPalettedFormat(cleanInternalFormat)) {
|
||||
INFO_MSG("Strided paletted textures are unsupported");
|
||||
_glKosThrowError(GL_INVALID_OPERATION, __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(_glIsCompressedFormat(cleanInternalFormat)) {
|
||||
INFO_MSG("Strided compressed textures are unsupported");
|
||||
_glKosThrowError(GL_INVALID_OPERATION, __func__);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
GLuint w = width;
|
||||
GLuint h = height;
|
||||
if(level == 0){
|
||||
if(!_glValidTextureSize(w)) {
|
||||
if(!isStrided && !_glValidTextureSize(w)) {
|
||||
/* Width is not a power of two. Must be!*/
|
||||
INFO_MSG("Unsupported width");
|
||||
_glKosThrowError(GL_INVALID_VALUE, __func__);
|
||||
@ -1510,7 +1642,7 @@ static bool _glTexImage2DValidate(GLenum target, GLint level, GLint internalForm
|
||||
}
|
||||
|
||||
|
||||
if(!_glValidTextureSize(h)) {
|
||||
if(!isStrided && !_glValidTextureSize(h)) {
|
||||
/* height is not a power of two. Must be!*/
|
||||
INFO_MSG("Unsupported height");
|
||||
_glKosThrowError(GL_INVALID_VALUE, __func__);
|
||||
@ -1630,10 +1762,6 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
||||
GLenum format, GLenum type, const GLvoid *data) {
|
||||
|
||||
TRACE();
|
||||
if(!_glTexImage2DValidate(target, level, internalFormat, width, height, border, format, type)) {
|
||||
return;
|
||||
}
|
||||
|
||||
gl_assert(ACTIVE_TEXTURE < MAX_GLDC_TEXTURE_UNITS);
|
||||
TextureObject* active = TEXTURE_UNITS[ACTIVE_TEXTURE];
|
||||
|
||||
@ -1643,21 +1771,33 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
||||
return;
|
||||
}
|
||||
|
||||
GLenum cleanInternalFormat = _cleanInternalFormatForTexture(active, internalFormat);
|
||||
|
||||
if(!_glTexImage2DValidate(active, target, level, internalFormat, cleanInternalFormat, width, height, border, format, type)) {
|
||||
return;
|
||||
}
|
||||
|
||||
GLboolean isPaletted = (
|
||||
internalFormat == GL_COLOR_INDEX8_EXT ||
|
||||
internalFormat == GL_COLOR_INDEX4_EXT ||
|
||||
internalFormat == GL_COLOR_INDEX4_TWID_KOS ||
|
||||
internalFormat == GL_COLOR_INDEX8_TWID_KOS
|
||||
) ? GL_TRUE : GL_FALSE;
|
||||
GLenum cleanInternalFormat = _cleanInternalFormat(internalFormat);
|
||||
|
||||
GLuint pvrFormat = _determinePVRFormat(cleanInternalFormat);
|
||||
GLuint originalId = active->index;
|
||||
GLboolean isStrided = active->strideWidth ? GL_TRUE : GL_FALSE;
|
||||
GLuint texturePitch = isStrided ? active->strideWidth : (GLuint) width;
|
||||
GLuint pvrWidth = isStrided ? _glNextPowerOfTwo((GLuint) width) : (GLuint) width;
|
||||
GLuint pvrHeight = isStrided ? _glNextPowerOfTwo((GLuint) height) : (GLuint) height;
|
||||
|
||||
if(active->data && (level == 0)) {
|
||||
/* pre-existing texture - check if changed */
|
||||
if(active->width != width ||
|
||||
active->height != height ||
|
||||
active->internalFormat != cleanInternalFormat) {
|
||||
active->internalFormat != cleanInternalFormat ||
|
||||
active->isStrided != isStrided ||
|
||||
active->strideWidth != (isStrided ? texturePitch : 0)) {
|
||||
/* changed - free old texture memory */
|
||||
alloc_free(ALLOC_BASE, active->data);
|
||||
active->data = NULL;
|
||||
@ -1676,7 +1816,8 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
||||
GLint destStride = _determineStrideInternal(cleanInternalFormat);
|
||||
GLint sourceStride = _determineStride(format, type);
|
||||
GLuint srcBytes = ((GLuint)width * (GLuint)height * (GLuint)sourceStride);
|
||||
GLuint destBytes = ((GLuint)width * (GLuint)height * (GLuint)destStride);
|
||||
GLuint texelCount = texturePitch * (GLuint)height;
|
||||
GLuint destBytes = texelCount * (GLuint)destStride;
|
||||
|
||||
TextureConversionFunc conversion = NULL;
|
||||
int needs_conversion = _determineConversion(cleanInternalFormat, format, type, &conversion);
|
||||
@ -1703,6 +1844,14 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
||||
/* need texture memory */
|
||||
active->width = width;
|
||||
active->height = height;
|
||||
active->logicalWidth = width;
|
||||
active->logicalHeight = height;
|
||||
active->pvrWidth = pvrWidth;
|
||||
active->pvrHeight = pvrHeight;
|
||||
active->isStrided = isStrided;
|
||||
if(!isStrided) {
|
||||
active->strideWidth = 0;
|
||||
}
|
||||
active->color = pvrFormat;
|
||||
active->internalFormat = cleanInternalFormat;
|
||||
/* Set the required mipmap count */
|
||||
@ -1745,6 +1894,13 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
||||
GLubyte* targetData = (active->baseDataOffset == 0) ? active->data : _glGetMipmapLocation(active, level);
|
||||
gl_assert(targetData);
|
||||
|
||||
if(!data) {
|
||||
MEMSET4(targetData, 0x0, destBytes);
|
||||
gl_assert(active->index == originalId);
|
||||
_glGPUStateMarkDirty();
|
||||
return;
|
||||
}
|
||||
|
||||
if(needs_conversion < 0) {
|
||||
_glKosThrowError(GL_INVALID_VALUE, __func__);
|
||||
INFO_MSG("Couldn't find necessary texture conversion\n");
|
||||
@ -1842,7 +1998,6 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
||||
} else {
|
||||
/* No conversion necessary, we can just upload data directly */
|
||||
gl_assert(targetData);
|
||||
gl_assert(data);
|
||||
gl_assert(destBytes);
|
||||
|
||||
/* No conversion? Just copy the data, and the pvr_format is correct */
|
||||
@ -1931,6 +2086,21 @@ void APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param) {
|
||||
case GL_SHARED_TEXTURE_BANK_KOS:
|
||||
active->shared_bank = param;
|
||||
break;
|
||||
case GL_TEXTURE_STRIDE_KOS:
|
||||
if(active->data) {
|
||||
_glKosThrowError(GL_INVALID_OPERATION, __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if(param < 0 ||
|
||||
(param != 0 && ((param % 32) != 0 || param > GL_KOS_MAX_STRIDE_WIDTH))) {
|
||||
_glKosThrowError(GL_INVALID_VALUE, __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
active->strideWidth = (GLushort) param;
|
||||
active->isStrided = (param != 0) ? GL_TRUE : GL_FALSE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -2155,22 +2325,21 @@ void APIENTRY glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint y
|
||||
return;
|
||||
}
|
||||
|
||||
if(active->isStrided && level != 0) {
|
||||
_glKosThrowError(GL_INVALID_VALUE, __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
// Retrieve the dimensions of the currently bound texture
|
||||
GLsizei textureWidth = active->width;
|
||||
GLsizei textureHeight = active->height;
|
||||
GLsizei textureWidth = active->logicalWidth ? active->logicalWidth : active->width;
|
||||
GLsizei textureHeight = active->logicalHeight ? active->logicalHeight : active->height;
|
||||
GLsizei texturePitch = active->isStrided ? active->strideWidth : textureWidth;
|
||||
|
||||
if (!_glTexSubImage2DValidate(target, level, xoffset, yoffset, width, height, format, type, textureWidth, textureHeight)) {
|
||||
INFO_MSG("Error: _glTexSubImage2DValidate failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
GLboolean isPaletted = (
|
||||
active->internalFormat == GL_COLOR_INDEX8_EXT ||
|
||||
active->internalFormat == GL_COLOR_INDEX4_EXT ||
|
||||
active->internalFormat == GL_COLOR_INDEX4_TWID_KOS ||
|
||||
active->internalFormat == GL_COLOR_INDEX8_TWID_KOS
|
||||
) ? GL_TRUE : GL_FALSE;
|
||||
|
||||
GLenum cleanInternalFormat = _cleanInternalFormat(active->internalFormat);
|
||||
|
||||
// Determine source stride
|
||||
@ -2181,7 +2350,7 @@ void APIENTRY glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint y
|
||||
GLint destStride = _determineStrideInternal(cleanInternalFormat);
|
||||
|
||||
// Calculate destBytes using the texture's full dimensions
|
||||
GLuint destBytes = (textureWidth * textureHeight * destStride);
|
||||
GLuint destBytes = (texturePitch * textureHeight * destStride);
|
||||
|
||||
TextureConversionFunc conversion = NULL;
|
||||
int needs_conversion = _determineConversion(cleanInternalFormat, format, type, &conversion);
|
||||
@ -2220,7 +2389,7 @@ void APIENTRY glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint y
|
||||
}
|
||||
if (needs_conversion == CONVERSION_TYPE_CONVERT) {
|
||||
for (uint32_t y = 0; y < height; ++y) {
|
||||
dst = conversionBuffer + ((y + yoffset) * textureWidth + xoffset) * destStride;
|
||||
dst = conversionBuffer + ((y + yoffset) * texturePitch + xoffset) * destStride;
|
||||
for (uint32_t x = 0; x < width; ++x) {
|
||||
conversion(src, dst);
|
||||
dst += destStride;
|
||||
@ -2269,7 +2438,7 @@ void APIENTRY glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint y
|
||||
// No conversion necessary, we can update data directly
|
||||
for (GLsizei y = 0; y < height; ++y) {
|
||||
GLsizei srcRowWidth = width * sourceStride;
|
||||
GLubyte* destRow = targetData + ((y + yoffset) * textureWidth + xoffset) * destStride;
|
||||
GLubyte* destRow = targetData + ((y + yoffset) * texturePitch + xoffset) * destStride;
|
||||
FASTCPY(destRow, (GLubyte*)data + y * srcRowWidth, srcRowWidth);
|
||||
}
|
||||
}
|
||||
|
||||
@ -214,4 +214,13 @@ GLAPI GLvoid APIENTRY glDefragmentTextureMemory_KOS(void);
|
||||
/* If enabled, will twiddle texture uploads where possible */
|
||||
#define GL_TEXTURE_TWIDDLE_KOS 0xEF51
|
||||
|
||||
/*
|
||||
* CUSTOM EXTENSION GL_KOS_texture_stride
|
||||
*
|
||||
* Allows explicitly opting a texture into the Dreamcast PVR's non-twiddled
|
||||
* x32 strided texture mode. Pass GL_TEXTURE_STRIDE_KOS to glTexParameteri
|
||||
* before glTexImage2D. The stride is specified in pixels.
|
||||
*/
|
||||
#define GL_TEXTURE_STRIDE_KOS 0xEF52
|
||||
|
||||
__END_DECLS
|
||||
|
||||
192
samples/nehe06_strided/main.c
Normal file
192
samples/nehe06_strided/main.c
Normal file
@ -0,0 +1,192 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef _arch_dreamcast
|
||||
#include <kos.h>
|
||||
#endif
|
||||
|
||||
#include "GL/gl.h"
|
||||
#include "GL/glu.h"
|
||||
#include "GL/glext.h"
|
||||
#include "GL/glkos.h"
|
||||
|
||||
#ifdef _arch_dreamcast
|
||||
extern uint8_t romdisk[];
|
||||
KOS_INIT_ROMDISK(romdisk);
|
||||
#define IMAGE_FILENAME "/rd/NeHe.bmp"
|
||||
#else
|
||||
#define IMAGE_FILENAME "../samples/nehe06_strided/romdisk/NeHe.bmp"
|
||||
#endif
|
||||
|
||||
#include "../loadbmp.h"
|
||||
|
||||
/* floats for x rotation, y rotation, z rotation */
|
||||
float xrot, yrot, zrot;
|
||||
|
||||
/* storage for one texture */
|
||||
GLuint texture[1];
|
||||
|
||||
// Load Bitmaps And Convert To Textures
|
||||
void LoadGLTextures() {
|
||||
// Load Texture
|
||||
Image *image1;
|
||||
|
||||
// allocate space for texture
|
||||
image1 = (Image *) malloc(sizeof(Image));
|
||||
if (image1 == NULL) {
|
||||
printf("Error allocating space for image");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!ImageLoad(IMAGE_FILENAME, image1)) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("Loaded strided texture %dx%d\n", image1->sizeX, image1->sizeY);
|
||||
|
||||
// Create Texture
|
||||
glGenTextures(1, &texture[0]);
|
||||
glBindTexture(GL_TEXTURE_2D, texture[0]); // 2d texture (x and y size)
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // scale linearly when image bigger than texture
|
||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // scale linearly when image smaller than texture
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_STRIDE_KOS, image1->sizeX);
|
||||
|
||||
// 2d texture, level of detail 0 (normal), 3 components (red, green, blue), x size from image, y size from image,
|
||||
// border 0 (normal), rgb color data, unsigned byte data, and finally the data itself.
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image1->sizeX, image1->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->data);
|
||||
free(image1);
|
||||
}
|
||||
|
||||
/* A general OpenGL initialization function. Sets all of the initial parameters. */
|
||||
void InitGL(int Width, int Height) // We call this right after our OpenGL window is created.
|
||||
{
|
||||
LoadGLTextures();
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // This Will Clear The Background Color To Black
|
||||
glClearDepth(1.0); // Enables Clearing Of The Depth Buffer
|
||||
glDepthFunc(GL_LESS); // The Type Of Depth Test To Do
|
||||
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
|
||||
glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity(); // Reset The Projection Matrix
|
||||
|
||||
gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f); // Calculate The Aspect Ratio Of The Window
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
}
|
||||
|
||||
/* The function called when our window is resized (which shouldn't happen, because we're fullscreen) */
|
||||
void ReSizeGLScene(int Width, int Height)
|
||||
{
|
||||
if (Height == 0) // Prevent A Divide By Zero If The Window Is Too Small
|
||||
Height = 1;
|
||||
|
||||
glViewport(0, 0, Width, Height); // Reset The Current Viewport And Perspective Transformation
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
|
||||
gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
}
|
||||
|
||||
int check_start() {
|
||||
#ifdef _arch_dreamcast
|
||||
maple_device_t *cont;
|
||||
cont_state_t *state;
|
||||
|
||||
cont = maple_enum_type(0, MAPLE_FUNC_CONTROLLER);
|
||||
|
||||
if(cont) {
|
||||
state = (cont_state_t *)maple_dev_status(cont);
|
||||
|
||||
if(state)
|
||||
return state->buttons & CONT_START;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The main drawing function. */
|
||||
void DrawGLScene()
|
||||
{
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
|
||||
glLoadIdentity(); // Reset The View
|
||||
|
||||
glTranslatef(0.0f,0.0f,-5.0f); // move 5 units into the screen.
|
||||
|
||||
glRotatef(xrot,1.0f,0.0f,0.0f); // Rotate On The X Axis
|
||||
glRotatef(yrot,0.0f,1.0f,0.0f); // Rotate On The Y Axis
|
||||
glRotatef(zrot,0.0f,0.0f,1.0f); // Rotate On The Z Axis
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture[0]); // choose the texture to use.
|
||||
|
||||
glBegin(GL_QUADS); // begin drawing a cube
|
||||
|
||||
// Front Face (note that the texture's corners have to match the quad's corners)
|
||||
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Left Of The Texture and Quad
|
||||
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); // Bottom Right Of The Texture and Quad
|
||||
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); // Top Right Of The Texture and Quad
|
||||
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // Top Left Of The Texture and Quad
|
||||
|
||||
// Back Face
|
||||
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom Right Of The Texture and Quad
|
||||
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // Top Right Of The Texture and Quad
|
||||
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); // Top Left Of The Texture and Quad
|
||||
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); // Bottom Left Of The Texture and Quad
|
||||
|
||||
// Top Face
|
||||
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // Top Left Of The Texture and Quad
|
||||
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // Bottom Left Of The Texture and Quad
|
||||
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 1.0f); // Bottom Right Of The Texture and Quad
|
||||
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); // Top Right Of The Texture and Quad
|
||||
|
||||
// Bottom Face
|
||||
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // Top Right Of The Texture and Quad
|
||||
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f); // Top Left Of The Texture and Quad
|
||||
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); // Bottom Left Of The Texture and Quad
|
||||
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Right Of The Texture and Quad
|
||||
|
||||
// Right face
|
||||
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); // Bottom Right Of The Texture and Quad
|
||||
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); // Top Right Of The Texture and Quad
|
||||
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); // Top Left Of The Texture and Quad
|
||||
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); // Bottom Left Of The Texture and Quad
|
||||
|
||||
// Left Face
|
||||
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom Left Of The Texture and Quad
|
||||
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Right Of The Texture and Quad
|
||||
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // Top Right Of The Texture and Quad
|
||||
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // Top Left Of The Texture and Quad
|
||||
|
||||
glEnd(); // done with the polygon.
|
||||
|
||||
xrot+=1.5f; // X Axis Rotation
|
||||
yrot+=1.5f; // Y Axis Rotation
|
||||
zrot+=1.5f; // Z Axis Rotation
|
||||
//
|
||||
// swap buffers to display, since we're double buffered.
|
||||
glKosSwapBuffers();
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
glKosInit();
|
||||
|
||||
InitGL(640, 480);
|
||||
ReSizeGLScene(640, 480);
|
||||
|
||||
while(1) {
|
||||
if(check_start())
|
||||
break;
|
||||
|
||||
DrawGLScene();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
BIN
samples/nehe06_strided/romdisk/NeHe.bmp
Normal file
BIN
samples/nehe06_strided/romdisk/NeHe.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 281 KiB |
0
samples/nehe06_strided/romdisk/PLACEHOLDER
Normal file
0
samples/nehe06_strided/romdisk/PLACEHOLDER
Normal file
279
samples/nehe20_strided/main.c
Normal file
279
samples/nehe20_strided/main.c
Normal file
@ -0,0 +1,279 @@
|
||||
/* DREAMCAST
|
||||
*IAN MICHEAL Ported SDL+OPENGL USING SDL[DREAMHAL][GLDC][KOS2.0]2021
|
||||
* Cleaned and tested on dreamcast hardware by Ianmicheal
|
||||
* This Code Was Created By Pet & Commented/Cleaned Up By Jeff Molofee
|
||||
* If You've Found This Code Useful, Please Let Me Know.
|
||||
* Visit NeHe Productions At http://nehe.gamedev.net
|
||||
*/
|
||||
|
||||
#include <math.h> // Header File For Windows Math Library
|
||||
#include <stdio.h> // Header File For Standard Input/Output
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
#ifdef _arch_dreamcast
|
||||
#include <kos.h>
|
||||
#endif
|
||||
|
||||
#define FPS 60
|
||||
uint32_t waittime = 1000.0f/FPS;
|
||||
uint32_t framestarttime = 0;
|
||||
int32_t delaytime;
|
||||
|
||||
#ifdef _arch_dreamcast
|
||||
extern uint8_t romdisk[];
|
||||
KOS_INIT_ROMDISK(romdisk);
|
||||
#define IMG_LOGO_PATH "/rd/logo.bmp"
|
||||
#define IMG_MASK1_PATH "/rd/mask1.bmp"
|
||||
#define IMG_IMAGE1_PATH "/rd/image1.bmp"
|
||||
#define IMG_MASK2_PATH "/rd/mask2.bmp"
|
||||
#define IMG_IMAGE2_PATH "/rd/image2.bmp"
|
||||
#else
|
||||
#define IMG_LOGO_PATH "../samples/nehe20_strided/romdisk/logo.bmp"
|
||||
#define IMG_MASK1_PATH "../samples/nehe20_strided/romdisk/mask1.bmp"
|
||||
#define IMG_IMAGE1_PATH "../samples/nehe20_strided/romdisk/image1.bmp"
|
||||
#define IMG_MASK2_PATH "../samples/nehe20_strided/romdisk/mask2.bmp"
|
||||
#define IMG_IMAGE2_PATH "../samples/nehe20_strided/romdisk/image2.bmp"
|
||||
#endif
|
||||
|
||||
#include "../loadbmp.h"
|
||||
|
||||
/*
|
||||
* This Code Was Created By Jeff Molofee 2000
|
||||
* And Modified By Giuseppe D'Agata (waveform@tiscalinet.it)
|
||||
* If You've Found This Code Useful, Please Let Me Know.
|
||||
* Visit My Site At nehe.gamedev.net
|
||||
*/
|
||||
|
||||
#include <math.h> // Header File For Windows Math Library
|
||||
#include <stdio.h> // Header File For Standard Input/Output
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#endif
|
||||
#if defined(__APPLE__) && defined(__MACH__)
|
||||
#include <OpenGL/gl.h> // Header File For The OpenGL32 Library
|
||||
#include <OpenGL/glu.h> // Header File For The GLu32 Library
|
||||
#elif defined(_arch_dreamcast)
|
||||
#include <kos.h>
|
||||
#include <GL/gl.h> // Header File For The OpenGL32 Library
|
||||
#include <GL/glu.h> // Header File For The GLu32 Library
|
||||
#include <GL/glkos.h>
|
||||
#else
|
||||
#include <GL/gl.h> // Header File For The OpenGL32 Library
|
||||
#include <GL/glkos.h>
|
||||
#include <GL/glu.h> // Header File For The GLu32 Library
|
||||
#endif
|
||||
|
||||
#define BOOL int
|
||||
#define FALSE 0
|
||||
#define TRUE 1
|
||||
|
||||
|
||||
uint8_t* keys; // Array Used For The Keyboard Routine
|
||||
BOOL active=TRUE; // Window Active Flag Set To TRUE By Default
|
||||
BOOL fullscreen=FALSE; // Fullscreen Flag Set To Fullscreen Mode By Default
|
||||
BOOL masking=TRUE; // Masking On/Off
|
||||
BOOL mp; // M Pressed?
|
||||
BOOL sp; // Space Pressed?
|
||||
BOOL scene; // Which Scene To Draw
|
||||
|
||||
GLuint texture[5]; // Storage For Our Five Textures
|
||||
GLuint loop; // Generic Loop Variable
|
||||
|
||||
GLfloat roll; // Rolling Texture
|
||||
|
||||
int LoadGLTextures() // Load Bitmaps And Convert To Textures
|
||||
{
|
||||
int Status=FALSE; // Status Indicator
|
||||
|
||||
Image TextureImage[5];
|
||||
|
||||
if ((ImageLoad(IMG_LOGO_PATH, &TextureImage[0])) && // Logo Texture
|
||||
(ImageLoad(IMG_MASK1_PATH, &TextureImage[1])) && // First Mask
|
||||
(ImageLoad(IMG_IMAGE1_PATH, &TextureImage[2])) && // First Image
|
||||
(ImageLoad(IMG_MASK2_PATH, &TextureImage[3])) && // Second Mask
|
||||
(ImageLoad(IMG_IMAGE2_PATH, &TextureImage[4]))) // Second Image
|
||||
{
|
||||
Status=TRUE; // Set The Status To TRUE
|
||||
glGenTextures(5, &texture[0]); // Create Five Textures
|
||||
|
||||
for (loop=0; loop<5; loop++) // Loop Through All 5 Textures
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, texture[loop]);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
if (loop == 0)
|
||||
{
|
||||
printf("Uploading strided logo texture %dx%d\n",
|
||||
TextureImage[loop].sizeX, TextureImage[loop].sizeY);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_STRIDE_KOS, TextureImage[loop].sizeX);
|
||||
}
|
||||
glTexImage2D(
|
||||
GL_TEXTURE_2D, 0, 3,
|
||||
TextureImage[loop].sizeX,
|
||||
TextureImage[loop].sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE,
|
||||
TextureImage[loop].data
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return Status; // Return The Status
|
||||
}
|
||||
|
||||
GLvoid ReSizeGLScene(GLsizei width, GLsizei height) // Resize And Initialize The GL Window
|
||||
{
|
||||
if (height==0) // Prevent A Divide By Zero By
|
||||
{
|
||||
height=1; // Making Height Equal One
|
||||
}
|
||||
|
||||
glViewport(0,0,width,height); // Reset The Current Viewport
|
||||
glMatrixMode(GL_PROJECTION); // Select The Projection Matrix
|
||||
glLoadIdentity(); // Reset The Projection Matrix
|
||||
gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f); // Calculate Window Aspect Ratio
|
||||
glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
|
||||
glLoadIdentity(); // Reset The Modelview Matrix
|
||||
}
|
||||
|
||||
int InitGL(GLvoid) // All Setup For OpenGL Goes Here
|
||||
{
|
||||
if (!LoadGLTextures()) // Jump To Texture Loading Routine
|
||||
{
|
||||
return FALSE; // If Texture Didn't Load Return FALSE
|
||||
}
|
||||
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Clear The Background Color To Black
|
||||
glClearDepth(1.0); // Enables Clearing Of The Depth Buffer
|
||||
glEnable(GL_DEPTH_TEST); // Enable Depth Testing
|
||||
glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading
|
||||
glEnable(GL_TEXTURE_2D); // Enable 2D Texture Mapping
|
||||
return TRUE; // Initialization Went OK
|
||||
}
|
||||
|
||||
int DrawGLScene(GLvoid) // Here's Where We Do All The Drawing
|
||||
{
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
|
||||
glLoadIdentity(); // Reset The Modelview Matrix
|
||||
glTranslatef(0.0f,0.0f,-2.0f); // Move Into The Screen 5 Units
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture[0]); // Select Our Logo Texture
|
||||
glBegin(GL_QUADS); // Start Drawing A Textured Quad
|
||||
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.1f, -1.1f, 0.0f); // Bottom Left
|
||||
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.1f, -1.1f, 0.0f); // Bottom Right
|
||||
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.1f, 1.1f, 0.0f); // Top Right
|
||||
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.1f, 1.1f, 0.0f); // Top Left
|
||||
glEnd(); // Done Drawing The Quad
|
||||
|
||||
glEnable(GL_BLEND); // Enable Blending
|
||||
glDisable(GL_DEPTH_TEST); // Disable Depth Testing
|
||||
|
||||
if (masking) // Is Masking Enabled?
|
||||
{
|
||||
glBlendFunc(GL_DST_COLOR,GL_ZERO); // Blend Screen Color With Zero (Black)
|
||||
}
|
||||
|
||||
if (scene) // Are We Drawing The Second Scene?
|
||||
{
|
||||
glTranslatef(0.0f,0.0f,-1.0f); // Translate Into The Screen One Unit
|
||||
glRotatef(roll*360,0.0f,0.0f,1.0f); // Rotate On The Z Axis 360 Degrees.
|
||||
if (masking) // Is Masking On?
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, texture[3]); // Select The Second Mask Texture
|
||||
glBegin(GL_QUADS); // Start Drawing A Textured Quad
|
||||
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.1f, -1.1f, 0.0f); // Bottom Left
|
||||
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.1f, -1.1f, 0.0f); // Bottom Right
|
||||
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.1f, 1.1f, 0.0f); // Top Right
|
||||
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.1f, 1.1f, 0.0f); // Top Left
|
||||
glEnd(); // Done Drawing The Quad
|
||||
}
|
||||
|
||||
glBlendFunc(GL_ONE, GL_ONE); // Copy Image 2 Color To The Screen
|
||||
glBindTexture(GL_TEXTURE_2D, texture[4]); // Select The Second Image Texture
|
||||
glBegin(GL_QUADS); // Start Drawing A Textured Quad
|
||||
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.1f, -1.1f, 0.0f); // Bottom Left
|
||||
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.1f, -1.1f, 0.0f); // Bottom Right
|
||||
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.1f, 1.1f, 0.0f); // Top Right
|
||||
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.1f, 1.1f, 0.0f); // Top Left
|
||||
glEnd(); // Done Drawing The Quad
|
||||
}
|
||||
else // Otherwise
|
||||
{
|
||||
if (masking) // Is Masking On?
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, texture[1]); // Select The First Mask Texture
|
||||
glBegin(GL_QUADS); // Start Drawing A Textured Quad
|
||||
glTexCoord2f(roll+0.0f, 0.0f); glVertex3f(-1.1f, -1.1f, 0.0f); // Bottom Left
|
||||
glTexCoord2f(roll+4.0f, 0.0f); glVertex3f( 1.1f, -1.1f, 0.0f); // Bottom Right
|
||||
glTexCoord2f(roll+4.0f, 4.0f); glVertex3f( 1.1f, 1.1f, 0.0f); // Top Right
|
||||
glTexCoord2f(roll+0.0f, 4.0f); glVertex3f(-1.1f, 1.1f, 0.0f); // Top Left
|
||||
glEnd(); // Done Drawing The Quad
|
||||
}
|
||||
|
||||
glBlendFunc(GL_ONE, GL_ONE); // Copy Image 1 Color To The Screen
|
||||
glBindTexture(GL_TEXTURE_2D, texture[2]); // Select The First Image Texture
|
||||
glBegin(GL_QUADS); // Start Drawing A Textured Quad
|
||||
glTexCoord2f(roll+0.0f, 0.0f); glVertex3f(-1.1f, -1.1f, 0.0f); // Bottom Left
|
||||
glTexCoord2f(roll+4.0f, 0.0f); glVertex3f( 1.1f, -1.1f, 0.0f); // Bottom Right
|
||||
glTexCoord2f(roll+4.0f, 4.0f); glVertex3f( 1.1f, 1.1f, 0.0f); // Top Right
|
||||
glTexCoord2f(roll+0.0f, 4.0f); glVertex3f(-1.1f, 1.1f, 0.0f); // Top Left
|
||||
glEnd(); // Done Drawing The Quad
|
||||
}
|
||||
|
||||
glEnable(GL_DEPTH_TEST); // Enable Depth Testing
|
||||
glDisable(GL_BLEND); // Disable Blending
|
||||
|
||||
roll+=0.002f; // Increase Our Texture Roll Variable
|
||||
if (roll>1.0f) // Is Roll Greater Than One
|
||||
{
|
||||
roll-=1.0f; // Subtract 1 From Roll
|
||||
}
|
||||
|
||||
glKosSwapBuffers();
|
||||
|
||||
return TRUE; // Everything Went OK
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
glKosInit();
|
||||
|
||||
InitGL();
|
||||
ReSizeGLScene(640, 480);
|
||||
|
||||
#ifdef _arch_dreamcast
|
||||
maple_device_t* cont = maple_enum_type(0, MAPLE_FUNC_CONTROLLER);
|
||||
assert(cont);
|
||||
#endif
|
||||
|
||||
while(1) {
|
||||
DrawGLScene();
|
||||
|
||||
#ifdef _arch_dreamcast
|
||||
cont_state_t* state = (cont_state_t *)maple_dev_status(cont);
|
||||
|
||||
if((state->buttons & CONT_A) && !sp) {
|
||||
sp = TRUE;
|
||||
scene = !scene;
|
||||
} else {
|
||||
sp = FALSE;
|
||||
}
|
||||
|
||||
if((state->buttons & CONT_B) && !mp) {
|
||||
mp = TRUE;
|
||||
masking = !masking;
|
||||
} else {
|
||||
mp = FALSE;
|
||||
}
|
||||
|
||||
if(state->buttons & CONT_START) {
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
BIN
samples/nehe20_strided/romdisk/image1.bmp
Normal file
BIN
samples/nehe20_strided/romdisk/image1.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 192 KiB |
BIN
samples/nehe20_strided/romdisk/image2.bmp
Normal file
BIN
samples/nehe20_strided/romdisk/image2.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 192 KiB |
BIN
samples/nehe20_strided/romdisk/logo.bmp
Normal file
BIN
samples/nehe20_strided/romdisk/logo.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 225 KiB |
BIN
samples/nehe20_strided/romdisk/mask1.bmp
Normal file
BIN
samples/nehe20_strided/romdisk/mask1.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 192 KiB |
BIN
samples/nehe20_strided/romdisk/mask2.bmp
Normal file
BIN
samples/nehe20_strided/romdisk/mask2.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 192 KiB |
@ -8,6 +8,7 @@
|
||||
class TexImage2DTests : public test::TestCase {
|
||||
public:
|
||||
uint8_t image_data[8 * 8 * 4] = {0};
|
||||
uint8_t stride_image_data[96 * 48 * 4] = {0};
|
||||
|
||||
void set_up() {
|
||||
GLdcConfig config;
|
||||
@ -74,4 +75,54 @@ public:
|
||||
|
||||
assert_equal(internalFormat, GL_ARGB4444_TWID_KOS);
|
||||
}
|
||||
|
||||
void test_npot_rejected_without_stride_parameter() {
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 96, 48, 0, GL_RGB, GL_UNSIGNED_BYTE, stride_image_data);
|
||||
assert_equal(glGetError(), GL_INVALID_VALUE);
|
||||
}
|
||||
|
||||
void test_strided_npot_upload_allowed_after_opt_in() {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_STRIDE_KOS, 96);
|
||||
assert_equal(glGetError(), GL_NO_ERROR);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 96, 48, 0, GL_RGB, GL_UNSIGNED_BYTE, stride_image_data);
|
||||
assert_equal(glGetError(), GL_NO_ERROR);
|
||||
|
||||
GLint internalFormat;
|
||||
glGetIntegerv(GL_TEXTURE_INTERNAL_FORMAT_KOS, &internalFormat);
|
||||
|
||||
assert_equal(internalFormat, GL_RGB565_KOS);
|
||||
}
|
||||
|
||||
void test_strided_texture_width_must_match_stride() {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_STRIDE_KOS, 64);
|
||||
assert_equal(glGetError(), GL_NO_ERROR);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 96, 48, 0, GL_RGB, GL_UNSIGNED_BYTE, stride_image_data);
|
||||
assert_equal(glGetError(), GL_INVALID_VALUE);
|
||||
}
|
||||
|
||||
void test_strided_texture_rejects_invalid_stride_parameter() {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_STRIDE_KOS, 65);
|
||||
assert_equal(glGetError(), GL_INVALID_VALUE);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_STRIDE_KOS, 1024);
|
||||
assert_equal(glGetError(), GL_INVALID_VALUE);
|
||||
}
|
||||
|
||||
void test_strided_texture_rejects_twiddled_storage() {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_STRIDE_KOS, 96);
|
||||
assert_equal(glGetError(), GL_NO_ERROR);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB_TWID_KOS, 96, 48, 0, GL_RGB, GL_UNSIGNED_BYTE, stride_image_data);
|
||||
assert_equal(glGetError(), GL_INVALID_OPERATION);
|
||||
}
|
||||
|
||||
void test_strided_texture_rejects_mipmap_level() {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_STRIDE_KOS, 96);
|
||||
assert_equal(glGetError(), GL_NO_ERROR);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 1, GL_RGB, 96, 48, 0, GL_RGB, GL_UNSIGNED_BYTE, stride_image_data);
|
||||
assert_equal(glGetError(), GL_INVALID_VALUE);
|
||||
}
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user