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