Add GL_KOS_texture_stride support

This commit is contained in:
GPF 2026-06-20 00:45:11 -07:00
parent c94bfd7c9c
commit 8aa9a0ec43
18 changed files with 802 additions and 33 deletions

View File

@ -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)

View File

@ -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

View File

@ -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;

View File

@ -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();
}

View File

@ -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 {

View File

@ -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";

View File

@ -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);
}
}

View File

@ -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

View 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;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 281 KiB

View 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;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 225 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

View File

@ -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);
}
};