/***************************************************************************
                           draw.c  -  description
                             -------------------
    begin                : Sun Mar 08 2009
    copyright            : (C) 1999-2009 by Pete Bernert
    web                  : www.pbernert.com   
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version. See also the license.txt file for *
 *   additional informations.                                              *
 *                                                                         *
 ***************************************************************************/

//*************************************************************************// 
// History of changes:
//
// 2009/03/08 - Pete  
// - generic cleanup for the Peops release
//
//*************************************************************************// 


#define _IN_DRAW


#include "gpuExternals.h"
#include "gpuPlugin.h"
#include "gpuDraw.h"
#include "gpuPrim.h"
#include "gpuTexture.h"
#include "gpuStdafx.h"

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
//#include "menu.h"
            
////////////////////////////////////////////////////////////////////////////////////
// defines

#define SIGNBIT 0x800
#define S_MASK  0xf000
#define L_MASK  0xfffff000

// ownscale: some ogl drivers have buggy texture matrix funcs, so it
//           is safer to calc sow/tow ourselves

#ifdef OWNSCALE

///////////////////////////////////////////////////////////////

#define ST_FACSPRITE       255.99f
#define ST_BFFACSPRITE     0.5f/256.0f
#define ST_BFFACSPRITESORT 0.333f/256.0f

#define ST_OFFSET          0.5f/256.0f;

#define ST_FAC             255.99f
#define ST_BFFAC           0.5f/256.0f
#define ST_BFFACSORT       0.333f/256.0f

#define ST_FACTRI          255.99f
#define ST_BFFACTRI        0.5f/256.0f
#define ST_BFFACTRISORT    0.333f/256.0f

#define ST_FACVRAMX        255.0f
#define ST_FACVRAM         256.0f

///////////////////////////////////////////////////////////////

#else

#define ST_BFFACSPRITE     0.5f
#define ST_BFFACSPRITESORT 0.333f

#define ST_BFFAC           0.5f
#define ST_BFFACSORT       0.333f

#define ST_BFFACTRI        0.5f
#define ST_BFFACTRISORT    0.333f

#define ST_OFFSET          0.5f;
                
#endif

////////////////////////////////////////////////////////////////////////////////////
// draw globals

void  glBlendEquationEXT(GLenum mode);
void  glColorTableEXT(GLenum target, GLenum internalFormat, GLsizei width, GLenum format,GLenum type, const GLvoid *data);

// draw globals; most will be initialized again later (by config or checks) 

BOOL           bIsFirstFrame=TRUE;

// resolution/ratio vars

int            iResX;
int            iResY;
BOOL           bKeepRatio=FALSE;
RECT           rRatioRect;

// psx mask related vars

BOOL           bCheckMask=FALSE;
int            iUseMask=0;
int            iSetMask=0;
unsigned short sSetMask=0;
unsigned int   lSetMask=0;

// drawing/coord vars

OGLVertex      vertex[4];
GLubyte        gl_ux[8];
GLubyte        gl_vy[8];
short          sprtY,sprtX,sprtH,sprtW;

// drawing options

BOOL           bOpaquePass;
BOOL           bAdvancedBlend;

// OGL extension support


// gfx card buffer infos

int            iDepthFunc=0;
int            iZBufferDepth=0;
GLbitfield     uiBufferBits=GL_COLOR_BUFFER_BIT;

////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////
// Set OGL pixel format
////////////////////////////////////////////////////////////////////////
 

////////////////////////////////////////////////////////////////////////
// Get extension infos (f.e. pal textures / packed pixels)
////////////////////////////////////////////////////////////////////////

void GetExtInfos(void)                              
{
 BOOL bPacked=FALSE;                                   // default: no packed pixel support

 if(strstr((char *)glGetString(GL_EXTENSIONS),         // packed pixels available?
    "GL_EXT_packed_pixels"))                          
  bPacked=TRUE;                                        // -> ok

 
 iClampType=GL_CLAMP_TO_EDGE;
}

////////////////////////////////////////////////////////////////////////
// Setup some stuff depending on user settings or in-game toggle
////////////////////////////////////////////////////////////////////////

void SetExtGLFuncs(void)
{
 //----------------------------------------------------//

 SetFixes();                                           // update fix infos

 //----------------------------------------------------//

  {
   if(bAdvancedBlend) bUseMultiPass=TRUE;              // -> pseudo-advanced with 2 passes
   else               bUseMultiPass=FALSE;             // -> or simple 'bright color' mode
//   bGLBlend=FALSE;                                     // -> no ext blending!
   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glError();
  }

 if(bOpaquePass)                                        // opaque mode?
  {
   if(dwActFixes&32) 
    {
     TCF[0]=CP8RGBA_0;
     PalTexturedColourFn=CP8RGBA;                      // -> init col func
    }
   else
    {
     TCF[0]=XP8RGBA_0;
     PalTexturedColourFn=XP8RGBA;                      // -> init col func
    }

   TCF[1]=XP8RGBA_1;
   glAlphaFuncx(GL_GREATER,0.49f); glError();

  }
 else                                                  // no opaque mode?
  {
   TCF[0]=TCF[1]=P8RGBA;
   PalTexturedColourFn=P8RGBA;                         // -> init col func
   glAlphaFuncx(GL_NOTEQUAL,0); glError();             // --> set alpha func

  }

 //----------------------------------------------------//

 LoadSubTexFn=LoadSubTexturePageSort;                  // init load tex ptr

 bBlendEnable=FALSE;                                   // init blending: off
 glDisable(GL_BLEND); glError();


 SetScanTrans();                                       // init scan lines (if wanted)
}

////////////////////////////////////////////////////////////////////////
// setup scan lines
////////////////////////////////////////////////////////////////////////

#define R_TSP 0x00,0x45,0x00,0xff
#define G_TSP 0x00,0x00,0x45,0xff
#define B_TSP 0x45,0x00,0x00,0xff
#define O_TSP 0x45,0x45,0x45,0xff
#define N_TSP 0x00,0x00,0x00,0xff

GLuint  gTexScanName=0;

