@@ -183,6 +183,22 @@ static void setup_cull_mode()
183183 }
184184}
185185
186+ static void update_scissor ()
187+ {
188+ int * params , y ;
189+ if (glparamstate .scissor_enabled ) {
190+ params = glparamstate .scissor ;
191+ /* Take into account that OpenGL Y coordinates are inverted */
192+ y = glparamstate .viewport [3 ] - (params [3 ] + params [1 ]);
193+ } else {
194+ params = glparamstate .viewport ;
195+ y = params [1 ];
196+ }
197+ GX_SetScissor (params [0 ], y , params [2 ], params [3 ]);
198+
199+ glparamstate .dirty .bits .dirty_scissor = 0 ;
200+ }
201+
186202int ogx_enable_double_buffering (int double_buffering )
187203{
188204 int had_double_buffering = glparamstate .active_buffer == GL_BACK ;
@@ -288,6 +304,11 @@ void ogx_initialize()
288304 glMatrixMode (GL_MODELVIEW );
289305 glLoadIdentity ();
290306
307+ glparamstate .scissor [0 ] = glparamstate .scissor [1 ] = 0 ;
308+ /* Scissor width and height are initialized when a window is attached */
309+ glparamstate .scissor [2 ] = glparamstate .scissor [3 ] = -1 ;
310+ glparamstate .scissor_enabled = 0 ;
311+
291312 glparamstate .imm_mode .current_color [0 ] = 1.0f ; // Default imm data, could be wrong
292313 glparamstate .imm_mode .current_color [1 ] = 1.0f ;
293314 glparamstate .imm_mode .current_color [2 ] = 1.0f ;
@@ -542,6 +563,10 @@ void glEnable(GLenum cap)
542563 HANDLE_CALL_LIST (ENABLE , cap );
543564
544565 switch (cap ) {
566+ case GL_SCISSOR_TEST :
567+ glparamstate .scissor_enabled = 1 ;
568+ glparamstate .dirty .bits .dirty_scissor = 1 ;
569+ break ;
545570 case GL_TEXTURE_2D :
546571 glparamstate .texture_enabled |= (1 << glparamstate .active_texture );
547572 glparamstate .dirty .bits .dirty_tev = 1 ;
@@ -619,6 +644,10 @@ void glDisable(GLenum cap)
619644 HANDLE_CALL_LIST (DISABLE , cap );
620645
621646 switch (cap ) {
647+ case GL_SCISSOR_TEST :
648+ glparamstate .scissor_enabled = 0 ;
649+ glparamstate .dirty .bits .dirty_scissor = 1 ;
650+ break ;
622651 case GL_TEXTURE_2D :
623652 glparamstate .texture_enabled &= ~(1 << glparamstate .active_texture );
624653 glparamstate .dirty .bits .dirty_tev = 1 ;
@@ -991,14 +1020,22 @@ void glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
9911020 glparamstate .viewport [2 ] = width ;
9921021 glparamstate .viewport [3 ] = height ;
9931022 GX_SetViewport (x , y , width , height , 0.0f , 1.0f );
994- GX_SetScissor (x , y , width , height );
1023+ if (glparamstate .scissor [2 ] < 0 ) {
1024+ glparamstate .scissor [2 ] = width ;
1025+ glparamstate .scissor [3 ] = height ;
1026+ }
1027+ glparamstate .dirty .bits .dirty_scissor = 1 ;
9951028 _ogx_stencil_update ();
9961029 _ogx_efb_buffer_handle_resize (& s_efb_scene_buffer );
9971030}
9981031
9991032void glScissor (GLint x , GLint y , GLsizei width , GLsizei height )
10001033{
1001- GX_SetScissor (x , y , width , height );
1034+ glparamstate .scissor [0 ] = x ;
1035+ glparamstate .scissor [1 ] = y ;
1036+ glparamstate .scissor [2 ] = width ;
1037+ glparamstate .scissor [3 ] = height ;
1038+ glparamstate .dirty .bits .dirty_scissor = 1 ;
10021039}
10031040
10041041void glMatrixMode (GLenum mode )
@@ -1306,6 +1343,12 @@ void glClear(GLbitfield mask)
13061343 return ;
13071344 }
13081345
1346+ /* Since this function is typically called at the beginning of a frame, and
1347+ * the integration library might have draw something on the screen right
1348+ * before (typically, a mouse cursor), we assume the scissor to be dirty
1349+ * and reset it. */
1350+ update_scissor ();
1351+
13091352 _ogx_efb_set_content_type (OGX_EFB_SCENE );
13101353
13111354 if (mask & GL_STENCIL_BUFFER_BIT ) {
@@ -2313,6 +2356,10 @@ void _ogx_apply_state()
23132356 glparamstate .dirty .bits .dirty_fog = 0 ;
23142357 }
23152358
2359+ if (glparamstate .dirty .bits .dirty_scissor ) {
2360+ update_scissor ();
2361+ }
2362+
23162363 /* Reset the updated bits to 0. We don't unconditionally reset everything
23172364 * to 0 because some states might still be dirty: for example, the stencil
23182365 * checks alters the texture coordinate generation. */
0 commit comments