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