Implement glScissor correctly

This commit is contained in:
Luke Benstead 2021-04-14 21:38:33 +01:00
parent 7146ed303b
commit f03f0e8f04
5 changed files with 217 additions and 14 deletions

View File

@ -139,6 +139,7 @@ gen_sample(terrain samples/terrain/main.c)
gen_sample(zclip samples/zclip/main.c)
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)
if(PLATFORM_DREAMCAST)
gen_sample(polymark samples/polymark/main.c)

View File

@ -18,6 +18,14 @@ PolyList* _glActivePolyList() {
}
}
PolyList* _glOpaquePolyList() {
return &OP_LIST;
}
PolyList* _glPunchThruPolyList() {
return &PT_LIST;
}
PolyList *_glTransparentPolyList() {
return &TR_LIST;
}
@ -105,6 +113,8 @@ void APIENTRY glKosSwapBuffers() {
aligned_vector_clear(&PT_LIST.vector);
aligned_vector_clear(&TR_LIST.vector);
_glApplyScissor(true);
profiler_checkpoint("scene");
profiler_pop();

View File

@ -265,6 +265,8 @@ float _glClipLineToNearZ(const Vertex* v1, const Vertex* v2, Vertex* vout);
void _glClipTriangleStrip(SubmissionTarget* target, uint8_t fladeShade);
PolyList *_glActivePolyList();
PolyList* _glOpaquePolyList();
PolyList* _glPunchThruPolyList();
PolyList *_glTransparentPolyList();
void _glInitAttributePointers();
@ -356,6 +358,8 @@ GLuint _glFreeTextureMemory();
GLuint _glUsedTextureMemory();
GLuint _glFreeContiguousTextureMemory();
void _glApplyScissor(bool force);
#define MAX_TEXTURE_UNITS 2
#define MAX_LIGHTS 8

View File

@ -29,10 +29,22 @@ static GLboolean POLYGON_OFFSET_ENABLED = GL_FALSE;
static GLboolean NORMALIZE_ENABLED = GL_FALSE;
static struct {
GLint x;
GLint y;
GLsizei width;
GLsizei height;
GLboolean applied;
} SCISSOR_RECT = {
0, 0, 640, 480, false
};
GLboolean _glIsSharedTexturePaletteEnabled() {
return SHARED_PALETTE_ENABLED;
}
void _glApplyScissor(bool force);
static int _calc_pvr_face_culling() {
if(!CULLING_ENABLED) {
return GPU_CULLING_NONE;
@ -261,6 +273,13 @@ void _glInitContext() {
GL_CONTEXT.fmt.uv = GPU_UVFMT_32BIT;
GL_CONTEXT.gen.color_clamp = GPU_CLRCLAMP_DISABLE;
const VideoMode* mode = GetVideoMode();
SCISSOR_RECT.x = 0;
SCISSOR_RECT.y = 0;
SCISSOR_RECT.width = mode->width;
SCISSOR_RECT.height = mode->height;
glClearDepth(1.0f);
glDepthFunc(GL_LESS);
glDepthMask(GL_TRUE);
@ -302,6 +321,7 @@ GLAPI void APIENTRY glEnable(GLenum cap) {
} break;
case GL_SCISSOR_TEST: {
GL_CONTEXT.gen.clip_mode = GPU_USERCLIP_INSIDE;
_glApplyScissor(false);
} break;
case GL_LIGHTING: {
LIGHTING_ENABLED = GL_TRUE;
@ -537,6 +557,23 @@ void glPixelStorei(GLenum pname, GLint param) {
}
void APIENTRY glScissor(GLint x, GLint y, GLsizei width, GLsizei height) {
if(SCISSOR_RECT.x == x &&
SCISSOR_RECT.y == y &&
SCISSOR_RECT.width == width &&
SCISSOR_RECT.height == height) {
return;
}
SCISSOR_RECT.x = x;
SCISSOR_RECT.y = y;
SCISSOR_RECT.width = width;
SCISSOR_RECT.height = height;
SCISSOR_RECT.applied = false;
_glApplyScissor(false);
}
/* Setup the hardware user clip rectangle.
The minimum clip rectangle is a 32x32 area which is dependent on the tile
@ -549,30 +586,55 @@ void glPixelStorei(GLenum pname, GLint param) {
glScissor(0, 0, 32, 32) allows only the 'tile' in the lower left
hand corner of the screen to be modified and glScissor(0, 0, 0, 0)
disallows modification to all 'tiles' on the screen.
We call this in the following situations:
- glEnable(GL_SCISSOR_TEST) is called
- glScissor() is called
- After glKosSwapBuffers()
This ensures that a clip command is added to every vertex list
at the right place, either when enabling the scissor test, or
when the scissor test changes.
*/
void APIENTRY glScissor(GLint x, GLint y, GLsizei width, GLsizei height) {
/*!!! FIXME: Shouldn't this be added to *all* lists? */
PVRTileClipCommand *c = aligned_vector_extend(&_glActivePolyList()->vector, 1);
void _glApplyScissor(bool force) {
/* Don't do anyting if clipping is disabled */
if(GL_CONTEXT.gen.clip_mode == GPU_USERCLIP_DISABLE) {
return;
}
/* Don't apply if we already applied - nothing changed */
if(SCISSOR_RECT.applied && !force) {
return;
}
PVRTileClipCommand c;
GLint miny, maxx, maxy;
const VideoMode* vid_mode = GetVideoMode();
GLsizei gl_scissor_width = MAX( MIN(width, vid_mode->width), 0 );
GLsizei gl_scissor_height = MAX( MIN(height, vid_mode->height), 0 );
GLsizei scissor_width = MAX(MIN(SCISSOR_RECT.width, vid_mode->width), 0);
GLsizei scissor_height = MAX(MIN(SCISSOR_RECT.height, vid_mode->height), 0);
/* force the origin to the lower left-hand corner of the screen */
miny = (vid_mode->height - gl_scissor_height) - y;
maxx = (gl_scissor_width + x);
maxy = (gl_scissor_height + miny);
miny = (vid_mode->height - scissor_height) - SCISSOR_RECT.y;
maxx = (scissor_width + SCISSOR_RECT.x);
maxy = (scissor_height + miny);
/* load command structure while mapping screen coords to TA tiles */
c->flags = GPU_CMD_USERCLIP;
c->d1 = c->d2 = c->d3 = 0;
c->sx = CLAMP(x / 32, 0, vid_mode->width / 32);
c->sy = CLAMP(miny / 32, 0, vid_mode->height / 32);
c->ex = CLAMP((maxx / 32) - 1, 0, vid_mode->width / 32);
c->ey = CLAMP((maxy / 32) - 1, 0, vid_mode->height / 32);
c.flags = GPU_CMD_USERCLIP;
c.d1 = c.d2 = c.d3 = 0;
c.sx = CLAMP(SCISSOR_RECT.x / 32, 0, vid_mode->width / 32);
c.sy = CLAMP(miny / 32, 0, vid_mode->height / 32);
c.ex = CLAMP((maxx / 32) - 1, 0, vid_mode->width / 32);
c.ey = CLAMP((maxy / 32) - 1, 0, vid_mode->height / 32);
aligned_vector_push_back(&_glOpaquePolyList()->vector, &c, 1);
aligned_vector_push_back(&_glPunchThruPolyList()->vector, &c, 1);
aligned_vector_push_back(&_glTransparentPolyList()->vector, &c, 1);
SCISSOR_RECT.applied = true;
}
GLboolean APIENTRY glIsEnabled(GLenum cap) {

126
samples/scissor/main.c Normal file
View File

@ -0,0 +1,126 @@
#include "GL/gl.h"
#include "GL/glu.h"
#include "GL/glkos.h"
void InitGL(int Width, int Height)
{
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0);
glDepthFunc(GL_LEQUAL);
glEnable(GL_DEPTH_TEST);
glShadeModel(GL_SMOOTH);
glMatrixMode(GL_PROJECTION);
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);
glScissor(160, 120, 320, 240);
}
/* 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)
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);
}
/* The main drawing function. */
void DrawGLScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(-3.0f, 1.5f, -10.0f);
glBegin(GL_TRIANGLES);
glVertex3f( 0.0f, 1.0f, 0.0f);
glVertex3f( 1.0f,-1.0f, 0.0f);
glVertex3f(-1.0f,-1.0f, 0.0f);
glEnd();
glTranslatef(3.0f, 0.0f, 0.0f);
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);
glEnd();
glTranslatef(3.0f, 0.0f, 0.0f);
glBegin(GL_POLYGON);
glVertex3f(-0.0f, 1.0f, 0.0f);
glVertex3f(-0.75f, 0.75f, 0.0f);
glVertex3f(-1.0f, 0.0f, 0.0f);
glVertex3f(-0.75f,-0.75f, 0.0f);
glVertex3f(-0.0f,-1.0f, 0.0f);
glVertex3f( 0.75f,-0.75f, 0.0f);
glVertex3f( 1.0f, 0.0f, 0.0f);
glVertex3f( 0.75f, 0.75f, 0.0f);
glEnd();
glTranslatef(-6.0f, -3.0f, 0.0f);
glBegin(GL_POLYGON);
glVertex3f( 0.0f, 1.0f, 0.0f);
glVertex3f( 1.0f,-1.0f, 0.0f);
glVertex3f(-1.0f,-1.0f, 0.0f);
glEnd();
glTranslatef(3.0f, 0.0f, 0.0f);
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);
glEnd();
glTranslatef(3.0f, 0.0f, 0.0f);
glBegin(GL_POLYGON);
glVertex3f(-0.0f, 1.0f, 0.0f);
glVertex3f(-0.75f, 0.75f, 0.0f);
glVertex3f(-1.0f, 0.0f, 0.0f);
glVertex3f(-0.75f,-0.75f, 0.0f);
glVertex3f(-0.0f,-1.0f, 0.0f);
glVertex3f( 0.75f,-0.75f, 0.0f);
glVertex3f( 1.0f, 0.0f, 0.0f);
glVertex3f( 0.75f, 0.75f, 0.0f);
glEnd();
glKosSwapBuffers();
}
int main(int argc, char **argv)
{
glKosInit();
InitGL(640, 480);
ReSizeGLScene(640, 480);
while(1) {
DrawGLScene();
}
return 0;
}