gpu-gles: refactor for caanoo/wiz support
[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  glViewport(rRatioRect.left,                           // init viewport by ratio rect\r
446             iResY-(rRatioRect.top+rRatioRect.bottom),\r
447             rRatioRect.right, \r
448             rRatioRect.bottom); glError();\r
449                                                       \r
450  glScissor(0, 0, iResX, iResY); glError();             // init clipping (fullscreen)\r
451  glEnable(GL_SCISSOR_TEST); glError();\r
452 \r
453 #ifndef OWNSCALE\r
454  glMatrixMode(GL_TEXTURE);                             // init psx tex sow and tow if not "ownscale"\r
455  glLoadIdentity();\r
456  glScalef(1.0f/255.99f,1.0f/255.99f,1.0f);             // geforce precision hack\r
457 #endif \r
458  glDepthRangef(0.0f, 1.0f);glError();\r
459  \r
460  glPolygonOffset( -0.2f, -0.2f );glError();\r
461 \r
462  glMatrixMode(GL_PROJECTION); glError();               // init projection with psx resolution\r
463  glLoadIdentity(); glError();\r
464 \r
465  glOrtho(0,PSXDisplay.DisplayMode.x,\r
466          PSXDisplay.DisplayMode.y, 0, -1, 1); glError();\r
467 \r
468  if(iZBufferDepth)                                     // zbuffer?\r
469   {\r
470    uiBufferBits=GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT;\r
471    glEnable(GL_DEPTH_TEST); glError();\r
472    glDepthFunc(GL_ALWAYS); glError();\r
473    iDepthFunc=1;\r
474   }\r
475  else                                                  // no zbuffer?\r
476   {\r
477    uiBufferBits=GL_COLOR_BUFFER_BIT;\r
478    glDisable(GL_DEPTH_TEST); glError();\r
479   }\r
480 \r
481  glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glError();      // first buffer clear\r
482  glClear(uiBufferBits); glError();\r
483 \r
484  GetExtInfos();                                        // get ext infos\r
485  SetExtGLFuncs();                                      // init all kind of stuff (tex function pointers)\r
486  \r
487  glEnable(GL_ALPHA_TEST); glError();                   // wanna alpha test\r
488 \r
489   {\r
490    glDisable(GL_LINE_SMOOTH); glError();\r
491    glDisable(GL_POINT_SMOOTH); glError();\r
492   }\r
493 \r
494  ubGloAlpha=127;                                       // init some drawing vars\r
495  ubGloColAlpha=127;\r
496  TWin.UScaleFactor = 1;\r
497  TWin.VScaleFactor = 1;\r
498  bDrawMultiPass=FALSE;\r
499  bTexEnabled=FALSE;\r
500  bUsingTWin=FALSE;\r
501       \r
502  if(bDrawDither)  glEnable(GL_DITHER);                 // dither mode\r
503  else             glDisable(GL_DITHER); \r
504  glError(); \r
505  glDisable(GL_FOG); glError();                          // turn all (currently) unused modes off\r
506  glDisable(GL_LIGHTING); glError();  \r
507  glDisable(GL_STENCIL_TEST); glError();  \r
508  glDisable(GL_TEXTURE_2D); glError();\r
509  glDisable(GL_CULL_FACE);\r
510 \r
511  glFlush(); glError();                                 // we are done...\r
512  glFinish(); glError();                           \r
513 \r
514  CreateScanLines();                                    // setup scanline stuff (if wanted)\r
515 \r
516  CheckTextureMemory();                                 // check available tex memory\r
517 \r
518  if(bKeepRatio) SetAspectRatio();                      // set ratio\r
519 \r
520  \r
521  bIsFirstFrame = FALSE;                                // we have survived the first frame :)\r
522 \r
523  return 0;\r
524 }\r
525 \r
526 ////////////////////////////////////////////////////////////////////////\r
527 // clean up OGL stuff\r
528 ////////////////////////////////////////////////////////////////////////\r
529 \r
530 void GLcleanup() \r
531 {                                                     \r
532  CleanupTextureStore();                                // bye textures\r
533 \r
534         eglMakeCurrent( display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );\r
535         eglDestroySurface( display, surface );\r
536         eglDestroyContext( display, context );\r
537         eglTerminate( display );\r
538 \r
539 #if defined(USE_X11)\r
540                 if (x11Window) XDestroyWindow(x11Display, x11Window);\r
541                 if (x11Colormap) XFreeColormap( x11Display, x11Colormap );\r
542                 if (x11Display) XCloseDisplay(x11Display);\r
543 #endif\r
544 }\r
545 \r
546 ////////////////////////////////////////////////////////////////////////\r
547 ////////////////////////////////////////////////////////////////////////\r
548 ////////////////////////////////////////////////////////////////////////\r
549 \r
550 ////////////////////////////////////////////////////////////////////////\r
551 ////////////////////////////////////////////////////////////////////////\r
552 ////////////////////////////////////////////////////////////////////////\r
553 \r
554 ////////////////////////////////////////////////////////////////////////\r
555 // Offset stuff\r
556 ////////////////////////////////////////////////////////////////////////\r
557 \r
558 // please note: it is hardly do-able in a hw/accel plugin to get the \r
559 //              real psx polygon coord mapping right... the following\r
560 //              works not to bad with many games, though\r
561 \r
562 __inline BOOL CheckCoord4()\r
563 {\r
564  if(lx0<0)\r
565   {\r
566    if(((lx1-lx0)>CHKMAX_X) ||\r
567       ((lx2-lx0)>CHKMAX_X)) \r
568     {\r
569      if(lx3<0)\r
570       {\r
571        if((lx1-lx3)>CHKMAX_X) return TRUE;\r
572        if((lx2-lx3)>CHKMAX_X) return TRUE;\r
573       }\r
574     }\r
575   }\r
576  if(lx1<0)\r
577   {\r
578    if((lx0-lx1)>CHKMAX_X) return TRUE;\r
579    if((lx2-lx1)>CHKMAX_X) return TRUE;\r
580    if((lx3-lx1)>CHKMAX_X) return TRUE;\r
581   }\r
582  if(lx2<0)\r
583   {\r
584    if((lx0-lx2)>CHKMAX_X) return TRUE;\r
585    if((lx1-lx2)>CHKMAX_X) return TRUE;\r
586    if((lx3-lx2)>CHKMAX_X) return TRUE;\r
587   }\r
588  if(lx3<0)\r
589   {\r
590    if(((lx1-lx3)>CHKMAX_X) ||\r
591       ((lx2-lx3)>CHKMAX_X))\r
592     {\r
593      if(lx0<0)\r
594       {\r
595        if((lx1-lx0)>CHKMAX_X) return TRUE;\r
596        if((lx2-lx0)>CHKMAX_X) return TRUE;\r
597       }\r
598     }\r
599   }\r
600  \r
601 \r
602  if(ly0<0)\r
603   {\r
604    if((ly1-ly0)>CHKMAX_Y) return TRUE;\r
605    if((ly2-ly0)>CHKMAX_Y) return TRUE;\r
606   }\r
607  if(ly1<0)\r
608   {\r
609    if((ly0-ly1)>CHKMAX_Y) return TRUE;\r
610    if((ly2-ly1)>CHKMAX_Y) return TRUE;\r
611    if((ly3-ly1)>CHKMAX_Y) return TRUE;\r
612   }\r
613  if(ly2<0)\r
614   {\r
615    if((ly0-ly2)>CHKMAX_Y) return TRUE;\r
616    if((ly1-ly2)>CHKMAX_Y) return TRUE;\r
617    if((ly3-ly2)>CHKMAX_Y) return TRUE;\r
618   }\r
619  if(ly3<0)\r
620   {\r
621    if((ly1-ly3)>CHKMAX_Y) return TRUE;\r
622    if((ly2-ly3)>CHKMAX_Y) return TRUE;\r
623   }\r
624 \r
625  return FALSE;\r
626 }\r
627 \r
628 __inline BOOL CheckCoord3()\r
629 {\r
630  if(lx0<0)\r
631   {\r
632    if((lx1-lx0)>CHKMAX_X) return TRUE;\r
633    if((lx2-lx0)>CHKMAX_X) return TRUE;\r
634   }\r
635  if(lx1<0)\r
636   {\r
637    if((lx0-lx1)>CHKMAX_X) return TRUE;\r
638    if((lx2-lx1)>CHKMAX_X) return TRUE;\r
639   }\r
640  if(lx2<0)\r
641   {\r
642    if((lx0-lx2)>CHKMAX_X) return TRUE;\r
643    if((lx1-lx2)>CHKMAX_X) return TRUE;\r
644   }\r
645  if(ly0<0)\r
646   {\r
647    if((ly1-ly0)>CHKMAX_Y) return TRUE;\r
648    if((ly2-ly0)>CHKMAX_Y) return TRUE;\r
649   }\r
650  if(ly1<0)\r
651   {\r
652    if((ly0-ly1)>CHKMAX_Y) return TRUE;\r
653    if((ly2-ly1)>CHKMAX_Y) return TRUE;\r
654   }\r
655  if(ly2<0)\r
656   {\r
657    if((ly0-ly2)>CHKMAX_Y) return TRUE;\r
658    if((ly1-ly2)>CHKMAX_Y) return TRUE;\r
659   }\r
660 \r
661  return FALSE;\r
662 }\r
663 \r
664 \r
665 __inline BOOL CheckCoord2()\r
666 {\r
667  if(lx0<0)\r
668   {\r
669    if((lx1-lx0)>CHKMAX_X) return TRUE;\r
670   }\r
671  if(lx1<0)\r
672   {\r
673    if((lx0-lx1)>CHKMAX_X) return TRUE;\r
674   }\r
675  if(ly0<0)\r
676   {\r
677    if((ly1-ly0)>CHKMAX_Y) return TRUE;\r
678   }\r
679  if(ly1<0)\r
680   {\r
681    if((ly0-ly1)>CHKMAX_Y) return TRUE;\r
682   }\r
683 \r
684  return FALSE;\r
685 }\r
686 \r
687 // Pete's way: a very easy (and hopefully fast) approach for lines\r
688 // without sqrt... using a small float -> short cast trick :)\r
689 \r
690 #define VERTEX_OFFX 0.2f\r
691 #define VERTEX_OFFY 0.2f\r
692 \r
693 BOOL offsetline(void)           \r
694 {\r
695  short x0,x1,y0,y1,dx,dy;float px,py;\r
696 \r
697  if(bDisplayNotSet)\r
698   SetOGLDisplaySettings(1);\r
699 \r
700  if(!(dwActFixes&16))\r
701   {\r
702    lx0=(short)(((int)lx0<<SIGNSHIFT)>>SIGNSHIFT);\r
703    lx1=(short)(((int)lx1<<SIGNSHIFT)>>SIGNSHIFT);\r
704    ly0=(short)(((int)ly0<<SIGNSHIFT)>>SIGNSHIFT);\r
705    ly1=(short)(((int)ly1<<SIGNSHIFT)>>SIGNSHIFT);\r
706 \r
707    if(CheckCoord2()) return TRUE;\r
708   }\r
709 \r
710  x0 = (lx0 + PSXDisplay.CumulOffset.x)+1;\r
711  x1 = (lx1 + PSXDisplay.CumulOffset.x)+1;\r
712  y0 = (ly0 + PSXDisplay.CumulOffset.y)+1;\r
713  y1 = (ly1 + PSXDisplay.CumulOffset.y)+1;\r
714  \r
715  dx=x1-x0;\r
716  dy=y1-y0;\r
717  \r
718  if(dx>=0)\r
719   {\r
720    if(dy>=0)\r
721     {\r
722      px=0.5f;\r
723           if(dx>dy) py=-0.5f;\r
724      else if(dx<dy) py= 0.5f;\r
725      else           py= 0.0f;\r
726     }\r
727    else\r
728     {\r
729      py=-0.5f;\r
730      dy=-dy;\r
731           if(dx>dy) px= 0.5f;\r
732      else if(dx<dy) px=-0.5f;\r
733      else           px= 0.0f;\r
734     }\r
735   }\r
736  else\r
737   {\r
738    if(dy>=0)\r
739     {\r
740      py=0.5f;\r
741      dx=-dx;\r
742           if(dx>dy) px=-0.5f;\r
743      else if(dx<dy) px= 0.5f;\r
744      else           px= 0.0f;\r
745     }\r
746    else\r
747     {\r
748      px=-0.5f;\r
749           if(dx>dy) py=-0.5f;\r
750      else if(dx<dy) py= 0.5f;\r
751      else           py= 0.0f;\r
752     }\r
753   } \r
754  \r
755  vertex[0].x=(short)((float)x0-px);\r
756  vertex[3].x=(short)((float)x0+py);\r
757  \r
758  vertex[0].y=(short)((float)y0-py);\r
759  vertex[3].y=(short)((float)y0-px);\r
760  \r
761  vertex[1].x=(short)((float)x1-py);\r
762  vertex[2].x=(short)((float)x1+px);\r
763 \r
764  vertex[1].y=(short)((float)y1+px);\r
765  vertex[2].y=(short)((float)y1+py);\r
766 \r
767  if(vertex[0].x==vertex[3].x &&                        // ortho rect? done\r
768     vertex[1].x==vertex[2].x &&\r
769     vertex[0].y==vertex[1].y &&\r
770     vertex[2].y==vertex[3].y) return FALSE;\r
771  if(vertex[0].x==vertex[1].x &&\r
772     vertex[2].x==vertex[3].x &&\r
773     vertex[0].y==vertex[3].y &&\r
774     vertex[1].y==vertex[2].y) return FALSE;\r
775 \r
776  vertex[0].x-=VERTEX_OFFX;                             // otherwise a small offset\r
777  vertex[0].y-=VERTEX_OFFY;                             // to get better accuracy\r
778  vertex[1].x-=VERTEX_OFFX;\r
779  vertex[1].y-=VERTEX_OFFY;\r
780  vertex[2].x-=VERTEX_OFFX;\r
781  vertex[2].y-=VERTEX_OFFY;\r
782  vertex[3].x-=VERTEX_OFFX;\r
783  vertex[3].y-=VERTEX_OFFY;\r
784 \r
785  return FALSE;\r
786 }\r
787 \r
788 ///////////////////////////////////////////////////////// \r
789 \r
790 BOOL offset2(void)\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  vertex[0].x=lx0+PSXDisplay.CumulOffset.x;\r
806  vertex[1].x=lx1+PSXDisplay.CumulOffset.x;\r
807  vertex[0].y=ly0+PSXDisplay.CumulOffset.y;\r
808  vertex[1].y=ly1+PSXDisplay.CumulOffset.y;\r
809 \r
810  return FALSE;\r
811 }\r
812 \r
813 ///////////////////////////////////////////////////////// \r
814 \r
815 BOOL offset3(void)\r
816 {\r
817  if(bDisplayNotSet)\r
818   SetOGLDisplaySettings(1);\r
819 \r
820  if(!(dwActFixes&16))\r
821   {\r
822    lx0=(short)(((int)lx0<<SIGNSHIFT)>>SIGNSHIFT);\r
823    lx1=(short)(((int)lx1<<SIGNSHIFT)>>SIGNSHIFT);\r
824    lx2=(short)(((int)lx2<<SIGNSHIFT)>>SIGNSHIFT);\r
825    ly0=(short)(((int)ly0<<SIGNSHIFT)>>SIGNSHIFT);\r
826    ly1=(short)(((int)ly1<<SIGNSHIFT)>>SIGNSHIFT);\r
827    ly2=(short)(((int)ly2<<SIGNSHIFT)>>SIGNSHIFT);\r
828 \r
829    if(CheckCoord3()) return TRUE;\r
830   }\r
831 \r
832  vertex[0].x=lx0+PSXDisplay.CumulOffset.x;\r
833  vertex[1].x=lx1+PSXDisplay.CumulOffset.x;\r
834  vertex[2].x=lx2+PSXDisplay.CumulOffset.x;\r
835  vertex[0].y=ly0+PSXDisplay.CumulOffset.y;\r
836  vertex[1].y=ly1+PSXDisplay.CumulOffset.y;\r
837  vertex[2].y=ly2+PSXDisplay.CumulOffset.y;\r
838 \r
839  return FALSE;\r
840 }\r
841 \r
842 ///////////////////////////////////////////////////////// \r
843 \r
844 BOOL offset4(void)\r
845 {\r
846  if(bDisplayNotSet)\r
847   SetOGLDisplaySettings(1);\r
848 \r
849  if(!(dwActFixes&16))\r
850   {\r
851    lx0=(short)(((int)lx0<<SIGNSHIFT)>>SIGNSHIFT);\r
852    lx1=(short)(((int)lx1<<SIGNSHIFT)>>SIGNSHIFT);\r
853    lx2=(short)(((int)lx2<<SIGNSHIFT)>>SIGNSHIFT);\r
854    lx3=(short)(((int)lx3<<SIGNSHIFT)>>SIGNSHIFT);\r
855    ly0=(short)(((int)ly0<<SIGNSHIFT)>>SIGNSHIFT);\r
856    ly1=(short)(((int)ly1<<SIGNSHIFT)>>SIGNSHIFT);\r
857    ly2=(short)(((int)ly2<<SIGNSHIFT)>>SIGNSHIFT);\r
858    ly3=(short)(((int)ly3<<SIGNSHIFT)>>SIGNSHIFT);\r
859 \r
860    if(CheckCoord4()) return TRUE;\r
861   }\r
862 \r
863  vertex[0].x=lx0+PSXDisplay.CumulOffset.x;\r
864  vertex[1].x=lx1+PSXDisplay.CumulOffset.x;\r
865  vertex[2].x=lx2+PSXDisplay.CumulOffset.x;\r
866  vertex[3].x=lx3+PSXDisplay.CumulOffset.x;\r
867  vertex[0].y=ly0+PSXDisplay.CumulOffset.y;\r
868  vertex[1].y=ly1+PSXDisplay.CumulOffset.y;\r
869  vertex[2].y=ly2+PSXDisplay.CumulOffset.y;\r
870  vertex[3].y=ly3+PSXDisplay.CumulOffset.y;\r
871 \r
872  return FALSE;\r
873 }\r
874 \r
875 ///////////////////////////////////////////////////////// \r
876 \r
877 void offsetST(void)\r
878 {\r
879  if(bDisplayNotSet)\r
880   SetOGLDisplaySettings(1);\r
881 \r
882  if(!(dwActFixes&16))\r
883   {\r
884    lx0=(short)(((int)lx0<<SIGNSHIFT)>>SIGNSHIFT);\r
885    ly0=(short)(((int)ly0<<SIGNSHIFT)>>SIGNSHIFT);\r
886 \r
887    if(lx0<-512 && PSXDisplay.DrawOffset.x<=-512)\r
888     lx0+=2048;\r
889 \r
890    if(ly0<-512 && PSXDisplay.DrawOffset.y<=-512)\r
891     ly0+=2048;\r
892   }\r
893 \r
894  ly1 = ly0;\r
895  ly2 = ly3 = ly0+sprtH;\r
896  lx3 = lx0;\r
897  lx1 = lx2 = lx0+sprtW;\r
898 \r
899  vertex[0].x=lx0+PSXDisplay.CumulOffset.x;\r
900  vertex[1].x=lx1+PSXDisplay.CumulOffset.x;\r
901  vertex[2].x=lx2+PSXDisplay.CumulOffset.x;\r
902  vertex[3].x=lx3+PSXDisplay.CumulOffset.x;\r
903  vertex[0].y=ly0+PSXDisplay.CumulOffset.y;\r
904  vertex[1].y=ly1+PSXDisplay.CumulOffset.y;\r
905  vertex[2].y=ly2+PSXDisplay.CumulOffset.y;\r
906  vertex[3].y=ly3+PSXDisplay.CumulOffset.y;\r
907 }\r
908 \r
909 ///////////////////////////////////////////////////////// \r
910 \r
911 void offsetScreenUpload(long Position)\r
912 {\r
913  if(bDisplayNotSet)\r
914   SetOGLDisplaySettings(1);\r
915 \r
916  if(Position==-1)\r
917   {\r
918    long lmdx,lmdy;\r
919 \r
920    lmdx=xrUploadArea.x0;\r
921    lmdy=xrUploadArea.y0;\r
922 \r
923    lx0-=lmdx;\r
924    ly0-=lmdy;\r
925    lx1-=lmdx;\r
926    ly1-=lmdy;\r
927    lx2-=lmdx;\r
928    ly2-=lmdy;\r
929    lx3-=lmdx;\r
930    ly3-=lmdy;\r
931   }\r
932  else\r
933  if(Position)\r
934   {\r
935    lx0-=PSXDisplay.DisplayPosition.x;\r
936    ly0-=PSXDisplay.DisplayPosition.y;\r
937    lx1-=PSXDisplay.DisplayPosition.x;\r
938    ly1-=PSXDisplay.DisplayPosition.y;\r
939    lx2-=PSXDisplay.DisplayPosition.x;\r
940    ly2-=PSXDisplay.DisplayPosition.y;\r
941    lx3-=PSXDisplay.DisplayPosition.x;\r
942    ly3-=PSXDisplay.DisplayPosition.y;\r
943   }\r
944  else\r
945   {\r
946    lx0-=PreviousPSXDisplay.DisplayPosition.x;\r
947    ly0-=PreviousPSXDisplay.DisplayPosition.y;\r
948    lx1-=PreviousPSXDisplay.DisplayPosition.x;\r
949    ly1-=PreviousPSXDisplay.DisplayPosition.y;\r
950    lx2-=PreviousPSXDisplay.DisplayPosition.x;\r
951    ly2-=PreviousPSXDisplay.DisplayPosition.y;\r
952    lx3-=PreviousPSXDisplay.DisplayPosition.x;\r
953    ly3-=PreviousPSXDisplay.DisplayPosition.y;\r
954   }\r
955 \r
956  vertex[0].x=lx0 + PreviousPSXDisplay.Range.x0;\r
957  vertex[1].x=lx1 + PreviousPSXDisplay.Range.x0;\r
958  vertex[2].x=lx2 + PreviousPSXDisplay.Range.x0;\r
959  vertex[3].x=lx3 + PreviousPSXDisplay.Range.x0;\r
960  vertex[0].y=ly0 + PreviousPSXDisplay.Range.y0;\r
961  vertex[1].y=ly1 + PreviousPSXDisplay.Range.y0;\r
962  vertex[2].y=ly2 + PreviousPSXDisplay.Range.y0;\r
963  vertex[3].y=ly3 + PreviousPSXDisplay.Range.y0;\r
964 \r
965  if(iUseMask)\r
966   {\r
967    vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=gl_z;\r
968    gl_z+=0.00004f;\r
969   }\r
970 }\r
971  \r
972 ///////////////////////////////////////////////////////// \r
973 \r
974 void offsetBlk(void)\r
975 {\r
976  if(bDisplayNotSet)\r
977   SetOGLDisplaySettings(1);\r
978                                             \r
979  vertex[0].x=lx0-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0;\r
980  vertex[1].x=lx1-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0;\r
981  vertex[2].x=lx2-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0;\r
982  vertex[3].x=lx3-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0;\r
983  vertex[0].y=ly0-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0;\r
984  vertex[1].y=ly1-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0;\r
985  vertex[2].y=ly2-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0;\r
986  vertex[3].y=ly3-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0;\r
987 \r
988  if(iUseMask)\r
989   {\r
990    vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=gl_z;\r
991    gl_z+=0.00004f;\r
992   }\r
993 }\r
994 \r
995 ////////////////////////////////////////////////////////////////////////\r
996 // texture sow/tow calculations\r
997 ////////////////////////////////////////////////////////////////////////\r
998 \r
999 void assignTextureVRAMWrite(void)\r
1000 {\r
1001 #ifdef OWNSCALE\r
1002 \r
1003  vertex[0].sow=0.5f/ ST_FACVRAMX;\r
1004  vertex[0].tow=0.5f/ ST_FACVRAM;\r
1005 \r
1006  vertex[1].sow=(float)gl_ux[1]/ ST_FACVRAMX;\r
1007  vertex[1].tow=0.5f/ ST_FACVRAM;\r
1008 \r
1009  vertex[2].sow=(float)gl_ux[2]/ ST_FACVRAMX;\r
1010  vertex[2].tow=(float)gl_vy[2]/ ST_FACVRAM;\r
1011 \r
1012  vertex[3].sow=0.5f/ ST_FACVRAMX;\r
1013  vertex[3].tow=(float)gl_vy[3]/ ST_FACVRAM;\r
1014 \r
1015 #else\r
1016 \r
1017  if(gl_ux[1]==255)\r
1018   {\r
1019    vertex[0].sow=(gl_ux[0]*255.99f)/255.0f;\r
1020    vertex[1].sow=(gl_ux[1]*255.99f)/255.0f;\r
1021    vertex[2].sow=(gl_ux[2]*255.99f)/255.0f;\r
1022    vertex[3].sow=(gl_ux[3]*255.99f)/255.0f;\r
1023   }\r
1024  else\r
1025   {\r
1026    vertex[0].sow=gl_ux[0];\r
1027    vertex[1].sow=gl_ux[1];\r
1028    vertex[2].sow=gl_ux[2];\r
1029    vertex[3].sow=gl_ux[3];\r
1030   }\r
1031 \r
1032  vertex[0].tow=gl_vy[0];\r
1033  vertex[1].tow=gl_vy[1];\r
1034  vertex[2].tow=gl_vy[2];\r
1035  vertex[3].tow=gl_vy[3];\r
1036 \r
1037 #endif\r
1038 }\r
1039 \r
1040 GLuint  gLastTex=0;\r
1041 GLuint  gLastFMode=(GLuint)-1;\r
1042 \r
1043 ///////////////////////////////////////////////////////// \r
1044 \r
1045 void assignTextureSprite(void)\r
1046 {\r
1047  if(bUsingTWin)\r
1048   {\r
1049    vertex[0].sow=vertex[3].sow=(float)gl_ux[0]/TWin.UScaleFactor;\r
1050    vertex[1].sow=vertex[2].sow=(float)sSprite_ux2/TWin.UScaleFactor;\r
1051    vertex[0].tow=vertex[1].tow=(float)gl_vy[0]/TWin.VScaleFactor;\r
1052    vertex[2].tow=vertex[3].tow=(float)sSprite_vy2/TWin.VScaleFactor;\r
1053    gLastTex=gTexName;\r
1054   }\r
1055  else\r
1056   {\r
1057 #ifdef OWNSCALE\r
1058 \r
1059    vertex[0].sow=vertex[3].sow=(float)gl_ux[0]     / ST_FACSPRITE;\r
1060    vertex[1].sow=vertex[2].sow=(float)sSprite_ux2  / ST_FACSPRITE;\r
1061    vertex[0].tow=vertex[1].tow=(float)gl_vy[0]     / ST_FACSPRITE;\r
1062    vertex[2].tow=vertex[3].tow=(float)sSprite_vy2  / ST_FACSPRITE;\r
1063 \r
1064 #else\r
1065  \r
1066    vertex[0].sow=vertex[3].sow=gl_ux[0];\r
1067    vertex[1].sow=vertex[2].sow=sSprite_ux2;\r
1068    vertex[0].tow=vertex[1].tow=gl_vy[0];\r
1069    vertex[2].tow=vertex[3].tow=sSprite_vy2;\r
1070 \r
1071 #endif\r
1072 \r
1073    if(iFilterType>2) \r
1074     {\r
1075      if(gLastTex!=gTexName || gLastFMode!=0)\r
1076       {\r
1077        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glError();\r
1078        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glError();\r
1079        gLastTex=gTexName;gLastFMode=0;\r
1080       }\r
1081     }\r
1082   }\r
1083 \r
1084  if(usMirror & 0x1000) \r
1085   {\r
1086    vertex[0].sow=vertex[1].sow;\r
1087    vertex[1].sow=vertex[2].sow=vertex[3].sow;\r
1088    vertex[3].sow=vertex[0].sow;\r
1089   }\r
1090 \r
1091  if(usMirror & 0x2000) \r
1092   {\r
1093    vertex[0].tow=vertex[3].tow;\r
1094    vertex[2].tow=vertex[3].tow=vertex[1].tow;\r
1095    vertex[1].tow=vertex[0].tow;\r
1096   }\r
1097 \r
1098 }\r
1099 \r
1100 ///////////////////////////////////////////////////////// \r
1101 \r
1102 void assignTexture3(void)\r
1103 {\r
1104  if(bUsingTWin)\r
1105   {\r
1106    vertex[0].sow=(float)gl_ux[0]/TWin.UScaleFactor;\r
1107    vertex[0].tow=(float)gl_vy[0]/TWin.VScaleFactor;\r
1108    vertex[1].sow=(float)gl_ux[1]/TWin.UScaleFactor;\r
1109    vertex[1].tow=(float)gl_vy[1]/TWin.VScaleFactor;\r
1110    vertex[2].sow=(float)gl_ux[2]/TWin.UScaleFactor;\r
1111    vertex[2].tow=(float)gl_vy[2]/TWin.VScaleFactor;\r
1112    gLastTex=gTexName;\r
1113   }\r
1114  else\r
1115   {\r
1116 #ifdef OWNSCALE\r
1117    vertex[0].sow=(float)gl_ux[0] / ST_FACTRI;\r
1118    vertex[0].tow=(float)gl_vy[0] / ST_FACTRI;\r
1119    vertex[1].sow=(float)gl_ux[1] / ST_FACTRI;\r
1120 \r
1121    vertex[1].tow=(float)gl_vy[1] / ST_FACTRI;\r
1122    vertex[2].sow=(float)gl_ux[2] / ST_FACTRI;\r
1123    vertex[2].tow=(float)gl_vy[2] / ST_FACTRI;\r
1124 #else\r
1125    vertex[0].sow=gl_ux[0];\r
1126    vertex[0].tow=gl_vy[0];\r
1127    vertex[1].sow=gl_ux[1];\r
1128    vertex[1].tow=gl_vy[1];\r
1129    vertex[2].sow=gl_ux[2];\r
1130    vertex[2].tow=gl_vy[2];\r
1131 #endif\r
1132 \r
1133    if(iFilterType>2) \r
1134     {\r
1135      if(gLastTex!=gTexName || gLastFMode!=1)\r
1136       {\r
1137        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glError();\r
1138        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glError();\r
1139        gLastTex=gTexName;gLastFMode=1;\r
1140       }\r
1141     }\r
1142 \r
1143    if(iFilterType) \r
1144     {\r
1145      float fxmin=256.0f,fxmax=0.0f,fymin=256.0f,fymax=0.0f;int i;\r
1146      for(i=0;i<3;i++)\r
1147       {\r
1148        if(vertex[i].sow<fxmin) fxmin=vertex[i].sow;\r
1149        if(vertex[i].tow<fymin) fymin=vertex[i].tow;\r
1150        if(vertex[i].sow>fxmax) fxmax=vertex[i].sow;\r
1151        if(vertex[i].tow>fymax) fymax=vertex[i].tow; \r
1152       }\r
1153 \r
1154      for(i=0;i<3;i++)\r
1155       {\r
1156        if(vertex[i].sow==fxmin) vertex[i].sow+=ST_BFFACSORT;\r
1157        if(vertex[i].sow==fxmax) vertex[i].sow-=ST_BFFACSORT;\r
1158        if(vertex[i].tow==fymin) vertex[i].tow+=ST_BFFACSORT;\r
1159        if(vertex[i].tow==fymax) vertex[i].tow-=ST_BFFACSORT;\r
1160       }\r
1161     }\r
1162   }\r
1163 }\r
1164 \r
1165 ///////////////////////////////////////////////////////// \r
1166 \r
1167 void assignTexture4(void)\r
1168 {\r
1169  if(bUsingTWin)\r
1170   {\r
1171    vertex[0].sow=(float)gl_ux[0]/TWin.UScaleFactor;\r
1172    vertex[0].tow=(float)gl_vy[0]/TWin.VScaleFactor;\r
1173    vertex[1].sow=(float)gl_ux[1]/TWin.UScaleFactor;\r
1174    vertex[1].tow=(float)gl_vy[1]/TWin.VScaleFactor;\r
1175    vertex[2].sow=(float)gl_ux[2]/TWin.UScaleFactor;\r
1176    vertex[2].tow=(float)gl_vy[2]/TWin.VScaleFactor;\r
1177    vertex[3].sow=(float)gl_ux[3]/TWin.UScaleFactor;\r
1178    vertex[3].tow=(float)gl_vy[3]/TWin.VScaleFactor;\r
1179    gLastTex=gTexName;\r
1180   }\r
1181  else\r
1182   {\r
1183 #ifdef OWNSCALE\r
1184    vertex[0].sow=(float)gl_ux[0] / ST_FAC;\r
1185    vertex[0].tow=(float)gl_vy[0] / ST_FAC;\r
1186    vertex[1].sow=(float)gl_ux[1] / ST_FAC;\r
1187    vertex[1].tow=(float)gl_vy[1] / ST_FAC;\r
1188    vertex[2].sow=(float)gl_ux[2] / ST_FAC;\r
1189    vertex[2].tow=(float)gl_vy[2] / ST_FAC;\r
1190    vertex[3].sow=(float)gl_ux[3] / ST_FAC;\r
1191    vertex[3].tow=(float)gl_vy[3] / ST_FAC;\r
1192 #else\r
1193    vertex[0].sow=gl_ux[0];\r
1194    vertex[0].tow=gl_vy[0];\r
1195    vertex[1].sow=gl_ux[1];\r
1196    vertex[1].tow=gl_vy[1];\r
1197    vertex[2].sow=gl_ux[2];\r
1198    vertex[2].tow=gl_vy[2];\r
1199    vertex[3].sow=gl_ux[3];\r
1200    vertex[3].tow=gl_vy[3];\r
1201 #endif\r
1202 \r
1203    if(iFilterType>2) \r
1204     {\r
1205      if(gLastTex!=gTexName || gLastFMode!=1)\r
1206       {\r
1207        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glError();\r
1208        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glError();\r
1209        gLastTex=gTexName;gLastFMode=1;\r
1210       }\r
1211     }\r
1212 \r
1213    if(iFilterType) \r
1214     {\r
1215      float fxmin=256.0f,fxmax=0.0f,fymin=256.0f,fymax=0.0f;int i;\r
1216      for(i=0;i<4;i++)\r
1217       {\r
1218        if(vertex[i].sow<fxmin) fxmin=vertex[i].sow;\r
1219        if(vertex[i].tow<fymin) fymin=vertex[i].tow;\r
1220        if(vertex[i].sow>fxmax) fxmax=vertex[i].sow;\r
1221        if(vertex[i].tow>fymax) fymax=vertex[i].tow; \r
1222       }\r
1223 \r
1224      for(i=0;i<4;i++)\r
1225       {\r
1226        if(vertex[i].sow==fxmin) vertex[i].sow+=ST_BFFACSORT;\r
1227        if(vertex[i].sow==fxmax) vertex[i].sow-=ST_BFFACSORT;\r
1228        if(vertex[i].tow==fymin) vertex[i].tow+=ST_BFFACSORT;\r
1229        if(vertex[i].tow==fymax) vertex[i].tow-=ST_BFFACSORT;\r
1230       }\r
1231     }\r
1232   }\r
1233 }\r
1234 \r
1235 ////////////////////////////////////////////////////////////////////////\r
1236 ////////////////////////////////////////////////////////////////////////\r
1237 ////////////////////////////////////////////////////////////////////////\r
1238 \r
1239 ////////////////////////////////////////////////////////////////////////\r
1240 // render pos / buffers\r
1241 ////////////////////////////////////////////////////////////////////////\r
1242 \r
1243 #define EqualRect(pr1,pr2) ((pr1)->left==(pr2)->left && (pr1)->top==(pr2)->top && (pr1)->right==(pr2)->right && (pr1)->bottom==(pr2)->bottom)\r
1244 \r
1245 ////////////////////////////////////////////////////////////////////////\r
1246 // SetDisplaySettings: "simply" calcs the new drawing area and updates\r
1247 //                     the ogl clipping (scissor) \r
1248 \r
1249 BOOL bSetClip=FALSE;\r
1250 \r
1251 void SetOGLDisplaySettings(BOOL DisplaySet)\r
1252 {\r
1253  static RECT rprev={0,0,0,0};\r
1254  static RECT rC   ={0,0,0,0};\r
1255  static int iOldX=0;\r
1256  static int iOldY=0;\r
1257  RECT r;float XS,YS;\r
1258 \r
1259  bDisplayNotSet = FALSE;\r
1260 \r
1261  //----------------------------------------------------// that's a whole screen upload\r
1262  if(!DisplaySet)\r
1263   {\r
1264    RECT rX;\r
1265    PSXDisplay.GDrawOffset.x=0;\r
1266    PSXDisplay.GDrawOffset.y=0;\r
1267 \r
1268    PSXDisplay.CumulOffset.x = PSXDisplay.DrawOffset.x+PreviousPSXDisplay.Range.x0;\r
1269    PSXDisplay.CumulOffset.y = PSXDisplay.DrawOffset.y+PreviousPSXDisplay.Range.y0;\r
1270 \r
1271    rprev.left=rprev.left+1;\r
1272 \r
1273    rX=rRatioRect;\r
1274    rX.top=iResY-(rRatioRect.top+rRatioRect.bottom);\r
1275 \r
1276    if(bSetClip || !EqualRect(&rC,&rX))\r
1277     {\r
1278      rC=rX;\r
1279      glScissor(rC.left,rC.top,rC.right,rC.bottom); glError();\r
1280      //LOGE("glscissor:%d %d %d %d",rC.left,rC.top,rC.right,rC.bottom);\r
1281      bSetClip=FALSE; \r
1282     }\r
1283    return;\r
1284   }\r
1285  //----------------------------------------------------// \r
1286 \r
1287  PSXDisplay.GDrawOffset.y = PreviousPSXDisplay.DisplayPosition.y;\r
1288  PSXDisplay.GDrawOffset.x = PreviousPSXDisplay.DisplayPosition.x;\r
1289  PSXDisplay.CumulOffset.x = PSXDisplay.DrawOffset.x - PSXDisplay.GDrawOffset.x+PreviousPSXDisplay.Range.x0;\r
1290  PSXDisplay.CumulOffset.y = PSXDisplay.DrawOffset.y - PSXDisplay.GDrawOffset.y+PreviousPSXDisplay.Range.y0;\r
1291 \r
1292  r.top   =PSXDisplay.DrawArea.y0 - PreviousPSXDisplay.DisplayPosition.y;\r
1293  r.bottom=PSXDisplay.DrawArea.y1 - PreviousPSXDisplay.DisplayPosition.y;\r
1294 \r
1295  if(r.bottom<0 || r.top>=PSXDisplay.DisplayMode.y)\r
1296   {\r
1297    r.top   =PSXDisplay.DrawArea.y0 - PSXDisplay.DisplayPosition.y;\r
1298    r.bottom=PSXDisplay.DrawArea.y1 - PSXDisplay.DisplayPosition.y;\r
1299   }\r
1300 \r
1301  r.left  =PSXDisplay.DrawArea.x0 - PreviousPSXDisplay.DisplayPosition.x;\r
1302  r.right =PSXDisplay.DrawArea.x1 - PreviousPSXDisplay.DisplayPosition.x;\r
1303 \r
1304  if(r.right<0 || r.left>=PSXDisplay.DisplayMode.x)\r
1305   {\r
1306    r.left  =PSXDisplay.DrawArea.x0 - PSXDisplay.DisplayPosition.x;\r
1307    r.right =PSXDisplay.DrawArea.x1 - PSXDisplay.DisplayPosition.x;\r
1308   }\r
1309 \r
1310  if(!bSetClip && EqualRect(&r,&rprev) &&\r
1311     iOldX == PSXDisplay.DisplayMode.x &&\r
1312     iOldY == PSXDisplay.DisplayMode.y)\r
1313   return;\r
1314 \r
1315  rprev = r;\r
1316  iOldX = PSXDisplay.DisplayMode.x;\r
1317  iOldY = PSXDisplay.DisplayMode.y;\r
1318 \r
1319  XS=(float)rRatioRect.right/(float)PSXDisplay.DisplayMode.x;\r
1320  YS=(float)rRatioRect.bottom/(float)PSXDisplay.DisplayMode.y;\r
1321 \r
1322  if(PreviousPSXDisplay.Range.x0)\r
1323   {\r
1324    short s=PreviousPSXDisplay.Range.x0+PreviousPSXDisplay.Range.x1;\r
1325 \r
1326    r.left+=PreviousPSXDisplay.Range.x0+1;\r
1327 \r
1328    r.right+=PreviousPSXDisplay.Range.x0;\r
1329 \r
1330    if(r.left>s)  r.left=s;\r
1331    if(r.right>s) r.right=s;\r
1332   }\r
1333 \r
1334  if(PreviousPSXDisplay.Range.y0)\r
1335   {\r
1336    short s=PreviousPSXDisplay.Range.y0+PreviousPSXDisplay.Range.y1;\r
1337 \r
1338    r.top+=PreviousPSXDisplay.Range.y0+1;\r
1339    r.bottom+=PreviousPSXDisplay.Range.y0;\r
1340 \r
1341    if(r.top>s)    r.top=s;\r
1342    if(r.bottom>s) r.bottom=s;\r
1343   }\r
1344 \r
1345  // Set the ClipArea variables to reflect the new screen,\r
1346  // offset from zero (since it is a new display buffer)\r
1347  r.left   = (int)(((float)(r.left))      *XS);\r
1348  r.top    = (int)(((float)(r.top))       *YS);\r
1349  r.right  = (int)(((float)(r.right  + 1))*XS);\r
1350  r.bottom = (int)(((float)(r.bottom + 1))*YS);\r
1351 \r
1352  // Limit clip area to the screen size\r
1353  if (r.left   > iResX)   r.left   = iResX;\r
1354  if (r.left   < 0)       r.left   = 0;\r
1355  if (r.top    > iResY)   r.top    = iResY;\r
1356  if (r.top    < 0)       r.top    = 0;\r
1357  if (r.right  > iResX)   r.right  = iResX;\r
1358  if (r.right  < 0)       r.right  = 0;\r
1359  if (r.bottom > iResY)   r.bottom = iResY;\r
1360  if (r.bottom < 0)       r.bottom = 0;\r
1361 \r
1362  r.right -=r.left;\r
1363  r.bottom-=r.top;\r
1364  r.top=iResY-(r.top+r.bottom);\r
1365 \r
1366  r.left+=rRatioRect.left;\r
1367  r.top -=rRatioRect.top;\r
1368 \r
1369  if(bSetClip || !EqualRect(&r,&rC))\r
1370   {\r
1371    glScissor(r.left,r.top,r.right,r.bottom); glError();\r
1372 \r
1373    rC=r;\r
1374    bSetClip=FALSE;\r
1375   }\r
1376 }\r
1377 \r
1378 ////////////////////////////////////////////////////////////////////////\r
1379 ////////////////////////////////////////////////////////////////////////\r
1380 ////////////////////////////////////////////////////////////////////////\r
1381 \r