/*************************************************************************** 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 #ifdef _WINDOWS #include "stdafx.h" #include #include #include #include "externals.h" #include "gpu.h" #include "draw.h" #include "prim.h" #include "texture.h" #else #include "gpuExternals.h" #include "GPUPlugin.h" #include "gpuDraw.h" #include "gpuPrim.h" #include "gpuTexture.h" #include "gpuStdafx.h" #include #include #include #endif //#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 #ifdef _WINDOWS HDC dcGlobal=NULL; HWND hWWindow; #else void glBlendEquationEXT(GLenum mode); void glColorTableEXT(GLenum target, GLenum internalFormat, GLsizei width, GLenum format,GLenum type, const GLvoid *data); #endif // 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 long 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 //////////////////////////////////////////////////////////////////////// #ifdef _WINDOWS BOOL bSetupPixelFormat(HDC hDC) { int pixelformat; static PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd 1, // version number PFD_DRAW_TO_WINDOW | // support window PFD_SUPPORT_OPENGL | // support OpenGL PFD_DOUBLEBUFFER, // double buffered PFD_TYPE_RGBA, // RGBA type 16, // 16-bit color depth (adjusted later) 0, 0, 0, 0, 0, 0, // color bits ignored 0, // no alpha buffer 0, // shift bit ignored 0, // no accumulation buffer 0, 0, 0, 0, // accum bits ignored 0, // z-buffer 0, 0, // no auxiliary buffer PFD_MAIN_PLANE, // main layer 0, // reserved 0, 0, 0 // layer masks ignored }; pfd.cColorBits=iColDepth; // set user color depth pfd.cDepthBits=iZBufferDepth; // set user zbuffer (by psx mask) if((pixelformat=ChoosePixelFormat(hDC,&pfd))==0) { MessageBox(NULL,"ChoosePixelFormat failed","Error",MB_OK); return FALSE; } if(SetPixelFormat(hDC,pixelformat, &pfd)==FALSE) { MessageBox(NULL,"SetPixelFormat failed","Error",MB_OK); return FALSE; } return TRUE; } #endif //////////////////////////////////////////////////////////////////////// // Get extension infos (f.e. pal textures / packed pixels) //////////////////////////////////////////////////////////////////////// void GetExtInfos(void) { BOOL bPacked=FALSE; // default: no packed pixel support if(strstr((s8 *)glGetString(GL_EXTENSIONS), // packed pixels available? "GL_EXT_packed_pixels")) bPacked=TRUE; // -> ok #ifdef _WINDOWS iClampType=GL_CLAMP; #else iClampType=GL_CLAMP_TO_EDGE; #endif } //////////////////////////////////////////////////////////////////////// // 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); } 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); } else // no opaque mode? { TCF[0]=TCF[1]=P8RGBA; PalTexturedColourFn=P8RGBA; // -> init col func glAlphaFuncx(GL_NOTEQUAL,0); // --> set alpha func } //----------------------------------------------------// LoadSubTexFn=LoadSubTexturePageSort; // init load tex ptr bBlendEnable=FALSE; // init blending: off glDisable(GL_BLEND); 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 //////////////////////////////////////////////////////////////////////// #ifdef _WINDOWS HGLRC GLCONTEXT=NULL; #endif #ifdef MAEMO_CHANGES 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 (%d).\n", pszLocation, iErr); return false; } return true; } void maemoGLinit(){ iResX= 800; iResY =480; printf ("maemo GL init\n"); long int winxid=GDK_WINDOW_XID(GTK_WIDGET(windowG)->window); printf ("%d\n",winxid); EGLContext context = 0; EGLConfig eglConfig = 0; EGLContext eglContext = 0; display = eglGetDisplay( EGL_DEFAULT_DISPLAY ); if( eglInitialize( display, NULL, NULL ) == EGL_FALSE ) { printf( "EGL Initialize failed!\n" ); } const EGLint attributeList[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, /*EGL_BUFFER_SIZE, 32, */ EGL_NONE }; EGLint pi32ConfigAttribs[5]; pi32ConfigAttribs[0] = EGL_SURFACE_TYPE; pi32ConfigAttribs[1] = EGL_WINDOW_BIT; pi32ConfigAttribs[2] = EGL_RENDERABLE_TYPE; pi32ConfigAttribs[3] = EGL_OPENGL_ES2_BIT; pi32ConfigAttribs[4] = EGL_NONE; EGLint pi32ContextAttribs[3]; pi32ContextAttribs[0] = EGL_CONTEXT_CLIENT_VERSION; pi32ContextAttribs[1] = 2; pi32ContextAttribs[2] = EGL_NONE; int iConfigs; if (!eglChooseConfig(display, attributeList, &eglConfig, 1, &iConfigs) || (iConfigs != 1)) { printf("Error: eglChooseConfig() failed.\n"); } printf ("%d\n",iConfigs); surface = eglCreateWindowSurface(display, eglConfig, (void*)winxid, NULL); printf ("%d\n",surface); if (!TestEGLError("eglCreateWindowSurface")) { printf ("eglCreateWindowSurface fail"); } //context = eglCreateContext(display, eglConfig, NULL, pi32ContextAttribs); context =eglCreateContext( display, eglConfig, EGL_NO_CONTEXT, NULL ); printf ("%d\n",context); if (!TestEGLError("eglCreateContext")) { printf("error eglCreateContext"); } eglMakeCurrent(display, surface, surface, context); if (!TestEGLError("eglMakeCurrent")) { printf("error eglMakeCurrent"); } } #endif int GLinitialize() { //----------------------------------------------------// #ifdef _WINDOWS HGLRC objectRC; // init dcGlobal = GetDC(hWWindow); // FIRST: dc/rc stuff objectRC = wglCreateContext(dcGlobal); GLCONTEXT=objectRC; wglMakeCurrent(dcGlobal, objectRC); // CheckWGLExtensions(dcGlobal); if(bWindowMode) ReleaseDC(hWWindow,dcGlobal); // win mode: release dc again #endif #ifdef MAEMO_CHANGES maemoGLinit(); #endif //----------------------------------------------------// glViewport(rRatioRect.left, // init viewport by ratio rect iResY-(rRatioRect.top+rRatioRect.bottom), rRatioRect.right, rRatioRect.bottom); glScissor(0, 0, iResX, iResY); // init clipping (fullscreen) glEnable(GL_SCISSOR_TEST); #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 glMatrixMode(GL_PROJECTION); // init projection with psx resolution glLoadIdentity(); glOrtho(0,PSXDisplay.DisplayMode.x, PSXDisplay.DisplayMode.y, 0, -1, 1); if(iZBufferDepth) // zbuffer? { uiBufferBits=GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT; glEnable(GL_DEPTH_TEST); glDepthFunc(GL_ALWAYS); iDepthFunc=1; } else // no zbuffer? { uiBufferBits=GL_COLOR_BUFFER_BIT; glDisable(GL_DEPTH_TEST); } glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // first buffer clear glClear(uiBufferBits); GetExtInfos(); // get ext infos SetExtGLFuncs(); // init all kind of stuff (tex function pointers) glEnable(GL_ALPHA_TEST); // wanna alpha test { glDisable(GL_LINE_SMOOTH); glDisable(GL_POINT_SMOOTH); } 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); glDisable(GL_FOG); // turn all (currently) unused modes off glDisable(GL_LIGHTING); glDisable(GL_STENCIL_TEST); glDisable(GL_TEXTURE_2D); glDisable(GL_CULL_FACE); glFlush(); // we are done... glFinish(); 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 #ifdef _WINDOWS wglMakeCurrent(NULL, NULL); // bye context if(GLCONTEXT) wglDeleteContext(GLCONTEXT); if(!bWindowMode && dcGlobal) ReleaseDC(hWWindow,dcGlobal); #endif } //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// // 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 __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; } __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; } __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); lx1=(short)(((int)lx1<>SIGNSHIFT); ly0=(short)(((int)ly0<>SIGNSHIFT); ly1=(short)(((int)ly1<>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(dxdy) px= 0.5f; else if(dx=0) { py=0.5f; dx=-dx; if(dx>dy) px=-0.5f; else if(dxdy) py=-0.5f; else if(dx>SIGNSHIFT); lx1=(short)(((int)lx1<>SIGNSHIFT); ly0=(short)(((int)ly0<>SIGNSHIFT); ly1=(short)(((int)ly1<>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); lx1=(short)(((int)lx1<>SIGNSHIFT); lx2=(short)(((int)lx2<>SIGNSHIFT); ly0=(short)(((int)ly0<>SIGNSHIFT); ly1=(short)(((int)ly1<>SIGNSHIFT); ly2=(short)(((int)ly2<>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); lx1=(short)(((int)lx1<>SIGNSHIFT); lx2=(short)(((int)lx2<>SIGNSHIFT); lx3=(short)(((int)lx3<>SIGNSHIFT); ly0=(short)(((int)ly0<>SIGNSHIFT); ly1=(short)(((int)ly1<>SIGNSHIFT); ly2=(short)(((int)ly2<>SIGNSHIFT); ly3=(short)(((int)ly3<>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); ly0=(short)(((int)ly0<>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(long Position) { if(bDisplayNotSet) SetOGLDisplaySettings(1); if(Position==-1) { long 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); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 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); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 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].sowfxmax) 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); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 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].sowfxmax) 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 //////////////////////////////////////////////////////////////////////// #ifndef _WINDOWS #define EqualRect(pr1,pr2) ((pr1)->left==(pr2)->left && (pr1)->top==(pr2)->top && (pr1)->right==(pr2)->right && (pr1)->bottom==(pr2)->bottom) #endif //////////////////////////////////////////////////////////////////////// // 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); 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); rC=r; bSetClip=FALSE; } } //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////