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