texture: fix Dreamcast hardware texture and scissor regressions
Fix several Dreamcast hardware regressions found while testing real PVR behavior. - Upload the default white texture through the platform texture loader instead of memcpy directly into PVR texture memory. - Add GPUTextureLoad so SH4 uses pvr_txr_load while the software backend keeps memcpy behavior. - Track scissor/userclip application per polygon list and invalidate scissor state at buffer swap. - Submit queued geometry before USERCLIP/header transitions in the SH4 submit path. - Remove the stale packed 4bpp source-size double-halving in glTexImage2D. - Add texture regression coverage for packed 4bpp, unpack row length, compressed palette4 forwarding, and 8bpp-to-4bpp packing. - Update the scissor sample and add polygon_compare as a small hardware comparison sample. Verified: - make -C dcbuild gldc_tests scissor polygon_compare - scissor sample on Dreamcast hardware - polygon_compare sample on Dreamcast hardware - existing strided texture sample on Dreamcast hardware
This commit is contained in:
parent
862bcf70d1
commit
f11f7c966a
@ -181,6 +181,7 @@ if(BUILD_SAMPLES)
|
|||||||
gen_sample(zclip_triangle samples/zclip_triangle/main.c)
|
gen_sample(zclip_triangle samples/zclip_triangle/main.c)
|
||||||
gen_sample(zclip_trianglestrip samples/zclip_trianglestrip/main.c)
|
gen_sample(zclip_trianglestrip samples/zclip_trianglestrip/main.c)
|
||||||
gen_sample(scissor samples/scissor/main.c)
|
gen_sample(scissor samples/scissor/main.c)
|
||||||
|
gen_sample(polygon_compare samples/polygon_compare/main.c)
|
||||||
gen_sample(polymark samples/polymark/main.c)
|
gen_sample(polymark samples/polymark/main.c)
|
||||||
gen_sample(cubes samples/cubes/main.cpp)
|
gen_sample(cubes samples/cubes/main.cpp)
|
||||||
gen_sample(zclip_test tests/zclip/main.cpp)
|
gen_sample(zclip_test tests/zclip/main.cpp)
|
||||||
|
|||||||
@ -867,8 +867,9 @@ GL_FORCE_INLINE void submitVertices(GLenum mode, GLsizei first, GLuint count, GL
|
|||||||
target->output = _glActivePolyList();
|
target->output = _glActivePolyList();
|
||||||
gl_assert(target->output);
|
gl_assert(target->output);
|
||||||
|
|
||||||
uint32_t vector_size = aligned_vector_size(&target->output->vector);
|
_glApplyScissor(false);
|
||||||
|
|
||||||
|
uint32_t vector_size = aligned_vector_size(&target->output->vector);
|
||||||
GLboolean header_required = (vector_size == 0) || _glGPUStateIsDirty();
|
GLboolean header_required = (vector_size == 0) || _glGPUStateIsDirty();
|
||||||
|
|
||||||
target->count = calcFinalVertices(mode, count);
|
target->count = calcFinalVertices(mode, count);
|
||||||
|
|||||||
@ -141,5 +141,5 @@ void APIENTRY glKosSwapBuffers() {
|
|||||||
aligned_vector_clear(&PT_LIST.vector);
|
aligned_vector_clear(&PT_LIST.vector);
|
||||||
aligned_vector_clear(&TR_LIST.vector);
|
aligned_vector_clear(&TR_LIST.vector);
|
||||||
|
|
||||||
_glApplyScissor(true);
|
_glInvalidateScissor();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -390,6 +390,7 @@ static inline int DimensionFlag(const int w) {
|
|||||||
|
|
||||||
static uint8_t* DEFAULT_TEXTURE = NULL;
|
static uint8_t* DEFAULT_TEXTURE = NULL;
|
||||||
extern void* GPUMemoryAlloc(size_t size);
|
extern void* GPUMemoryAlloc(size_t size);
|
||||||
|
extern void GPUTextureLoad(const void* src, void* dst, size_t size);
|
||||||
|
|
||||||
/* Compile a polygon context into a polygon header */
|
/* Compile a polygon context into a polygon header */
|
||||||
static inline void CompilePolyHeader(PolyHeader *dst, const PolyContext *src) {
|
static inline void CompilePolyHeader(PolyHeader *dst, const PolyContext *src) {
|
||||||
@ -437,18 +438,23 @@ static inline void CompilePolyHeader(PolyHeader *dst, const PolyContext *src) {
|
|||||||
dst->mode2 |= (src->gen.color_clamp << GPU_TA_PM2_CLAMP_SHIFT) & GPU_TA_PM2_CLAMP_MASK;
|
dst->mode2 |= (src->gen.color_clamp << GPU_TA_PM2_CLAMP_SHIFT) & GPU_TA_PM2_CLAMP_MASK;
|
||||||
dst->mode2 |= (src->gen.alpha << GPU_TA_PM2_ALPHA_SHIFT) & GPU_TA_PM2_ALPHA_MASK;
|
dst->mode2 |= (src->gen.alpha << GPU_TA_PM2_ALPHA_SHIFT) & GPU_TA_PM2_ALPHA_MASK;
|
||||||
|
|
||||||
|
dst->mode3 = 0;
|
||||||
|
|
||||||
if(src->txr.enable == GPU_TEXTURE_DISABLE) {
|
if(src->txr.enable == GPU_TEXTURE_DISABLE) {
|
||||||
/* Texturing was disabled so we simulate it with a white texture */
|
/* Texturing was disabled so we simulate it with a white texture */
|
||||||
if(!DEFAULT_TEXTURE) {
|
if(!DEFAULT_TEXTURE) {
|
||||||
|
uint16_t texture[8 * 8];
|
||||||
|
|
||||||
DEFAULT_TEXTURE = (uint8_t*) GPUMemoryAlloc(8 * 8 * 2);
|
DEFAULT_TEXTURE = (uint8_t*) GPUMemoryAlloc(8 * 8 * 2);
|
||||||
for(int i = 0; i < 8 * 8 * 2; ++i) {
|
for(int i = 0; i < 8 * 8; ++i) {
|
||||||
DEFAULT_TEXTURE[i] = 0xff;
|
texture[i] = 0xffff;
|
||||||
}
|
}
|
||||||
|
GPUTextureLoad(texture, DEFAULT_TEXTURE, sizeof(texture));
|
||||||
}
|
}
|
||||||
dst->mode2 |= (DimensionFlag(8) << GPU_TA_PM2_USIZE_SHIFT) & GPU_TA_PM2_USIZE_MASK;
|
dst->mode2 |= (DimensionFlag(8) << GPU_TA_PM2_USIZE_SHIFT) & GPU_TA_PM2_USIZE_MASK;
|
||||||
dst->mode2 |= (DimensionFlag(8) << GPU_TA_PM2_VSIZE_SHIFT) & GPU_TA_PM2_VSIZE_MASK;
|
dst->mode2 |= (DimensionFlag(8) << GPU_TA_PM2_VSIZE_SHIFT) & GPU_TA_PM2_VSIZE_MASK;
|
||||||
dst->mode2 |= (GPU_TXRENV_MODULATE << GPU_TA_PM2_TXRENV_SHIFT) & GPU_TA_PM2_TXRENV_MASK;
|
dst->mode2 |= (GPU_TXRENV_MODULATE << GPU_TA_PM2_TXRENV_SHIFT) & GPU_TA_PM2_TXRENV_MASK;
|
||||||
dst->mode3 |= (GPU_TXRFMT_RGB565 << GPU_TA_PM3_TXRFMT_SHIFT) & GPU_TA_PM3_TXRFMT_MASK;
|
dst->mode3 |= ((GPU_TXRFMT_RGB565 | GPU_TXRFMT_NONTWIDDLED) << GPU_TA_PM3_TXRFMT_SHIFT) & GPU_TA_PM3_TXRFMT_MASK;
|
||||||
/* Convert the texture address */
|
/* Convert the texture address */
|
||||||
txr_base = (uint32_t) DEFAULT_TEXTURE;
|
txr_base = (uint32_t) DEFAULT_TEXTURE;
|
||||||
txr_base = (txr_base & 0x00fffff8) >> 3;
|
txr_base = (txr_base & 0x00fffff8) >> 3;
|
||||||
|
|||||||
@ -20,6 +20,10 @@ void* GPUMemoryAlloc(size_t size) {
|
|||||||
return pvr_mem_malloc(size);
|
return pvr_mem_malloc(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GPUTextureLoad(const void* src, void* dst, size_t size) {
|
||||||
|
pvr_txr_load(src, dst, size);
|
||||||
|
}
|
||||||
|
|
||||||
GL_FORCE_INLINE bool glIsVertex(const float flags) {
|
GL_FORCE_INLINE bool glIsVertex(const float flags) {
|
||||||
return flags == GPU_CMD_VERTEX_EOL || flags == GPU_CMD_VERTEX;
|
return flags == GPU_CMD_VERTEX_EOL || flags == GPU_CMD_VERTEX;
|
||||||
}
|
}
|
||||||
@ -199,7 +203,15 @@ void SceneListSubmit(Vertex* vertices, int n) {
|
|||||||
|
|
||||||
Vertex* v0 = vertices;
|
Vertex* v0 = vertices;
|
||||||
for(int i = 0; i < n - 1; ++i, ++v0) {
|
for(int i = 0; i < n - 1; ++i, ++v0) {
|
||||||
|
if(v0->flags == GPU_CMD_USERCLIP) {
|
||||||
|
SUBMIT_QUEUED_VERTEX(GPU_CMD_VERTEX_EOL);
|
||||||
|
_glPushHeader(v0, 1);
|
||||||
|
visible_mask = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if(is_header(v0)) {
|
if(is_header(v0)) {
|
||||||
|
SUBMIT_QUEUED_VERTEX(GPU_CMD_VERTEX_EOL);
|
||||||
PolyHeader* header = (PolyHeader*) v0;
|
PolyHeader* header = (PolyHeader*) v0;
|
||||||
if(header->meta.texture_is_strided && header->meta.texture_stride != CURRENT_TEXTURE_STRIDE) {
|
if(header->meta.texture_is_strided && header->meta.texture_stride != CURRENT_TEXTURE_STRIDE) {
|
||||||
_glPVRSetTextureStride(header->meta.texture_stride);
|
_glPVRSetTextureStride(header->meta.texture_stride);
|
||||||
|
|||||||
@ -167,6 +167,7 @@ static inline size_t GPUMemoryAvailable() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void* GPUMemoryAlloc(size_t size);
|
void* GPUMemoryAlloc(size_t size);
|
||||||
|
void GPUTextureLoad(const void* src, void* dst, size_t size);
|
||||||
static inline void GPUSetPaletteFormat(GPUPaletteFormat format) {
|
static inline void GPUSetPaletteFormat(GPUPaletteFormat format) {
|
||||||
pvr_set_pal_format((pvr_palfmt_t) format);
|
pvr_set_pal_format((pvr_palfmt_t) format);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -569,6 +569,10 @@ void* GPUMemoryAlloc(size_t size) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GPUTextureLoad(const void* src, void* dst, size_t size) {
|
||||||
|
memcpy(dst, src, size);
|
||||||
|
}
|
||||||
|
|
||||||
void GPUSetPaletteFormat(GPUPaletteFormat format) {
|
void GPUSetPaletteFormat(GPUPaletteFormat format) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -62,6 +62,7 @@ enum GPUPaletteFormat;
|
|||||||
|
|
||||||
size_t GPUMemoryAvailable();
|
size_t GPUMemoryAvailable();
|
||||||
void* GPUMemoryAlloc(size_t size);
|
void* GPUMemoryAlloc(size_t size);
|
||||||
|
void GPUTextureLoad(const void* src, void* dst, size_t size);
|
||||||
void GPUSetPaletteFormat(GPUPaletteFormat format);
|
void GPUSetPaletteFormat(GPUPaletteFormat format);
|
||||||
void GPUSetPaletteEntry(uint32_t idx, uint32_t value);
|
void GPUSetPaletteEntry(uint32_t idx, uint32_t value);
|
||||||
|
|
||||||
@ -73,4 +74,3 @@ void GPUSetFogLinear(float start, float end);
|
|||||||
void GPUSetFogExp(float density);
|
void GPUSetFogExp(float density);
|
||||||
void GPUSetFogExp2(float density);
|
void GPUSetFogExp2(float density);
|
||||||
void GPUSetFogColor(float r, float g, float b, float a);
|
void GPUSetFogColor(float r, float g, float b, float a);
|
||||||
|
|
||||||
|
|||||||
@ -441,6 +441,7 @@ GLuint _glUsedTextureMemory();
|
|||||||
GLuint _glFreeContiguousTextureMemory();
|
GLuint _glFreeContiguousTextureMemory();
|
||||||
|
|
||||||
void _glApplyScissor(bool force);
|
void _glApplyScissor(bool force);
|
||||||
|
void _glInvalidateScissor(void);
|
||||||
void _glSetColorMaterialMask(GLenum mask);
|
void _glSetColorMaterialMask(GLenum mask);
|
||||||
void _glSetColorMaterialMode(GLenum mode);
|
void _glSetColorMaterialMode(GLenum mode);
|
||||||
GLenum _glColorMaterialMode();
|
GLenum _glColorMaterialMode();
|
||||||
|
|||||||
100
GL/state.c
100
GL/state.c
@ -5,6 +5,10 @@
|
|||||||
#include "../include/GL/glext.h"
|
#include "../include/GL/glext.h"
|
||||||
#include "private.h"
|
#include "private.h"
|
||||||
|
|
||||||
|
#define SCISSOR_APPLIED_OP 0x1u
|
||||||
|
#define SCISSOR_APPLIED_PT 0x2u
|
||||||
|
#define SCISSOR_APPLIED_TR 0x4u
|
||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
GLboolean is_dirty;
|
GLboolean is_dirty;
|
||||||
|
|
||||||
@ -33,7 +37,7 @@ static struct {
|
|||||||
GLint y;
|
GLint y;
|
||||||
GLsizei width;
|
GLsizei width;
|
||||||
GLsizei height;
|
GLsizei height;
|
||||||
GLboolean applied;
|
unsigned int applied_lists;
|
||||||
} scissor_rect;
|
} scissor_rect;
|
||||||
|
|
||||||
GLenum blend_sfactor;
|
GLenum blend_sfactor;
|
||||||
@ -87,7 +91,7 @@ static struct {
|
|||||||
.scissor_test_enabled = GL_FALSE,
|
.scissor_test_enabled = GL_FALSE,
|
||||||
.fog_enabled = GL_FALSE,
|
.fog_enabled = GL_FALSE,
|
||||||
.depth_mask_enabled = GL_FALSE,
|
.depth_mask_enabled = GL_FALSE,
|
||||||
.scissor_rect = {0, 0, 640, 480, false},
|
.scissor_rect = {0, 0, 640, 480, 0},
|
||||||
.blend_sfactor = GL_ONE,
|
.blend_sfactor = GL_ONE,
|
||||||
.blend_dfactor = GL_ZERO,
|
.blend_dfactor = GL_ZERO,
|
||||||
.blend_enabled = GL_FALSE,
|
.blend_enabled = GL_FALSE,
|
||||||
@ -553,6 +557,7 @@ GLAPI void APIENTRY glEnable(GLenum cap) {
|
|||||||
case GL_SCISSOR_TEST: {
|
case GL_SCISSOR_TEST: {
|
||||||
if(GPUState.scissor_test_enabled != GL_TRUE) {
|
if(GPUState.scissor_test_enabled != GL_TRUE) {
|
||||||
GPUState.scissor_test_enabled = GL_TRUE;
|
GPUState.scissor_test_enabled = GL_TRUE;
|
||||||
|
GPUState.scissor_rect.applied_lists = 0;
|
||||||
GPUState.is_dirty = GL_TRUE;
|
GPUState.is_dirty = GL_TRUE;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
@ -670,6 +675,7 @@ GLAPI void APIENTRY glDisable(GLenum cap) {
|
|||||||
case GL_SCISSOR_TEST: {
|
case GL_SCISSOR_TEST: {
|
||||||
if(GPUState.scissor_test_enabled != GL_FALSE) {
|
if(GPUState.scissor_test_enabled != GL_FALSE) {
|
||||||
GPUState.scissor_test_enabled = GL_FALSE;
|
GPUState.scissor_test_enabled = GL_FALSE;
|
||||||
|
GPUState.scissor_rect.applied_lists = 0;
|
||||||
GPUState.is_dirty = GL_TRUE;
|
GPUState.is_dirty = GL_TRUE;
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
@ -953,10 +959,8 @@ void APIENTRY glScissor(GLint x, GLint y, GLsizei width, GLsizei height) {
|
|||||||
GPUState.scissor_rect.y = y;
|
GPUState.scissor_rect.y = y;
|
||||||
GPUState.scissor_rect.width = width;
|
GPUState.scissor_rect.width = width;
|
||||||
GPUState.scissor_rect.height = height;
|
GPUState.scissor_rect.height = height;
|
||||||
GPUState.scissor_rect.applied = false;
|
GPUState.scissor_rect.applied_lists = 0;
|
||||||
GPUState.is_dirty = GL_TRUE; // FIXME: do we need this?
|
GPUState.is_dirty = GL_TRUE; // FIXME: do we need this?
|
||||||
|
|
||||||
_glApplyScissor(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Setup the hardware user clip rectangle.
|
/* Setup the hardware user clip rectangle.
|
||||||
@ -982,48 +986,88 @@ void APIENTRY glScissor(GLint x, GLint y, GLsizei width, GLsizei height) {
|
|||||||
at the right place, either when enabling the scissor test, or
|
at the right place, either when enabling the scissor test, or
|
||||||
when the scissor test changes.
|
when the scissor test changes.
|
||||||
*/
|
*/
|
||||||
|
static unsigned int _glActiveScissorListBit(const PolyList* list) {
|
||||||
|
if(list == _glOpaquePolyList()) {
|
||||||
|
return SCISSOR_APPLIED_OP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(list == _glPunchThruPolyList()) {
|
||||||
|
return SCISSOR_APPLIED_PT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SCISSOR_APPLIED_TR;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _glInvalidateScissor(void) {
|
||||||
|
GPUState.scissor_rect.applied_lists = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void _glApplyScissor(bool force) {
|
void _glApplyScissor(bool force) {
|
||||||
/* Don't do anyting if clipping is disabled */
|
/* Don't do anything if clipping is disabled */
|
||||||
if(!GPUState.scissor_test_enabled) {
|
if(!GPUState.scissor_test_enabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Don't apply if we already applied - nothing changed */
|
PolyList* target = _glActivePolyList();
|
||||||
if(GPUState.scissor_rect.applied && !force) {
|
unsigned int active_list_bit = _glActiveScissorListBit(target);
|
||||||
|
|
||||||
|
/* Don't apply if this list already has the current clip rectangle. */
|
||||||
|
if((GPUState.scissor_rect.applied_lists & active_list_bit) && !force) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PVRTileClipCommand c;
|
typedef union {
|
||||||
|
Vertex vertex;
|
||||||
GLint miny, maxx, maxy;
|
PVRTileClipCommand clip;
|
||||||
|
} ScissorCommand;
|
||||||
|
|
||||||
|
ScissorCommand c = {0};
|
||||||
const VideoMode* vid_mode = GetVideoMode();
|
const VideoMode* vid_mode = GetVideoMode();
|
||||||
|
|
||||||
GLsizei scissor_width = MAX(MIN(GPUState.scissor_rect.width, vid_mode->width), 0);
|
GLint x0 = GPUState.scissor_rect.x;
|
||||||
GLsizei scissor_height = MAX(MIN(GPUState.scissor_rect.height, vid_mode->height), 0);
|
GLint y0 = GPUState.scissor_rect.y;
|
||||||
|
GLint x1 = x0 + GPUState.scissor_rect.width;
|
||||||
|
GLint y1 = y0 + GPUState.scissor_rect.height;
|
||||||
|
|
||||||
/* force the origin to the lower left-hand corner of the screen */
|
/*
|
||||||
miny = (vid_mode->height - scissor_height) - GPUState.scissor_rect.y;
|
* glScissor uses OpenGL window coordinates: lower-left origin,
|
||||||
maxx = (scissor_width + GPUState.scissor_rect.x);
|
* x/y inclusive start, width/height extent. Clip to the framebuffer
|
||||||
maxy = (scissor_height + miny);
|
* before converting to PVR tile coordinates.
|
||||||
|
*/
|
||||||
|
x0 = CLAMP(x0, 0, vid_mode->width);
|
||||||
|
y0 = CLAMP(y0, 0, vid_mode->height);
|
||||||
|
x1 = CLAMP(x1, 0, vid_mode->width);
|
||||||
|
y1 = CLAMP(y1, 0, vid_mode->height);
|
||||||
|
|
||||||
/* load command structure while mapping screen coords to TA tiles */
|
|
||||||
c.flags = GPU_CMD_USERCLIP;
|
|
||||||
c.d1 = c.d2 = c.d3 = 0;
|
|
||||||
|
|
||||||
uint16_t vw = vid_mode->width >> 5;
|
uint16_t vw = vid_mode->width >> 5;
|
||||||
uint16_t vh = vid_mode->height >> 5;
|
uint16_t vh = vid_mode->height >> 5;
|
||||||
|
uint16_t max_tx = vw - 1;
|
||||||
|
uint16_t max_ty = vh - 1;
|
||||||
|
|
||||||
c.sx = CLAMP(GPUState.scissor_rect.x >> 5, 0, vw);
|
/* load command structure while mapping screen coords to TA tiles */
|
||||||
c.sy = CLAMP(miny >> 5, 0, vh);
|
c.clip.flags = GPU_CMD_USERCLIP;
|
||||||
c.ex = CLAMP((maxx >> 5) - 1, 0, vw);
|
c.clip.d1 = c.clip.d2 = c.clip.d3 = 0;
|
||||||
c.ey = CLAMP((maxy >> 5) - 1, 0, vh);
|
|
||||||
|
|
||||||
aligned_vector_push_back(&_glOpaquePolyList()->vector, &c, 1);
|
if(x1 <= x0 || y1 <= y0) {
|
||||||
aligned_vector_push_back(&_glPunchThruPolyList()->vector, &c, 1);
|
c.clip.sx = 0;
|
||||||
aligned_vector_push_back(&_glTransparentPolyList()->vector, &c, 1);
|
c.clip.sy = 0;
|
||||||
|
c.clip.ex = 0;
|
||||||
|
c.clip.ey = 0;
|
||||||
|
} else {
|
||||||
|
GLint pvr_y0 = vid_mode->height - y1;
|
||||||
|
GLint pvr_y1 = vid_mode->height - y0;
|
||||||
|
|
||||||
GPUState.scissor_rect.applied = true;
|
c.clip.sx = CLAMP(x0 >> 5, 0, max_tx);
|
||||||
|
c.clip.sy = CLAMP(pvr_y0 >> 5, 0, max_ty);
|
||||||
|
c.clip.ex = CLAMP((x1 - 1) >> 5, 0, max_tx);
|
||||||
|
c.clip.ey = CLAMP((pvr_y1 - 1) >> 5, 0, max_ty);
|
||||||
|
}
|
||||||
|
|
||||||
|
aligned_vector_push_back(&target->vector, &c.vertex, 1);
|
||||||
|
|
||||||
|
GPUState.scissor_rect.applied_lists |= active_list_bit;
|
||||||
|
GPUState.is_dirty = GL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void glStencilFunc(GLenum func, GLint ref, GLuint mask) {
|
void glStencilFunc(GLenum func, GLint ref, GLuint mask) {
|
||||||
|
|||||||
@ -1842,12 +1842,6 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
|||||||
TextureConversionFunc conversion = NULL;
|
TextureConversionFunc conversion = NULL;
|
||||||
int needs_conversion = _determineConversion(cleanInternalFormat, format, type, &conversion);
|
int needs_conversion = _determineConversion(cleanInternalFormat, format, type, &conversion);
|
||||||
|
|
||||||
// Hack: If we're doing a 4bpp source (via glCompressedTexture...)
|
|
||||||
// halve the srcBytes
|
|
||||||
if(format == GL_COLOR_INDEX4_EXT || format == GL_COLOR_INDEX4_TWID_KOS) {
|
|
||||||
srcBytes /= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If we're packing stuff, then the dest size is half what it would be */
|
/* If we're packing stuff, then the dest size is half what it would be */
|
||||||
if((needs_conversion & CONVERSION_TYPE_PACK) == CONVERSION_TYPE_PACK) {
|
if((needs_conversion & CONVERSION_TYPE_PACK) == CONVERSION_TYPE_PACK) {
|
||||||
destBytes /= 2;
|
destBytes /= 2;
|
||||||
|
|||||||
159
samples/polygon_compare/main.c
Normal file
159
samples/polygon_compare/main.c
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
#ifdef _arch_dreamcast
|
||||||
|
#include <kos.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "GL/gl.h"
|
||||||
|
#include "GL/glkos.h"
|
||||||
|
|
||||||
|
#define SCREEN_W 640
|
||||||
|
#define SCREEN_H 480
|
||||||
|
|
||||||
|
static int check_start(void)
|
||||||
|
{
|
||||||
|
#ifdef _arch_dreamcast
|
||||||
|
static maple_device_t *cont;
|
||||||
|
cont_state_t *state;
|
||||||
|
|
||||||
|
if(!cont || !cont->valid)
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setup(void)
|
||||||
|
{
|
||||||
|
glKosInit();
|
||||||
|
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
glDisable(GL_TEXTURE_2D);
|
||||||
|
glDisable(GL_LIGHTING);
|
||||||
|
glShadeModel(GL_SMOOTH);
|
||||||
|
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
glViewport(0, 0, SCREEN_W, SCREEN_H);
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity();
|
||||||
|
glOrtho(0.0, SCREEN_W, SCREEN_H, 0.0, -1.0, 1.0);
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
glDisable(GL_SCISSOR_TEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rect_quad(float x0, float y0, float x1, float y1)
|
||||||
|
{
|
||||||
|
glBegin(GL_QUADS);
|
||||||
|
glVertex2f(x0, y0);
|
||||||
|
glVertex2f(x1, y0);
|
||||||
|
glVertex2f(x1, y1);
|
||||||
|
glVertex2f(x0, y1);
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rect_triangles(float x0, float y0, float x1, float y1)
|
||||||
|
{
|
||||||
|
glBegin(GL_TRIANGLES);
|
||||||
|
glVertex2f(x0, y0);
|
||||||
|
glVertex2f(x1, y0);
|
||||||
|
glVertex2f(x1, y1);
|
||||||
|
|
||||||
|
glVertex2f(x0, y0);
|
||||||
|
glVertex2f(x1, y1);
|
||||||
|
glVertex2f(x0, y1);
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rect_polygon4(float x0, float y0, float x1, float y1)
|
||||||
|
{
|
||||||
|
glBegin(GL_POLYGON);
|
||||||
|
glVertex2f(x0, y0);
|
||||||
|
glVertex2f(x1, y0);
|
||||||
|
glVertex2f(x1, y1);
|
||||||
|
glVertex2f(x0, y1);
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void octagon_points(float cx, float cy, float r)
|
||||||
|
{
|
||||||
|
glVertex2f(cx + 0.00f * r, cy - 1.00f * r);
|
||||||
|
glVertex2f(cx + 0.71f * r, cy - 0.71f * r);
|
||||||
|
glVertex2f(cx + 1.00f * r, cy + 0.00f * r);
|
||||||
|
glVertex2f(cx + 0.71f * r, cy + 0.71f * r);
|
||||||
|
glVertex2f(cx + 0.00f * r, cy + 1.00f * r);
|
||||||
|
glVertex2f(cx - 0.71f * r, cy + 0.71f * r);
|
||||||
|
glVertex2f(cx - 1.00f * r, cy + 0.00f * r);
|
||||||
|
glVertex2f(cx - 0.71f * r, cy - 0.71f * r);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fan8(float cx, float cy, float r)
|
||||||
|
{
|
||||||
|
glBegin(GL_TRIANGLE_FAN);
|
||||||
|
octagon_points(cx, cy, r);
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void polygon8(float cx, float cy, float r)
|
||||||
|
{
|
||||||
|
glBegin(GL_POLYGON);
|
||||||
|
octagon_points(cx, cy, r);
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void draw_case(float y, void (*draw)(float, float, float, float),
|
||||||
|
float x0, float y0, float x1, float y1,
|
||||||
|
GLubyte r, GLubyte g, GLubyte b)
|
||||||
|
{
|
||||||
|
glColor4ub(r, g, b, 255);
|
||||||
|
draw(x0, y0 + y, x1, y1 + y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void draw_scene(void)
|
||||||
|
{
|
||||||
|
static int announced = 0;
|
||||||
|
|
||||||
|
if(!announced) {
|
||||||
|
printf("case 1: GL_QUADS cyan\n");
|
||||||
|
printf("case 2: GL_POLYGON(4) cyan\n");
|
||||||
|
printf("case 3: GL_TRIANGLES cyan\n");
|
||||||
|
printf("case 4: GL_POLYGON(4) blue\n");
|
||||||
|
printf("case 5: GL_POLYGON(4) magenta\n");
|
||||||
|
printf("case 6: GL_TRIANGLE_FAN(8) cyan\n");
|
||||||
|
printf("case 7: GL_POLYGON(8) cyan\n");
|
||||||
|
announced = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
draw_case(0.0f, rect_quad, 40.0f, 40.0f, 140.0f, 140.0f, 0, 255, 255);
|
||||||
|
draw_case(0.0f, rect_polygon4, 180.0f, 40.0f, 280.0f, 140.0f, 0, 255, 255);
|
||||||
|
draw_case(0.0f, rect_triangles, 320.0f, 40.0f, 420.0f, 140.0f, 0, 255, 255);
|
||||||
|
draw_case(150.0f, rect_polygon4, 40.0f, 40.0f, 140.0f, 140.0f, 0, 0, 255);
|
||||||
|
draw_case(150.0f, rect_polygon4, 180.0f, 40.0f, 280.0f, 140.0f, 255, 0, 255);
|
||||||
|
glColor4ub(0, 255, 255, 255);
|
||||||
|
fan8(360.0f, 205.0f, 42.0f);
|
||||||
|
glColor4ub(0, 255, 255, 255);
|
||||||
|
polygon8(520.0f, 205.0f, 42.0f);
|
||||||
|
|
||||||
|
glKosSwapBuffers();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
setup();
|
||||||
|
|
||||||
|
while(!check_start()) {
|
||||||
|
draw_scene();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@ -6,8 +6,30 @@
|
|||||||
#include "GL/glu.h"
|
#include "GL/glu.h"
|
||||||
#include "GL/glkos.h"
|
#include "GL/glkos.h"
|
||||||
|
|
||||||
|
#define SCREEN_W 640
|
||||||
|
#define SCREEN_H 480
|
||||||
|
|
||||||
void InitGL(int Width, int Height)
|
#define SCISSOR_X 160
|
||||||
|
#define SCISSOR_Y 128
|
||||||
|
#define SCISSOR_W 320
|
||||||
|
#define SCISSOR_H 224
|
||||||
|
|
||||||
|
static void setup_projection(int width, int height)
|
||||||
|
{
|
||||||
|
if(height == 0)
|
||||||
|
height = 1;
|
||||||
|
|
||||||
|
glViewport(0, 0, width, height);
|
||||||
|
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glLoadIdentity();
|
||||||
|
gluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f);
|
||||||
|
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glLoadIdentity();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void init_gl(int width, int height)
|
||||||
{
|
{
|
||||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
glClearDepth(1.0);
|
glClearDepth(1.0);
|
||||||
@ -15,39 +37,20 @@ void InitGL(int Width, int Height)
|
|||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
glShadeModel(GL_SMOOTH);
|
glShadeModel(GL_SMOOTH);
|
||||||
|
|
||||||
glMatrixMode(GL_PROJECTION);
|
setup_projection(width, height);
|
||||||
glLoadIdentity();
|
|
||||||
|
|
||||||
gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);
|
|
||||||
|
|
||||||
glMatrixMode(GL_MODELVIEW);
|
|
||||||
|
|
||||||
/* We cut out a square in the middle of the viewport to render to */
|
|
||||||
glEnable(GL_SCISSOR_TEST);
|
glEnable(GL_SCISSOR_TEST);
|
||||||
glScissor(160, 120, 320, 240);
|
glScissor(SCISSOR_X, SCISSOR_Y, SCISSOR_W, SCISSOR_H);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The function called when our window is resized (which shouldn't happen, because we're fullscreen) */
|
static int check_start(void)
|
||||||
void ReSizeGLScene(int Width, int Height)
|
|
||||||
{
|
{
|
||||||
if (Height == 0)
|
|
||||||
Height = 1;
|
|
||||||
|
|
||||||
glViewport(0, 0, Width, Height);
|
|
||||||
|
|
||||||
glMatrixMode(GL_PROJECTION);
|
|
||||||
glLoadIdentity();
|
|
||||||
|
|
||||||
gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);
|
|
||||||
glMatrixMode(GL_MODELVIEW);
|
|
||||||
}
|
|
||||||
|
|
||||||
int check_start() {
|
|
||||||
#ifdef _arch_dreamcast
|
#ifdef _arch_dreamcast
|
||||||
maple_device_t *cont;
|
static maple_device_t *cont;
|
||||||
cont_state_t *state;
|
cont_state_t *state;
|
||||||
|
|
||||||
cont = maple_enum_type(0, MAPLE_FUNC_CONTROLLER);
|
if(!cont || !cont->valid)
|
||||||
|
cont = maple_enum_type(0, MAPLE_FUNC_CONTROLLER);
|
||||||
|
|
||||||
if(cont) {
|
if(cont) {
|
||||||
state = (cont_state_t *)maple_dev_status(cont);
|
state = (cont_state_t *)maple_dev_status(cont);
|
||||||
@ -60,14 +63,62 @@ int check_start() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The main drawing function. */
|
static void draw_scissor_outline(void)
|
||||||
void DrawGLScene()
|
{
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
glDisable(GL_SCISSOR_TEST);
|
||||||
|
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glPushMatrix();
|
||||||
|
glLoadIdentity();
|
||||||
|
glOrtho(0.0, SCREEN_W, SCREEN_H, 0.0, -1.0, 1.0);
|
||||||
|
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
glPushMatrix();
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
{
|
||||||
|
GLfloat x = (GLfloat)SCISSOR_X;
|
||||||
|
GLfloat y = (GLfloat)(SCREEN_H - SCISSOR_Y - SCISSOR_H);
|
||||||
|
GLfloat w = (GLfloat)SCISSOR_W;
|
||||||
|
GLfloat h = (GLfloat)SCISSOR_H;
|
||||||
|
|
||||||
|
glDisable(GL_TEXTURE_2D);
|
||||||
|
glColor4ub(255, 255, 0, 255);
|
||||||
|
|
||||||
|
glBegin(GL_LINES);
|
||||||
|
glVertex2f(x, y);
|
||||||
|
glVertex2f(x + w, y);
|
||||||
|
|
||||||
|
glVertex2f(x + w, y);
|
||||||
|
glVertex2f(x + w, y + h);
|
||||||
|
|
||||||
|
glVertex2f(x + w, y + h);
|
||||||
|
glVertex2f(x, y + h);
|
||||||
|
|
||||||
|
glVertex2f(x, y + h);
|
||||||
|
glVertex2f(x, y);
|
||||||
|
glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glEnable(GL_SCISSOR_TEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void draw_scene_geometry(void)
|
||||||
{
|
{
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
|
|
||||||
glTranslatef(-3.0f, 1.5f, -10.0f);
|
glTranslatef(-3.0f, 1.5f, -10.0f);
|
||||||
|
|
||||||
|
glColor4ub(255, 0, 0, 255);
|
||||||
glBegin(GL_TRIANGLES);
|
glBegin(GL_TRIANGLES);
|
||||||
glVertex3f( 0.0f, 1.0f, 0.0f);
|
glVertex3f( 0.0f, 1.0f, 0.0f);
|
||||||
glVertex3f( 1.0f,-1.0f, 0.0f);
|
glVertex3f( 1.0f,-1.0f, 0.0f);
|
||||||
@ -76,7 +127,7 @@ void DrawGLScene()
|
|||||||
|
|
||||||
glTranslatef(3.0f, 0.0f, 0.0f);
|
glTranslatef(3.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
glColor4ub(0, 255, 0, 255);
|
||||||
glBegin(GL_QUADS);
|
glBegin(GL_QUADS);
|
||||||
glVertex3f(-1.0f, 1.0f, 0.0f);
|
glVertex3f(-1.0f, 1.0f, 0.0f);
|
||||||
glVertex3f( 1.0f, 1.0f, 0.0f);
|
glVertex3f( 1.0f, 1.0f, 0.0f);
|
||||||
@ -86,6 +137,7 @@ void DrawGLScene()
|
|||||||
|
|
||||||
glTranslatef(3.0f, 0.0f, 0.0f);
|
glTranslatef(3.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
glColor4ub(0, 0, 255, 255);
|
||||||
glBegin(GL_POLYGON);
|
glBegin(GL_POLYGON);
|
||||||
glVertex3f(-0.0f, 1.0f, 0.0f);
|
glVertex3f(-0.0f, 1.0f, 0.0f);
|
||||||
glVertex3f(-0.75f, 0.75f, 0.0f);
|
glVertex3f(-0.75f, 0.75f, 0.0f);
|
||||||
@ -99,8 +151,8 @@ void DrawGLScene()
|
|||||||
|
|
||||||
glTranslatef(-6.0f, -3.0f, 0.0f);
|
glTranslatef(-6.0f, -3.0f, 0.0f);
|
||||||
|
|
||||||
|
glColor4ub(255, 128, 0, 255);
|
||||||
glBegin(GL_POLYGON);
|
glBegin(GL_TRIANGLES);
|
||||||
glVertex3f( 0.0f, 1.0f, 0.0f);
|
glVertex3f( 0.0f, 1.0f, 0.0f);
|
||||||
glVertex3f( 1.0f,-1.0f, 0.0f);
|
glVertex3f( 1.0f,-1.0f, 0.0f);
|
||||||
glVertex3f(-1.0f,-1.0f, 0.0f);
|
glVertex3f(-1.0f,-1.0f, 0.0f);
|
||||||
@ -108,7 +160,7 @@ void DrawGLScene()
|
|||||||
|
|
||||||
glTranslatef(3.0f, 0.0f, 0.0f);
|
glTranslatef(3.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
glColor4ub(0, 255, 255, 255);
|
||||||
glBegin(GL_POLYGON);
|
glBegin(GL_POLYGON);
|
||||||
glVertex3f(-1.0f, 1.0f, 0.0f);
|
glVertex3f(-1.0f, 1.0f, 0.0f);
|
||||||
glVertex3f( 1.0f, 1.0f, 0.0f);
|
glVertex3f( 1.0f, 1.0f, 0.0f);
|
||||||
@ -118,6 +170,7 @@ void DrawGLScene()
|
|||||||
|
|
||||||
glTranslatef(3.0f, 0.0f, 0.0f);
|
glTranslatef(3.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
|
glColor4ub(255, 0, 255, 255);
|
||||||
glBegin(GL_POLYGON);
|
glBegin(GL_POLYGON);
|
||||||
glVertex3f(-0.0f, 1.0f, 0.0f);
|
glVertex3f(-0.0f, 1.0f, 0.0f);
|
||||||
glVertex3f(-0.75f, 0.75f, 0.0f);
|
glVertex3f(-0.75f, 0.75f, 0.0f);
|
||||||
@ -128,22 +181,36 @@ void DrawGLScene()
|
|||||||
glVertex3f( 1.0f, 0.0f, 0.0f);
|
glVertex3f( 1.0f, 0.0f, 0.0f);
|
||||||
glVertex3f( 0.75f, 0.75f, 0.0f);
|
glVertex3f( 0.75f, 0.75f, 0.0f);
|
||||||
glEnd();
|
glEnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void draw_gl_scene(void)
|
||||||
|
{
|
||||||
|
glDisable(GL_SCISSOR_TEST);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
draw_scissor_outline();
|
||||||
|
|
||||||
|
glEnable(GL_SCISSOR_TEST);
|
||||||
|
glScissor(SCISSOR_X, SCISSOR_Y, SCISSOR_W, SCISSOR_H);
|
||||||
|
|
||||||
|
draw_scene_geometry();
|
||||||
|
|
||||||
glKosSwapBuffers();
|
glKosSwapBuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
glKosInit();
|
(void)argc;
|
||||||
|
(void)argv;
|
||||||
|
|
||||||
InitGL(640, 480);
|
glKosInit();
|
||||||
ReSizeGLScene(640, 480);
|
init_gl(SCREEN_W, SCREEN_H);
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
if(check_start())
|
if(check_start())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
DrawGLScene();
|
draw_gl_scene();
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@ -251,6 +251,63 @@ public:
|
|||||||
assert_is_not_null(t->palette);
|
assert_is_not_null(t->palette);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_packed_color_index4_upload_uses_packed_source_size() {
|
||||||
|
std::vector<uint8_t> img((8 * 8) / 2, 0xaa);
|
||||||
|
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX4_EXT, 8, 8, 0,
|
||||||
|
GL_COLOR_INDEX4_EXT, GL_UNSIGNED_BYTE, img.data());
|
||||||
|
assert_equal(glGetError(), GL_NO_ERROR);
|
||||||
|
|
||||||
|
TextureObject* t = _glGetBoundTexture();
|
||||||
|
assert_true(t->isPaletted);
|
||||||
|
assert_equal(t->internalFormat, GL_COLOR_INDEX4_TWID_KOS);
|
||||||
|
assert_equal(t->baseDataSize, (GLuint)((8 * 8) / 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_packed_color_index4_upload_respects_unpack_row_length() {
|
||||||
|
std::vector<uint8_t> img(((12 * 8) + 1) / 2, 0xaa);
|
||||||
|
|
||||||
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||||
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, 12);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX4_EXT, 8, 8, 0,
|
||||||
|
GL_COLOR_INDEX4_EXT, GL_UNSIGNED_BYTE, img.data());
|
||||||
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||||
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
|
||||||
|
assert_equal(glGetError(), GL_NO_ERROR);
|
||||||
|
|
||||||
|
TextureObject* t = _glGetBoundTexture();
|
||||||
|
assert_true(t->isPaletted);
|
||||||
|
assert_equal(t->internalFormat, GL_COLOR_INDEX4_TWID_KOS);
|
||||||
|
assert_equal(t->baseDataSize, (GLuint)((8 * 8) / 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_compressed_palette4_upload_uses_packed_source_size() {
|
||||||
|
std::vector<uint8_t> img((16 * 3) + ((8 * 8) / 2), 0xaa);
|
||||||
|
|
||||||
|
glCompressedTexImage2DARB(GL_TEXTURE_2D, 0, GL_PALETTE4_RGB8_OES,
|
||||||
|
8, 8, 0, (GLsizei)img.size(), img.data());
|
||||||
|
assert_equal(glGetError(), GL_NO_ERROR);
|
||||||
|
|
||||||
|
TextureObject* t = _glGetBoundTexture();
|
||||||
|
assert_true(t->isPaletted);
|
||||||
|
assert_equal(t->internalFormat, GL_COLOR_INDEX4_TWID_KOS);
|
||||||
|
assert_equal(t->baseDataSize, (GLuint)((8 * 8) / 2));
|
||||||
|
assert_is_not_null(t->palette);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_color_index8_source_can_pack_to_color_index4() {
|
||||||
|
std::vector<uint8_t> img(8 * 8, 0x0a);
|
||||||
|
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX4_EXT, 8, 8, 0,
|
||||||
|
GL_COLOR_INDEX, GL_UNSIGNED_BYTE, img.data());
|
||||||
|
assert_equal(glGetError(), GL_NO_ERROR);
|
||||||
|
|
||||||
|
TextureObject* t = _glGetBoundTexture();
|
||||||
|
assert_true(t->isPaletted);
|
||||||
|
assert_equal(t->internalFormat, GL_COLOR_INDEX4_TWID_KOS);
|
||||||
|
assert_equal(t->baseDataSize, (GLuint)((8 * 8) / 2));
|
||||||
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------- Error handling */
|
/* ------------------------------------------------- Error handling */
|
||||||
|
|
||||||
void test_non_power_of_two_width_raises_invalid_value() {
|
void test_non_power_of_two_width_raises_invalid_value() {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user