Implement glScissor correctly
This commit is contained in:
parent
7146ed303b
commit
f03f0e8f04
|
@ -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)
|
||||
|
|
10
GL/flush.c
10
GL/flush.c
|
@ -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();
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
90
GL/state.c
90
GL/state.c
|
@ -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
126
samples/scissor/main.c
Normal 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user