GLubyte texscan[4][16]= 
{
{R_TSP, G_TSP, B_TSP, N_TSP},
{O_TSP, N_TSP, O_TSP, N_TSP},
{B_TSP, N_TSP, R_TSP, G_TSP},
{O_TSP, N_TSP, O_TSP, N_TSP}
};

void CreateScanLines(void)
{
}

////////////////////////////////////////////////////////////////////////
// Initialize OGL
////////////////////////////////////////////////////////////////////////

#define MODE_RAW 0
#define MODE_X11 1
#define MODE_SDL 2
int use_fsaa = 0;

EGLDisplay display;
EGLSurface surface;
static EGLConfig  config;
static EGLContext context;

#if defined(USE_X11)
#include "X11/Xlib.h"
#include "X11/Xutil.h"
#include "X11/Xatom.h"

Window			x11Window	= 0;
Display*		x11Display	= 0;
long			x11Screen	= 0;
XVisualInfo		x11Visual;
XVisualInfo*	px11Visual	= 0;
Colormap        x11Colormap	= 0;
#endif

EGLint attrib_list_fsaa[] =
{
	EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
	EGL_BUFFER_SIZE,    0,
	EGL_DEPTH_SIZE,     16,
	EGL_SAMPLE_BUFFERS, 1,
	EGL_SAMPLES,        4,
	EGL_NONE
};

EGLint attrib_list[] =
{
//	EGL_DEPTH_SIZE,   16,
	EGL_NONE
};

bool TestEGLError(const char* pszLocation)
{
	/*
		eglGetError returns the last error that has happened using egl,
		not the status of the last called function. The user has to
		check after every single egl call or at least once every frame.
	*/
	EGLint iErr = eglGetError();
	if (iErr != EGL_SUCCESS)
	{
		printf("%s failed (0x%x).\n", pszLocation, (int)iErr);
		return FALSE;
	}

	return TRUE;
}

static int initEGL(void)
{
	NativeWindowType window = 0;

	printf ("GL init\n");

	EGLint numConfigs;
	EGLint majorVersion;
	EGLint minorVersion;
#if defined(USE_X11)
	enum
	{
	_NET_WM_STATE_REMOVE =0,
	_NET_WM_STATE_ADD = 1,
	_NET_WM_STATE_TOGGLE =2
	};
	
	Window			        sRootWindow;
	XSetWindowAttributes	sWA;
	unsigned int		    ui32Mask;
	int			            i32Depth;
#endif
	
	EGLint *attribList = NULL;
	if (use_fsaa)
	{
		printf( "GLES: Using Full Scene Antialiasing\n" );
		attribList = attrib_list_fsaa;
	}
	else
	{
		attribList = attrib_list;
	}

#if defined(USE_X11)
            // Initializes the display and screen
            x11Display = XOpenDisplay( ":0" );
            if (!x11Display)
            {
                printf("GLES Error: Unable to open X display\n");
                return -1;
            }
            x11Screen = XDefaultScreen( x11Display );

            // Gets the display parameters so we can pass the same parameters to the window to be created.
            sRootWindow	= RootWindow(x11Display, x11Screen);
            i32Depth	= DefaultDepth(x11Display, x11Screen);
            px11Visual	= &x11Visual;
            XMatchVisualInfo( x11Display, x11Screen, i32Depth, TrueColor, px11Visual);
            if (!px11Visual)
            {
                printf("GLES Error: Unable to acquire visual\n");
                return -1;
            }
            // Colormap of the specified visual type for the display.
            x11Colormap = XCreateColormap( x11Display, sRootWindow, px11Visual->visual, AllocNone );
            sWA.colormap = x11Colormap;

            // List of events to be handled by the application. Add to these for handling other events.
            sWA.event_mask = StructureNotifyMask | ExposureMask | ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask;

            // Display capabilities list.
            ui32Mask = CWBackPixel | CWBorderPixel | CWEventMask | CWColormap;

            // Creates the X11 window
            x11Window = XCreateWindow( x11Display, RootWindow(x11Display, x11Screen), 0, 0, iResX, iResY,
                                        0, CopyFromParent, InputOutput, CopyFromParent, ui32Mask, &sWA);

            // Make the window viewable and flush the output buffer.
            XMapWindow(x11Display, x11Window);
            XFlush(x11Display);

            // Make the window fullscreen
            unsigned char fullScreen = 1;
            Atom wmState = XInternAtom(x11Display, "_NET_WM_STATE", False);
            Atom wmFullScreen = XInternAtom(x11Display,"_NET_WM_STATE_FULLSCREEN", False);

            XEvent xev;
            xev.xclient.type		    = ClientMessage;
            xev.xclient.serial		    = 0;
            xev.xclient.send_event      = True;
            xev.xclient.window		    = x11Window;
            xev.xclient.message_type    = wmState;
            xev.xclient.format		    = 32;
            xev.xclient.data.l[0]		= (fullScreen ? _NET_WM_STATE_ADD : _NET_WM_STATE_REMOVE);
            xev.xclient.data.l[1]		= wmFullScreen;
            xev.xclient.data.l[2]		= 0;

            XSendEvent(x11Display, DefaultRootWindow(x11Display), False, SubstructureRedirectMask | SubstructureNotifyMask, &xev);

            display = eglGetDisplay( (EGLNativeDisplayType)x11Display );
            window = x11Window;
#else
            display = eglGetDisplay( (EGLNativeDisplayType)0 );
#endif

	if( display == EGL_NO_DISPLAY )
	{
		printf( "GLES EGL Error: GL No Display\n" );
		return -1;
	}

	if( !eglInitialize( display, &majorVersion, &minorVersion ) )
	{
		printf( "GLES EGL Error: eglInitialize failed\n" );
		return -1;
	}

	if( !eglChooseConfig( display, attribList, &config, 1, &numConfigs ) )
	{
		printf( "GLES EGL Error: eglChooseConfig failed\n" );
		return -1;
	}

	context = eglCreateContext( display, config, NULL, NULL );
	if( context==0 )
	{
		printf( "GLES EGL Error: eglCreateContext failed\n" );
		return -1;
	}

#ifdef FAKE_WINDOW
	// broken Caanoo libs won't accept NULL window
	window = (NativeWindowType)1;
#endif
	surface = eglCreateWindowSurface( display, config, window, NULL );
	if (!TestEGLError("eglCreateWindowSurface"))
		return -1;

	eglMakeCurrent( display, surface, surface, context );
	if (!TestEGLError("eglMakeCurrent"))
		return -1;

	printf("GLES init ok\n");
	return 0;
}

