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