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_trianglestrip samples/zclip_trianglestrip/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(cubes samples/cubes/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();
|
||||
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();
|
||||
|
||||
target->count = calcFinalVertices(mode, count);
|
||||
|
||||
@ -141,5 +141,5 @@ void APIENTRY glKosSwapBuffers() {
|
||||
aligned_vector_clear(&PT_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;
|
||||
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 */
|
||||
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.alpha << GPU_TA_PM2_ALPHA_SHIFT) & GPU_TA_PM2_ALPHA_MASK;
|
||||
|
||||
dst->mode3 = 0;
|
||||
|
||||
if(src->txr.enable == GPU_TEXTURE_DISABLE) {
|
||||
/* Texturing was disabled so we simulate it with a white texture */
|
||||
if(!DEFAULT_TEXTURE) {
|
||||
uint16_t texture[8 * 8];
|
||||
|
||||
DEFAULT_TEXTURE = (uint8_t*) GPUMemoryAlloc(8 * 8 * 2);
|
||||
for(int i = 0; i < 8 * 8 * 2; ++i) {
|
||||
DEFAULT_TEXTURE[i] = 0xff;
|
||||
for(int i = 0; i < 8 * 8; ++i) {
|
||||
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_VSIZE_SHIFT) & GPU_TA_PM2_VSIZE_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 */
|
||||
txr_base = (uint32_t) DEFAULT_TEXTURE;
|
||||
txr_base = (txr_base & 0x00fffff8) >> 3;
|
||||
|
||||
@ -20,6 +20,10 @@ void* GPUMemoryAlloc(size_t 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) {
|
||||
return flags == GPU_CMD_VERTEX_EOL || flags == GPU_CMD_VERTEX;
|
||||
}
|
||||
@ -199,7 +203,15 @@ void SceneListSubmit(Vertex* vertices, int n) {
|
||||
|
||||
Vertex* v0 = vertices;
|
||||
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)) {
|
||||
SUBMIT_QUEUED_VERTEX(GPU_CMD_VERTEX_EOL);
|
||||
PolyHeader* header = (PolyHeader*) v0;
|
||||
if(header->meta.texture_is_strided && header->meta.texture_stride != CURRENT_TEXTURE_STRIDE) {
|
||||
_glPVRSetTextureStride(header->meta.texture_stride);
|
||||
|
||||
@ -167,6 +167,7 @@ static inline size_t GPUMemoryAvailable() {
|
||||
}
|
||||
|
||||
void* GPUMemoryAlloc(size_t size);
|
||||
void GPUTextureLoad(const void* src, void* dst, size_t size);
|
||||
static inline void GPUSetPaletteFormat(GPUPaletteFormat 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) {
|
||||
|
||||
}
|
||||
|
||||
@ -62,6 +62,7 @@ enum GPUPaletteFormat;
|
||||
|
||||
size_t GPUMemoryAvailable();
|
||||
void* GPUMemoryAlloc(size_t size);
|
||||
void GPUTextureLoad(const void* src, void* dst, size_t size);
|
||||
void GPUSetPaletteFormat(GPUPaletteFormat format);
|
||||
void GPUSetPaletteEntry(uint32_t idx, uint32_t value);
|
||||
|
||||
@ -73,4 +74,3 @@ void GPUSetFogLinear(float start, float end);
|
||||
void GPUSetFogExp(float density);
|
||||
void GPUSetFogExp2(float density);
|
||||
void GPUSetFogColor(float r, float g, float b, float a);
|
||||
|
||||
|
||||
@ -441,6 +441,7 @@ GLuint _glUsedTextureMemory();
|
||||
GLuint _glFreeContiguousTextureMemory();
|
||||
|
||||
void _glApplyScissor(bool force);
|
||||
void _glInvalidateScissor(void);
|
||||
void _glSetColorMaterialMask(GLenum mask);
|
||||
void _glSetColorMaterialMode(GLenum mode);
|
||||
GLenum _glColorMaterialMode();
|
||||
|
||||
100
GL/state.c
100
GL/state.c
@ -5,6 +5,10 @@
|
||||
#include "../include/GL/glext.h"
|
||||
#include "private.h"
|
||||
|
||||
#define SCISSOR_APPLIED_OP 0x1u
|
||||
#define SCISSOR_APPLIED_PT 0x2u
|
||||
#define SCISSOR_APPLIED_TR 0x4u
|
||||
|
||||
static struct {
|
||||
GLboolean is_dirty;
|
||||
|
||||
@ -33,7 +37,7 @@ static struct {
|
||||
GLint y;
|
||||
GLsizei width;
|
||||
GLsizei height;
|
||||
GLboolean applied;
|
||||
unsigned int applied_lists;
|
||||
} scissor_rect;
|
||||
|
||||
GLenum blend_sfactor;
|
||||
@ -87,7 +91,7 @@ static struct {
|
||||
.scissor_test_enabled = GL_FALSE,
|
||||
.fog_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_dfactor = GL_ZERO,
|
||||
.blend_enabled = GL_FALSE,
|
||||
@ -553,6 +557,7 @@ GLAPI void APIENTRY glEnable(GLenum cap) {
|
||||
case GL_SCISSOR_TEST: {
|
||||
if(GPUState.scissor_test_enabled != GL_TRUE) {
|
||||
GPUState.scissor_test_enabled = GL_TRUE;
|
||||
GPUState.scissor_rect.applied_lists = 0;
|
||||
GPUState.is_dirty = GL_TRUE;
|
||||
}
|
||||
} break;
|
||||
@ -670,6 +675,7 @@ GLAPI void APIENTRY glDisable(GLenum cap) {
|
||||
case GL_SCISSOR_TEST: {
|
||||
if(GPUState.scissor_test_enabled != GL_FALSE) {
|
||||
GPUState.scissor_test_enabled = GL_FALSE;
|
||||
GPUState.scissor_rect.applied_lists = 0;
|
||||
GPUState.is_dirty = GL_TRUE;
|
||||
}
|
||||
} break;
|
||||
@ -953,10 +959,8 @@ void APIENTRY glScissor(GLint x, GLint y, GLsizei width, GLsizei height) {
|
||||
GPUState.scissor_rect.y = y;
|
||||
GPUState.scissor_rect.width = width;
|
||||
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?
|
||||
|
||||
_glApplyScissor(false);
|
||||
}
|
||||
|
||||
/* 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
|
||||
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) {
|
||||
/* Don't do anyting if clipping is disabled */
|
||||
/* Don't do anything if clipping is disabled */
|
||||
if(!GPUState.scissor_test_enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Don't apply if we already applied - nothing changed */
|
||||
if(GPUState.scissor_rect.applied && !force) {
|
||||
PolyList* target = _glActivePolyList();
|
||||
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;
|
||||
}
|
||||
|
||||
PVRTileClipCommand c;
|
||||
|
||||
GLint miny, maxx, maxy;
|
||||
typedef union {
|
||||
Vertex vertex;
|
||||
PVRTileClipCommand clip;
|
||||
} ScissorCommand;
|
||||
|
||||
ScissorCommand c = {0};
|
||||
const VideoMode* vid_mode = GetVideoMode();
|
||||
|
||||
GLsizei scissor_width = MAX(MIN(GPUState.scissor_rect.width, vid_mode->width), 0);
|
||||
GLsizei scissor_height = MAX(MIN(GPUState.scissor_rect.height, vid_mode->height), 0);
|
||||
GLint x0 = GPUState.scissor_rect.x;
|
||||
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;
|
||||
maxx = (scissor_width + GPUState.scissor_rect.x);
|
||||
maxy = (scissor_height + miny);
|
||||
/*
|
||||
* glScissor uses OpenGL window coordinates: lower-left origin,
|
||||
* x/y inclusive start, width/height extent. Clip to the framebuffer
|
||||
* 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 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);
|
||||
c.sy = CLAMP(miny >> 5, 0, vh);
|
||||
c.ex = CLAMP((maxx >> 5) - 1, 0, vw);
|
||||
c.ey = CLAMP((maxy >> 5) - 1, 0, vh);
|
||||
/* load command structure while mapping screen coords to TA tiles */
|
||||
c.clip.flags = GPU_CMD_USERCLIP;
|
||||
c.clip.d1 = c.clip.d2 = c.clip.d3 = 0;
|
||||
|
||||
aligned_vector_push_back(&_glOpaquePolyList()->vector, &c, 1);
|
||||
aligned_vector_push_back(&_glPunchThruPolyList()->vector, &c, 1);
|
||||
aligned_vector_push_back(&_glTransparentPolyList()->vector, &c, 1);
|
||||
if(x1 <= x0 || y1 <= y0) {
|
||||
c.clip.sx = 0;
|
||||
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) {
|
||||
|
||||
@ -1842,12 +1842,6 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
||||
TextureConversionFunc conversion = NULL;
|
||||
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((needs_conversion & CONVERSION_TYPE_PACK) == CONVERSION_TYPE_PACK) {
|
||||
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/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);
|
||||
glClearDepth(1.0);
|
||||
@ -15,39 +37,20 @@ void InitGL(int Width, int Height)
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glShadeModel(GL_SMOOTH);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
setup_projection(width, height);
|
||||
|
||||
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);
|
||||
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) */
|
||||
void ReSizeGLScene(int Width, int Height)
|
||||
static int check_start(void)
|
||||
{
|
||||
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
|
||||
maple_device_t *cont;
|
||||
static maple_device_t *cont;
|
||||
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) {
|
||||
state = (cont_state_t *)maple_dev_status(cont);
|
||||
@ -60,14 +63,62 @@ int check_start() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The main drawing function. */
|
||||
void DrawGLScene()
|
||||
static void draw_scissor_outline(void)
|
||||
{
|
||||
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();
|
||||
|
||||
glTranslatef(-3.0f, 1.5f, -10.0f);
|
||||
|
||||
glColor4ub(255, 0, 0, 255);
|
||||
glBegin(GL_TRIANGLES);
|
||||
glVertex3f( 0.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);
|
||||
|
||||
|
||||
glColor4ub(0, 255, 0, 255);
|
||||
glBegin(GL_QUADS);
|
||||
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);
|
||||
|
||||
glColor4ub(0, 0, 255, 255);
|
||||
glBegin(GL_POLYGON);
|
||||
glVertex3f(-0.0f, 1.0f, 0.0f);
|
||||
glVertex3f(-0.75f, 0.75f, 0.0f);
|
||||
@ -99,8 +151,8 @@ void DrawGLScene()
|
||||
|
||||
glTranslatef(-6.0f, -3.0f, 0.0f);
|
||||
|
||||
|
||||
glBegin(GL_POLYGON);
|
||||
glColor4ub(255, 128, 0, 255);
|
||||
glBegin(GL_TRIANGLES);
|
||||
glVertex3f( 0.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);
|
||||
|
||||
|
||||
glColor4ub(0, 255, 255, 255);
|
||||
glBegin(GL_POLYGON);
|
||||
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);
|
||||
|
||||
glColor4ub(255, 0, 255, 255);
|
||||
glBegin(GL_POLYGON);
|
||||
glVertex3f(-0.0f, 1.0f, 0.0f);
|
||||
glVertex3f(-0.75f, 0.75f, 0.0f);
|
||||
@ -128,22 +181,36 @@ void DrawGLScene()
|
||||
glVertex3f( 1.0f, 0.0f, 0.0f);
|
||||
glVertex3f( 0.75f, 0.75f, 0.0f);
|
||||
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();
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
glKosInit();
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
InitGL(640, 480);
|
||||
ReSizeGLScene(640, 480);
|
||||
glKosInit();
|
||||
init_gl(SCREEN_W, SCREEN_H);
|
||||
|
||||
while(1) {
|
||||
if(check_start())
|
||||
break;
|
||||
|
||||
DrawGLScene();
|
||||
draw_gl_scene();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@ -251,6 +251,63 @@ public:
|
||||
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 */
|
||||
|
||||
void test_non_power_of_two_width_raises_invalid_value() {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user