Path: blob/master/libmupen64plus/mupen64plus-video-glide64mk2/src/Glitch64/glitchmain.cpp
2 views
/*1* Glide64 - Glide video plugin for Nintendo 64 emulators.2* Copyright (c) 2002 Dave20013* Copyright (c) 2003-2009 Sergey 'Gonetz' Lipski4*5* This program is free software; you can redistribute it and/or modify6* it under the terms of the GNU General Public License as published by7* the Free Software Foundation; either version 2 of the License, or8* any later version.9*10* This program is distributed in the hope that it will be useful,11* but WITHOUT ANY WARRANTY; without even the implied warranty of12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the13* GNU General Public License for more details.14*15* You should have received a copy of the GNU General Public License16* along with this program; if not, write to the Free Software17* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA18*/1920#define SAVE_CBUFFER2122#ifdef _WIN3223#include <windows.h>24#include <commctrl.h>25#else26#include <stdint.h>27#include <stdarg.h>28#include <string.h>29#include <SDL.h>30#endif // _WIN3231#include <stdlib.h>32#include <stdio.h>33#include <iostream>34#include <fstream>35#include <math.h>36#include "glide.h"37#include "g3ext.h"38#include "main.h"39#include "m64p.h"4041#ifdef VPDEBUG42#include <IL/il.h>43#endif4445extern void (*renderCallback)(int);4647wrapper_config config = {0, 0, 0, 0};48int screen_width, screen_height;4950static inline void opt_glCopyTexImage2D( GLenum target,51GLint level,52GLenum internalFormat,53GLint x,54GLint y,55GLsizei width,56GLsizei height,57GLint border )5859{60int w, h, fmt;61glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);62glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);63glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt);64//printf("copyteximage %dx%d fmt %x oldfmt %x\n", width, height, internalFormat, fmt);65if (w == (int) width && h == (int) height && fmt == (int) internalFormat) {66if (x+width >= screen_width) {67width = screen_width - x;68//printf("resizing w --> %d\n", width);69}70if (y+height >= screen_height+viewport_offset) {71height = screen_height+viewport_offset - y;72//printf("resizing h --> %d\n", height);73}74glCopyTexSubImage2D(target, level, 0, 0, x, y, width, height);75} else {76//printf("copyteximage %dx%d fmt %x old %dx%d oldfmt %x\n", width, height, internalFormat, w, h, fmt);77// glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, internalFormat, GL_UNSIGNED_BYTE, 0);78// glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt);79// printf("--> %dx%d newfmt %x\n", width, height, fmt);80glCopyTexImage2D(target, level, internalFormat, x, y, width, height, border);81}82}83#define glCopyTexImage2D opt_glCopyTexImage2D848586#ifdef _WIN3287PFNGLACTIVETEXTUREARBPROC glActiveTextureARB;88PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT;89PFNGLMULTITEXCOORD2FARBPROC glMultiTexCoord2fARB;90PFNGLFOGCOORDFPROC glFogCoordfEXT;9192PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB;9394PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT;95PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT;96PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT;97PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT = NULL;98PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT = NULL;99PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT = NULL;100PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT = NULL;101PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT = NULL;102PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT;103PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT;104105PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB;106PFNGLSHADERSOURCEARBPROC glShaderSourceARB;107PFNGLCOMPILESHADERARBPROC glCompileShaderARB;108PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB;109PFNGLATTACHOBJECTARBPROC glAttachObjectARB;110PFNGLLINKPROGRAMARBPROC glLinkProgramARB;111PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB;112PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB;113PFNGLUNIFORM1IARBPROC glUniform1iARB;114PFNGLUNIFORM4IARBPROC glUniform4iARB;115PFNGLUNIFORM4FARBPROC glUniform4fARB;116PFNGLUNIFORM1FARBPROC glUniform1fARB;117PFNGLDELETEOBJECTARBPROC glDeleteObjectARB;118PFNGLGETINFOLOGARBPROC glGetInfoLogARB;119PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB;120PFNGLSECONDARYCOLOR3FPROC glSecondaryColor3f;121122// FXT1,DXT1,DXT5 support - Hiroshi Morii <koolsmoky(at)users.sourceforge.net>123// NOTE: Glide64 + GlideHQ use the following formats124// GL_COMPRESSED_RGB_S3TC_DXT1_EXT125// GL_COMPRESSED_RGBA_S3TC_DXT5_EXT126// GL_COMPRESSED_RGB_FXT1_3DFX127// GL_COMPRESSED_RGBA_FXT1_3DFX128PFNGLCOMPRESSEDTEXIMAGE2DPROC glCompressedTexImage2DARB;129#endif // _WIN32130131132133typedef struct134{135unsigned int address;136int width;137int height;138unsigned int fbid;139unsigned int zbid;140unsigned int texid;141int buff_clear;142} fb;143144int nbTextureUnits;145int nbAuxBuffers, current_buffer;146int width, widtho, heighto, height;147int saved_width, saved_height;148int blend_func_separate_support;149int npot_support;150int fog_coord_support;151int render_to_texture = 0;152int texture_unit;153int use_fbo;154int buffer_cleared;155// ZIGGY156// to allocate a new static texture name, take the value (free_texture++)157int free_texture;158int default_texture; // the infamous "32*1024*1024" is now configurable159int current_texture;160int depth_texture, color_texture;161int glsl_support = 1;162int viewport_width, viewport_height, viewport_offset = 0, nvidia_viewport_hack = 0;163int save_w, save_h;164int lfb_color_fmt;165float invtex[2];166//Gonetz167int UMAmode = 0; //support for VSA-100 UMA mode;168169#ifdef _WIN32170static HDC hDC = NULL;171static HGLRC hGLRC = NULL;172static HWND hToolBar = NULL;173static HWND hwnd_win = NULL;174static unsigned long windowedExStyle, windowedStyle;175#endif // _WIN32176static unsigned long fullscreen;177#ifdef _WIN32178static RECT windowedRect;179static HMENU windowedMenu;180#endif // _WIN32181182static int savedWidtho, savedHeighto;183static int savedWidth, savedHeight;184unsigned int pBufferAddress;185static int pBufferFmt;186static int pBufferWidth, pBufferHeight;187static fb fbs[100];188static int nb_fb = 0;189static unsigned int curBufferAddr = 0;190191struct TMU_USAGE { int min, max; } tmu_usage[2] = { {0xfffffff, 0}, {0xfffffff, 0} };192193struct texbuf_t {194FxU32 start, end;195int fmt;196};197#define NB_TEXBUFS 128 // MUST be a power of two198static texbuf_t texbufs[NB_TEXBUFS];199static int texbuf_i;200201unsigned short *frameBuffer = NULL;202unsigned short *depthBuffer = NULL;203204//#define VOODOO1205206void display_warning(const char *text, ...)207{208static int first_message = 100;209if (first_message)210{211char buf[1000];212213va_list ap;214215va_start(ap, text);216vsprintf(buf, text, ap);217va_end(ap);218first_message--;219}220}221222#ifdef _WIN32223void display_error()224{225LPVOID lpMsgBuf;226if (!FormatMessage(227FORMAT_MESSAGE_ALLOCATE_BUFFER |228FORMAT_MESSAGE_FROM_SYSTEM |229FORMAT_MESSAGE_IGNORE_INSERTS,230NULL,231GetLastError(),232MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language233(LPTSTR) &lpMsgBuf,2340,235NULL ))236{237// Handle the error.238return;239}240// Process any inserts in lpMsgBuf.241// ...242// Display the string.243MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );244245// Free the buffer.246LocalFree( lpMsgBuf );247}248#endif // _WIN32249250#ifdef LOGGING251char out_buf[256];252bool log_open = false;253std::ofstream log_file;254255void OPEN_LOG()256{257if (!log_open)258{259log_file.open ("wrapper_log.txt", std::ios_base::out|std::ios_base::app);260log_open = true;261}262}263264void CLOSE_LOG()265{266if (log_open)267{268log_file.close();269log_open = false;270}271}272273void LOG(const char *text, ...)274{275#ifdef VPDEBUG276if (!dumping) return;277#endif278if (!log_open)279return;280va_list ap;281va_start(ap, text);282vsprintf(out_buf, text, ap);283log_file << out_buf;284log_file.flush();285va_end(ap);286}287288class LogManager {289public:290LogManager() {291OPEN_LOG();292}293~LogManager() {294CLOSE_LOG();295}296};297298LogManager logManager;299300#else // LOGGING301#define OPEN_LOG()302#define CLOSE_LOG()303//#define LOG304#endif // LOGGING305306FX_ENTRY void FX_CALL307grSstOrigin(GrOriginLocation_t origin)308{309LOG("grSstOrigin(%d)\r\n", origin);310if (origin != GR_ORIGIN_UPPER_LEFT)311display_warning("grSstOrigin : %x", origin);312}313314FX_ENTRY void FX_CALL315grClipWindow( FxU32 minx, FxU32 miny, FxU32 maxx, FxU32 maxy )316{317LOG("grClipWindow(%d,%d,%d,%d)\r\n", minx, miny, maxx, maxy);318319if (use_fbo && render_to_texture) {320if (int(minx) < 0) minx = 0;321if (int(miny) < 0) miny = 0;322if (maxx < minx) maxx = minx;323if (maxy < miny) maxy = miny;324glScissor(minx, miny, maxx - minx, maxy - miny);325glEnable(GL_SCISSOR_TEST);326return;327}328329if (!use_fbo) {330int th = height;331if (th > screen_height)332th = screen_height;333maxy = th - maxy;334miny = th - miny;335FxU32 tmp = maxy; maxy = miny; miny = tmp;336if (maxx > (FxU32) width) maxx = width;337if (maxy > (FxU32) height) maxy = height;338if (int(minx) < 0) minx = 0;339if (int(miny) < 0) miny = 0;340if (maxx < minx) maxx = minx;341if (maxy < miny) maxy = miny;342glScissor(minx, miny+viewport_offset, maxx - minx, maxy - miny);343//printf("gl scissor %d %d %d %d\n", minx, miny, maxx, maxy);344} else {345glScissor(minx, (viewport_offset)+height-maxy, maxx - minx, maxy - miny);346}347glEnable(GL_SCISSOR_TEST);348}349350FX_ENTRY void FX_CALL351grColorMask( FxBool rgb, FxBool a )352{353LOG("grColorMask(%d, %d)\r\n", rgb, a);354glColorMask(rgb, rgb, rgb, a);355}356357FX_ENTRY void FX_CALL358grGlideInit( void )359{360LOG("grGlideInit()\r\n");361}362363FX_ENTRY void FX_CALL364grSstSelect( int which_sst )365{366LOG("grSstSelect(%d)\r\n", which_sst);367}368369int isExtensionSupported(const char *extension)370{371const GLubyte *extensions = NULL;372const GLubyte *start;373GLubyte *where, *terminator;374375where = (GLubyte *)strchr(extension, ' ');376if (where || *extension == '\0')377return 0;378379extensions = glGetString(GL_EXTENSIONS);380381start = extensions;382for (;;)383{384where = (GLubyte *) strstr((const char *) start, extension);385if (!where)386break;387388terminator = where + strlen(extension);389if (where == start || *(where - 1) == ' ')390if (*terminator == ' ' || *terminator == '\0')391return 1;392393start = terminator;394}395396return 0;397}398399#ifdef _WIN32400int isWglExtensionSupported(const char *extension)401{402const GLubyte *extensions = NULL;403const GLubyte *start;404GLubyte *where, *terminator;405406where = (GLubyte *)strchr(extension, ' ');407if (where || *extension == '\0')408return 0;409410extensions = (GLubyte*)wglGetExtensionsStringARB(wglGetCurrentDC());411412start = extensions;413for (;;)414{415where = (GLubyte *) strstr((const char *) start, extension);416if (!where)417break;418419terminator = where + strlen(extension);420if (where == start || *(where - 1) == ' ')421if (*terminator == ' ' || *terminator == '\0')422return 1;423424start = terminator;425}426427return 0;428}429#endif // _WIN32430431#define GrPixelFormat_t int432433FX_ENTRY GrContext_t FX_CALL434grSstWinOpenExt(435HWND hWnd,436GrScreenResolution_t screen_resolution,437GrScreenRefresh_t refresh_rate,438GrColorFormat_t color_format,439GrOriginLocation_t origin_location,440GrPixelFormat_t pixelformat,441int nColBuffers,442int nAuxBuffers)443{444LOG("grSstWinOpenExt(%d, %d, %d, %d, %d, %d %d)\r\n", hWnd, screen_resolution, refresh_rate, color_format, origin_location, nColBuffers, nAuxBuffers);445return grSstWinOpen(hWnd, screen_resolution, refresh_rate, color_format,446origin_location, nColBuffers, nAuxBuffers);447}448449#ifdef WIN32450# include <fcntl.h>451# ifndef ATTACH_PARENT_PROCESS452# define ATTACH_PARENT_PROCESS ((FxU32)-1)453# endif454#endif455456FX_ENTRY GrContext_t FX_CALL457grSstWinOpen(458HWND hWnd,459GrScreenResolution_t screen_resolution,460GrScreenRefresh_t refresh_rate,461GrColorFormat_t color_format,462GrOriginLocation_t origin_location,463int nColBuffers,464int nAuxBuffers)465{466static int show_warning = 1;467468// ZIGGY469// allocate static texture names470// the initial value should be big enough to support the maximal resolution471free_texture = 32*2048*2048;472default_texture = free_texture++;473color_texture = free_texture++;474depth_texture = free_texture++;475476LOG("grSstWinOpen(%08lx, %d, %d, %d, %d, %d %d)\r\n", hWnd, screen_resolution&~0x80000000, refresh_rate, color_format, origin_location, nColBuffers, nAuxBuffers);477478#ifdef _WIN32479if ((HWND)hWnd == NULL) hWnd = GetActiveWindow();480hwnd_win = (HWND)hWnd;481#endif // _WIN32482width = height = 0;483484m64p_handle video_general_section;485printf("&ConfigOpenSection is %p\n", &ConfigOpenSection);486if (ConfigOpenSection("Video-General", &video_general_section) != M64ERR_SUCCESS)487{488printf("Could not open video settings");489return false;490}491width = ConfigGetParamInt(video_general_section, "ScreenWidth");492height = ConfigGetParamInt(video_general_section, "ScreenHeight");493fullscreen = ConfigGetParamBool(video_general_section, "Fullscreen");494int vsync = ConfigGetParamBool(video_general_section, "VerticalSync");495//viewport_offset = ((screen_resolution>>2) > 20) ? screen_resolution >> 2 : 20;496// ZIGGY viewport_offset is WIN32 specific, with SDL just set it to zero497viewport_offset = 0; //-10 //-20;498499frameBuffer = (unsigned short *)_aligned_malloc(height*width*4, 256);500depthBuffer = (unsigned short *)_aligned_malloc(height*width*2, 256);501502// ZIGGY not sure, but it might be better to let the system choose503CoreVideo_GL_SetAttribute(M64P_GL_DOUBLEBUFFER, 1);504CoreVideo_GL_SetAttribute(M64P_GL_SWAP_CONTROL, vsync);505CoreVideo_GL_SetAttribute(M64P_GL_BUFFER_SIZE, 16);506// SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32);507// SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);508// SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);509// SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);510// SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);511CoreVideo_GL_SetAttribute(M64P_GL_DEPTH_SIZE, 16);512513printf("(II) Setting video mode %dx%d...\n", width, height);514if(CoreVideo_SetVideoMode(width, height, 0, fullscreen ? M64VIDEO_FULLSCREEN : M64VIDEO_WINDOWED, (m64p_video_flags) 0) != M64ERR_SUCCESS)515{516printf("(EE) Error setting videomode %dx%d\n", width, height);517return false;518}519520char caption[500];521# ifdef _DEBUG522sprintf(caption, "Glide64mk2 debug");523# else // _DEBUG524sprintf(caption, "Glide64mk2");525# endif // _DEBUG526CoreVideo_SetCaption(caption);527528glViewport(0, viewport_offset, width, height);529lfb_color_fmt = color_format;530if (origin_location != GR_ORIGIN_UPPER_LEFT) display_warning("origin must be in upper left corner");531if (nColBuffers != 2) display_warning("number of color buffer is not 2");532if (nAuxBuffers != 1) display_warning("number of auxiliary buffer is not 1");533534if (isExtensionSupported("GL_ARB_texture_env_combine") == 0 &&535isExtensionSupported("GL_EXT_texture_env_combine") == 0 &&536show_warning)537display_warning("Your video card doesn't support GL_ARB_texture_env_combine extension");538if (isExtensionSupported("GL_ARB_multitexture") == 0 && show_warning)539display_warning("Your video card doesn't support GL_ARB_multitexture extension");540if (isExtensionSupported("GL_ARB_texture_mirrored_repeat") == 0 && show_warning)541display_warning("Your video card doesn't support GL_ARB_texture_mirrored_repeat extension");542show_warning = 0;543544#ifdef _WIN32545glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC)wglGetProcAddress("glActiveTextureARB");546glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FARBPROC)wglGetProcAddress("glMultiTexCoord2fARB");547#endif // _WIN32548549nbTextureUnits = 0;550glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &nbTextureUnits);551if (nbTextureUnits == 1) display_warning("You need a video card that has at least 2 texture units");552553nbAuxBuffers = 0;554glGetIntegerv(GL_AUX_BUFFERS, &nbAuxBuffers);555if (nbAuxBuffers > 0)556printf("Congratulations, you have %d auxilliary buffers, we'll use them wisely !\n", nbAuxBuffers);557558#ifdef VOODOO1559nbTextureUnits = 2;560#endif561562if (isExtensionSupported("GL_EXT_blend_func_separate") == 0)563blend_func_separate_support = 0;564else565blend_func_separate_support = 1;566567if (isExtensionSupported("GL_EXT_packed_pixels") == 0)568packed_pixels_support = 0;569else {570printf("packed pixels extension used\n");571packed_pixels_support = 1;572}573574if (isExtensionSupported("GL_ARB_texture_non_power_of_two") == 0)575npot_support = 0;576else {577printf("NPOT extension used\n");578npot_support = 1;579}580581#ifdef _WIN32582glBlendFuncSeparateEXT = (PFNGLBLENDFUNCSEPARATEEXTPROC)wglGetProcAddress("glBlendFuncSeparateEXT");583#endif // _WIN32584585if (isExtensionSupported("GL_EXT_fog_coord") == 0)586fog_coord_support = 0;587else588fog_coord_support = 1;589590#ifdef _WIN32591glFogCoordfEXT = (PFNGLFOGCOORDFPROC)wglGetProcAddress("glFogCoordfEXT");592#endif // _WIN32593594#ifdef _WIN32595wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB");596#endif // _WIN32597598#ifdef _WIN32599glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC)wglGetProcAddress("glBindFramebufferEXT");600glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)wglGetProcAddress("glFramebufferTexture2DEXT");601glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC)wglGetProcAddress("glGenFramebuffersEXT");602glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)wglGetProcAddress("glCheckFramebufferStatusEXT");603glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC)wglGetProcAddress("glDeleteFramebuffersEXT");604605glBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC)wglGetProcAddress("glBindRenderbufferEXT");606glDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC)wglGetProcAddress("glDeleteRenderbuffersEXT");607glGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC)wglGetProcAddress("glGenRenderbuffersEXT");608glRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC)wglGetProcAddress("glRenderbufferStorageEXT");609glFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)wglGetProcAddress("glFramebufferRenderbufferEXT");610use_fbo = config.fbo && (glFramebufferRenderbufferEXT != NULL);611#else612use_fbo = config.fbo;613#endif // _WIN32614615printf("use_fbo %d\n", use_fbo);616617if (isExtensionSupported("GL_ARB_shading_language_100") &&618isExtensionSupported("GL_ARB_shader_objects") &&619isExtensionSupported("GL_ARB_fragment_shader") &&620isExtensionSupported("GL_ARB_vertex_shader"))621{622623#ifdef _WIN32624glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC)wglGetProcAddress("glCreateShaderObjectARB");625glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC)wglGetProcAddress("glShaderSourceARB");626glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC)wglGetProcAddress("glCompileShaderARB");627glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC)wglGetProcAddress("glCreateProgramObjectARB");628glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC)wglGetProcAddress("glAttachObjectARB");629glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC)wglGetProcAddress("glLinkProgramARB");630glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC)wglGetProcAddress("glUseProgramObjectARB");631glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC)wglGetProcAddress("glGetUniformLocationARB");632glUniform1iARB = (PFNGLUNIFORM1IARBPROC)wglGetProcAddress("glUniform1iARB");633glUniform4iARB = (PFNGLUNIFORM4IARBPROC)wglGetProcAddress("glUniform4iARB");634glUniform4fARB = (PFNGLUNIFORM4FARBPROC)wglGetProcAddress("glUniform4fARB");635glUniform1fARB = (PFNGLUNIFORM1FARBPROC)wglGetProcAddress("glUniform1fARB");636glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC)wglGetProcAddress("glDeleteObjectARB");637glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC)wglGetProcAddress("glGetInfoLogARB");638glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC)wglGetProcAddress("glGetObjectParameterivARB");639640glSecondaryColor3f = (PFNGLSECONDARYCOLOR3FPROC)wglGetProcAddress("glSecondaryColor3f");641#endif // _WIN32642}643644if (isExtensionSupported("GL_EXT_texture_compression_s3tc") == 0 && show_warning)645display_warning("Your video card doesn't support GL_EXT_texture_compression_s3tc extension");646if (isExtensionSupported("GL_3DFX_texture_compression_FXT1") == 0 && show_warning)647display_warning("Your video card doesn't support GL_3DFX_texture_compression_FXT1 extension");648649#ifdef _WIN32650glCompressedTexImage2DARB = (PFNGLCOMPRESSEDTEXIMAGE2DPROC)wglGetProcAddress("glCompressedTexImage2DARB");651#endif652653654#ifdef _WIN32655glViewport(0, viewport_offset, width, height);656viewport_width = width;657viewport_height = height;658nvidia_viewport_hack = 1;659#else660glViewport(0, viewport_offset, width, height);661viewport_width = width;662viewport_height = height;663#endif // _WIN32664665// void do_benchmarks();666// do_benchmarks();667668// VP try to resolve z precision issues669glMatrixMode(GL_MODELVIEW);670glLoadIdentity();671glTranslatef(0, 0, 1-zscale);672glScalef(1, 1, zscale);673674widtho = width/2;675heighto = height/2;676677pBufferWidth = pBufferHeight = -1;678679current_buffer = GL_BACK;680681texture_unit = GL_TEXTURE0_ARB;682683{684int i;685for (i=0; i<NB_TEXBUFS; i++)686texbufs[i].start = texbufs[i].end = 0xffffffff;687}688689if (!use_fbo && nbAuxBuffers == 0) {690// create the framebuffer saving texture691int w = width, h = height;692glBindTexture(GL_TEXTURE_2D, color_texture);693if (!npot_support) {694w = h = 1;695while (w<width) w*=2;696while (h<height) h*=2;697}698glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);699glBindTexture(GL_TEXTURE_2D, 0);700save_w = save_h = 0;701}702703void FindBestDepthBias();704FindBestDepthBias();705706init_geometry();707init_textures();708init_combiner();709710// Aniso filter check711if (config.anisofilter > 0 )712glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_supported_anisotropy);713714// ATI hack - certain texture formats are slow on ATI?715// Hmm, perhaps the internal format need to be specified explicitly...716{717GLint ifmt;718glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, NULL);719glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &ifmt);720if (ifmt != GL_RGB5_A1) {721display_warning("ATI SUCKS %x\n", ifmt);722ati_sucks = 1;723} else724ati_sucks = 0;725}726727return 1;728}729730FX_ENTRY void FX_CALL731grGlideShutdown( void )732{733LOG("grGlideShutdown\r\n");734}735736FX_ENTRY FxBool FX_CALL737grSstWinClose( GrContext_t context )738{739int i, clear_texbuff = use_fbo;740LOG("grSstWinClose(%d)\r\n", context);741742for (i=0; i<2; i++) {743tmu_usage[i].min = 0xfffffff;744tmu_usage[i].max = 0;745invtex[i] = 0;746}747748if (frameBuffer)749_aligned_free(frameBuffer);750if (depthBuffer)751_aligned_free(depthBuffer);752frameBuffer = depthBuffer = NULL;753754free_combiners();755#ifndef WIN32756try // I don't know why, but opengl can be killed before this function call when emulator is closed (Gonetz).757// ZIGGY : I found the problem : it is a function pointer, when the extension isn't supported , it is then zero, so just need to check the pointer prior to do the call.758{759if (use_fbo)760glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );761}762catch (...)763{764clear_texbuff = 0;765}766767if (clear_texbuff)768{769for (i=0; i<nb_fb; i++)770{771glDeleteTextures( 1, &(fbs[i].texid) );772glDeleteFramebuffersEXT( 1, &(fbs[i].fbid) );773glDeleteRenderbuffersEXT( 1, &(fbs[i].zbid) );774}775}776#endif777nb_fb = 0;778779free_textures();780#ifndef WIN32781// ZIGGY for some reasons, Pj64 doesn't like remove_tex on exit782remove_tex(0, 0xfffffff);783#endif784785//*/786#ifdef _WIN32787if (hGLRC)788{789wglMakeCurrent(hDC,NULL);790wglDeleteContext(hGLRC);791hGLRC = NULL;792}793if (fullscreen)794{795ChangeDisplaySettings(NULL, 0);796SetWindowPos(hwnd_win, NULL,797windowedRect.left, windowedRect.top,7980, 0,799SWP_NOZORDER | SWP_NOSIZE);800SetWindowLong(hwnd_win, GWL_STYLE, windowedStyle);801SetWindowLong(hwnd_win, GWL_EXSTYLE, windowedExStyle);802if (windowedMenu) SetMenu(hwnd_win, windowedMenu);803fullscreen = 0;804}805#else806//SDL_QuitSubSystem(SDL_INIT_VIDEO);807//sleep(2);808#endif809return FXTRUE;810}811812FX_ENTRY void FX_CALL grTextureBufferExt( GrChipID_t tmu,813FxU32 startAddress,814GrLOD_t lodmin,815GrLOD_t lodmax,816GrAspectRatio_t aspect,817GrTextureFormat_t fmt,818FxU32 evenOdd)819{820int i;821static int fbs_init = 0;822823//printf("grTextureBufferExt(%d, %d, %d, %d, %d, %d, %d)\r\n", tmu, startAddress, lodmin, lodmax, aspect, fmt, evenOdd);824LOG("grTextureBufferExt(%d, %d, %d, %d %d, %d, %d)\r\n", tmu, startAddress, lodmin, lodmax, aspect, fmt, evenOdd);825if (lodmin != lodmax) display_warning("grTextureBufferExt : loading more than one LOD");826if (!use_fbo) {827828if (!render_to_texture) { //initialization829return;830}831832render_to_texture = 2;833834if (aspect < 0)835{836pBufferHeight = 1 << lodmin;837pBufferWidth = pBufferHeight >> -aspect;838}839else840{841pBufferWidth = 1 << lodmin;842pBufferHeight = pBufferWidth >> aspect;843}844845if (curBufferAddr && startAddress+1 != curBufferAddr)846updateTexture();847#ifdef SAVE_CBUFFER848//printf("saving %dx%d\n", pBufferWidth, pBufferHeight);849// save color buffer850if (nbAuxBuffers > 0) {851glDrawBuffer(GL_AUX0);852current_buffer = GL_AUX0;853} else {854int tw, th;855if (pBufferWidth < screen_width)856tw = pBufferWidth;857else858tw = screen_width;859if (pBufferHeight < screen_height)860th = pBufferHeight;861else862th = screen_height;863glReadBuffer(GL_BACK);864glActiveTextureARB(texture_unit);865glBindTexture(GL_TEXTURE_2D, color_texture);866// save incrementally the framebuffer867if (save_w) {868if (tw > save_w && th > save_h) {869glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, save_h,8700, viewport_offset+save_h, tw, th-save_h);871glCopyTexSubImage2D(GL_TEXTURE_2D, 0, save_w, 0,872save_w, viewport_offset, tw-save_w, save_h);873save_w = tw;874save_h = th;875} else if (tw > save_w) {876glCopyTexSubImage2D(GL_TEXTURE_2D, 0, save_w, 0,877save_w, viewport_offset, tw-save_w, save_h);878save_w = tw;879} else if (th > save_h) {880glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, save_h,8810, viewport_offset+save_h, save_w, th-save_h);882save_h = th;883}884} else {885glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,8860, viewport_offset, tw, th);887save_w = tw;888save_h = th;889}890glBindTexture(GL_TEXTURE_2D, default_texture);891}892#endif893894if (startAddress+1 != curBufferAddr ||895(curBufferAddr == 0L && nbAuxBuffers == 0))896buffer_cleared = 0;897898curBufferAddr = pBufferAddress = startAddress+1;899pBufferFmt = fmt;900901int rtmu = startAddress < grTexMinAddress(GR_TMU1)? 0 : 1;902int size = pBufferWidth*pBufferHeight*2; //grTexFormatSize(fmt);903if ((unsigned int) tmu_usage[rtmu].min > pBufferAddress)904tmu_usage[rtmu].min = pBufferAddress;905if ((unsigned int) tmu_usage[rtmu].max < pBufferAddress+size)906tmu_usage[rtmu].max = pBufferAddress+size;907// printf("tmu %d usage now %gMb - %gMb\n",908// rtmu, tmu_usage[rtmu].min/1024.0f, tmu_usage[rtmu].max/1024.0f);909910911width = pBufferWidth;912height = pBufferHeight;913914widtho = width/2;915heighto = height/2;916917// this could be improved, but might be enough as long as the set of918// texture buffer addresses stay small919for (i=(texbuf_i-1)&(NB_TEXBUFS-1) ; i!=texbuf_i; i=(i-1)&(NB_TEXBUFS-1))920if (texbufs[i].start == pBufferAddress)921break;922texbufs[i].start = pBufferAddress;923texbufs[i].end = pBufferAddress + size;924texbufs[i].fmt = fmt;925if (i == texbuf_i)926texbuf_i = (texbuf_i+1)&(NB_TEXBUFS-1);927//printf("texbuf %x fmt %x\n", pBufferAddress, fmt);928929// ZIGGY it speeds things up to not delete the buffers930// a better thing would be to delete them *sometimes*931// remove_tex(pBufferAddress+1, pBufferAddress + size);932add_tex(pBufferAddress);933934//printf("viewport %dx%d\n", width, height);935if (height > screen_height) {936glViewport( 0, viewport_offset + screen_height - height, width, height);937} else938glViewport( 0, viewport_offset, width, height);939940glScissor(0, viewport_offset, width, height);941942943} else {944if (!render_to_texture) //initialization945{946if(!fbs_init)947{948for(i=0; i<100; i++) fbs[i].address = 0;949fbs_init = 1;950nb_fb = 0;951}952return; //no need to allocate FBO if render buffer is not texture buffer953}954955render_to_texture = 2;956957if (aspect < 0)958{959pBufferHeight = 1 << lodmin;960pBufferWidth = pBufferHeight >> -aspect;961}962else963{964pBufferWidth = 1 << lodmin;965pBufferHeight = pBufferWidth >> aspect;966}967pBufferAddress = startAddress+1;968969width = pBufferWidth;970height = pBufferHeight;971972widtho = width/2;973heighto = height/2;974975for (i=0; i<nb_fb; i++)976{977if (fbs[i].address == pBufferAddress)978{979if (fbs[i].width == width && fbs[i].height == height) //select already allocated FBO980{981glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );982glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fbs[i].fbid );983glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, fbs[i].texid, 0 );984glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, fbs[i].zbid );985glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbs[i].zbid );986glViewport( 0, 0, width, height);987glScissor( 0, 0, width, height);988if (fbs[i].buff_clear)989{990glDepthMask(1);991glClear( GL_DEPTH_BUFFER_BIT ); //clear z-buffer only. we may need content, stored in the frame buffer992fbs[i].buff_clear = 0;993}994CHECK_FRAMEBUFFER_STATUS();995curBufferAddr = pBufferAddress;996return;997}998else //create new FBO at the same address, delete old one999{1000glDeleteFramebuffersEXT( 1, &(fbs[i].fbid) );1001glDeleteRenderbuffersEXT( 1, &(fbs[i].zbid) );1002if (nb_fb > 1)1003memmove(&(fbs[i]), &(fbs[i+1]), sizeof(fb)*(nb_fb-i));1004nb_fb--;1005break;1006}1007}1008}10091010remove_tex(pBufferAddress, pBufferAddress + width*height*2/*grTexFormatSize(fmt)*/);1011//create new FBO1012glGenFramebuffersEXT( 1, &(fbs[nb_fb].fbid) );1013glGenRenderbuffersEXT( 1, &(fbs[nb_fb].zbid) );1014glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, fbs[nb_fb].zbid );1015glRenderbufferStorageEXT( GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, height);1016fbs[nb_fb].address = pBufferAddress;1017fbs[nb_fb].width = width;1018fbs[nb_fb].height = height;1019fbs[nb_fb].texid = pBufferAddress;1020fbs[nb_fb].buff_clear = 0;1021add_tex(fbs[nb_fb].texid);1022glBindTexture(GL_TEXTURE_2D, fbs[nb_fb].texid);1023glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0,1024GL_RGB, GL_UNSIGNED_BYTE, NULL);1025glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );1026glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );10271028glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fbs[nb_fb].fbid);1029glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,1030GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, fbs[nb_fb].texid, 0);1031glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, fbs[nb_fb].zbid );1032glViewport(0,0,width,height);1033glScissor(0,0,width,height);1034glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );1035glDepthMask(1);1036glClear( GL_DEPTH_BUFFER_BIT );1037CHECK_FRAMEBUFFER_STATUS();1038curBufferAddr = pBufferAddress;1039nb_fb++;1040}1041}10421043int CheckTextureBufferFormat(GrChipID_t tmu, FxU32 startAddress, GrTexInfo *info )1044{1045int found, i;1046if (!use_fbo) {1047for (found=i=0; i<2; i++)1048if ((FxU32) tmu_usage[i].min <= startAddress && (FxU32) tmu_usage[i].max > startAddress) {1049//printf("tmu %d == framebuffer %x\n", tmu, startAddress);1050found = 1;1051break;1052}1053} else {1054found = i = 0;1055while (i < nb_fb)1056{1057unsigned int end = fbs[i].address + fbs[i].width*fbs[i].height*2;1058if (startAddress >= fbs[i].address && startAddress < end)1059{1060found = 1;1061break;1062}1063i++;1064}1065}10661067if (!use_fbo && found) {1068int tw, th, rh, cw, ch;1069if (info->aspectRatioLog2 < 0)1070{1071th = 1 << info->largeLodLog2;1072tw = th >> -info->aspectRatioLog2;1073}1074else1075{1076tw = 1 << info->largeLodLog2;1077th = tw >> info->aspectRatioLog2;1078}10791080if (info->aspectRatioLog2 < 0)1081{1082ch = 256;1083cw = ch >> -info->aspectRatioLog2;1084}1085else1086{1087cw = 256;1088ch = cw >> info->aspectRatioLog2;1089}10901091if (use_fbo || th < screen_height)1092rh = th;1093else1094rh = screen_height;10951096//printf("th %d rh %d ch %d\n", th, rh, ch);10971098invtex[tmu] = 1.0f - (th - rh) / (float)th;1099} else1100invtex[tmu] = 0;11011102if (info->format == GR_TEXFMT_ALPHA_INTENSITY_88 ) {1103if (!found) {1104return 0;1105}1106if(tmu == 0)1107{1108if(blackandwhite1 != found)1109{1110blackandwhite1 = found;1111need_to_compile = 1;1112}1113}1114else1115{1116if(blackandwhite0 != found)1117{1118blackandwhite0 = found;1119need_to_compile = 1;1120}1121}1122return 1;1123}1124return 0;11251126}112711281129FX_ENTRY void FX_CALL1130grTextureAuxBufferExt( GrChipID_t tmu,1131FxU32 startAddress,1132GrLOD_t thisLOD,1133GrLOD_t largeLOD,1134GrAspectRatio_t aspectRatio,1135GrTextureFormat_t format,1136FxU32 odd_even_mask )1137{1138LOG("grTextureAuxBufferExt(%d, %d, %d, %d %d, %d, %d)\r\n", tmu, startAddress, thisLOD, largeLOD, aspectRatio, format, odd_even_mask);1139//display_warning("grTextureAuxBufferExt");1140}11411142FX_ENTRY void FX_CALL grAuxBufferExt( GrBuffer_t buffer );11431144FX_ENTRY GrProc FX_CALL1145grGetProcAddress( char *procName )1146{1147LOG("grGetProcAddress(%s)\r\n", procName);1148if(!strcmp(procName, "grSstWinOpenExt"))1149return (GrProc)grSstWinOpenExt;1150if(!strcmp(procName, "grTextureBufferExt"))1151return (GrProc)grTextureBufferExt;1152if(!strcmp(procName, "grChromaRangeExt"))1153return (GrProc)grChromaRangeExt;1154if(!strcmp(procName, "grChromaRangeModeExt"))1155return (GrProc)grChromaRangeModeExt;1156if(!strcmp(procName, "grTexChromaRangeExt"))1157return (GrProc)grTexChromaRangeExt;1158if(!strcmp(procName, "grTexChromaModeExt"))1159return (GrProc)grTexChromaModeExt;1160// ZIGGY framebuffer copy extension1161if(!strcmp(procName, "grFramebufferCopyExt"))1162return (GrProc)grFramebufferCopyExt;1163if(!strcmp(procName, "grColorCombineExt"))1164return (GrProc)grColorCombineExt;1165if(!strcmp(procName, "grAlphaCombineExt"))1166return (GrProc)grAlphaCombineExt;1167if(!strcmp(procName, "grTexColorCombineExt"))1168return (GrProc)grTexColorCombineExt;1169if(!strcmp(procName, "grTexAlphaCombineExt"))1170return (GrProc)grTexAlphaCombineExt;1171if(!strcmp(procName, "grConstantColorValueExt"))1172return (GrProc)grConstantColorValueExt;1173if(!strcmp(procName, "grTextureAuxBufferExt"))1174return (GrProc)grTextureAuxBufferExt;1175if(!strcmp(procName, "grAuxBufferExt"))1176return (GrProc)grAuxBufferExt;1177if(!strcmp(procName, "grWrapperFullScreenResolutionExt"))1178return (GrProc)grWrapperFullScreenResolutionExt;1179if(!strcmp(procName, "grConfigWrapperExt"))1180return (GrProc)grConfigWrapperExt;1181if(!strcmp(procName, "grKeyPressedExt"))1182return (GrProc)grKeyPressedExt;1183if(!strcmp(procName, "grQueryResolutionsExt"))1184return (GrProc)grQueryResolutionsExt;1185if(!strcmp(procName, "grGetGammaTableExt"))1186return (GrProc)grGetGammaTableExt;1187display_warning("grGetProcAddress : %s", procName);1188return 0;1189}11901191FX_ENTRY FxU32 FX_CALL1192grGet( FxU32 pname, FxU32 plength, FxI32 *params )1193{1194LOG("grGet(%d,%d)\r\n", pname, plength);1195switch(pname)1196{1197case GR_MAX_TEXTURE_SIZE:1198if (plength < 4 || params == NULL) return 0;1199params[0] = 2048;1200return 4;1201break;1202case GR_NUM_TMU:1203if (plength < 4 || params == NULL) return 0;1204if (!nbTextureUnits)1205{1206grSstWinOpen((unsigned long)NULL, GR_RESOLUTION_640x480 | 0x80000000, 0, GR_COLORFORMAT_ARGB,1207GR_ORIGIN_UPPER_LEFT, 2, 1);1208grSstWinClose(0);1209}1210#ifdef VOODOO11211params[0] = 1;1212#else1213if (nbTextureUnits > 2)1214params[0] = 2;1215else1216params[0] = 1;1217#endif1218return 4;1219break;1220case GR_NUM_BOARDS:1221case GR_NUM_FB:1222case GR_REVISION_FB:1223case GR_REVISION_TMU:1224if (plength < 4 || params == NULL) return 0;1225params[0] = 1;1226return 4;1227break;1228case GR_MEMORY_FB:1229if (plength < 4 || params == NULL) return 0;1230params[0] = 16*1024*1024;1231return 4;1232break;1233case GR_MEMORY_TMU:1234if (plength < 4 || params == NULL) return 0;1235params[0] = 16*1024*1024;1236return 4;1237break;1238case GR_MEMORY_UMA:1239if (plength < 4 || params == NULL) return 0;1240params[0] = 16*1024*1024*nbTextureUnits;1241return 4;1242break;1243case GR_BITS_RGBA:1244if (plength < 16 || params == NULL) return 0;1245params[0] = 8;1246params[1] = 8;1247params[2] = 8;1248params[3] = 8;1249return 16;1250break;1251case GR_BITS_DEPTH:1252if (plength < 4 || params == NULL) return 0;1253params[0] = 16;1254return 4;1255break;1256case GR_BITS_GAMMA:1257if (plength < 4 || params == NULL) return 0;1258params[0] = 8;1259return 4;1260break;1261case GR_GAMMA_TABLE_ENTRIES:1262if (plength < 4 || params == NULL) return 0;1263params[0] = 256;1264return 4;1265break;1266case GR_FOG_TABLE_ENTRIES:1267if (plength < 4 || params == NULL) return 0;1268params[0] = 64;1269return 4;1270break;1271case GR_WDEPTH_MIN_MAX:1272if (plength < 8 || params == NULL) return 0;1273params[0] = 0;1274params[1] = 65528;1275return 8;1276break;1277case GR_ZDEPTH_MIN_MAX:1278if (plength < 8 || params == NULL) return 0;1279params[0] = 0;1280params[1] = 65535;1281return 8;1282break;1283case GR_LFB_PIXEL_PIPE:1284if (plength < 4 || params == NULL) return 0;1285params[0] = FXFALSE;1286return 4;1287break;1288case GR_MAX_TEXTURE_ASPECT_RATIO:1289if (plength < 4 || params == NULL) return 0;1290params[0] = 3;1291return 4;1292break;1293case GR_NON_POWER_OF_TWO_TEXTURES:1294if (plength < 4 || params == NULL) return 0;1295params[0] = FXFALSE;1296return 4;1297break;1298case GR_TEXTURE_ALIGN:1299if (plength < 4 || params == NULL) return 0;1300params[0] = 0;1301return 4;1302break;1303default:1304display_warning("unknown pname in grGet : %x", pname);1305}1306return 0;1307}13081309FX_ENTRY const char * FX_CALL1310grGetString( FxU32 pname )1311{1312LOG("grGetString(%d)\r\n", pname);1313switch(pname)1314{1315case GR_EXTENSION:1316{1317static char extension[] = "CHROMARANGE TEXCHROMA TEXMIRROR PALETTE6666 FOGCOORD EVOODOO TEXTUREBUFFER TEXUMA TEXFMT COMBINE GETGAMMA";1318return extension;1319}1320break;1321case GR_HARDWARE:1322{1323static char hardware[] = "Voodoo5 (tm)";1324return hardware;1325}1326break;1327case GR_VENDOR:1328{1329static char vendor[] = "3Dfx Interactive";1330return vendor;1331}1332break;1333case GR_RENDERER:1334{1335static char renderer[] = "Glide";1336return renderer;1337}1338break;1339case GR_VERSION:1340{1341static char version[] = "3.0";1342return version;1343}1344break;1345default:1346display_warning("unknown grGetString selector : %x", pname);1347}1348return NULL;1349}13501351static void render_rectangle(int texture_number,1352int dst_x, int dst_y,1353int src_width, int src_height,1354int tex_width, int tex_height, int invert)1355{1356glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);1357glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);1358glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);1359glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);1360glBegin(GL_QUADS);1361glMultiTexCoord2fARB(texture_number, 0.0f, 0.0f);1362glVertex2f(((int)dst_x - widtho) / (float)(width/2),1363invert*-((int)dst_y - heighto) / (float)(height/2));1364glMultiTexCoord2fARB(texture_number, 0.0f, (float)src_height / (float)tex_height);1365glVertex2f(((int)dst_x - widtho) / (float)(width/2),1366invert*-((int)dst_y + (int)src_height - heighto) / (float)(height/2));1367glMultiTexCoord2fARB(texture_number, (float)src_width / (float)tex_width, (float)src_height / (float)tex_height);1368glVertex2f(((int)dst_x + (int)src_width - widtho) / (float)(width/2),1369invert*-((int)dst_y + (int)src_height - heighto) / (float)(height/2));1370glMultiTexCoord2fARB(texture_number, (float)src_width / (float)tex_width, 0.0f);1371glVertex2f(((int)dst_x + (int)src_width - widtho) / (float)(width/2),1372invert*-((int)dst_y - heighto) / (float)(height/2));1373glMultiTexCoord2fARB(texture_number, 0.0f, 0.0f);1374glVertex2f(((int)dst_x - widtho) / (float)(width/2),1375invert*-((int)dst_y - heighto) / (float)(height/2));1376glEnd();13771378compile_shader();13791380glEnable(GL_DEPTH_TEST);1381glEnable(GL_BLEND);1382}13831384void reloadTexture()1385{1386if (use_fbo || !render_to_texture || buffer_cleared)1387return;13881389LOG("reload texture %dx%d\n", width, height);1390//printf("reload texture %dx%d\n", width, height);13911392buffer_cleared = 1;13931394glPushAttrib(GL_ALL_ATTRIB_BITS);1395glActiveTextureARB(texture_unit);1396glBindTexture(GL_TEXTURE_2D, pBufferAddress);1397glDisable(GL_ALPHA_TEST);1398glDrawBuffer(current_buffer);1399glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);1400set_copy_shader();1401glDisable(GL_DEPTH_TEST);1402glDisable(GL_CULL_FACE);1403int w = 0, h = 0;1404if (height > screen_height) h = screen_height - height;1405render_rectangle(texture_unit,1406-w, -h,1407width, height,1408width, height, -1);1409glBindTexture(GL_TEXTURE_2D, default_texture);1410glPopAttrib();1411}14121413void updateTexture()1414{1415if (!use_fbo && render_to_texture == 2) {1416LOG("update texture %x\n", pBufferAddress);1417//printf("update texture %x\n", pBufferAddress);14181419// nothing changed, don't update the texture1420if (!buffer_cleared) {1421LOG("update cancelled\n", pBufferAddress);1422return;1423}14241425glPushAttrib(GL_ALL_ATTRIB_BITS);14261427// save result of render to texture into actual texture1428glReadBuffer(current_buffer);1429glActiveTextureARB(texture_unit);1430// ZIGGY1431// deleting the texture before resampling it increases speed on certain old1432// nvidia cards (geforce 2 for example), unfortunatly it slows down a lot1433// on newer cards.1434//glDeleteTextures( 1, &pBufferAddress );1435glBindTexture(GL_TEXTURE_2D, pBufferAddress);1436glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,14370, viewport_offset, width, height, 0);14381439glBindTexture(GL_TEXTURE_2D, default_texture);1440glPopAttrib();1441}1442}14431444FX_ENTRY void FX_CALL grFramebufferCopyExt(int x, int y, int w, int h,1445int from, int to, int mode)1446{1447if (mode == GR_FBCOPY_MODE_DEPTH) {14481449int tw = 1, th = 1;1450if (npot_support) {1451tw = width; th = height;1452} else {1453while (tw < width) tw <<= 1;1454while (th < height) th <<= 1;1455}14561457if (from == GR_FBCOPY_BUFFER_BACK && to == GR_FBCOPY_BUFFER_FRONT) {1458//printf("save depth buffer %d\n", render_to_texture);1459// save the depth image in a texture1460glReadBuffer(current_buffer);1461glBindTexture(GL_TEXTURE_2D, depth_texture);1462glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT,14630, viewport_offset, tw, th, 0);1464glBindTexture(GL_TEXTURE_2D, default_texture);1465return;1466}1467if (from == GR_FBCOPY_BUFFER_FRONT && to == GR_FBCOPY_BUFFER_BACK) {1468//printf("writing to depth buffer %d\n", render_to_texture);1469glPushAttrib(GL_ALL_ATTRIB_BITS);1470glDisable(GL_ALPHA_TEST);1471glDrawBuffer(current_buffer);1472glActiveTextureARB(texture_unit);1473glBindTexture(GL_TEXTURE_2D, depth_texture);1474glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);1475set_depth_shader();1476glEnable(GL_DEPTH_TEST);1477glDepthFunc(GL_ALWAYS);1478glDisable(GL_CULL_FACE);1479render_rectangle(texture_unit,14800, 0,1481width, height,1482tw, th, -1);1483glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);1484glBindTexture(GL_TEXTURE_2D, default_texture);1485glPopAttrib();1486return;1487}14881489}1490}14911492FX_ENTRY void FX_CALL1493grRenderBuffer( GrBuffer_t buffer )1494{1495#ifdef _WIN321496static HANDLE region = NULL;1497int realWidth = pBufferWidth, realHeight = pBufferHeight;1498#endif // _WIN321499LOG("grRenderBuffer(%d)\r\n", buffer);1500//printf("grRenderBuffer(%d)\n", buffer);15011502switch(buffer)1503{1504case GR_BUFFER_BACKBUFFER:1505if(render_to_texture)1506{1507updateTexture();15081509// VP z fix1510glMatrixMode(GL_MODELVIEW);1511glLoadIdentity();1512glTranslatef(0, 0, 1-zscale);1513glScalef(1, 1, zscale);1514inverted_culling = 0;1515grCullMode(culling_mode);15161517width = savedWidth;1518height = savedHeight;1519widtho = savedWidtho;1520heighto = savedHeighto;1521if (use_fbo) {1522glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);1523glBindRenderbufferEXT( GL_RENDERBUFFER_EXT, 0 );1524}1525curBufferAddr = 0;15261527glViewport(0, viewport_offset, width, viewport_height);1528glScissor(0, viewport_offset, width, height);15291530#ifdef SAVE_CBUFFER1531if (!use_fbo && render_to_texture == 2) {1532// restore color buffer1533if (nbAuxBuffers > 0) {1534glDrawBuffer(GL_BACK);1535current_buffer = GL_BACK;1536} else if (save_w) {1537int tw = 1, th = 1;1538//printf("restore %dx%d\n", save_w, save_h);1539if (npot_support) {1540tw = screen_width;1541th = screen_height;1542} else {1543while (tw < screen_width) tw <<= 1;1544while (th < screen_height) th <<= 1;1545}15461547glPushAttrib(GL_ALL_ATTRIB_BITS);1548glDisable(GL_ALPHA_TEST);1549glDrawBuffer(GL_BACK);1550glActiveTextureARB(texture_unit);1551glBindTexture(GL_TEXTURE_2D, color_texture);1552glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);1553set_copy_shader();1554glDisable(GL_DEPTH_TEST);1555glDisable(GL_CULL_FACE);1556render_rectangle(texture_unit,15570, 0,1558save_w, save_h,1559tw, th, -1);1560glBindTexture(GL_TEXTURE_2D, default_texture);1561glPopAttrib();15621563save_w = save_h = 0;1564}1565}1566#endif1567render_to_texture = 0;1568}1569glDrawBuffer(GL_BACK);1570break;1571case 6: // RENDER TO TEXTURE1572if(!render_to_texture)1573{1574savedWidth = width;1575savedHeight = height;1576savedWidtho = widtho;1577savedHeighto = heighto;1578}15791580{1581if (!use_fbo) {1582glMatrixMode(GL_MODELVIEW);1583glLoadIdentity();1584glTranslatef(0, 0, 1-zscale);1585glScalef(1, 1, zscale);1586inverted_culling = 0;1587} else {1588float m[4*4] = {1.0f, 0.0f, 0.0f, 0.0f,15890.0f,-1.0f, 0.0f, 0.0f,15900.0f, 0.0f, 1.0f, 0.0f,15910.0f, 0.0f, 0.0f, 1.0f};1592glMatrixMode(GL_MODELVIEW);1593glLoadMatrixf(m);1594// VP z fix1595glTranslatef(0, 0, 1-zscale);1596glScalef(1, 1*1, zscale);1597inverted_culling = 1;1598grCullMode(culling_mode);1599}1600}1601render_to_texture = 1;1602break;1603default:1604display_warning("grRenderBuffer : unknown buffer : %x", buffer);1605}1606}16071608FX_ENTRY void FX_CALL1609grAuxBufferExt( GrBuffer_t buffer )1610{1611LOG("grAuxBufferExt(%d)\r\n", buffer);1612//display_warning("grAuxBufferExt");16131614if (buffer == GR_BUFFER_AUXBUFFER) {1615invtex[0] = 0;1616invtex[1] = 0;1617need_to_compile = 0;1618set_depth_shader();1619glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);1620glEnable(GL_DEPTH_TEST);1621glDepthFunc(GL_ALWAYS);1622glDisable(GL_CULL_FACE);1623glDisable(GL_ALPHA_TEST);1624glDepthMask(GL_TRUE);1625grTexFilterMode(GR_TMU1, GR_TEXTUREFILTER_POINT_SAMPLED, GR_TEXTUREFILTER_POINT_SAMPLED);1626} else {1627glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);1628need_to_compile = 1;1629}1630}16311632FX_ENTRY void FX_CALL1633grBufferClear( GrColor_t color, GrAlpha_t alpha, FxU32 depth )1634{1635LOG("grBufferClear(%d,%d,%d)\r\n", color, alpha, depth);1636switch(lfb_color_fmt)1637{1638case GR_COLORFORMAT_ARGB:1639glClearColor(((color >> 16) & 0xFF) / 255.0f,1640((color >> 8) & 0xFF) / 255.0f,1641( color & 0xFF) / 255.0f,1642alpha / 255.0f);1643break;1644case GR_COLORFORMAT_RGBA:1645glClearColor(((color >> 24) & 0xFF) / 255.0f,1646((color >> 16) & 0xFF) / 255.0f,1647(color & 0xFF) / 255.0f,1648alpha / 255.0f);1649break;1650default:1651display_warning("grBufferClear: unknown color format : %x", lfb_color_fmt);1652}16531654if (w_buffer_mode)1655glClearDepth(1.0f - ((1.0f + (depth >> 4) / 4096.0f) * (1 << (depth & 0xF))) / 65528.0);1656else1657glClearDepth(depth / 65535.0f);1658glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);16591660// ZIGGY TODO check that color mask is on1661buffer_cleared = 1;16621663}16641665// #include <unistd.h>1666FX_ENTRY void FX_CALL1667grBufferSwap( FxU32 swap_interval )1668{1669glFinish();1670glUseProgramObjectARB(0);1671// printf("rendercallback is %p\n", renderCallback);1672if(renderCallback)1673(*renderCallback)(1);1674int i;1675LOG("grBufferSwap(%d)\r\n", swap_interval);1676//printf("swap\n");1677if (render_to_texture) {1678display_warning("swap while render_to_texture\n");1679return;1680}16811682CoreVideo_GL_SwapBuffers();1683for (i = 0; i < nb_fb; i++)1684fbs[i].buff_clear = 1;16851686// VP debugging1687#ifdef VPDEBUG1688dump_stop();1689SDL_Event event;1690while (SDL_PollEvent(&event)) {1691switch (event.type) {1692case SDL_KEYDOWN:1693switch (event.key.keysym.sym) {1694case 'd':1695printf("Dumping !\n");1696dump_start();1697break;1698case 'w': {1699static int wireframe;1700wireframe = !wireframe;1701glPolygonMode(GL_FRONT_AND_BACK, wireframe? GL_LINE : GL_FILL);1702break;1703}1704}1705break;1706}1707}1708#endif1709}17101711// frame buffer17121713FX_ENTRY FxBool FX_CALL1714grLfbLock( GrLock_t type, GrBuffer_t buffer, GrLfbWriteMode_t writeMode,1715GrOriginLocation_t origin, FxBool pixelPipeline,1716GrLfbInfo_t *info )1717{1718LOG("grLfbLock(%d,%d,%d,%d,%d)\r\n", type, buffer, writeMode, origin, pixelPipeline);1719if (type == GR_LFB_WRITE_ONLY)1720{1721display_warning("grLfbLock : write only");1722}1723else1724{1725unsigned char *buf;1726int i,j;17271728switch(buffer)1729{1730case GR_BUFFER_FRONTBUFFER:1731glReadBuffer(GL_FRONT);1732break;1733case GR_BUFFER_BACKBUFFER:1734glReadBuffer(GL_BACK);1735break;1736default:1737display_warning("grLfbLock : unknown buffer : %x", buffer);1738}17391740if(buffer != GR_BUFFER_AUXBUFFER)1741{1742if (writeMode == GR_LFBWRITEMODE_888) {1743//printf("LfbLock GR_LFBWRITEMODE_888\n");1744info->lfbPtr = frameBuffer;1745info->strideInBytes = width*4;1746info->writeMode = GR_LFBWRITEMODE_888;1747info->origin = origin;1748glReadPixels(0, viewport_offset, width, height, GL_BGRA, GL_UNSIGNED_BYTE, frameBuffer);1749} else {1750buf = (unsigned char*)malloc(width*height*4);17511752info->lfbPtr = frameBuffer;1753info->strideInBytes = width*2;1754info->writeMode = GR_LFBWRITEMODE_565;1755info->origin = origin;1756glReadPixels(0, viewport_offset, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buf);17571758for (j=0; j<height; j++)1759{1760for (i=0; i<width; i++)1761{1762frameBuffer[(height-j-1)*width+i] =1763((buf[j*width*4+i*4+0] >> 3) << 11) |1764((buf[j*width*4+i*4+1] >> 2) << 5) |1765(buf[j*width*4+i*4+2] >> 3);1766}1767}1768free(buf);1769}1770}1771else1772{1773info->lfbPtr = depthBuffer;1774info->strideInBytes = width*2;1775info->writeMode = GR_LFBWRITEMODE_ZA16;1776info->origin = origin;1777glReadPixels(0, viewport_offset, width, height, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, depthBuffer);1778}1779}17801781return FXTRUE;1782}17831784FX_ENTRY FxBool FX_CALL1785grLfbUnlock( GrLock_t type, GrBuffer_t buffer )1786{1787LOG("grLfbUnlock(%d,%d)\r\n", type, buffer);1788if (type == GR_LFB_WRITE_ONLY)1789{1790display_warning("grLfbUnlock : write only");1791}1792return FXTRUE;1793}17941795FX_ENTRY FxBool FX_CALL1796grLfbReadRegion( GrBuffer_t src_buffer,1797FxU32 src_x, FxU32 src_y,1798FxU32 src_width, FxU32 src_height,1799FxU32 dst_stride, void *dst_data )1800{1801unsigned char *buf;1802unsigned int i,j;1803unsigned short *frameBuffer = (unsigned short*)dst_data;1804unsigned short *depthBuffer = (unsigned short*)dst_data;1805LOG("grLfbReadRegion(%d,%d,%d,%d,%d,%d)\r\n", src_buffer, src_x, src_y, src_width, src_height, dst_stride);18061807switch(src_buffer)1808{1809case GR_BUFFER_FRONTBUFFER:1810glReadBuffer(GL_FRONT);1811break;1812case GR_BUFFER_BACKBUFFER:1813glReadBuffer(GL_BACK);1814break;1815/*case GR_BUFFER_AUXBUFFER:1816glReadBuffer(current_buffer);1817break;*/1818default:1819display_warning("grReadRegion : unknown buffer : %x", src_buffer);1820}18211822if(src_buffer != GR_BUFFER_AUXBUFFER)1823{1824buf = (unsigned char*)malloc(src_width*src_height*4);18251826glReadPixels(src_x, (viewport_offset)+height-src_y-src_height, src_width, src_height, GL_RGBA, GL_UNSIGNED_BYTE, buf);18271828for (j=0; j<src_height; j++)1829{1830for (i=0; i<src_width; i++)1831{1832frameBuffer[j*(dst_stride/2)+i] =1833((buf[(src_height-j-1)*src_width*4+i*4+0] >> 3) << 11) |1834((buf[(src_height-j-1)*src_width*4+i*4+1] >> 2) << 5) |1835(buf[(src_height-j-1)*src_width*4+i*4+2] >> 3);1836}1837}1838free(buf);1839}1840else1841{1842buf = (unsigned char*)malloc(src_width*src_height*2);18431844glReadPixels(src_x, (viewport_offset)+height-src_y-src_height, src_width, src_height, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, depthBuffer);18451846for (j=0;j<src_height; j++)1847{1848for (i=0; i<src_width; i++)1849{1850depthBuffer[j*(dst_stride/2)+i] =1851((unsigned short*)buf)[(src_height-j-1)*src_width*4+i*4];1852}1853}1854free(buf);1855}18561857return FXTRUE;1858}18591860FX_ENTRY FxBool FX_CALL1861grLfbWriteRegion( GrBuffer_t dst_buffer,1862FxU32 dst_x, FxU32 dst_y,1863GrLfbSrcFmt_t src_format,1864FxU32 src_width, FxU32 src_height,1865FxBool pixelPipeline,1866FxI32 src_stride, void *src_data )1867{1868unsigned char *buf;1869unsigned int i,j;1870unsigned short *frameBuffer = (unsigned short*)src_data;1871int texture_number;1872unsigned int tex_width = 1, tex_height = 1;1873LOG("grLfbWriteRegion(%d,%d,%d,%d,%d,%d,%d,%d)\r\n",dst_buffer, dst_x, dst_y, src_format, src_width, src_height, pixelPipeline, src_stride);18741875glPushAttrib(GL_ALL_ATTRIB_BITS);18761877while (tex_width < src_width) tex_width <<= 1;1878while (tex_height < src_height) tex_height <<= 1;18791880switch(dst_buffer)1881{1882case GR_BUFFER_BACKBUFFER:1883glDrawBuffer(GL_BACK);1884break;1885case GR_BUFFER_AUXBUFFER:1886glDrawBuffer(current_buffer);1887break;1888default:1889display_warning("grLfbWriteRegion : unknown buffer : %x", dst_buffer);1890}18911892if(dst_buffer != GR_BUFFER_AUXBUFFER)1893{1894buf = (unsigned char*)malloc(tex_width*tex_height*4);18951896texture_number = GL_TEXTURE0_ARB;1897glActiveTextureARB(texture_number);18981899const unsigned int half_stride = src_stride / 2;1900switch(src_format)1901{1902case GR_LFB_SRC_FMT_1555:1903for (j=0; j<src_height; j++)1904{1905for (i=0; i<src_width; i++)1906{1907const unsigned int col = frameBuffer[j*half_stride+i];1908buf[j*tex_width*4+i*4+0]=((col>>10)&0x1F)<<3;1909buf[j*tex_width*4+i*4+1]=((col>>5)&0x1F)<<3;1910buf[j*tex_width*4+i*4+2]=((col>>0)&0x1F)<<3;1911buf[j*tex_width*4+i*4+3]= (col>>15) ? 0xFF : 0;1912}1913}1914break;1915case GR_LFBWRITEMODE_555:1916for (j=0; j<src_height; j++)1917{1918for (i=0; i<src_width; i++)1919{1920const unsigned int col = frameBuffer[j*half_stride+i];1921buf[j*tex_width*4+i*4+0]=((col>>10)&0x1F)<<3;1922buf[j*tex_width*4+i*4+1]=((col>>5)&0x1F)<<3;1923buf[j*tex_width*4+i*4+2]=((col>>0)&0x1F)<<3;1924buf[j*tex_width*4+i*4+3]=0xFF;1925}1926}1927break;1928case GR_LFBWRITEMODE_565:1929for (j=0; j<src_height; j++)1930{1931for (i=0; i<src_width; i++)1932{1933const unsigned int col = frameBuffer[j*half_stride+i];1934buf[j*tex_width*4+i*4+0]=((col>>11)&0x1F)<<3;1935buf[j*tex_width*4+i*4+1]=((col>>5)&0x3F)<<2;1936buf[j*tex_width*4+i*4+2]=((col>>0)&0x1F)<<3;1937buf[j*tex_width*4+i*4+3]=0xFF;1938}1939}1940break;1941default:1942display_warning("grLfbWriteRegion : unknown format : %d", src_format);1943}19441945#ifdef VPDEBUG1946if (dumping) {1947ilTexImage(tex_width, tex_height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, buf);1948char name[128];1949static int id;1950sprintf(name, "dump/writecolor%d.png", id++);1951ilSaveImage(name);1952//printf("dumped gdLfbWriteRegion %s\n", name);1953}1954#endif19551956glBindTexture(GL_TEXTURE_2D, default_texture);1957glTexImage2D(GL_TEXTURE_2D, 0, 4, tex_width, tex_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);1958free(buf);19591960set_copy_shader();19611962glDisable(GL_DEPTH_TEST);1963glDisable(GL_BLEND);1964render_rectangle(texture_number,1965dst_x, dst_y,1966src_width, src_height,1967tex_width, tex_height, +1);19681969}1970else1971{1972float *buf = (float*)malloc(src_width*(src_height+(viewport_offset))*sizeof(float));19731974if (src_format != GR_LFBWRITEMODE_ZA16)1975display_warning("unknown depth buffer write format:%x", src_format);19761977if(dst_x || dst_y)1978display_warning("dst_x:%d, dst_y:%d\n",dst_x, dst_y);19791980for (j=0; j<src_height; j++)1981{1982for (i=0; i<src_width; i++)1983{1984buf[(j+(viewport_offset))*src_width+i] =1985(frameBuffer[(src_height-j-1)*(src_stride/2)+i]/(65536.0f*(2.0f/zscale)))+1-zscale/2.0f;1986}1987}19881989#ifdef VPDEBUG1990if (dumping) {1991unsigned char * buf2 = (unsigned char *)malloc(src_width*(src_height+(viewport_offset)));1992for (i=0; i<src_width*src_height ; i++)1993buf2[i] = buf[i]*255.0f;1994ilTexImage(src_width, src_height, 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, buf2);1995char name[128];1996static int id;1997sprintf(name, "dump/writedepth%d.png", id++);1998ilSaveImage(name);1999//printf("dumped gdLfbWriteRegion %s\n", name);2000free(buf2);2001}2002#endif20032004glEnable(GL_DEPTH_TEST);2005glDepthFunc(GL_ALWAYS);20062007glDrawBuffer(GL_BACK);2008glClear( GL_DEPTH_BUFFER_BIT );2009glDepthMask(1);2010glDrawPixels(src_width, src_height+(viewport_offset), GL_DEPTH_COMPONENT, GL_FLOAT, buf);20112012free(buf);2013}2014glDrawBuffer(current_buffer);2015glPopAttrib();2016return FXTRUE;2017}20182019/* wrapper-specific glide extensions */20202021FX_ENTRY char ** FX_CALL2022grQueryResolutionsExt(FxI32 * Size)2023{2024return 0;2025/*2026LOG("grQueryResolutionsExt\r\n");2027return g_FullScreenResolutions.getResolutionsList(Size);2028*/2029}20302031FX_ENTRY GrScreenResolution_t FX_CALL grWrapperFullScreenResolutionExt(FxU32* width, FxU32* height)2032{2033return 0;2034/*2035LOG("grWrapperFullScreenResolutionExt\r\n");2036g_FullScreenResolutions.getResolution(config.res, width, height);2037return config.res;2038*/2039}20402041FX_ENTRY FxBool FX_CALL grKeyPressedExt(FxU32 key)2042{2043return 0;2044/*2045#ifdef _WIN322046return (GetAsyncKeyState(key) & 0x8000);2047#else2048if (key == 1) //LBUTTON2049{2050Uint8 mstate = SDL_GetMouseState(NULL, NULL);2051return (mstate & SDL_BUTTON_LMASK);2052}2053else2054{2055Uint8 *keystates = SDL_GetKeyState( NULL );2056if( keystates[ key ] )2057{2058return 1;2059}2060else2061{2062return 0;2063}2064}2065#endif2066*/2067}20682069FX_ENTRY void FX_CALL grConfigWrapperExt(FxI32 resolution, FxI32 vram, FxBool fbo, FxBool aniso)2070{2071LOG("grConfigWrapperExt\r\n");2072config.res = resolution;2073config.vram_size = vram;2074config.fbo = fbo;2075config.anisofilter = aniso;2076}20772078// unused by glide6420792080FX_ENTRY FxI32 FX_CALL2081grQueryResolutions( const GrResolution *resTemplate, GrResolution *output )2082{2083int res_inf = 0;2084int res_sup = 0xf;2085int i;2086int n=0;2087LOG("grQueryResolutions\r\n");2088display_warning("grQueryResolutions");2089if ((unsigned int)resTemplate->resolution != GR_QUERY_ANY)2090{2091res_inf = res_sup = resTemplate->resolution;2092}2093if ((unsigned int)resTemplate->refresh == GR_QUERY_ANY) display_warning("querying any refresh rate");2094if ((unsigned int)resTemplate->numAuxBuffers == GR_QUERY_ANY) display_warning("querying any numAuxBuffers");2095if ((unsigned int)resTemplate->numColorBuffers == GR_QUERY_ANY) display_warning("querying any numColorBuffers");20962097if (output == NULL) return res_sup - res_inf + 1;2098for (i=res_inf; i<=res_sup; i++)2099{2100output[n].resolution = i;2101output[n].refresh = resTemplate->refresh;2102output[n].numAuxBuffers = resTemplate->numAuxBuffers;2103output[n].numColorBuffers = resTemplate->numColorBuffers;2104n++;2105}2106return res_sup - res_inf + 1;2107}21082109FX_ENTRY FxBool FX_CALL2110grReset( FxU32 what )2111{2112display_warning("grReset");2113return 1;2114}21152116FX_ENTRY void FX_CALL2117grEnable( GrEnableMode_t mode )2118{2119LOG("grEnable(%d)\r\n", mode);2120if (mode == GR_TEXTURE_UMA_EXT)2121UMAmode = 1;2122}21232124FX_ENTRY void FX_CALL2125grDisable( GrEnableMode_t mode )2126{2127LOG("grDisable(%d)\r\n", mode);2128if (mode == GR_TEXTURE_UMA_EXT)2129UMAmode = 0;2130}21312132FX_ENTRY void FX_CALL2133grDisableAllEffects( void )2134{2135display_warning("grDisableAllEffects");2136}21372138FX_ENTRY void FX_CALL2139grErrorSetCallback( GrErrorCallbackFnc_t fnc )2140{2141display_warning("grErrorSetCallback");2142}21432144FX_ENTRY void FX_CALL2145grFinish(void)2146{2147display_warning("grFinish");2148}21492150FX_ENTRY void FX_CALL2151grFlush(void)2152{2153display_warning("grFlush");2154}21552156FX_ENTRY void FX_CALL2157grTexMultibase( GrChipID_t tmu,2158FxBool enable )2159{2160display_warning("grTexMultibase");2161}21622163FX_ENTRY void FX_CALL2164grTexMipMapMode( GrChipID_t tmu,2165GrMipMapMode_t mode,2166FxBool lodBlend )2167{2168display_warning("grTexMipMapMode");2169}21702171FX_ENTRY void FX_CALL2172grTexDownloadTablePartial( GrTexTable_t type,2173void *data,2174int start,2175int end )2176{2177display_warning("grTexDownloadTablePartial");2178}21792180FX_ENTRY void FX_CALL2181grTexDownloadTable( GrTexTable_t type,2182void *data )2183{2184display_warning("grTexDownloadTable");2185}21862187FX_ENTRY FxBool FX_CALL2188grTexDownloadMipMapLevelPartial( GrChipID_t tmu,2189FxU32 startAddress,2190GrLOD_t thisLod,2191GrLOD_t largeLod,2192GrAspectRatio_t aspectRatio,2193GrTextureFormat_t format,2194FxU32 evenOdd,2195void *data,2196int start,2197int end )2198{2199display_warning("grTexDownloadMipMapLevelPartial");2200return 1;2201}22022203FX_ENTRY void FX_CALL2204grTexDownloadMipMapLevel( GrChipID_t tmu,2205FxU32 startAddress,2206GrLOD_t thisLod,2207GrLOD_t largeLod,2208GrAspectRatio_t aspectRatio,2209GrTextureFormat_t format,2210FxU32 evenOdd,2211void *data )2212{2213display_warning("grTexDownloadMipMapLevel");2214}22152216FX_ENTRY void FX_CALL2217grTexNCCTable( GrNCCTable_t table )2218{2219display_warning("grTexNCCTable");2220}22212222FX_ENTRY void FX_CALL2223grViewport( FxI32 x, FxI32 y, FxI32 width, FxI32 height )2224{2225display_warning("grViewport");2226}22272228FX_ENTRY void FX_CALL2229grDepthRange( FxFloat n, FxFloat f )2230{2231display_warning("grDepthRange");2232}22332234FX_ENTRY void FX_CALL2235grSplash(float x, float y, float width, float height, FxU32 frame)2236{2237display_warning("grSplash");2238}22392240FX_ENTRY FxBool FX_CALL2241grSelectContext( GrContext_t context )2242{2243display_warning("grSelectContext");2244return 1;2245}22462247FX_ENTRY void FX_CALL2248grAADrawTriangle(2249const void *a, const void *b, const void *c,2250FxBool ab_antialias, FxBool bc_antialias, FxBool ca_antialias2251)2252{2253display_warning("grAADrawTriangle");2254}22552256FX_ENTRY void FX_CALL2257grAlphaControlsITRGBLighting( FxBool enable )2258{2259display_warning("grAlphaControlsITRGBLighting");2260}22612262FX_ENTRY void FX_CALL2263grGlideSetVertexLayout( const void *layout )2264{2265display_warning("grGlideSetVertexLayout");2266}22672268FX_ENTRY void FX_CALL2269grGlideGetVertexLayout( void *layout )2270{2271display_warning("grGlideGetVertexLayout");2272}22732274FX_ENTRY void FX_CALL2275grGlideSetState( const void *state )2276{2277display_warning("grGlideSetState");2278}22792280FX_ENTRY void FX_CALL2281grGlideGetState( void *state )2282{2283display_warning("grGlideGetState");2284}22852286FX_ENTRY void FX_CALL2287grLfbWriteColorFormat(GrColorFormat_t colorFormat)2288{2289display_warning("grLfbWriteColorFormat");2290}22912292FX_ENTRY void FX_CALL2293grLfbWriteColorSwizzle(FxBool swizzleBytes, FxBool swapWords)2294{2295display_warning("grLfbWriteColorSwizzle");2296}22972298FX_ENTRY void FX_CALL2299grLfbConstantDepth( FxU32 depth )2300{2301display_warning("grLfbConstantDepth");2302}23032304FX_ENTRY void FX_CALL2305grLfbConstantAlpha( GrAlpha_t alpha )2306{2307display_warning("grLfbConstantAlpha");2308}23092310FX_ENTRY void FX_CALL2311grTexMultibaseAddress( GrChipID_t tmu,2312GrTexBaseRange_t range,2313FxU32 startAddress,2314FxU32 evenOdd,2315GrTexInfo *info )2316{2317display_warning("grTexMultibaseAddress");2318}23192320/*2321inline void MySleep(FxU32 ms)2322{2323#ifdef _WIN322324Sleep(ms);2325#else2326SDL_Delay(ms);2327#endif2328}2329*/23302331#ifdef _WIN322332static void CorrectGamma(LPVOID apGammaRamp)2333{2334HDC hdc = GetDC(NULL);2335if (hdc != NULL)2336{2337SetDeviceGammaRamp(hdc, apGammaRamp);2338ReleaseDC(NULL, hdc);2339}2340}2341#else2342static void CorrectGamma(const FxU16 aGammaRamp[3][256])2343{2344//TODO?2345//int res = SDL_SetGammaRamp(aGammaRamp[0], aGammaRamp[1], aGammaRamp[2]);2346//LOG("SDL_SetGammaRamp returned %d\r\n", res);2347}2348#endif23492350FX_ENTRY void FX_CALL2351grLoadGammaTable( FxU32 nentries, FxU32 *red, FxU32 *green, FxU32 *blue)2352{2353LOG("grLoadGammaTable\r\n");2354if (!fullscreen)2355return;2356FxU16 aGammaRamp[3][256];2357for (int i = 0; i < 256; i++)2358{2359aGammaRamp[0][i] = (FxU16)((red[i] << 8) & 0xFFFF);2360aGammaRamp[1][i] = (FxU16)((green[i] << 8) & 0xFFFF);2361aGammaRamp[2][i] = (FxU16)((blue[i] << 8) & 0xFFFF);2362}2363CorrectGamma(aGammaRamp);2364//MySleep(1000); //workaround for Mupen642365}23662367FX_ENTRY void FX_CALL2368grGetGammaTableExt(FxU32 nentries, FxU32 *red, FxU32 *green, FxU32 *blue)2369{2370return;2371//TODO?2372/*2373LOG("grGetGammaTableExt()\r\n");2374FxU16 aGammaRamp[3][256];2375#ifdef _WIN322376HDC hdc = GetDC(NULL);2377if (hdc == NULL)2378return;2379if (GetDeviceGammaRamp(hdc, aGammaRamp) == TRUE)2380{2381ReleaseDC(NULL, hdc);2382#else2383if (SDL_GetGammaRamp(aGammaRamp[0], aGammaRamp[1], aGammaRamp[2]) != -1)2384{2385#endif2386for (int i = 0; i < 256; i++)2387{2388red[i] = aGammaRamp[0][i] >> 8;2389green[i] = aGammaRamp[1][i] >> 8;2390blue[i] = aGammaRamp[2][i] >> 8;2391}2392}2393*/2394}23952396FX_ENTRY void FX_CALL2397guGammaCorrectionRGB( FxFloat gammaR, FxFloat gammaG, FxFloat gammaB )2398{2399LOG("guGammaCorrectionRGB()\r\n");2400if (!fullscreen)2401return;2402FxU16 aGammaRamp[3][256];2403for (int i = 0; i < 256; i++)2404{2405aGammaRamp[0][i] = (((FxU16)((pow(i/255.0F, 1.0F/gammaR)) * 255.0F + 0.5F)) << 8) & 0xFFFF;2406aGammaRamp[1][i] = (((FxU16)((pow(i/255.0F, 1.0F/gammaG)) * 255.0F + 0.5F)) << 8) & 0xFFFF;2407aGammaRamp[2][i] = (((FxU16)((pow(i/255.0F, 1.0F/gammaB)) * 255.0F + 0.5F)) << 8) & 0xFFFF;2408}2409CorrectGamma(aGammaRamp);2410}24112412FX_ENTRY void FX_CALL2413grDitherMode( GrDitherMode_t mode )2414{2415display_warning("grDitherMode");2416}24172418void grChromaRangeExt(GrColor_t color0, GrColor_t color1, FxU32 mode)2419{2420display_warning("grChromaRangeExt");2421}24222423void grChromaRangeModeExt(GrChromakeyMode_t mode)2424{2425display_warning("grChromaRangeModeExt");2426}24272428void grTexChromaRangeExt(GrChipID_t tmu, GrColor_t color0, GrColor_t color1, GrTexChromakeyMode_t mode)2429{2430display_warning("grTexChromaRangeExt");2431}24322433void grTexChromaModeExt(GrChipID_t tmu, GrChromakeyMode_t mode)2434{2435display_warning("grTexChromaRangeModeExt");2436}24372438// VP debug2439#ifdef VPDEBUG2440int dumping = 0;2441static int tl_i;2442static int tl[10240];24432444void dump_start()2445{2446static int init;2447if (!init) {2448init = 1;2449ilInit();2450ilEnable(IL_FILE_OVERWRITE);2451}2452dumping = 1;2453tl_i = 0;2454}24552456void dump_stop()2457{2458if (!dumping) return;24592460int i, j;2461for (i=0; i<nb_fb; i++) {2462dump_tex(fbs[i].texid);2463}2464dump_tex(default_texture);2465dump_tex(depth_texture);24662467dumping = 0;24682469glReadBuffer(GL_FRONT);2470glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, frameBuffer);2471ilTexImage(width, height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, frameBuffer);2472ilSaveImage("dump/framecolor.png");2473glReadPixels(0, 0, width, height, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, depthBuffer);2474// FILE * fp = fopen("glide_depth1.bin", "rb");2475// fread(depthBuffer, 2, width*height, fp);2476// fclose(fp);2477for (j=0; j<height; j++) {2478for (i=0; i<width; i++) {2479//uint16_t d = ( (uint16_t *)depthBuffer )[i+(height-1-j)*width]/2 + 0x8000;2480uint16_t d = ( (uint16_t *)depthBuffer )[i+j*width];2481uint32_t c = ( (uint32_t *)frameBuffer )[i+j*width];2482( (unsigned char *)frameBuffer )[(i+j*width)*3] = d&0xff;2483( (unsigned char *)frameBuffer )[(i+j*width)*3+1] = d>>8;2484( (unsigned char *)frameBuffer )[(i+j*width)*3+2] = c&0xff;2485}2486}2487ilTexImage(width, height, 1, 3, IL_RGB, IL_UNSIGNED_BYTE, frameBuffer);2488ilSaveImage("dump/framedepth.png");24892490for (i=0; i<tl_i; i++) {2491glBindTexture(GL_TEXTURE_2D, tl[i]);2492GLint w, h, fmt;2493glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);2494glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);2495glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt);2496fprintf(stderr, "Texture %d %dx%d fmt %x\n", tl[i], (int)w, (int)h, (int) fmt);24972498uint32_t * pixels = (uint32_t *) malloc(w*h*4);2499// 0x1902 is another constant meaning GL_DEPTH_COMPONENT2500// (but isn't defined in gl's headers !!)2501if (fmt != GL_DEPTH_COMPONENT && fmt != 0x1902) {2502glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);2503ilTexImage(w, h, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, pixels);2504} else {2505glGetTexImage(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, pixels);2506int i;2507for (i=0; i<w*h; i++)2508((unsigned char *)frameBuffer)[i] = ((unsigned short *)pixels)[i]/256;2509ilTexImage(w, h, 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, frameBuffer);2510}2511char name[128];2512// sprintf(name, "mkdir -p dump ; rm -f dump/tex%04d.png", i);2513// system(name);2514sprintf(name, "dump/tex%04d.png", i);2515fprintf(stderr, "Writing '%s'\n", name);2516ilSaveImage(name);25172518// SDL_FreeSurface(surf);2519free(pixels);2520}2521glBindTexture(GL_TEXTURE_2D, default_texture);2522}25232524void dump_tex(int id)2525{2526if (!dumping) return;25272528int n;2529// yes, it's inefficient2530for (n=0; n<tl_i; n++)2531if (tl[n] == id)2532return;25332534tl[tl_i++] = id;25352536int i = tl_i-1;2537}25382539#endif254025412542