static int created_gles_context;

int GLinitialize(void *ext_gles_display, void *ext_gles_surface)
{
 if(ext_gles_display != NULL && ext_gles_surface != NULL) { 
  display = (EGLDisplay)ext_gles_display;
  surface = (EGLSurface)ext_gles_surface;
 }
 else {
  if(initEGL()!=0)
   return -1;
  created_gles_context=1;
 }

 //----------------------------------------------------// 

 glDepthRangef(0.0f, 1.0f);glError();

 glViewport(rRatioRect.left,                           // init viewport by ratio rect
            iResY-(rRatioRect.top+rRatioRect.bottom),
            rRatioRect.right, 
            rRatioRect.bottom); glError();

 glScissor(0, 0, iResX, iResY); glError();             // init clipping (fullscreen)
 glEnable(GL_SCISSOR_TEST); glError();

#ifndef OWNSCALE
 glMatrixMode(GL_TEXTURE);                             // init psx tex sow and tow if not "ownscale"
 glLoadIdentity();
 glScalef(1.0f/255.99f,1.0f/255.99f,1.0f);             // geforce precision hack
#endif 
 
 //glPolygonOffset( -0.2f, -0.2f );glError();

 glMatrixMode(GL_PROJECTION); glError();               // init projection with psx resolution
 glLoadIdentity(); glError();

 glOrtho(0,PSXDisplay.DisplayMode.x,
         PSXDisplay.DisplayMode.y, 0, -1, 1); glError();

 if(iZBufferDepth)                                     // zbuffer?
  {
   uiBufferBits=GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT;
   glEnable(GL_DEPTH_TEST); glError();
   glDepthFunc(GL_ALWAYS); glError();
   iDepthFunc=1;
  }
 else                                                  // no zbuffer?
  {
   uiBufferBits=GL_COLOR_BUFFER_BIT;
   glDisable(GL_DEPTH_TEST); glError();
  }

 glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glError();      // first buffer clear
 glClear(uiBufferBits); glError();

 GetExtInfos();                                        // get ext infos
 SetExtGLFuncs();                                      // init all kind of stuff (tex function pointers)
 
 glEnable(GL_ALPHA_TEST); glError();                   // wanna alpha test

  {
   glDisable(GL_LINE_SMOOTH); glError();
   glDisable(GL_POINT_SMOOTH); glError();
  }

 ubGloAlpha=127;                                       // init some drawing vars
 ubGloColAlpha=127;
 TWin.UScaleFactor = 1;
 TWin.VScaleFactor = 1;
 bDrawMultiPass=FALSE;
 bTexEnabled=FALSE;
 bUsingTWin=FALSE;
      
 if(bDrawDither)  glEnable(GL_DITHER);                 // dither mode
 else             glDisable(GL_DITHER); 
 glError(); 
 glDisable(GL_FOG); glError();                          // turn all (currently) unused modes off
 glDisable(GL_LIGHTING); glError();  
 glDisable(GL_STENCIL_TEST); glError();  
 glDisable(GL_TEXTURE_2D); glError();
 glDisable(GL_CULL_FACE);

 glFlush(); glError();                                 // we are done...
 glFinish(); glError();                           

 CreateScanLines();                                    // setup scanline stuff (if wanted)

 CheckTextureMemory();                                 // check available tex memory

 if(bKeepRatio) SetAspectRatio();                      // set ratio

 
 bIsFirstFrame = FALSE;                                // we have survived the first frame :)

 return 0;
}

////////////////////////////////////////////////////////////////////////
// clean up OGL stuff
////////////////////////////////////////////////////////////////////////

void GLcleanup() 
{                                                     
 CleanupTextureStore();                                // bye textures

 if(created_gles_context) {
  eglMakeCurrent( display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT );
  eglDestroySurface( display, surface );
  eglDestroyContext( display, context );
  eglTerminate( display );

#if defined(USE_X11)
		if (x11Window) XDestroyWindow(x11Display, x11Window);
		if (x11Colormap) XFreeColormap( x11Display, x11Colormap );
		if (x11Display) XCloseDisplay(x11Display);
#endif
  created_gles_context=0;
 }
}

////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////
// Offset stuff
////////////////////////////////////////////////////////////////////////

// please note: it is hardly do-able in a hw/accel plugin to get the 
//              real psx polygon coord mapping right... the following
//              works not to bad with many games, though

static __inline BOOL CheckCoord4()
{
 if(lx0<0)
  {
   if(((lx1-lx0)>CHKMAX_X) ||
      ((lx2-lx0)>CHKMAX_X)) 
    {
     if(lx3<0)
      {
       if((lx1-lx3)>CHKMAX_X) return TRUE;
       if((lx2-lx3)>CHKMAX_X) return TRUE;
      }
    }
  }
 if(lx1<0)
  {
   if((lx0-lx1)>CHKMAX_X) return TRUE;
   if((lx2-lx1)>CHKMAX_X) return TRUE;
   if((lx3-lx1)>CHKMAX_X) return TRUE;
  }
 if(lx2<0)
  {
   if((lx0-lx2)>CHKMAX_X) return TRUE;
   if((lx1-lx2)>CHKMAX_X) return TRUE;
   if((lx3-lx2)>CHKMAX_X) return TRUE;
  }
 if(lx3<0)
  {
   if(((lx1-lx3)>CHKMAX_X) ||
      ((lx2-lx3)>CHKMAX_X))
    {
     if(lx0<0)
      {
       if((lx1-lx0)>CHKMAX_X) return TRUE;
       if((lx2-lx0)>CHKMAX_X) return TRUE;
      }
    }
  }
 

 if(ly0<0)
  {
   if((ly1-ly0)>CHKMAX_Y) return TRUE;
   if((ly2-ly0)>CHKMAX_Y) return TRUE;
  }
 if(ly1<0)
  {
   if((ly0-ly1)>CHKMAX_Y) return TRUE;
   if((ly2-ly1)>CHKMAX_Y) return TRUE;
   if((ly3-ly1)>CHKMAX_Y) return TRUE;
  }
 if(ly2<0)
  {
   if((ly0-ly2)>CHKMAX_Y) return TRUE;
   if((ly1-ly2)>CHKMAX_Y) return TRUE;
   if((ly3-ly2)>CHKMAX_Y) return TRUE;
  }
 if(ly3<0)
  {
   if((ly1-ly3)>CHKMAX_Y) return TRUE;
   if((ly2-ly3)>CHKMAX_Y) return TRUE;
  }

 return FALSE;
}

