release r5
[pcsx_rearmed.git] / plugins / gpu-gles / gpuDraw.c
1 /***************************************************************************\r
2                            draw.c  -  description\r
3                              -------------------\r
4     begin                : Sun Mar 08 2009\r
5     copyright            : (C) 1999-2009 by Pete Bernert\r
6     web                  : www.pbernert.com   \r
7  ***************************************************************************/\r
8 \r
9 /***************************************************************************\r
10  *                                                                         *\r
11  *   This program is free software; you can redistribute it and/or modify  *\r
12  *   it under the terms of the GNU General Public License as published by  *\r
13  *   the Free Software Foundation; either version 2 of the License, or     *\r
14  *   (at your option) any later version. See also the license.txt file for *\r
15  *   additional informations.                                              *\r
16  *                                                                         *\r
17  ***************************************************************************/\r
18 \r
19 //*************************************************************************// \r
20 // History of changes:\r
21 //\r
22 // 2009/03/08 - Pete  \r
23 // - generic cleanup for the Peops release\r
24 //\r
25 //*************************************************************************// \r
26 \r
27 \r
28 #define _IN_DRAW\r
29 \r
30 #ifdef _WINDOWS\r
31 #include "stdafx.h"\r
32 #include <stdio.h>\r
33 #include <stdlib.h>\r
34 #include <math.h>\r
35 #include "externals.h"\r
36 #include "gpu.h"\r
37 #include "draw.h"\r
38 #include "prim.h"\r
39 #include "texture.h"\r
40 #else\r
41 #include "gpuExternals.h"\r
42 #include "gpuPlugin.h"\r
43 #include "gpuDraw.h"\r
44 #include "gpuPrim.h"\r
45 #include "gpuTexture.h"\r
46 #include "gpuStdafx.h"\r
47 \r
48 #include <stdio.h>\r
49 #include <stdlib.h>\r
50 #include <math.h>\r
51 #endif\r
52 //#include "menu.h"\r
53             \r
54 ////////////////////////////////////////////////////////////////////////////////////\r
55 // defines\r
56 \r
57 #define SIGNBIT 0x800\r
58 #define S_MASK  0xf000\r
59 #define L_MASK  0xfffff000\r
60 \r
61 // ownscale: some ogl drivers have buggy texture matrix funcs, so it\r
62 //           is safer to calc sow/tow ourselves\r
63 \r
64 #ifdef OWNSCALE\r
65 \r
66 ///////////////////////////////////////////////////////////////\r
67 \r
68 #define ST_FACSPRITE       255.99f\r
69 #define ST_BFFACSPRITE     0.5f/256.0f\r
70 #define ST_BFFACSPRITESORT 0.333f/256.0f\r
71 \r
72 #define ST_OFFSET          0.5f/256.0f;\r
73 \r
74 #define ST_FAC             255.99f\r
75 #define ST_BFFAC           0.5f/256.0f\r
76 #define ST_BFFACSORT       0.333f/256.0f\r
77 \r
78 #define ST_FACTRI          255.99f\r
79 #define ST_BFFACTRI        0.5f/256.0f\r
80 #define ST_BFFACTRISORT    0.333f/256.0f\r
81 \r
82 #define ST_FACVRAMX        255.0f\r
83 #define ST_FACVRAM         256.0f\r
84 \r
85 ///////////////////////////////////////////////////////////////\r
86 \r
87 #else\r
88 \r
89 #define ST_BFFACSPRITE     0.5f\r
90 #define ST_BFFACSPRITESORT 0.333f\r
91 \r
92 #define ST_BFFAC           0.5f\r
93 #define ST_BFFACSORT       0.333f\r
94 \r
95 #define ST_BFFACTRI        0.5f\r
96 #define ST_BFFACTRISORT    0.333f\r
97 \r
98 #define ST_OFFSET          0.5f;\r
99                 \r
100 #endif\r
101 \r
102 ////////////////////////////////////////////////////////////////////////////////////\r
103 // draw globals\r
104 \r
105 #ifdef _WINDOWS\r
106 HDC            dcGlobal=NULL;\r
107 HWND           hWWindow;\r
108 #else\r
109 void  glBlendEquationEXT(GLenum mode);\r
110 void  glColorTableEXT(GLenum target, GLenum internalFormat, GLsizei width, GLenum format,GLenum type, const GLvoid *data);\r
111 #endif\r
112 \r
113 // draw globals; most will be initialized again later (by config or checks) \r
114 \r
115 BOOL           bIsFirstFrame=TRUE;\r
116 \r
117 // resolution/ratio vars\r
118 \r
119 int            iResX;\r
120 int            iResY;\r
121 BOOL           bKeepRatio=FALSE;\r
122 RECT           rRatioRect;\r
123 \r
124 // psx mask related vars\r
125 \r
126 BOOL           bCheckMask=FALSE;\r
127 int            iUseMask=0;\r
128 int            iSetMask=0;\r
129 unsigned short sSetMask=0;\r
130 unsigned long  lSetMask=0;\r
131 \r
132 // drawing/coord vars\r
133 \r
134 OGLVertex      vertex[4];\r
135 GLubyte        gl_ux[8];\r
136 GLubyte        gl_vy[8];\r
137 short          sprtY,sprtX,sprtH,sprtW;\r
138 \r
139 // drawing options\r
140 \r
141 BOOL           bOpaquePass;\r
142 BOOL           bAdvancedBlend;\r
143 \r
144 // OGL extension support\r
145 \r
146 \r
147 // gfx card buffer infos\r
148 \r
149 int            iDepthFunc=0;\r
150 int            iZBufferDepth=0;\r
151 GLbitfield     uiBufferBits=GL_COLOR_BUFFER_BIT;\r
152 \r
153 ////////////////////////////////////////////////////////////////////////\r
154 ////////////////////////////////////////////////////////////////////////\r
155 ////////////////////////////////////////////////////////////////////////\r
156 \r
157 ////////////////////////////////////////////////////////////////////////\r
158 // Set OGL pixel format\r
159 ////////////////////////////////////////////////////////////////////////\r
160  \r
161 #ifdef _WINDOWS\r
162 BOOL bSetupPixelFormat(HDC hDC)\r
163 {\r
164  int pixelformat;\r
165  static PIXELFORMATDESCRIPTOR pfd = \r
166   {\r
167    sizeof(PIXELFORMATDESCRIPTOR),    // size of this pfd\r
168     1,                               // version number\r
169     PFD_DRAW_TO_WINDOW |             // support window\r
170       PFD_SUPPORT_OPENGL |           // support OpenGL\r
171       PFD_DOUBLEBUFFER,              // double buffered\r
172     PFD_TYPE_RGBA,                   // RGBA type\r
173     16,                              // 16-bit color depth  (adjusted later)\r
174     0, 0, 0, 0, 0, 0,                // color bits ignored\r
175     0,                               // no alpha buffer\r
176     0,                               // shift bit ignored\r
177     0,                               // no accumulation buffer\r
178     0, 0, 0, 0,                      // accum bits ignored\r
179     0,                               // z-buffer    \r
180     0,\r
181     0,                               // no auxiliary buffer\r
182     PFD_MAIN_PLANE,                  // main layer\r
183     0,                               // reserved\r
184     0, 0, 0                          // layer masks ignored\r
185   };\r
186  \r
187  pfd.cColorBits=iColDepth;                             // set user color depth\r
188  pfd.cDepthBits=iZBufferDepth;                         // set user zbuffer (by psx mask)\r
189 \r
190  if((pixelformat=ChoosePixelFormat(hDC,&pfd))==0)     \r
191   {\r
192    MessageBox(NULL,"ChoosePixelFormat failed","Error",MB_OK);\r
193    return FALSE;\r
194   }\r
195 \r
196  if(SetPixelFormat(hDC,pixelformat, &pfd)==FALSE)\r
197   {\r
198    MessageBox(NULL,"SetPixelFormat failed","Error",MB_OK);\r
199    return FALSE;\r
200   }\r
201 \r
202  return TRUE;\r
203 }\r
204 #endif\r
205 \r
206 ////////////////////////////////////////////////////////////////////////\r
207 // Get extension infos (f.e. pal textures / packed pixels)\r
208 ////////////////////////////////////////////////////////////////////////\r
209 \r
210 void GetExtInfos(void)                              \r
211 {\r
212  BOOL bPacked=FALSE;                                   // default: no packed pixel support\r
213 \r
214  if(strstr((s8 *)glGetString(GL_EXTENSIONS),         // packed pixels available?\r
215     "GL_EXT_packed_pixels"))                          \r
216   bPacked=TRUE;                                        // -> ok\r
217 \r
218  \r
219  #ifdef _WINDOWS\r
220  iClampType=GL_CLAMP;\r
221 #else\r
222  iClampType=GL_CLAMP_TO_EDGE;\r
223 #endif\r
224 }\r
225 \r
226 ////////////////////////////////////////////////////////////////////////\r
227 // Setup some stuff depending on user settings or in-game toggle\r
228 ////////////////////////////////////////////////////////////////////////\r
229 \r
230 void SetExtGLFuncs(void)\r
231 {\r
232  //----------------------------------------------------//\r
233 \r
234  SetFixes();                                           // update fix infos\r
235 \r
236  //----------------------------------------------------//\r
237 \r
238   {\r
239    if(bAdvancedBlend) bUseMultiPass=TRUE;              // -> pseudo-advanced with 2 passes\r
240    else               bUseMultiPass=FALSE;             // -> or simple 'bright color' mode\r
241 //   bGLBlend=FALSE;                                     // -> no ext blending!\r
242 \r
243    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);    \r
244   }\r
245 \r
246  if(bOpaquePass)                                        // opaque mode?\r
247   {\r
248    if(dwActFixes&32) \r
249     {\r
250      TCF[0]=CP8RGBA_0;\r
251      PalTexturedColourFn=CP8RGBA;                      // -> init col func\r
252     }\r
253    else\r
254     {\r
255      TCF[0]=XP8RGBA_0;\r
256      PalTexturedColourFn=XP8RGBA;                      // -> init col func\r
257     }\r
258 \r
259    TCF[1]=XP8RGBA_1;\r
260    glAlphaFuncx(GL_GREATER,0.49f);\r
261   }\r
262  else                                                  // no opaque mode?\r
263   {\r
264    TCF[0]=TCF[1]=P8RGBA;\r
265    PalTexturedColourFn=P8RGBA;                         // -> init col func\r
266    glAlphaFuncx(GL_NOTEQUAL,0);                         // --> set alpha func\r
267   }\r
268 \r
269  //----------------------------------------------------//\r
270 \r
271  LoadSubTexFn=LoadSubTexturePageSort;                  // init load tex ptr\r
272 \r
273  bBlendEnable=FALSE;                                   // init blending: off\r
274  glDisable(GL_BLEND);\r
275 \r
276  SetScanTrans();                                       // init scan lines (if wanted)\r
277 }\r
278 \r
279 ////////////////////////////////////////////////////////////////////////\r
280 // setup scan lines\r
281 ////////////////////////////////////////////////////////////////////////\r
282 \r
283 #define R_TSP 0x00,0x45,0x00,0xff\r
284 #define G_TSP 0x00,0x00,0x45,0xff\r
285 #define B_TSP 0x45,0x00,0x00,0xff\r
286 #define O_TSP 0x45,0x45,0x45,0xff\r
287 #define N_TSP 0x00,0x00,0x00,0xff\r
288 \r
289 GLuint  gTexScanName=0;\r
290 \r
291 GLubyte texscan[4][16]= \r
292 {\r
293 {R_TSP, G_TSP, B_TSP, N_TSP},\r
294 {O_TSP, N_TSP, O_TSP, N_TSP},\r
295 {B_TSP, N_TSP, R_TSP, G_TSP},\r
296 {O_TSP, N_TSP, O_TSP, N_TSP}\r
297 };\r
298 \r
299 void CreateScanLines(void)\r
300 {\r
301 }\r
302 \r
303 ////////////////////////////////////////////////////////////////////////\r
304 // Initialize OGL\r
305 ////////////////////////////////////////////////////////////////////////\r
306 \r
307 #ifdef _WINDOWS    \r
308 HGLRC GLCONTEXT=NULL;\r
309 #endif\r
310 \r
311 #ifdef MAEMO_CHANGES\r
312 #define MODE_RAW 0\r
313 #define MODE_X11 1\r
314 #define MODE_SDL 2\r
315 int pandora_driver_mode = MODE_RAW;\r
316 int use_fsaa = 0;\r
317 \r
318 EGLDisplay display;\r
319 EGLConfig  config;\r
320 EGLContext context;\r
321 EGLSurface surface;\r
322 \r
323 #if defined(USE_X11)\r
324 #include "X11/Xlib.h"\r
325 #include "X11/Xutil.h"\r
326 #include "X11/Xatom.h"\r
327 \r
328 Window                  x11Window       = 0;\r
329 Display*                x11Display      = 0;\r
330 long                    x11Screen       = 0;\r
331 XVisualInfo             x11Visual;\r
332 XVisualInfo*    px11Visual      = 0;\r
333 Colormap        x11Colormap     = 0;\r
334 #endif\r
335 \r
336 EGLint attrib_list_fsaa[] =\r
337 {\r
338         EGL_SURFACE_TYPE, EGL_WINDOW_BIT,\r
339         EGL_BUFFER_SIZE,    0,\r
340         EGL_DEPTH_SIZE,     16,\r
341         EGL_SAMPLE_BUFFERS, 1,\r
342         EGL_SAMPLES,        4,\r
343         EGL_NONE\r
344 };\r
345 \r
346 EGLint attrib_list[] =\r
347 {\r
348         EGL_SURFACE_TYPE, EGL_WINDOW_BIT,\r
349         EGL_BUFFER_SIZE,  0,\r
350         EGL_DEPTH_SIZE,   16,\r
351         EGL_NONE\r
352 };\r
353 \r
354 bool TestEGLError(const char* pszLocation)\r
355 {\r
356         /*\r
357                 eglGetError returns the last error that has happened using egl,\r
358                 not the status of the last called function. The user has to\r
359                 check after every single egl call or at least once every frame.\r
360         */\r
361         EGLint iErr = eglGetError();\r
362         if (iErr != EGL_SUCCESS)\r
363         {\r
364                 printf("%s failed (%d).\n", pszLocation, iErr);\r
365                 return FALSE;\r
366         }\r
367 \r
368         return TRUE;\r
369 }\r
370 \r
371 void maemoGLinit(){\r
372         printf ("GL init\n");\r
373 \r
374         EGLint numConfigs;\r
375         EGLint majorVersion;\r
376         EGLint minorVersion;\r
377 #if defined(USE_X11)\r
378         enum\r
379         {\r
380         _NET_WM_STATE_REMOVE =0,\r
381         _NET_WM_STATE_ADD = 1,\r
382         _NET_WM_STATE_TOGGLE =2\r
383         };\r
384         \r
385         Window                          sRootWindow;\r
386         XSetWindowAttributes    sWA;\r
387         unsigned int                ui32Mask;\r
388         int                                 i32Depth;\r
389 #endif\r
390         \r
391         EGLint *attribList = NULL;\r
392         if (use_fsaa)\r
393         {\r
394                 printf( "GLES: Using Full Scene Antialiasing\n" );\r
395                 attribList = attrib_list_fsaa;\r
396         }\r
397         else\r
398         {\r
399                 attribList = attrib_list;\r
400         }\r
401 \r
402 #if defined(USE_X11)\r
403         pandora_driver_mode = MODE_X11; // TODO make configurable\r
404 #else\r
405         pandora_driver_mode = MODE_RAW; // TODO make configurable\r
406 #endif\r
407         \r
408     switch(pandora_driver_mode)\r
409             {            \r
410 #if defined(USE_X11)\r
411         case MODE_X11:\r
412             // Initializes the display and screen\r
413             x11Display = XOpenDisplay( ":0" );\r
414             if (!x11Display)\r
415             {\r
416                 printf("GLES Error: Unable to open X display\n");\r
417             }\r
418             x11Screen = XDefaultScreen( x11Display );\r
419                                 \r
420             // Gets the display parameters so we can pass the same parameters to the window to be created.\r
421             sRootWindow = RootWindow(x11Display, x11Screen);\r
422             i32Depth    = DefaultDepth(x11Display, x11Screen);\r
423             px11Visual  = &x11Visual;\r
424             XMatchVisualInfo( x11Display, x11Screen, i32Depth, TrueColor, px11Visual);\r
425             if (!px11Visual)\r
426             {\r
427                 printf("GLES Error: Unable to acquire visual\n");\r
428                         }\r
429             // Colormap of the specified visual type for the display.\r
430             x11Colormap = XCreateColormap( x11Display, sRootWindow, px11Visual->visual, AllocNone );\r
431             sWA.colormap = x11Colormap;\r
432 \r
433             // List of events to be handled by the application. Add to these for handling other events.\r
434             sWA.event_mask = StructureNotifyMask | ExposureMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask;\r
435 \r
436             // Display capabilities list.\r
437             ui32Mask = CWBackPixel | CWBorderPixel | CWEventMask | CWColormap;\r
438                                                            \r
439             // Creates the X11 window\r
440             x11Window = XCreateWindow( x11Display, RootWindow(x11Display, x11Screen), 0, 0, iResX, iResY,\r
441                                         0, CopyFromParent, InputOutput, CopyFromParent, ui32Mask, &sWA);\r
442 \r
443             // Make the window viewable and flush the output buffer.\r
444             XMapWindow(x11Display, x11Window);\r
445             XFlush(x11Display);\r
446 \r
447             // Make the window fullscreen\r
448             unsigned char fullScreen = 1;\r
449             Atom wmState = XInternAtom(x11Display, "_NET_WM_STATE", False);\r
450             Atom wmFullScreen = XInternAtom(x11Display,"_NET_WM_STATE_FULLSCREEN", False);\r
451 \r
452             XEvent xev;\r
453             xev.xclient.type                = ClientMessage;\r
454             xev.xclient.serial              = 0;\r
455             xev.xclient.send_event      = True;\r
456             xev.xclient.window              = x11Window;\r
457             xev.xclient.message_type    = wmState;\r
458             xev.xclient.format              = 32;\r
459             xev.xclient.data.l[0]               = (fullScreen ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE);\r
460             xev.xclient.data.l[1]               = wmFullScreen;\r
461             xev.xclient.data.l[2]               = 0;\r
462 \r
463             XSendEvent(x11Display, DefaultRootWindow(x11Display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);\r
464 \r
465             display = eglGetDisplay( (EGLNativeDisplayType)x11Display );\r
466             break;\r
467 #endif\r
468         case MODE_RAW:\r
469         default:\r
470             display = eglGetDisplay( (EGLNativeDisplayType)0 );\r
471             break;\r
472     }\r
473 \r
474         if( display == EGL_NO_DISPLAY )\r
475         {\r
476                 printf( "GLES EGL Error: GL No Display\n" );\r
477         }\r
478 \r
479         if( !eglInitialize( display, &majorVersion, &minorVersion ) )\r
480         {\r
481                 printf( "GLES EGL Error: eglInitialize failed\n" );\r
482         }\r
483 \r
484         if( !eglChooseConfig( display, attribList, &config, 1, &numConfigs ) )\r
485         {\r
486                 printf( "GLES EGL Error: eglChooseConfig failed\n" );\r
487         }\r
488 \r
489         context = eglCreateContext( display, config, NULL, NULL );\r
490         if( context==0 )\r
491         {\r
492                 printf( "GLES EGL Error: eglCreateContext failed\n" );\r
493         }\r
494 \r
495     switch(pandora_driver_mode)\r
496         {\r
497 #if defined(USE_X11)\r
498         case MODE_X11:\r
499             surface = eglCreateWindowSurface( display, config, (EGLNativeDisplayType)x11Window, NULL );\r
500             break;\r
501 #endif\r
502         case MODE_RAW:\r
503         default:\r
504             surface = eglCreateWindowSurface( display, config, (EGLNativeDisplayType)0, NULL );\r
505             break;\r
506         }\r
507 \r
508     eglMakeCurrent( display, surface, surface, context );\r
509     if (!TestEGLError("eglMakeCurrent"))\r
510         printf("error eglMakeCurrent");\r
511     else\r
512         printf("GLES Window Opened\n");\r
513 }\r
514 #endif\r
515 \r
516 int GLinitialize() \r
517 {\r
518  //----------------------------------------------------// \r
519 #ifdef _WINDOWS\r
520  HGLRC objectRC;\r
521  // init\r
522  dcGlobal = GetDC(hWWindow);                           // FIRST: dc/rc stuff\r
523  objectRC = wglCreateContext(dcGlobal); \r
524  GLCONTEXT=objectRC;\r
525  wglMakeCurrent(dcGlobal, objectRC);\r
526  // CheckWGLExtensions(dcGlobal);\r
527  if(bWindowMode) ReleaseDC(hWWindow,dcGlobal);         // win mode: release dc again\r
528 #endif\r
529 #ifdef MAEMO_CHANGES\r
530          maemoGLinit();\r
531 #endif\r
532  //----------------------------------------------------// \r
533 \r
534  glViewport(rRatioRect.left,                           // init viewport by ratio rect\r
535             iResY-(rRatioRect.top+rRatioRect.bottom),\r
536             rRatioRect.right, \r
537             rRatioRect.bottom);         \r
538                                                       \r
539  glScissor(0, 0, iResX, iResY);                        // init clipping (fullscreen)\r
540  glEnable(GL_SCISSOR_TEST);                       \r
541 \r
542 #ifndef OWNSCALE\r
543  glMatrixMode(GL_TEXTURE);                             // init psx tex sow and tow if not "ownscale"\r
544  glLoadIdentity();\r
545  glScalef(1.0f/255.99f,1.0f/255.99f,1.0f);             // geforce precision hack\r
546 #endif \r
547 \r
548  glMatrixMode(GL_PROJECTION);                          // init projection with psx resolution\r
549  glLoadIdentity();\r
550  glOrtho(0,PSXDisplay.DisplayMode.x,\r
551          PSXDisplay.DisplayMode.y, 0, -1, 1);\r
552 \r
553  if(iZBufferDepth)                                     // zbuffer?\r
554   {\r
555    uiBufferBits=GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT;\r
556    glEnable(GL_DEPTH_TEST);    \r
557    glDepthFunc(GL_ALWAYS);\r
558    iDepthFunc=1;\r
559   }\r
560  else                                                  // no zbuffer?\r
561   {\r
562    uiBufferBits=GL_COLOR_BUFFER_BIT;\r
563    glDisable(GL_DEPTH_TEST);\r
564   }\r
565 \r
566  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);                 // first buffer clear\r
567  glClear(uiBufferBits);\r
568 \r
569  GetExtInfos();                                        // get ext infos\r
570  SetExtGLFuncs();                                      // init all kind of stuff (tex function pointers)\r
571  \r
572  glEnable(GL_ALPHA_TEST);                              // wanna alpha test\r
573 \r
574   {\r
575    glDisable(GL_LINE_SMOOTH);\r
576    glDisable(GL_POINT_SMOOTH);\r
577   }\r
578 \r
579  ubGloAlpha=127;                                       // init some drawing vars\r
580  ubGloColAlpha=127;\r
581  TWin.UScaleFactor = 1;\r
582  TWin.VScaleFactor = 1;\r
583  bDrawMultiPass=FALSE;\r
584  bTexEnabled=FALSE;\r
585  bUsingTWin=FALSE;\r
586       \r
587  if(bDrawDither)  glEnable(GL_DITHER);                 // dither mode\r
588  else             glDisable(GL_DITHER); \r
589 \r
590  glDisable(GL_FOG);                                    // turn all (currently) unused modes off\r
591  glDisable(GL_LIGHTING);  \r
592  glDisable(GL_STENCIL_TEST);  \r
593  glDisable(GL_TEXTURE_2D);\r
594  glDisable(GL_CULL_FACE);\r
595 \r
596  glFlush();                                            // we are done...\r
597  glFinish();                           \r
598 \r
599  CreateScanLines();                                    // setup scanline stuff (if wanted)\r
600 \r
601  CheckTextureMemory();                                 // check available tex memory\r
602 \r
603  if(bKeepRatio) SetAspectRatio();                      // set ratio\r
604 \r
605  \r
606  bIsFirstFrame = FALSE;                                // we have survived the first frame :)\r
607 \r
608  return 0;\r
609 }\r
610 \r
611 ////////////////////////////////////////////////////////////////////////\r
612 // clean up OGL stuff\r
613 ////////////////////////////////////////////////////////////////////////\r
614 \r
615 void GLcleanup() \r
616 {                                                     \r
617  CleanupTextureStore();                                // bye textures\r
618 \r
619 #ifdef _WINDOWS \r
620  wglMakeCurrent(NULL, NULL);                           // bye context\r
621  if(GLCONTEXT) wglDeleteContext(GLCONTEXT);\r
622  if(!bWindowMode && dcGlobal) \r
623   ReleaseDC(hWWindow,dcGlobal);\r
624 #endif\r
625 \r
626         eglMakeCurrent( display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );\r
627         eglDestroySurface( display, surface );\r
628         eglDestroyContext( display, context );\r
629         eglTerminate( display );\r
630 \r
631 #if defined(USE_X11)\r
632         if (pandora_driver_mode == MODE_X11)\r
633         {\r
634                 if (x11Window) XDestroyWindow(x11Display, x11Window);\r
635                 if (x11Colormap) XFreeColormap( x11Display, x11Colormap );\r
636                 if (x11Display) XCloseDisplay(x11Display);\r
637         }\r
638 #endif\r
639 }\r
640 \r
641 ////////////////////////////////////////////////////////////////////////\r
642 ////////////////////////////////////////////////////////////////////////\r
643 ////////////////////////////////////////////////////////////////////////\r
644 \r
645 ////////////////////////////////////////////////////////////////////////\r
646 ////////////////////////////////////////////////////////////////////////\r
647 ////////////////////////////////////////////////////////////////////////\r
648 \r
649 ////////////////////////////////////////////////////////////////////////\r
650 // Offset stuff\r
651 ////////////////////////////////////////////////////////////////////////\r
652 \r
653 // please note: it is hardly do-able in a hw/accel plugin to get the \r
654 //              real psx polygon coord mapping right... the following\r
655 //              works not to bad with many games, though\r
656 \r
657 __inline BOOL CheckCoord4()\r
658 {\r
659  if(lx0<0)\r
660   {\r
661    if(((lx1-lx0)>CHKMAX_X) ||\r
662       ((lx2-lx0)>CHKMAX_X)) \r
663     {\r
664      if(lx3<0)\r
665       {\r
666        if((lx1-lx3)>CHKMAX_X) return TRUE;\r
667        if((lx2-lx3)>CHKMAX_X) return TRUE;\r
668       }\r
669     }\r
670   }\r
671  if(lx1<0)\r
672   {\r
673    if((lx0-lx1)>CHKMAX_X) return TRUE;\r
674    if((lx2-lx1)>CHKMAX_X) return TRUE;\r
675    if((lx3-lx1)>CHKMAX_X) return TRUE;\r
676   }\r
677  if(lx2<0)\r
678   {\r
679    if((lx0-lx2)>CHKMAX_X) return TRUE;\r
680    if((lx1-lx2)>CHKMAX_X) return TRUE;\r
681    if((lx3-lx2)>CHKMAX_X) return TRUE;\r
682   }\r
683  if(lx3<0)\r
684   {\r
685    if(((lx1-lx3)>CHKMAX_X) ||\r
686       ((lx2-lx3)>CHKMAX_X))\r
687     {\r
688      if(lx0<0)\r
689       {\r
690        if((lx1-lx0)>CHKMAX_X) return TRUE;\r
691        if((lx2-lx0)>CHKMAX_X) return TRUE;\r
692       }\r
693     }\r
694   }\r
695  \r
696 \r
697  if(ly0<0)\r
698   {\r
699    if((ly1-ly0)>CHKMAX_Y) return TRUE;\r
700    if((ly2-ly0)>CHKMAX_Y) return TRUE;\r
701   }\r
702  if(ly1<0)\r
703   {\r
704    if((ly0-ly1)>CHKMAX_Y) return TRUE;\r
705    if((ly2-ly1)>CHKMAX_Y) return TRUE;\r
706    if((ly3-ly1)>CHKMAX_Y) return TRUE;\r
707   }\r
708  if(ly2<0)\r
709   {\r
710    if((ly0-ly2)>CHKMAX_Y) return TRUE;\r
711    if((ly1-ly2)>CHKMAX_Y) return TRUE;\r
712    if((ly3-ly2)>CHKMAX_Y) return TRUE;\r
713   }\r
714  if(ly3<0)\r
715   {\r
716    if((ly1-ly3)>CHKMAX_Y) return TRUE;\r
717    if((ly2-ly3)>CHKMAX_Y) return TRUE;\r
718   }\r
719 \r
720  return FALSE;\r
721 }\r
722 \r
723 __inline BOOL CheckCoord3()\r
724 {\r
725  if(lx0<0)\r
726   {\r
727    if((lx1-lx0)>CHKMAX_X) return TRUE;\r
728    if((lx2-lx0)>CHKMAX_X) return TRUE;\r
729   }\r
730  if(lx1<0)\r
731   {\r
732    if((lx0-lx1)>CHKMAX_X) return TRUE;\r
733    if((lx2-lx1)>CHKMAX_X) return TRUE;\r
734   }\r
735  if(lx2<0)\r
736   {\r
737    if((lx0-lx2)>CHKMAX_X) return TRUE;\r
738    if((lx1-lx2)>CHKMAX_X) return TRUE;\r
739   }\r
740  if(ly0<0)\r
741   {\r
742    if((ly1-ly0)>CHKMAX_Y) return TRUE;\r
743    if((ly2-ly0)>CHKMAX_Y) return TRUE;\r
744   }\r
745  if(ly1<0)\r
746   {\r
747    if((ly0-ly1)>CHKMAX_Y) return TRUE;\r
748    if((ly2-ly1)>CHKMAX_Y) return TRUE;\r
749   }\r
750  if(ly2<0)\r
751   {\r
752    if((ly0-ly2)>CHKMAX_Y) return TRUE;\r
753    if((ly1-ly2)>CHKMAX_Y) return TRUE;\r
754   }\r
755 \r
756  return FALSE;\r
757 }\r
758 \r
759 \r
760 __inline BOOL CheckCoord2()\r
761 {\r
762  if(lx0<0)\r
763   {\r
764    if((lx1-lx0)>CHKMAX_X) return TRUE;\r
765   }\r
766  if(lx1<0)\r
767   {\r
768    if((lx0-lx1)>CHKMAX_X) return TRUE;\r
769   }\r
770  if(ly0<0)\r
771   {\r
772    if((ly1-ly0)>CHKMAX_Y) return TRUE;\r
773   }\r
774  if(ly1<0)\r
775   {\r
776    if((ly0-ly1)>CHKMAX_Y) return TRUE;\r
777   }\r
778 \r
779  return FALSE;\r
780 }\r
781 \r
782 // Pete's way: a very easy (and hopefully fast) approach for lines\r
783 // without sqrt... using a small float -> short cast trick :)\r
784 \r
785 #define VERTEX_OFFX 0.2f\r
786 #define VERTEX_OFFY 0.2f\r
787 \r
788 BOOL offsetline(void)           \r
789 {\r
790  short x0,x1,y0,y1,dx,dy;float px,py;\r
791 \r
792  if(bDisplayNotSet)\r
793   SetOGLDisplaySettings(1);\r
794 \r
795  if(!(dwActFixes&16))\r
796   {\r
797    lx0=(short)(((int)lx0<<SIGNSHIFT)>>SIGNSHIFT);\r
798    lx1=(short)(((int)lx1<<SIGNSHIFT)>>SIGNSHIFT);\r
799    ly0=(short)(((int)ly0<<SIGNSHIFT)>>SIGNSHIFT);\r
800    ly1=(short)(((int)ly1<<SIGNSHIFT)>>SIGNSHIFT);\r
801 \r
802    if(CheckCoord2()) return TRUE;\r
803   }\r
804 \r
805  x0 = (lx0 + PSXDisplay.CumulOffset.x)+1;\r
806  x1 = (lx1 + PSXDisplay.CumulOffset.x)+1;\r
807  y0 = (ly0 + PSXDisplay.CumulOffset.y)+1;\r
808  y1 = (ly1 + PSXDisplay.CumulOffset.y)+1;\r
809  \r
810  dx=x1-x0;\r
811  dy=y1-y0;\r
812  \r
813  if(dx>=0)\r
814   {\r
815    if(dy>=0)\r
816     {\r
817      px=0.5f;\r
818           if(dx>dy) py=-0.5f;\r
819      else if(dx<dy) py= 0.5f;\r
820      else           py= 0.0f;\r
821     }\r
822    else\r
823     {\r
824      py=-0.5f;\r
825      dy=-dy;\r
826           if(dx>dy) px= 0.5f;\r
827      else if(dx<dy) px=-0.5f;\r
828      else           px= 0.0f;\r
829     }\r
830   }\r
831  else\r
832   {\r
833    if(dy>=0)\r
834     {\r
835      py=0.5f;\r
836      dx=-dx;\r
837           if(dx>dy) px=-0.5f;\r
838      else if(dx<dy) px= 0.5f;\r
839      else           px= 0.0f;\r
840     }\r
841    else\r
842     {\r
843      px=-0.5f;\r
844           if(dx>dy) py=-0.5f;\r
845      else if(dx<dy) py= 0.5f;\r
846      else           py= 0.0f;\r
847     }\r
848   } \r
849  \r
850  vertex[0].x=(short)((float)x0-px);\r
851  vertex[3].x=(short)((float)x0+py);\r
852  \r
853  vertex[0].y=(short)((float)y0-py);\r
854  vertex[3].y=(short)((float)y0-px);\r
855  \r
856  vertex[1].x=(short)((float)x1-py);\r
857  vertex[2].x=(short)((float)x1+px);\r
858 \r
859  vertex[1].y=(short)((float)y1+px);\r
860  vertex[2].y=(short)((float)y1+py);\r
861 \r
862  if(vertex[0].x==vertex[3].x &&                        // ortho rect? done\r
863     vertex[1].x==vertex[2].x &&\r
864     vertex[0].y==vertex[1].y &&\r
865     vertex[2].y==vertex[3].y) return FALSE;\r
866  if(vertex[0].x==vertex[1].x &&\r
867     vertex[2].x==vertex[3].x &&\r
868     vertex[0].y==vertex[3].y &&\r
869     vertex[1].y==vertex[2].y) return FALSE;\r
870 \r
871  vertex[0].x-=VERTEX_OFFX;                             // otherwise a small offset\r
872  vertex[0].y-=VERTEX_OFFY;                             // to get better accuracy\r
873  vertex[1].x-=VERTEX_OFFX;\r
874  vertex[1].y-=VERTEX_OFFY;\r
875  vertex[2].x-=VERTEX_OFFX;\r
876  vertex[2].y-=VERTEX_OFFY;\r
877  vertex[3].x-=VERTEX_OFFX;\r
878  vertex[3].y-=VERTEX_OFFY;\r
879 \r
880  return FALSE;\r
881 }\r
882 \r
883 ///////////////////////////////////////////////////////// \r
884 \r
885 BOOL offset2(void)\r
886 {\r
887  if(bDisplayNotSet)\r
888   SetOGLDisplaySettings(1);\r
889 \r
890  if(!(dwActFixes&16))\r
891   {\r
892    lx0=(short)(((int)lx0<<SIGNSHIFT)>>SIGNSHIFT);\r
893    lx1=(short)(((int)lx1<<SIGNSHIFT)>>SIGNSHIFT);\r
894    ly0=(short)(((int)ly0<<SIGNSHIFT)>>SIGNSHIFT);\r
895    ly1=(short)(((int)ly1<<SIGNSHIFT)>>SIGNSHIFT);\r
896 \r
897    if(CheckCoord2()) return TRUE;\r
898   }\r
899 \r
900  vertex[0].x=lx0+PSXDisplay.CumulOffset.x;\r
901  vertex[1].x=lx1+PSXDisplay.CumulOffset.x;\r
902  vertex[0].y=ly0+PSXDisplay.CumulOffset.y;\r
903  vertex[1].y=ly1+PSXDisplay.CumulOffset.y;\r
904 \r
905  return FALSE;\r
906 }\r
907 \r
908 ///////////////////////////////////////////////////////// \r
909 \r
910 BOOL offset3(void)\r
911 {\r
912  if(bDisplayNotSet)\r
913   SetOGLDisplaySettings(1);\r
914 \r
915  if(!(dwActFixes&16))\r
916   {\r
917    lx0=(short)(((int)lx0<<SIGNSHIFT)>>SIGNSHIFT);\r
918    lx1=(short)(((int)lx1<<SIGNSHIFT)>>SIGNSHIFT);\r
919    lx2=(short)(((int)lx2<<SIGNSHIFT)>>SIGNSHIFT);\r
920    ly0=(short)(((int)ly0<<SIGNSHIFT)>>SIGNSHIFT);\r
921    ly1=(short)(((int)ly1<<SIGNSHIFT)>>SIGNSHIFT);\r
922    ly2=(short)(((int)ly2<<SIGNSHIFT)>>SIGNSHIFT);\r
923 \r
924    if(CheckCoord3()) return TRUE;\r
925   }\r
926 \r
927  vertex[0].x=lx0+PSXDisplay.CumulOffset.x;\r
928  vertex[1].x=lx1+PSXDisplay.CumulOffset.x;\r
929  vertex[2].x=lx2+PSXDisplay.CumulOffset.x;\r
930  vertex[0].y=ly0+PSXDisplay.CumulOffset.y;\r
931  vertex[1].y=ly1+PSXDisplay.CumulOffset.y;\r
932  vertex[2].y=ly2+PSXDisplay.CumulOffset.y;\r
933 \r
934  return FALSE;\r
935 }\r
936 \r
937 ///////////////////////////////////////////////////////// \r
938 \r
939 BOOL offset4(void)\r
940 {\r
941  if(bDisplayNotSet)\r
942   SetOGLDisplaySettings(1);\r
943 \r
944  if(!(dwActFixes&16))\r
945   {\r
946    lx0=(short)(((int)lx0<<SIGNSHIFT)>>SIGNSHIFT);\r
947    lx1=(short)(((int)lx1<<SIGNSHIFT)>>SIGNSHIFT);\r
948    lx2=(short)(((int)lx2<<SIGNSHIFT)>>SIGNSHIFT);\r
949    lx3=(short)(((int)lx3<<SIGNSHIFT)>>SIGNSHIFT);\r
950    ly0=(short)(((int)ly0<<SIGNSHIFT)>>SIGNSHIFT);\r
951    ly1=(short)(((int)ly1<<SIGNSHIFT)>>SIGNSHIFT);\r
952    ly2=(short)(((int)ly2<<SIGNSHIFT)>>SIGNSHIFT);\r
953    ly3=(short)(((int)ly3<<SIGNSHIFT)>>SIGNSHIFT);\r
954 \r
955    if(CheckCoord4()) return TRUE;\r
956   }\r
957 \r
958  vertex[0].x=lx0+PSXDisplay.CumulOffset.x;\r
959  vertex[1].x=lx1+PSXDisplay.CumulOffset.x;\r
960  vertex[2].x=lx2+PSXDisplay.CumulOffset.x;\r
961  vertex[3].x=lx3+PSXDisplay.CumulOffset.x;\r
962  vertex[0].y=ly0+PSXDisplay.CumulOffset.y;\r
963  vertex[1].y=ly1+PSXDisplay.CumulOffset.y;\r
964  vertex[2].y=ly2+PSXDisplay.CumulOffset.y;\r
965  vertex[3].y=ly3+PSXDisplay.CumulOffset.y;\r
966 \r
967  return FALSE;\r
968 }\r
969 \r
970 ///////////////////////////////////////////////////////// \r
971 \r
972 void offsetST(void)\r
973 {\r
974  if(bDisplayNotSet)\r
975   SetOGLDisplaySettings(1);\r
976 \r
977  if(!(dwActFixes&16))\r
978   {\r
979    lx0=(short)(((int)lx0<<SIGNSHIFT)>>SIGNSHIFT);\r
980    ly0=(short)(((int)ly0<<SIGNSHIFT)>>SIGNSHIFT);\r
981 \r
982    if(lx0<-512 && PSXDisplay.DrawOffset.x<=-512)\r
983     lx0+=2048;\r
984 \r
985    if(ly0<-512 && PSXDisplay.DrawOffset.y<=-512)\r
986     ly0+=2048;\r
987   }\r
988 \r
989  ly1 = ly0;\r
990  ly2 = ly3 = ly0+sprtH;\r
991  lx3 = lx0;\r
992  lx1 = lx2 = lx0+sprtW;\r
993 \r
994  vertex[0].x=lx0+PSXDisplay.CumulOffset.x;\r
995  vertex[1].x=lx1+PSXDisplay.CumulOffset.x;\r
996  vertex[2].x=lx2+PSXDisplay.CumulOffset.x;\r
997  vertex[3].x=lx3+PSXDisplay.CumulOffset.x;\r
998  vertex[0].y=ly0+PSXDisplay.CumulOffset.y;\r
999  vertex[1].y=ly1+PSXDisplay.CumulOffset.y;\r
1000  vertex[2].y=ly2+PSXDisplay.CumulOffset.y;\r
1001  vertex[3].y=ly3+PSXDisplay.CumulOffset.y;\r
1002 }\r
1003 \r
1004 ///////////////////////////////////////////////////////// \r
1005 \r
1006 void offsetScreenUpload(long Position)\r
1007 {\r
1008  if(bDisplayNotSet)\r
1009   SetOGLDisplaySettings(1);\r
1010 \r
1011  if(Position==-1)\r
1012   {\r
1013    long lmdx,lmdy;\r
1014 \r
1015    lmdx=xrUploadArea.x0;\r
1016    lmdy=xrUploadArea.y0;\r
1017 \r
1018    lx0-=lmdx;\r
1019    ly0-=lmdy;\r
1020    lx1-=lmdx;\r
1021    ly1-=lmdy;\r
1022    lx2-=lmdx;\r
1023    ly2-=lmdy;\r
1024    lx3-=lmdx;\r
1025    ly3-=lmdy;\r
1026   }\r
1027  else\r
1028  if(Position)\r
1029   {\r
1030    lx0-=PSXDisplay.DisplayPosition.x;\r
1031    ly0-=PSXDisplay.DisplayPosition.y;\r
1032    lx1-=PSXDisplay.DisplayPosition.x;\r
1033    ly1-=PSXDisplay.DisplayPosition.y;\r
1034    lx2-=PSXDisplay.DisplayPosition.x;\r
1035    ly2-=PSXDisplay.DisplayPosition.y;\r
1036    lx3-=PSXDisplay.DisplayPosition.x;\r
1037    ly3-=PSXDisplay.DisplayPosition.y;\r
1038   }\r
1039  else\r
1040   {\r
1041    lx0-=PreviousPSXDisplay.DisplayPosition.x;\r
1042    ly0-=PreviousPSXDisplay.DisplayPosition.y;\r
1043    lx1-=PreviousPSXDisplay.DisplayPosition.x;\r
1044    ly1-=PreviousPSXDisplay.DisplayPosition.y;\r
1045    lx2-=PreviousPSXDisplay.DisplayPosition.x;\r
1046    ly2-=PreviousPSXDisplay.DisplayPosition.y;\r
1047    lx3-=PreviousPSXDisplay.DisplayPosition.x;\r
1048    ly3-=PreviousPSXDisplay.DisplayPosition.y;\r
1049   }\r
1050 \r
1051  vertex[0].x=lx0 + PreviousPSXDisplay.Range.x0;\r
1052  vertex[1].x=lx1 + PreviousPSXDisplay.Range.x0;\r
1053  vertex[2].x=lx2 + PreviousPSXDisplay.Range.x0;\r
1054  vertex[3].x=lx3 + PreviousPSXDisplay.Range.x0;\r
1055  vertex[0].y=ly0 + PreviousPSXDisplay.Range.y0;\r
1056  vertex[1].y=ly1 + PreviousPSXDisplay.Range.y0;\r
1057  vertex[2].y=ly2 + PreviousPSXDisplay.Range.y0;\r
1058  vertex[3].y=ly3 + PreviousPSXDisplay.Range.y0;\r
1059 \r
1060  if(iUseMask)\r
1061   {\r
1062    vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=gl_z;\r
1063    gl_z+=0.00004f;\r
1064   }\r
1065 }\r
1066  \r
1067 ///////////////////////////////////////////////////////// \r
1068 \r
1069 void offsetBlk(void)\r
1070 {\r
1071  if(bDisplayNotSet)\r
1072   SetOGLDisplaySettings(1);\r
1073                                             \r
1074  vertex[0].x=lx0-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0;\r
1075  vertex[1].x=lx1-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0;\r
1076  vertex[2].x=lx2-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0;\r
1077  vertex[3].x=lx3-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0;\r
1078  vertex[0].y=ly0-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0;\r
1079  vertex[1].y=ly1-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0;\r
1080  vertex[2].y=ly2-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0;\r
1081  vertex[3].y=ly3-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0;\r
1082 \r
1083  if(iUseMask)\r
1084   {\r
1085    vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=gl_z;\r
1086    gl_z+=0.00004f;\r
1087   }\r
1088 }\r
1089 \r
1090 ////////////////////////////////////////////////////////////////////////\r
1091 // texture sow/tow calculations\r
1092 ////////////////////////////////////////////////////////////////////////\r
1093 \r
1094 void assignTextureVRAMWrite(void)\r
1095 {\r
1096 #ifdef OWNSCALE\r
1097 \r
1098  vertex[0].sow=0.5f/ ST_FACVRAMX;\r
1099  vertex[0].tow=0.5f/ ST_FACVRAM;\r
1100 \r
1101  vertex[1].sow=(float)gl_ux[1]/ ST_FACVRAMX;\r
1102  vertex[1].tow=0.5f/ ST_FACVRAM;\r
1103 \r
1104  vertex[2].sow=(float)gl_ux[2]/ ST_FACVRAMX;\r
1105  vertex[2].tow=(float)gl_vy[2]/ ST_FACVRAM;\r
1106 \r
1107  vertex[3].sow=0.5f/ ST_FACVRAMX;\r
1108  vertex[3].tow=(float)gl_vy[3]/ ST_FACVRAM;\r
1109 \r
1110 #else\r
1111 \r
1112  if(gl_ux[1]==255)\r
1113   {\r
1114    vertex[0].sow=(gl_ux[0]*255.99f)/255.0f;\r
1115    vertex[1].sow=(gl_ux[1]*255.99f)/255.0f;\r
1116    vertex[2].sow=(gl_ux[2]*255.99f)/255.0f;\r
1117    vertex[3].sow=(gl_ux[3]*255.99f)/255.0f;\r
1118   }\r
1119  else\r
1120   {\r
1121    vertex[0].sow=gl_ux[0];\r
1122    vertex[1].sow=gl_ux[1];\r
1123    vertex[2].sow=gl_ux[2];\r
1124    vertex[3].sow=gl_ux[3];\r
1125   }\r
1126 \r
1127  vertex[0].tow=gl_vy[0];\r
1128  vertex[1].tow=gl_vy[1];\r
1129  vertex[2].tow=gl_vy[2];\r
1130  vertex[3].tow=gl_vy[3];\r
1131 \r
1132 #endif\r
1133 }\r
1134 \r
1135 GLuint  gLastTex=0;\r
1136 GLuint  gLastFMode=(GLuint)-1;\r
1137 \r
1138 ///////////////////////////////////////////////////////// \r
1139 \r
1140 void assignTextureSprite(void)\r
1141 {\r
1142  if(bUsingTWin)\r
1143   {\r
1144    vertex[0].sow=vertex[3].sow=(float)gl_ux[0]/TWin.UScaleFactor;\r
1145    vertex[1].sow=vertex[2].sow=(float)sSprite_ux2/TWin.UScaleFactor;\r
1146    vertex[0].tow=vertex[1].tow=(float)gl_vy[0]/TWin.VScaleFactor;\r
1147    vertex[2].tow=vertex[3].tow=(float)sSprite_vy2/TWin.VScaleFactor;\r
1148    gLastTex=gTexName;\r
1149   }\r
1150  else\r
1151   {\r
1152 #ifdef OWNSCALE\r
1153 \r
1154    vertex[0].sow=vertex[3].sow=(float)gl_ux[0]     / ST_FACSPRITE;\r
1155    vertex[1].sow=vertex[2].sow=(float)sSprite_ux2  / ST_FACSPRITE;\r
1156    vertex[0].tow=vertex[1].tow=(float)gl_vy[0]     / ST_FACSPRITE;\r
1157    vertex[2].tow=vertex[3].tow=(float)sSprite_vy2  / ST_FACSPRITE;\r
1158 \r
1159 #else\r
1160  \r
1161    vertex[0].sow=vertex[3].sow=gl_ux[0];\r
1162    vertex[1].sow=vertex[2].sow=sSprite_ux2;\r
1163    vertex[0].tow=vertex[1].tow=gl_vy[0];\r
1164    vertex[2].tow=vertex[3].tow=sSprite_vy2;\r
1165 \r
1166 #endif\r
1167 \r
1168    if(iFilterType>2) \r
1169     {\r
1170      if(gLastTex!=gTexName || gLastFMode!=0)\r
1171       {\r
1172        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);\r
1173        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);\r
1174        gLastTex=gTexName;gLastFMode=0;\r
1175       }\r
1176     }\r
1177   }\r
1178 \r
1179  if(usMirror & 0x1000) \r
1180   {\r
1181    vertex[0].sow=vertex[1].sow;\r
1182    vertex[1].sow=vertex[2].sow=vertex[3].sow;\r
1183    vertex[3].sow=vertex[0].sow;\r
1184   }\r
1185 \r
1186  if(usMirror & 0x2000) \r
1187   {\r
1188    vertex[0].tow=vertex[3].tow;\r
1189    vertex[2].tow=vertex[3].tow=vertex[1].tow;\r
1190    vertex[1].tow=vertex[0].tow;\r
1191   }\r
1192 \r
1193 }\r
1194 \r
1195 ///////////////////////////////////////////////////////// \r
1196 \r
1197 void assignTexture3(void)\r
1198 {\r
1199  if(bUsingTWin)\r
1200   {\r
1201    vertex[0].sow=(float)gl_ux[0]/TWin.UScaleFactor;\r
1202    vertex[0].tow=(float)gl_vy[0]/TWin.VScaleFactor;\r
1203    vertex[1].sow=(float)gl_ux[1]/TWin.UScaleFactor;\r
1204    vertex[1].tow=(float)gl_vy[1]/TWin.VScaleFactor;\r
1205    vertex[2].sow=(float)gl_ux[2]/TWin.UScaleFactor;\r
1206    vertex[2].tow=(float)gl_vy[2]/TWin.VScaleFactor;\r
1207    gLastTex=gTexName;\r
1208   }\r
1209  else\r
1210   {\r
1211 #ifdef OWNSCALE\r
1212    vertex[0].sow=(float)gl_ux[0] / ST_FACTRI;\r
1213    vertex[0].tow=(float)gl_vy[0] / ST_FACTRI;\r
1214    vertex[1].sow=(float)gl_ux[1] / ST_FACTRI;\r
1215 \r
1216    vertex[1].tow=(float)gl_vy[1] / ST_FACTRI;\r
1217    vertex[2].sow=(float)gl_ux[2] / ST_FACTRI;\r
1218    vertex[2].tow=(float)gl_vy[2] / ST_FACTRI;\r
1219 #else\r
1220    vertex[0].sow=gl_ux[0];\r
1221    vertex[0].tow=gl_vy[0];\r
1222    vertex[1].sow=gl_ux[1];\r
1223    vertex[1].tow=gl_vy[1];\r
1224    vertex[2].sow=gl_ux[2];\r
1225    vertex[2].tow=gl_vy[2];\r
1226 #endif\r
1227 \r
1228    if(iFilterType>2) \r
1229     {\r
1230      if(gLastTex!=gTexName || gLastFMode!=1)\r
1231       {\r
1232        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);\r
1233        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);\r
1234        gLastTex=gTexName;gLastFMode=1;\r
1235       }\r
1236     }\r
1237 \r
1238    if(iFilterType) \r
1239     {\r
1240      float fxmin=256.0f,fxmax=0.0f,fymin=256.0f,fymax=0.0f;int i;\r
1241      for(i=0;i<3;i++)\r
1242       {\r
1243        if(vertex[i].sow<fxmin) fxmin=vertex[i].sow;\r
1244        if(vertex[i].tow<fymin) fymin=vertex[i].tow;\r
1245        if(vertex[i].sow>fxmax) fxmax=vertex[i].sow;\r
1246        if(vertex[i].tow>fymax) fymax=vertex[i].tow; \r
1247       }\r
1248 \r
1249      for(i=0;i<3;i++)\r
1250       {\r
1251        if(vertex[i].sow==fxmin) vertex[i].sow+=ST_BFFACSORT;\r
1252        if(vertex[i].sow==fxmax) vertex[i].sow-=ST_BFFACSORT;\r
1253        if(vertex[i].tow==fymin) vertex[i].tow+=ST_BFFACSORT;\r
1254        if(vertex[i].tow==fymax) vertex[i].tow-=ST_BFFACSORT;\r
1255       }\r
1256     }\r
1257   }\r
1258 }\r
1259 \r
1260 ///////////////////////////////////////////////////////// \r
1261 \r
1262 void assignTexture4(void)\r
1263 {\r
1264  if(bUsingTWin)\r
1265   {\r
1266    vertex[0].sow=(float)gl_ux[0]/TWin.UScaleFactor;\r
1267    vertex[0].tow=(float)gl_vy[0]/TWin.VScaleFactor;\r
1268    vertex[1].sow=(float)gl_ux[1]/TWin.UScaleFactor;\r
1269    vertex[1].tow=(float)gl_vy[1]/TWin.VScaleFactor;\r
1270    vertex[2].sow=(float)gl_ux[2]/TWin.UScaleFactor;\r
1271    vertex[2].tow=(float)gl_vy[2]/TWin.VScaleFactor;\r
1272    vertex[3].sow=(float)gl_ux[3]/TWin.UScaleFactor;\r
1273    vertex[3].tow=(float)gl_vy[3]/TWin.VScaleFactor;\r
1274    gLastTex=gTexName;\r
1275   }\r
1276  else\r
1277   {\r
1278 #ifdef OWNSCALE\r
1279    vertex[0].sow=(float)gl_ux[0] / ST_FAC;\r
1280    vertex[0].tow=(float)gl_vy[0] / ST_FAC;\r
1281    vertex[1].sow=(float)gl_ux[1] / ST_FAC;\r
1282    vertex[1].tow=(float)gl_vy[1] / ST_FAC;\r
1283    vertex[2].sow=(float)gl_ux[2] / ST_FAC;\r
1284    vertex[2].tow=(float)gl_vy[2] / ST_FAC;\r
1285    vertex[3].sow=(float)gl_ux[3] / ST_FAC;\r
1286    vertex[3].tow=(float)gl_vy[3] / ST_FAC;\r
1287 #else\r
1288    vertex[0].sow=gl_ux[0];\r
1289    vertex[0].tow=gl_vy[0];\r
1290    vertex[1].sow=gl_ux[1];\r
1291    vertex[1].tow=gl_vy[1];\r
1292    vertex[2].sow=gl_ux[2];\r
1293    vertex[2].tow=gl_vy[2];\r
1294    vertex[3].sow=gl_ux[3];\r
1295    vertex[3].tow=gl_vy[3];\r
1296 #endif\r
1297 \r
1298    if(iFilterType>2) \r
1299     {\r
1300      if(gLastTex!=gTexName || gLastFMode!=1)\r
1301       {\r
1302        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);\r
1303        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);\r
1304        gLastTex=gTexName;gLastFMode=1;\r
1305       }\r
1306     }\r
1307 \r
1308    if(iFilterType) \r
1309     {\r
1310      float fxmin=256.0f,fxmax=0.0f,fymin=256.0f,fymax=0.0f;int i;\r
1311      for(i=0;i<4;i++)\r
1312       {\r
1313        if(vertex[i].sow<fxmin) fxmin=vertex[i].sow;\r
1314        if(vertex[i].tow<fymin) fymin=vertex[i].tow;\r
1315        if(vertex[i].sow>fxmax) fxmax=vertex[i].sow;\r
1316        if(vertex[i].tow>fymax) fymax=vertex[i].tow; \r
1317       }\r
1318 \r
1319      for(i=0;i<4;i++)\r
1320       {\r
1321        if(vertex[i].sow==fxmin) vertex[i].sow+=ST_BFFACSORT;\r
1322        if(vertex[i].sow==fxmax) vertex[i].sow-=ST_BFFACSORT;\r
1323        if(vertex[i].tow==fymin) vertex[i].tow+=ST_BFFACSORT;\r
1324        if(vertex[i].tow==fymax) vertex[i].tow-=ST_BFFACSORT;\r
1325       }\r
1326     }\r
1327   }\r
1328 }\r
1329 \r
1330 ////////////////////////////////////////////////////////////////////////\r
1331 ////////////////////////////////////////////////////////////////////////\r
1332 ////////////////////////////////////////////////////////////////////////\r
1333 \r
1334 ////////////////////////////////////////////////////////////////////////\r
1335 // render pos / buffers\r
1336 ////////////////////////////////////////////////////////////////////////\r
1337 \r
1338 #ifndef _WINDOWS\r
1339 #define EqualRect(pr1,pr2) ((pr1)->left==(pr2)->left && (pr1)->top==(pr2)->top && (pr1)->right==(pr2)->right && (pr1)->bottom==(pr2)->bottom)\r
1340 #endif\r
1341 \r
1342 ////////////////////////////////////////////////////////////////////////\r
1343 // SetDisplaySettings: "simply" calcs the new drawing area and updates\r
1344 //                     the ogl clipping (scissor) \r
1345 \r
1346 BOOL bSetClip=FALSE;\r
1347 \r
1348 void SetOGLDisplaySettings(BOOL DisplaySet)\r
1349 {\r
1350  static RECT rprev={0,0,0,0};\r
1351  static RECT rC   ={0,0,0,0};\r
1352  static int iOldX=0;\r
1353  static int iOldY=0;\r
1354  RECT r;float XS,YS;\r
1355 \r
1356  bDisplayNotSet = FALSE;\r
1357 \r
1358  //----------------------------------------------------// that's a whole screen upload\r
1359  if(!DisplaySet)\r
1360   {\r
1361    RECT rX;\r
1362    PSXDisplay.GDrawOffset.x=0;\r
1363    PSXDisplay.GDrawOffset.y=0;\r
1364 \r
1365    PSXDisplay.CumulOffset.x = PSXDisplay.DrawOffset.x+PreviousPSXDisplay.Range.x0;\r
1366    PSXDisplay.CumulOffset.y = PSXDisplay.DrawOffset.y+PreviousPSXDisplay.Range.y0;\r
1367 \r
1368    rprev.left=rprev.left+1;\r
1369 \r
1370    rX=rRatioRect;\r
1371    rX.top=iResY-(rRatioRect.top+rRatioRect.bottom);\r
1372 \r
1373    if(bSetClip || !EqualRect(&rC,&rX))\r
1374     {\r
1375      rC=rX;\r
1376      glScissor(rC.left,rC.top,rC.right,rC.bottom);\r
1377      bSetClip=FALSE; \r
1378     }\r
1379    return;\r
1380   }\r
1381  //----------------------------------------------------// \r
1382 \r
1383  PSXDisplay.GDrawOffset.y = PreviousPSXDisplay.DisplayPosition.y;\r
1384  PSXDisplay.GDrawOffset.x = PreviousPSXDisplay.DisplayPosition.x;\r
1385  PSXDisplay.CumulOffset.x = PSXDisplay.DrawOffset.x - PSXDisplay.GDrawOffset.x+PreviousPSXDisplay.Range.x0;\r
1386  PSXDisplay.CumulOffset.y = PSXDisplay.DrawOffset.y - PSXDisplay.GDrawOffset.y+PreviousPSXDisplay.Range.y0;\r
1387 \r
1388  r.top   =PSXDisplay.DrawArea.y0 - PreviousPSXDisplay.DisplayPosition.y;\r
1389  r.bottom=PSXDisplay.DrawArea.y1 - PreviousPSXDisplay.DisplayPosition.y;\r
1390 \r
1391  if(r.bottom<0 || r.top>=PSXDisplay.DisplayMode.y)\r
1392   {\r
1393    r.top   =PSXDisplay.DrawArea.y0 - PSXDisplay.DisplayPosition.y;\r
1394    r.bottom=PSXDisplay.DrawArea.y1 - PSXDisplay.DisplayPosition.y;\r
1395   }\r
1396 \r
1397  r.left  =PSXDisplay.DrawArea.x0 - PreviousPSXDisplay.DisplayPosition.x;\r
1398  r.right =PSXDisplay.DrawArea.x1 - PreviousPSXDisplay.DisplayPosition.x;\r
1399 \r
1400  if(r.right<0 || r.left>=PSXDisplay.DisplayMode.x)\r
1401   {\r
1402    r.left  =PSXDisplay.DrawArea.x0 - PSXDisplay.DisplayPosition.x;\r
1403    r.right =PSXDisplay.DrawArea.x1 - PSXDisplay.DisplayPosition.x;\r
1404   }\r
1405 \r
1406  if(!bSetClip && EqualRect(&r,&rprev) &&\r
1407     iOldX == PSXDisplay.DisplayMode.x &&\r
1408     iOldY == PSXDisplay.DisplayMode.y)\r
1409   return;\r
1410 \r
1411  rprev = r;\r
1412  iOldX = PSXDisplay.DisplayMode.x;\r
1413  iOldY = PSXDisplay.DisplayMode.y;\r
1414 \r
1415  XS=(float)rRatioRect.right/(float)PSXDisplay.DisplayMode.x;\r
1416  YS=(float)rRatioRect.bottom/(float)PSXDisplay.DisplayMode.y;\r
1417 \r
1418  if(PreviousPSXDisplay.Range.x0)\r
1419   {\r
1420    short s=PreviousPSXDisplay.Range.x0+PreviousPSXDisplay.Range.x1;\r
1421 \r
1422    r.left+=PreviousPSXDisplay.Range.x0+1;\r
1423 \r
1424    r.right+=PreviousPSXDisplay.Range.x0;\r
1425 \r
1426    if(r.left>s)  r.left=s;\r
1427    if(r.right>s) r.right=s;\r
1428   }\r
1429 \r
1430  if(PreviousPSXDisplay.Range.y0)\r
1431   {\r
1432    short s=PreviousPSXDisplay.Range.y0+PreviousPSXDisplay.Range.y1;\r
1433 \r
1434    r.top+=PreviousPSXDisplay.Range.y0+1;\r
1435    r.bottom+=PreviousPSXDisplay.Range.y0;\r
1436 \r
1437    if(r.top>s)    r.top=s;\r
1438    if(r.bottom>s) r.bottom=s;\r
1439   }\r
1440 \r
1441  // Set the ClipArea variables to reflect the new screen,\r
1442  // offset from zero (since it is a new display buffer)\r
1443  r.left   = (int)(((float)(r.left))      *XS);\r
1444  r.top    = (int)(((float)(r.top))       *YS);\r
1445  r.right  = (int)(((float)(r.right  + 1))*XS);\r
1446  r.bottom = (int)(((float)(r.bottom + 1))*YS);\r
1447 \r
1448  // Limit clip area to the screen size\r
1449  if (r.left   > iResX)   r.left   = iResX;\r
1450  if (r.left   < 0)       r.left   = 0;\r
1451  if (r.top    > iResY)   r.top    = iResY;\r
1452  if (r.top    < 0)       r.top    = 0;\r
1453  if (r.right  > iResX)   r.right  = iResX;\r
1454  if (r.right  < 0)       r.right  = 0;\r
1455  if (r.bottom > iResY)   r.bottom = iResY;\r
1456  if (r.bottom < 0)       r.bottom = 0;\r
1457 \r
1458  r.right -=r.left;\r
1459  r.bottom-=r.top;\r
1460  r.top=iResY-(r.top+r.bottom);\r
1461 \r
1462  r.left+=rRatioRect.left;\r
1463  r.top -=rRatioRect.top;\r
1464 \r
1465  if(bSetClip || !EqualRect(&r,&rC))\r
1466   {\r
1467    glScissor(r.left,r.top,r.right,r.bottom);\r
1468    rC=r;\r
1469    bSetClip=FALSE;\r
1470   }\r
1471 }\r
1472 \r
1473 ////////////////////////////////////////////////////////////////////////\r
1474 ////////////////////////////////////////////////////////////////////////\r
1475 ////////////////////////////////////////////////////////////////////////\r
1476 \r