Merge branch 'scissor' into 'master'

Implement glScissor correctly

See merge request simulant/GLdc!67
This commit is contained in:
Luke Benstead 2021-04-14 20:41:10 +00:00
commit fc1a18e002
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 samples/zclip/main.c)
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)
if(PLATFORM_DREAMCAST) if(PLATFORM_DREAMCAST)
gen_sample(polymark samples/polymark/main.c) 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() { PolyList *_glTransparentPolyList() {
return &TR_LIST; return &TR_LIST;
} }
@ -105,6 +113,8 @@ 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);
profiler_checkpoint("scene"); profiler_checkpoint("scene");
profiler_pop(); 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); void _glClipTriangleStrip(SubmissionTarget* target, uint8_t fladeShade);
PolyList *_glActivePolyList(); PolyList *_glActivePolyList();
PolyList* _glOpaquePolyList();
PolyList* _glPunchThruPolyList();
PolyList *_glTransparentPolyList(); PolyList *_glTransparentPolyList();
void _glInitAttributePointers(); void _glInitAttributePointers();
@ -356,6 +358,8 @@ GLuint _glFreeTextureMemory();
GLuint _glUsedTextureMemory(); GLuint _glUsedTextureMemory();
GLuint _glFreeContiguousTextureMemory(); GLuint _glFreeContiguousTextureMemory();
void _glApplyScissor(bool force);
#define MAX_TEXTURE_UNITS 2 #define MAX_TEXTURE_UNITS 2
#define MAX_LIGHTS 8 #define MAX_LIGHTS 8

View File

@ -29,10 +29,22 @@ static GLboolean POLYGON_OFFSET_ENABLED = GL_FALSE;
static GLboolean NORMALIZE_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() { GLboolean _glIsSharedTexturePaletteEnabled() {
return SHARED_PALETTE_ENABLED; return SHARED_PALETTE_ENABLED;
} }
void _glApplyScissor(bool force);
static int _calc_pvr_face_culling() { static int _calc_pvr_face_culling() {
if(!CULLING_ENABLED) { if(!CULLING_ENABLED) {
return GPU_CULLING_NONE; return GPU_CULLING_NONE;
@ -261,6 +273,13 @@ void _glInitContext() {
GL_CONTEXT.fmt.uv = GPU_UVFMT_32BIT; GL_CONTEXT.fmt.uv = GPU_UVFMT_32BIT;
GL_CONTEXT.gen.color_clamp = GPU_CLRCLAMP_DISABLE; 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); glClearDepth(1.0f);
glDepthFunc(GL_LESS); glDepthFunc(GL_LESS);
glDepthMask(GL_TRUE); glDepthMask(GL_TRUE);
@ -302,6 +321,7 @@ GLAPI void APIENTRY glEnable(GLenum cap) {
} break; } break;
case GL_SCISSOR_TEST: { case GL_SCISSOR_TEST: {
GL_CONTEXT.gen.clip_mode = GPU_USERCLIP_INSIDE; GL_CONTEXT.gen.clip_mode = GPU_USERCLIP_INSIDE;
_glApplyScissor(false);
} break; } break;
case GL_LIGHTING: { case GL_LIGHTING: {
LIGHTING_ENABLED = GL_TRUE; 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. /* Setup the hardware user clip rectangle.
The minimum clip rectangle is a 32x32 area which is dependent on the tile 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 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) hand corner of the screen to be modified and glScissor(0, 0, 0, 0)
disallows modification to all 'tiles' on the screen. 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) { void _glApplyScissor(bool force) {
/*!!! FIXME: Shouldn't this be added to *all* lists? */ /* Don't do anyting if clipping is disabled */
PVRTileClipCommand *c = aligned_vector_extend(&_glActivePolyList()->vector, 1); 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; GLint miny, maxx, maxy;
const VideoMode* vid_mode = GetVideoMode(); const VideoMode* vid_mode = GetVideoMode();
GLsizei gl_scissor_width = MAX( MIN(width, vid_mode->width), 0 ); GLsizei scissor_width = MAX(MIN(SCISSOR_RECT.width, vid_mode->width), 0);
GLsizei gl_scissor_height = MAX( MIN(height, vid_mode->height), 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 */ /* force the origin to the lower left-hand corner of the screen */
miny = (vid_mode->height - gl_scissor_height) - y; miny = (vid_mode->height - scissor_height) - SCISSOR_RECT.y;
maxx = (gl_scissor_width + x); maxx = (scissor_width + SCISSOR_RECT.x);
maxy = (gl_scissor_height + miny); maxy = (scissor_height + miny);
/* load command structure while mapping screen coords to TA tiles */ /* load command structure while mapping screen coords to TA tiles */
c->flags = GPU_CMD_USERCLIP; c.flags = GPU_CMD_USERCLIP;
c->d1 = c->d2 = c->d3 = 0; c.d1 = c.d2 = c.d3 = 0;
c->sx = CLAMP(x / 32, 0, vid_mode->width / 32); c.sx = CLAMP(SCISSOR_RECT.x / 32, 0, vid_mode->width / 32);
c->sy = CLAMP(miny / 32, 0, vid_mode->height / 32); c.sy = CLAMP(miny / 32, 0, vid_mode->height / 32);
c->ex = CLAMP((maxx / 32) - 1, 0, vid_mode->width / 32); c.ex = CLAMP((maxx / 32) - 1, 0, vid_mode->width / 32);
c->ey = CLAMP((maxy / 32) - 1, 0, vid_mode->height / 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) { 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;
}