static __inline BOOL CheckCoord3()
{
 if(lx0<0)
  {
   if((lx1-lx0)>CHKMAX_X) return TRUE;
   if((lx2-lx0)>CHKMAX_X) return TRUE;
  }
 if(lx1<0)
  {
   if((lx0-lx1)>CHKMAX_X) return TRUE;
   if((lx2-lx1)>CHKMAX_X) return TRUE;
  }
 if(lx2<0)
  {
   if((lx0-lx2)>CHKMAX_X) return TRUE;
   if((lx1-lx2)>CHKMAX_X) return TRUE;
  }
 if(ly0<0)
  {
   if((ly1-ly0)>CHKMAX_Y) return TRUE;
   if((ly2-ly0)>CHKMAX_Y) return TRUE;
  }
 if(ly1<0)
  {
   if((ly0-ly1)>CHKMAX_Y) return TRUE;
   if((ly2-ly1)>CHKMAX_Y) return TRUE;
  }
 if(ly2<0)
  {
   if((ly0-ly2)>CHKMAX_Y) return TRUE;
   if((ly1-ly2)>CHKMAX_Y) return TRUE;
  }

 return FALSE;
}


static __inline BOOL CheckCoord2()
{
 if(lx0<0)
  {
   if((lx1-lx0)>CHKMAX_X) return TRUE;
  }
 if(lx1<0)
  {
   if((lx0-lx1)>CHKMAX_X) return TRUE;
  }
 if(ly0<0)
  {
   if((ly1-ly0)>CHKMAX_Y) return TRUE;
  }
 if(ly1<0)
  {
   if((ly0-ly1)>CHKMAX_Y) return TRUE;
  }

 return FALSE;
}

// Pete's way: a very easy (and hopefully fast) approach for lines
// without sqrt... using a small float -> short cast trick :)

#define VERTEX_OFFX 0.2f
#define VERTEX_OFFY 0.2f

BOOL offsetline(void)           
{
 short x0,x1,y0,y1,dx,dy;float px,py;

 if(bDisplayNotSet)
  SetOGLDisplaySettings(1);

 if(!(dwActFixes&16))
  {
   lx0=(short)(((int)lx0<<SIGNSHIFT)>>SIGNSHIFT);
   lx1=(short)(((int)lx1<<SIGNSHIFT)>>SIGNSHIFT);
   ly0=(short)(((int)ly0<<SIGNSHIFT)>>SIGNSHIFT);
   ly1=(short)(((int)ly1<<SIGNSHIFT)>>SIGNSHIFT);

   if(CheckCoord2()) return TRUE;
  }

 x0 = (lx0 + PSXDisplay.CumulOffset.x)+1;
 x1 = (lx1 + PSXDisplay.CumulOffset.x)+1;
 y0 = (ly0 + PSXDisplay.CumulOffset.y)+1;
 y1 = (ly1 + PSXDisplay.CumulOffset.y)+1;
 
 dx=x1-x0;
 dy=y1-y0;
 
 if(dx>=0)
  {
   if(dy>=0)
    {
     px=0.5f;
          if(dx>dy) py=-0.5f;
     else if(dx<dy) py= 0.5f;
     else           py= 0.0f;
    }
   else
    {
     py=-0.5f;
     dy=-dy;
          if(dx>dy) px= 0.5f;
     else if(dx<dy) px=-0.5f;
     else           px= 0.0f;
    }
  }
 else
  {
   if(dy>=0)
    {
     py=0.5f;
     dx=-dx;
          if(dx>dy) px=-0.5f;
     else if(dx<dy) px= 0.5f;
     else           px= 0.0f;
    }
   else
    {
     px=-0.5f;
          if(dx>dy) py=-0.5f;
     else if(dx<dy) py= 0.5f;
     else           py= 0.0f;
    }
  } 
 
 vertex[0].x=(short)((float)x0-px);
 vertex[3].x=(short)((float)x0+py);
 
 vertex[0].y=(short)((float)y0-py);
 vertex[3].y=(short)((float)y0-px);
 
 vertex[1].x=(short)((float)x1-py);
 vertex[2].x=(short)((float)x1+px);

 vertex[1].y=(short)((float)y1+px);
 vertex[2].y=(short)((float)y1+py);

 if(vertex[0].x==vertex[3].x &&                        // ortho rect? done
    vertex[1].x==vertex[2].x &&
    vertex[0].y==vertex[1].y &&
    vertex[2].y==vertex[3].y) return FALSE;
 if(vertex[0].x==vertex[1].x &&
    vertex[2].x==vertex[3].x &&
    vertex[0].y==vertex[3].y &&
    vertex[1].y==vertex[2].y) return FALSE;

 vertex[0].x-=VERTEX_OFFX;                             // otherwise a small offset
 vertex[0].y-=VERTEX_OFFY;                             // to get better accuracy
 vertex[1].x-=VERTEX_OFFX;
 vertex[1].y-=VERTEX_OFFY;
 vertex[2].x-=VERTEX_OFFX;
 vertex[2].y-=VERTEX_OFFY;
 vertex[3].x-=VERTEX_OFFX;
 vertex[3].y-=VERTEX_OFFY;

 return FALSE;
}

///////////////////////////////////////////////////////// 

BOOL offset2(void)
{
 if(bDisplayNotSet)
  SetOGLDisplaySettings(1);

 if(!(dwActFixes&16))
  {
   lx0=(short)(((int)lx0<<SIGNSHIFT)>>SIGNSHIFT);
   lx1=(short)(((int)lx1<<SIGNSHIFT)>>SIGNSHIFT);
   ly0=(short)(((int)ly0<<SIGNSHIFT)>>SIGNSHIFT);
   ly1=(short)(((int)ly1<<SIGNSHIFT)>>SIGNSHIFT);

   if(CheckCoord2()) return TRUE;
  }

 vertex[0].x=lx0+PSXDisplay.CumulOffset.x;
 vertex[1].x=lx1+PSXDisplay.CumulOffset.x;
 vertex[0].y=ly0+PSXDisplay.CumulOffset.y;
 vertex[1].y=ly1+PSXDisplay.CumulOffset.y;

 return FALSE;
}

///////////////////////////////////////////////////////// 

BOOL offset3(void)
{
 if(bDisplayNotSet)
  SetOGLDisplaySettings(1);

 if(!(dwActFixes&16))
  {
   lx0=(short)(((int)lx0<<SIGNSHIFT)>>SIGNSHIFT);
   lx1=(short)(((int)lx1<<SIGNSHIFT)>>SIGNSHIFT);
   lx2=(short)(((int)lx2<<SIGNSHIFT)>>SIGNSHIFT);
   ly0=(short)(((int)ly0<<SIGNSHIFT)>>SIGNSHIFT);
   ly1=(short)(((int)ly1<<SIGNSHIFT)>>SIGNSHIFT);
   ly2=(short)(((int)ly2<<SIGNSHIFT)>>SIGNSHIFT);

   if(CheckCoord3()) return TRUE;
  }

 vertex[0].x=lx0+PSXDisplay.CumulOffset.x;
 vertex[1].x=lx1+PSXDisplay.CumulOffset.x;
 vertex[2].x=lx2+PSXDisplay.CumulOffset.x;
 vertex[0].y=ly0+PSXDisplay.CumulOffset.y;
 vertex[1].y=ly1+PSXDisplay.CumulOffset.y;
 vertex[2].y=ly2+PSXDisplay.CumulOffset.y;

 return FALSE;
}

///////////////////////////////////////////////////////// 

BOOL offset4(void)
{
 if(bDisplayNotSet)
  SetOGLDisplaySettings(1);

 if(!(dwActFixes&16))
  {
   lx0=(short)(((int)lx0<<SIGNSHIFT)>>SIGNSHIFT);
   lx1=(short)(((int)lx1<<SIGNSHIFT)>>SIGNSHIFT);
   lx2=(short)(((int)lx2<<SIGNSHIFT)>>SIGNSHIFT);
   lx3=(short)(((int)lx3<<SIGNSHIFT)>>SIGNSHIFT);
   ly0=(short)(((int)ly0<<SIGNSHIFT)>>SIGNSHIFT);
   ly1=(short)(((int)ly1<<SIGNSHIFT)>>SIGNSHIFT);
   ly2=(short)(((int)ly2<<SIGNSHIFT)>>SIGNSHIFT);
   ly3=(short)(((int)ly3<<SIGNSHIFT)>>SIGNSHIFT);

   if(CheckCoord4()) return TRUE;
  }

 vertex[0].x=lx0+PSXDisplay.CumulOffset.x;
 vertex[1].x=lx1+PSXDisplay.CumulOffset.x;
 vertex[2].x=lx2+PSXDisplay.CumulOffset.x;
 vertex[3].x=lx3+PSXDisplay.CumulOffset.x;
 vertex[0].y=ly0+PSXDisplay.CumulOffset.y;
 vertex[1].y=ly1+PSXDisplay.CumulOffset.y;
 vertex[2].y=ly2+PSXDisplay.CumulOffset.y;
 vertex[3].y=ly3+PSXDisplay.CumulOffset.y;

 return FALSE;
}

///////////////////////////////////////////////////////// 

void offsetST(void)
{
 if(bDisplayNotSet)
  SetOGLDisplaySettings(1);

 if(!(dwActFixes&16))
  {
   lx0=(short)(((int)lx0<<SIGNSHIFT)>>SIGNSHIFT);
   ly0=(short)(((int)ly0<<SIGNSHIFT)>>SIGNSHIFT);

   if(lx0<-512 && PSXDisplay.DrawOffset.x<=-512)
    lx0+=2048;

   if(ly0<-512 && PSXDisplay.DrawOffset.y<=-512)
    ly0+=2048;
  }

 ly1 = ly0;
 ly2 = ly3 = ly0+sprtH;
 lx3 = lx0;
 lx1 = lx2 = lx0+sprtW;

 vertex[0].x=lx0+PSXDisplay.CumulOffset.x;
 vertex[1].x=lx1+PSXDisplay.CumulOffset.x;
 vertex[2].x=lx2+PSXDisplay.CumulOffset.x;
 vertex[3].x=lx3+PSXDisplay.CumulOffset.x;
 vertex[0].y=ly0+PSXDisplay.CumulOffset.y;
 vertex[1].y=ly1+PSXDisplay.CumulOffset.y;
 vertex[2].y=ly2+PSXDisplay.CumulOffset.y;
 vertex[3].y=ly3+PSXDisplay.CumulOffset.y;
}

///////////////////////////////////////////////////////// 

void offsetScreenUpload(int Position)
{
 if(bDisplayNotSet)
  SetOGLDisplaySettings(1);

 if(Position==-1)
  {
   int lmdx,lmdy;

   lmdx=xrUploadArea.x0;
   lmdy=xrUploadArea.y0;

   lx0-=lmdx;
   ly0-=lmdy;
   lx1-=lmdx;
   ly1-=lmdy;
   lx2-=lmdx;
   ly2-=lmdy;
   lx3-=lmdx;
   ly3-=lmdy;
  }
 else
 if(Position)
  {
   lx0-=PSXDisplay.DisplayPosition.x;
   ly0-=PSXDisplay.DisplayPosition.y;
   lx1-=PSXDisplay.DisplayPosition.x;
   ly1-=PSXDisplay.DisplayPosition.y;
   lx2-=PSXDisplay.DisplayPosition.x;
   ly2-=PSXDisplay.DisplayPosition.y;
   lx3-=PSXDisplay.DisplayPosition.x;
   ly3-=PSXDisplay.DisplayPosition.y;
  }
 else
  {
   lx0-=PreviousPSXDisplay.DisplayPosition.x;
   ly0-=PreviousPSXDisplay.DisplayPosition.y;
   lx1-=PreviousPSXDisplay.DisplayPosition.x;
   ly1-=PreviousPSXDisplay.DisplayPosition.y;
   lx2-=PreviousPSXDisplay.DisplayPosition.x;
   ly2-=PreviousPSXDisplay.DisplayPosition.y;
   lx3-=PreviousPSXDisplay.DisplayPosition.x;
   ly3-=PreviousPSXDisplay.DisplayPosition.y;
  }

 vertex[0].x=lx0 + PreviousPSXDisplay.Range.x0;
 vertex[1].x=lx1 + PreviousPSXDisplay.Range.x0;
 vertex[2].x=lx2 + PreviousPSXDisplay.Range.x0;
 vertex[3].x=lx3 + PreviousPSXDisplay.Range.x0;
 vertex[0].y=ly0 + PreviousPSXDisplay.Range.y0;
 vertex[1].y=ly1 + PreviousPSXDisplay.Range.y0;
 vertex[2].y=ly2 + PreviousPSXDisplay.Range.y0;
 vertex[3].y=ly3 + PreviousPSXDisplay.Range.y0;

 if(iUseMask)
  {
   vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=gl_z;
   gl_z+=0.00004f;
  }
}
 
///////////////////////////////////////////////////////// 

void offsetBlk(void)
{
 if(bDisplayNotSet)
  SetOGLDisplaySettings(1);
                                            
 vertex[0].x=lx0-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0;
 vertex[1].x=lx1-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0;
 vertex[2].x=lx2-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0;
 vertex[3].x=lx3-PSXDisplay.GDrawOffset.x + PreviousPSXDisplay.Range.x0;
 vertex[0].y=ly0-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0;
 vertex[1].y=ly1-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0;
 vertex[2].y=ly2-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0;
 vertex[3].y=ly3-PSXDisplay.GDrawOffset.y + PreviousPSXDisplay.Range.y0;

 if(iUseMask)
  {
   vertex[0].z=vertex[1].z=vertex[2].z=vertex[3].z=gl_z;
   gl_z+=0.00004f;
  }
}

////////////////////////////////////////////////////////////////////////
// texture sow/tow calculations
////////////////////////////////////////////////////////////////////////

void assignTextureVRAMWrite(void)
{
#ifdef OWNSCALE

 vertex[0].sow=0.5f/ ST_FACVRAMX;
 vertex[0].tow=0.5f/ ST_FACVRAM;

 vertex[1].sow=(float)gl_ux[1]/ ST_FACVRAMX;
 vertex[1].tow=0.5f/ ST_FACVRAM;

 vertex[2].sow=(float)gl_ux[2]/ ST_FACVRAMX;
 vertex[2].tow=(float)gl_vy[2]/ ST_FACVRAM;

 vertex[3].sow=0.5f/ ST_FACVRAMX;
 vertex[3].tow=(float)gl_vy[3]/ ST_FACVRAM;

#else

 if(gl_ux[1]==255)
  {
   vertex[0].sow=(gl_ux[0]*255.99f)/255.0f;
   vertex[1].sow=(gl_ux[1]*255.99f)/255.0f;
   vertex[2].sow=(gl_ux[2]*255.99f)/255.0f;
   vertex[3].sow=(gl_ux[3]*255.99f)/255.0f;
  }
 else
  {
   vertex[0].sow=gl_ux[0];
   vertex[1].sow=gl_ux[1];
   vertex[2].sow=gl_ux[2];
   vertex[3].sow=gl_ux[3];
  }

 vertex[0].tow=gl_vy[0];
 vertex[1].tow=gl_vy[1];
 vertex[2].tow=gl_vy[2];
 vertex[3].tow=gl_vy[3];

#endif
}

GLuint  gLastTex=0;
GLuint  gLastFMode=(GLuint)-1;

///////////////////////////////////////////////////////// 

void assignTextureSprite(void)
{
 if(bUsingTWin)
  {
   vertex[0].sow=vertex[3].sow=(float)gl_ux[0]/TWin.UScaleFactor;
   vertex[1].sow=vertex[2].sow=(float)sSprite_ux2/TWin.UScaleFactor;
   vertex[0].tow=vertex[1].tow=(float)gl_vy[0]/TWin.VScaleFactor;
   vertex[2].tow=vertex[3].tow=(float)sSprite_vy2/TWin.VScaleFactor;
   gLastTex=gTexName;
  }
 else
  {
#ifdef OWNSCALE

   vertex[0].sow=vertex[3].sow=(float)gl_ux[0]     / ST_FACSPRITE;
   vertex[1].sow=vertex[2].sow=(float)sSprite_ux2  / ST_FACSPRITE;
   vertex[0].tow=vertex[1].tow=(float)gl_vy[0]     / ST_FACSPRITE;
   vertex[2].tow=vertex[3].tow=(float)sSprite_vy2  / ST_FACSPRITE;

#else
 
   vertex[0].sow=vertex[3].sow=gl_ux[0];
   vertex[1].sow=vertex[2].sow=sSprite_ux2;
   vertex[0].tow=vertex[1].tow=gl_vy[0];
   vertex[2].tow=vertex[3].tow=sSprite_vy2;

#endif

   if(iFilterType>2) 
    {
     if(gLastTex!=gTexName || gLastFMode!=0)
      {
       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glError();
       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glError();
       gLastTex=gTexName;gLastFMode=0;
      }
    }
  }

 if(usMirror & 0x1000) 
  {
   vertex[0].sow=vertex[1].sow;
   vertex[1].sow=vertex[2].sow=vertex[3].sow;
   vertex[3].sow=vertex[0].sow;
  }

 if(usMirror & 0x2000) 
  {
   vertex[0].tow=vertex[3].tow;
   vertex[2].tow=vertex[3].tow=vertex[1].tow;
   vertex[1].tow=vertex[0].tow;
  }

}

///////////////////////////////////////////////////////// 

void assignTexture3(void)
{
 if(bUsingTWin)
  {
   vertex[0].sow=(float)gl_ux[0]/TWin.UScaleFactor;
   vertex[0].tow=(float)gl_vy[0]/TWin.VScaleFactor;
   vertex[1].sow=(float)gl_ux[1]/TWin.UScaleFactor;
   vertex[1].tow=(float)gl_vy[1]/TWin.VScaleFactor;
   vertex[2].sow=(float)gl_ux[2]/TWin.UScaleFactor;
   vertex[2].tow=(float)gl_vy[2]/TWin.VScaleFactor;
   gLastTex=gTexName;
  }
 else
  {
#ifdef OWNSCALE
   vertex[0].sow=(float)gl_ux[0] / ST_FACTRI;
   vertex[0].tow=(float)gl_vy[0] / ST_FACTRI;
   vertex[1].sow=(float)gl_ux[1] / ST_FACTRI;

   vertex[1].tow=(float)gl_vy[1] / ST_FACTRI;
   vertex[2].sow=(float)gl_ux[2] / ST_FACTRI;
   vertex[2].tow=(float)gl_vy[2] / ST_FACTRI;
#else
   vertex[0].sow=gl_ux[0];
   vertex[0].tow=gl_vy[0];
   vertex[1].sow=gl_ux[1];
   vertex[1].tow=gl_vy[1];
   vertex[2].sow=gl_ux[2];
   vertex[2].tow=gl_vy[2];
#endif

   if(iFilterType>2) 
    {
     if(gLastTex!=gTexName || gLastFMode!=1)
      {
       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glError();
       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glError();
       gLastTex=gTexName;gLastFMode=1;
      }
    }

   if(iFilterType) 
    {
     float fxmin=256.0f,fxmax=0.0f,fymin=256.0f,fymax=0.0f;int i;
     for(i=0;i<3;i++)
      {
       if(vertex[i].sow<fxmin) fxmin=vertex[i].sow;
       if(vertex[i].tow<fymin) fymin=vertex[i].tow;
       if(vertex[i].sow>fxmax) fxmax=vertex[i].sow;
       if(vertex[i].tow>fymax) fymax=vertex[i].tow; 
      }

     for(i=0;i<3;i++)
      {
       if(vertex[i].sow==fxmin) vertex[i].sow+=ST_BFFACSORT;
       if(vertex[i].sow==fxmax) vertex[i].sow-=ST_BFFACSORT;
       if(vertex[i].tow==fymin) vertex[i].tow+=ST_BFFACSORT;
       if(vertex[i].tow==fymax) vertex[i].tow-=ST_BFFACSORT;
      }
    }
  }
}

///////////////////////////////////////////////////////// 

void assignTexture4(void)
{
 if(bUsingTWin)
  {
   vertex[0].sow=(float)gl_ux[0]/TWin.UScaleFactor;
   vertex[0].tow=(float)gl_vy[0]/TWin.VScaleFactor;
   vertex[1].sow=(float)gl_ux[1]/TWin.UScaleFactor;
   vertex[1].tow=(float)gl_vy[1]/TWin.VScaleFactor;
   vertex[2].sow=(float)gl_ux[2]/TWin.UScaleFactor;
   vertex[2].tow=(float)gl_vy[2]/TWin.VScaleFactor;
   vertex[3].sow=(float)gl_ux[3]/TWin.UScaleFactor;
   vertex[3].tow=(float)gl_vy[3]/TWin.VScaleFactor;
   gLastTex=gTexName;
  }
 else
  {
#ifdef OWNSCALE
   vertex[0].sow=(float)gl_ux[0] / ST_FAC;
   vertex[0].tow=(float)gl_vy[0] / ST_FAC;
   vertex[1].sow=(float)gl_ux[1] / ST_FAC;
   vertex[1].tow=(float)gl_vy[1] / ST_FAC;
   vertex[2].sow=(float)gl_ux[2] / ST_FAC;
   vertex[2].tow=(float)gl_vy[2] / ST_FAC;
   vertex[3].sow=(float)gl_ux[3] / ST_FAC;
   vertex[3].tow=(float)gl_vy[3] / ST_FAC;
#else
   vertex[0].sow=gl_ux[0];
   vertex[0].tow=gl_vy[0];
   vertex[1].sow=gl_ux[1];
   vertex[1].tow=gl_vy[1];
   vertex[2].sow=gl_ux[2];
   vertex[2].tow=gl_vy[2];
   vertex[3].sow=gl_ux[3];
   vertex[3].tow=gl_vy[3];
#endif

   if(iFilterType>2) 
    {
     if(gLastTex!=gTexName || gLastFMode!=1)
      {
       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glError();
       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glError();
       gLastTex=gTexName;gLastFMode=1;
      }
    }

   if(iFilterType) 
    {
     float fxmin=256.0f,fxmax=0.0f,fymin=256.0f,fymax=0.0f;int i;
     for(i=0;i<4;i++)
      {
       if(vertex[i].sow<fxmin) fxmin=vertex[i].sow;
       if(vertex[i].tow<fymin) fymin=vertex[i].tow;
       if(vertex[i].sow>fxmax) fxmax=vertex[i].sow;
       if(vertex[i].tow>fymax) fymax=vertex[i].tow; 
      }

     for(i=0;i<4;i++)
      {
       if(vertex[i].sow==fxmin) vertex[i].sow+=ST_BFFACSORT;
       if(vertex[i].sow==fxmax) vertex[i].sow-=ST_BFFACSORT;
       if(vertex[i].tow==fymin) vertex[i].tow+=ST_BFFACSORT;
       if(vertex[i].tow==fymax) vertex[i].tow-=ST_BFFACSORT;
      }
    }
  }
}

////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////
// render pos / buffers
////////////////////////////////////////////////////////////////////////

#define EqualRect(pr1,pr2) ((pr1)->left==(pr2)->left && (pr1)->top==(pr2)->top && (pr1)->right==(pr2)->right && (pr1)->bottom==(pr2)->bottom)

////////////////////////////////////////////////////////////////////////
// SetDisplaySettings: "simply" calcs the new drawing area and updates
//                     the ogl clipping (scissor) 

BOOL bSetClip=FALSE;

void SetOGLDisplaySettings(BOOL DisplaySet)
{
 static RECT rprev={0,0,0,0};
 static RECT rC   ={0,0,0,0};
 static int iOldX=0;
 static int iOldY=0;
 RECT r;float XS,YS;

 bDisplayNotSet = FALSE;

 //----------------------------------------------------// that's a whole screen upload
 if(!DisplaySet)
  {
   RECT rX;
   PSXDisplay.GDrawOffset.x=0;
   PSXDisplay.GDrawOffset.y=0;

   PSXDisplay.CumulOffset.x = PSXDisplay.DrawOffset.x+PreviousPSXDisplay.Range.x0;
   PSXDisplay.CumulOffset.y = PSXDisplay.DrawOffset.y+PreviousPSXDisplay.Range.y0;

   rprev.left=rprev.left+1;

   rX=rRatioRect;
   rX.top=iResY-(rRatioRect.top+rRatioRect.bottom);

   if(bSetClip || !EqualRect(&rC,&rX))
    {
     rC=rX;
     glScissor(rC.left,rC.top,rC.right,rC.bottom); glError();
     //LOGE("glscissor:%d %d %d %d",rC.left,rC.top,rC.right,rC.bottom);
     bSetClip=FALSE; 
    }
   return;
  }
 //----------------------------------------------------// 

 PSXDisplay.GDrawOffset.y = PreviousPSXDisplay.DisplayPosition.y;
 PSXDisplay.GDrawOffset.x = PreviousPSXDisplay.DisplayPosition.x;
 PSXDisplay.CumulOffset.x = PSXDisplay.DrawOffset.x - PSXDisplay.GDrawOffset.x+PreviousPSXDisplay.Range.x0;
 PSXDisplay.CumulOffset.y = PSXDisplay.DrawOffset.y - PSXDisplay.GDrawOffset.y+PreviousPSXDisplay.Range.y0;

 r.top   =PSXDisplay.DrawArea.y0 - PreviousPSXDisplay.DisplayPosition.y;
 r.bottom=PSXDisplay.DrawArea.y1 - PreviousPSXDisplay.DisplayPosition.y;

 if(r.bottom<0 || r.top>=PSXDisplay.DisplayMode.y)
  {
   r.top   =PSXDisplay.DrawArea.y0 - PSXDisplay.DisplayPosition.y;
   r.bottom=PSXDisplay.DrawArea.y1 - PSXDisplay.DisplayPosition.y;
  }

 r.left  =PSXDisplay.DrawArea.x0 - PreviousPSXDisplay.DisplayPosition.x;
 r.right =PSXDisplay.DrawArea.x1 - PreviousPSXDisplay.DisplayPosition.x;

 if(r.right<0 || r.left>=PSXDisplay.DisplayMode.x)
  {
   r.left  =PSXDisplay.DrawArea.x0 - PSXDisplay.DisplayPosition.x;
   r.right =PSXDisplay.DrawArea.x1 - PSXDisplay.DisplayPosition.x;
  }

 if(!bSetClip && EqualRect(&r,&rprev) &&
    iOldX == PSXDisplay.DisplayMode.x &&
    iOldY == PSXDisplay.DisplayMode.y)
  return;

 rprev = r;
 iOldX = PSXDisplay.DisplayMode.x;
 iOldY = PSXDisplay.DisplayMode.y;

 XS=(float)rRatioRect.right/(float)PSXDisplay.DisplayMode.x;
 YS=(float)rRatioRect.bottom/(float)PSXDisplay.DisplayMode.y;

 if(PreviousPSXDisplay.Range.x0)
  {
   short s=PreviousPSXDisplay.Range.x0+PreviousPSXDisplay.Range.x1;

   r.left+=PreviousPSXDisplay.Range.x0+1;

   r.right+=PreviousPSXDisplay.Range.x0;

   if(r.left>s)  r.left=s;
   if(r.right>s) r.right=s;
  }

 if(PreviousPSXDisplay.Range.y0)
  {
   short s=PreviousPSXDisplay.Range.y0+PreviousPSXDisplay.Range.y1;

   r.top+=PreviousPSXDisplay.Range.y0+1;
   r.bottom+=PreviousPSXDisplay.Range.y0;

   if(r.top>s)    r.top=s;
   if(r.bottom>s) r.bottom=s;
  }

 // Set the ClipArea variables to reflect the new screen,
 // offset from zero (since it is a new display buffer)
 r.left   = (int)(((float)(r.left))      *XS);
 r.top    = (int)(((float)(r.top))       *YS);
 r.right  = (int)(((float)(r.right  + 1))*XS);
 r.bottom = (int)(((float)(r.bottom + 1))*YS);

 // Limit clip area to the screen size
 if (r.left   > iResX)   r.left   = iResX;
 if (r.left   < 0)       r.left   = 0;
 if (r.top    > iResY)   r.top    = iResY;
 if (r.top    < 0)       r.top    = 0;
 if (r.right  > iResX)   r.right  = iResX;
 if (r.right  < 0)       r.right  = 0;
 if (r.bottom > iResY)   r.bottom = iResY;
 if (r.bottom < 0)       r.bottom = 0;

 r.right -=r.left;
 r.bottom-=r.top;
 r.top=iResY-(r.top+r.bottom);

 r.left+=rRatioRect.left;
 r.top -=rRatioRect.top;

 if(bSetClip || !EqualRect(&r,&rC))
  {
   glScissor(r.left,r.top,r.right,r.bottom); glError();

   rC=r;
   bSetClip=FALSE;
  }
}

////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////

