668cff99701163c8fa708fafa240afc5e346fb39
[mupen64plus-pandora.git] / source / gles2glide64 / src / Glitch64 / glitchmain.cpp
1 /*
2 * Glide64 - Glide video plugin for Nintendo 64 emulators.
3 * Copyright (c) 2002  Dave2001
4 * Copyright (c) 2003-2009  Sergey 'Gonetz' Lipski
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21 #define SAVE_CBUFFER
22
23 #ifdef _WIN32
24 #include <windows.h>
25 #include <commctrl.h>
26 #else
27 #include <stdint.h>
28 #include <stdarg.h>
29 #include <string.h>
30 #include <SDL.h>
31 #endif // _WIN32
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <iostream>
35 #include <fstream>
36 #include <math.h>
37 #include "glide.h"
38 #include "g3ext.h"
39 #include "main.h"
40 #include "m64p.h"
41
42 #define OPENGL_CHECK_ERRORS { const GLenum errcode = glGetError(); if (errcode != GL_NO_ERROR) LOG("OpenGL Error code %i in '%s' line %i\n", errcode, __FILE__, __LINE__-1); }
43
44 #ifdef VPDEBUG
45 #include <IL/il.h>
46 #endif
47
48 #include "../Glide64/ticks.h"   //*SEB*
49
50 extern void (*renderCallback)(int);
51
52 wrapper_config config = {0, 0, 0, 0};
53 int screen_width, screen_height;
54
55 /*
56 static inline void opt_glCopyTexImage2D( GLenum target,
57                                         GLint level,
58                                         GLenum internalFormat,
59                                         GLint x,
60                                         GLint y,
61                                         GLsizei width,
62                                         GLsizei height,
63                                         GLint border )
64
65 {
66   int w, h, fmt;
67   glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
68   glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
69   glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt);
70   //printf("copyteximage %dx%d fmt %x oldfmt %x\n", width, height, internalFormat, fmt);
71   if (w == (int) width && h == (int) height && fmt == (int) internalFormat) {
72     if (x+width >= screen_width) {
73       width = screen_width - x;
74       //printf("resizing w --> %d\n", width);
75     }
76     if (y+height >= screen_height+viewport_offset) {
77       height = screen_height+viewport_offset - y;
78       //printf("resizing h --> %d\n", height);
79     }
80     glCopyTexSubImage2D(target, level, 0, 0, x, y, width, height);
81   } else {
82     //printf("copyteximage %dx%d fmt %x old %dx%d oldfmt %x\n", width, height, internalFormat, w, h, fmt);
83     //       glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, internalFormat, GL_UNSIGNED_BYTE, 0);
84     //       glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt);
85     //       printf("--> %dx%d newfmt %x\n", width, height, fmt);
86     glCopyTexImage2D(target, level, internalFormat, x, y, width, height, border);
87   }
88 }
89 #define glCopyTexImage2D opt_glCopyTexImage2D
90 */
91
92
93 #ifdef _WIN32
94 PFNGLACTIVETEXTUREARBPROC glActiveTextureARB;
95 PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT;
96 PFNGLMULTITEXCOORD2FARBPROC glMultiTexCoord2fARB;
97 PFNGLFOGCOORDFPROC glFogCoordfEXT;
98
99 PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB;
100
101 PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT;
102 PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT;
103 PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT;
104 PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT = NULL;
105 PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT = NULL;
106 PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT = NULL;
107 PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT = NULL;
108 PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT = NULL;
109 PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT;
110 PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT;
111
112 PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB;
113 PFNGLSHADERSOURCEARBPROC glShaderSourceARB;
114 PFNGLCOMPILESHADERARBPROC glCompileShaderARB;
115 PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB;
116 PFNGLATTACHOBJECTARBPROC glAttachObjectARB;
117 PFNGLLINKPROGRAMARBPROC glLinkProgramARB;
118 PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB;
119 PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB;
120 PFNGLUNIFORM1IARBPROC glUniform1iARB;
121 PFNGLUNIFORM4IARBPROC glUniform4iARB;
122 PFNGLUNIFORM4FARBPROC glUniform4fARB;
123 PFNGLUNIFORM1FARBPROC glUniform1fARB;
124 PFNGLDELETEOBJECTARBPROC glDeleteObjectARB;
125 PFNGLGETINFOLOGARBPROC glGetInfoLogARB;
126 PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB;
127 PFNGLSECONDARYCOLOR3FPROC glSecondaryColor3f;
128
129 // FXT1,DXT1,DXT5 support - Hiroshi Morii <koolsmoky(at)users.sourceforge.net>
130 // NOTE: Glide64 + GlideHQ use the following formats
131 // GL_COMPRESSED_RGB_S3TC_DXT1_EXT
132 // GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
133 // GL_COMPRESSED_RGB_FXT1_3DFX
134 // GL_COMPRESSED_RGBA_FXT1_3DFX
135 PFNGLCOMPRESSEDTEXIMAGE2DPROC glCompressedTexImage2DARB;
136 #endif // _WIN32
137
138
139
140 typedef struct
141 {
142   unsigned int address;
143   int width;
144   int height;
145   int fb_width;
146   int fb_height;
147   unsigned int fbid;
148   unsigned int zbid;
149   unsigned int texid;
150   int buff_clear;
151 } fb;
152
153 int nbTextureUnits;
154 int nbAuxBuffers, current_buffer;
155 int width, widtho, heighto, height;
156 int saved_width, saved_height;
157 int blend_func_separate_support;
158 int npot_support;
159 int fog_coord_support;
160 int render_to_texture = 0;
161 int texture_unit;
162 int use_fbo;
163 int buffer_cleared;
164 // ZIGGY
165 // to allocate a new static texture name, take the value (free_texture++)
166 int free_texture;
167 int default_texture; // the infamous "32*1024*1024" is now configurable
168 int current_texture;
169 int depth_texture, color_texture;
170 int glsl_support = 1;
171 int viewport_width, viewport_height, viewport_offset = 0, nvidia_viewport_hack = 0;
172 int save_w, save_h;
173 int lfb_color_fmt;
174 float invtex[2];
175 //Gonetz
176 int UMAmode = 0; //support for VSA-100 UMA mode;
177
178 #ifdef _WIN32
179 static HDC hDC = NULL;
180 static HGLRC hGLRC = NULL;
181 static HWND hToolBar = NULL;
182 static HWND hwnd_win = NULL;
183 static unsigned long windowedExStyle, windowedStyle;
184 #endif // _WIN32
185 static unsigned long fullscreen;
186 #ifdef _WIN32
187 static RECT windowedRect;
188 static HMENU windowedMenu;
189 #endif // _WIN32
190
191 static int savedWidtho, savedHeighto;
192 static int savedWidth, savedHeight;
193 unsigned int pBufferAddress;
194 static int pBufferFmt;
195 static int pBufferWidth, pBufferHeight;
196 static fb fbs[100];
197 static int nb_fb = 0;
198 static unsigned int curBufferAddr = 0;
199
200 struct TMU_USAGE { int min, max; } tmu_usage[2] = { {0xfffffff, 0}, {0xfffffff, 0} };
201
202 struct texbuf_t {
203   FxU32 start, end;
204   int fmt;
205 };
206 #define NB_TEXBUFS 128 // MUST be a power of two
207 static texbuf_t texbufs[NB_TEXBUFS];
208 static int texbuf_i;
209
210 unsigned short frameBuffer[2048*2048];
211 unsigned short depthBuffer[2048*2048];
212
213 //#define VOODOO1
214
215 void display_warning(const char *text, ...)
216 {
217   static int first_message = 100;
218   if (first_message)
219   {
220     char buf[4096];
221
222     va_list ap;
223
224     va_start(ap, text);
225     vsprintf(buf, text, ap);
226     va_end(ap);
227     first_message--;
228     LOGINFO(buf);
229   }
230 }
231
232 #ifdef _WIN32
233 void display_error()
234 {
235   LPVOID lpMsgBuf;
236   if (!FormatMessage(
237     FORMAT_MESSAGE_ALLOCATE_BUFFER |
238     FORMAT_MESSAGE_FROM_SYSTEM |
239     FORMAT_MESSAGE_IGNORE_INSERTS,
240     NULL,
241     GetLastError(),
242     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
243     (LPTSTR) &lpMsgBuf,
244     0,
245     NULL ))
246   {
247     // Handle the error.
248     return;
249   }
250   // Process any inserts in lpMsgBuf.
251   // ...
252   // Display the string.
253   MessageBox( NULL, (LPCTSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
254
255   // Free the buffer.
256   LocalFree( lpMsgBuf );
257 }
258 #endif // _WIN32
259
260 #ifdef LOGGING
261 char out_buf[256];
262 bool log_open = false;
263 std::ofstream log_file;
264
265 void OPEN_LOG()
266 {
267   if (!log_open)
268   {
269     log_file.open ("wrapper_log.txt", std::ios_base::out|std::ios_base::app);
270     log_open = true;
271   }
272 }
273
274 void CLOSE_LOG()
275 {
276   if (log_open)
277   {
278     log_file.close();
279     log_open = false;
280   }
281 }
282
283 void LOG(const char *text, ...)
284 {
285 #ifdef VPDEBUG
286   if (!dumping) return;
287 #endif
288         if (!log_open)
289     return;
290         va_list ap;
291         va_start(ap, text);
292         vsprintf(out_buf, text, ap);
293   log_file << out_buf;
294   log_file.flush();
295         va_end(ap);
296 }
297
298 class LogManager {
299 public:
300         LogManager() {
301                 OPEN_LOG();
302         }
303         ~LogManager() {
304                 CLOSE_LOG();
305         }
306 };
307
308 LogManager logManager;
309
310 #else // LOGGING
311 #define OPEN_LOG()
312 #define CLOSE_LOG()
313 //#define LOG
314 #endif // LOGGING
315
316 FX_ENTRY void FX_CALL
317 grSstOrigin(GrOriginLocation_t  origin)
318 {
319   LOG("grSstOrigin(%d)\r\n", origin);
320   if (origin != GR_ORIGIN_UPPER_LEFT)
321     display_warning("grSstOrigin : %x", origin);
322 }
323
324 FX_ENTRY void FX_CALL
325 grClipWindow( FxU32 minx, FxU32 miny, FxU32 maxx, FxU32 maxy )
326 {
327   LOG("grClipWindow(%d,%d,%d,%d)\r\n", minx, miny, maxx, maxy);
328
329   if (use_fbo && render_to_texture) {
330     if (int(minx) < 0) minx = 0;
331     if (int(miny) < 0) miny = 0;
332     if (maxx < minx) maxx = minx;
333     if (maxy < miny) maxy = miny;
334     glScissor(minx, miny, maxx - minx, maxy - miny);
335     glEnable(GL_SCISSOR_TEST);
336     return;
337   }
338
339   if (!use_fbo) {
340     int th = height;
341     if (th > screen_height)
342       th = screen_height;
343     maxy = th - maxy;
344     miny = th - miny;
345     FxU32 tmp = maxy; maxy = miny; miny = tmp;
346     if (maxx > (FxU32) width) maxx = width;
347     if (maxy > (FxU32) height) maxy = height;
348     if (int(minx) < 0) minx = 0;
349     if (int(miny) < 0) miny = 0;
350     if (maxx < minx) maxx = minx;
351     if (maxy < miny) maxy = miny;
352     glScissor(minx, miny+viewport_offset, maxx - minx, maxy - miny);
353     //printf("gl scissor %d %d %d %d\n", minx, miny, maxx, maxy);
354   } else {
355     glScissor(minx, (viewport_offset)+height-maxy, maxx - minx, maxy - miny);
356   }
357   glEnable(GL_SCISSOR_TEST);
358 }
359
360 FX_ENTRY void FX_CALL
361 grColorMask( FxBool rgb, FxBool a )
362 {
363   LOG("grColorMask(%d, %d)\r\n", rgb, a);
364   glColorMask(rgb, rgb, rgb, a);
365 }
366
367 FX_ENTRY void FX_CALL
368 grGlideInit( void )
369 {
370   LOG("grGlideInit()\r\n");
371 }
372
373 FX_ENTRY void FX_CALL
374 grSstSelect( int which_sst )
375 {
376   LOG("grSstSelect(%d)\r\n", which_sst);
377 }
378
379 int isExtensionSupported(const char *extension)
380 {
381   return 0;
382   const GLubyte *extensions = NULL;
383   const GLubyte *start;
384   GLubyte *where, *terminator;
385
386   where = (GLubyte *)strchr(extension, ' ');
387   if (where || *extension == '\0')
388     return 0;
389
390   extensions = glGetString(GL_EXTENSIONS);
391
392   start = extensions;
393   for (;;)
394   {
395     where = (GLubyte *) strstr((const char *) start, extension);
396     if (!where)
397       break;
398
399     terminator = where + strlen(extension);
400     if (where == start || *(where - 1) == ' ')
401       if (*terminator == ' ' || *terminator == '\0')
402         return 1;
403
404     start = terminator;
405   }
406
407   return 0;
408 }
409
410 #ifdef _WIN32
411 int isWglExtensionSupported(const char *extension)
412 {
413   const GLubyte *extensions = NULL;
414   const GLubyte *start;
415   GLubyte *where, *terminator;
416
417   where = (GLubyte *)strchr(extension, ' ');
418   if (where || *extension == '\0')
419     return 0;
420
421   extensions = (GLubyte*)wglGetExtensionsStringARB(wglGetCurrentDC());
422
423   start = extensions;
424   for (;;)
425   {
426     where = (GLubyte *) strstr((const char *) start, extension);
427     if (!where)
428       break;
429
430     terminator = where + strlen(extension);
431     if (where == start || *(where - 1) == ' ')
432       if (*terminator == ' ' || *terminator == '\0')
433         return 1;
434
435     start = terminator;
436   }
437
438   return 0;
439 }
440 #endif // _WIN32
441
442 #define GrPixelFormat_t int
443
444 FX_ENTRY GrContext_t FX_CALL
445 grSstWinOpenExt(
446                 HWND                 hWnd,
447                 GrScreenResolution_t screen_resolution,
448                 GrScreenRefresh_t    refresh_rate,
449                 GrColorFormat_t      color_format,
450                 GrOriginLocation_t   origin_location,
451                 GrPixelFormat_t      pixelformat,
452                 int                  nColBuffers,
453                 int                  nAuxBuffers)
454 {
455   LOG("grSstWinOpenExt(%d, %d, %d, %d, %d, %d %d)\r\n", hWnd, screen_resolution, refresh_rate, color_format, origin_location, nColBuffers, nAuxBuffers);
456   return grSstWinOpen(hWnd, screen_resolution, refresh_rate, color_format,
457     origin_location, nColBuffers, nAuxBuffers);
458 }
459
460 #ifdef WIN32
461 # include <fcntl.h>
462 # ifndef ATTACH_PARENT_PROCESS
463 #  define ATTACH_PARENT_PROCESS ((FxU32)-1)
464 # endif
465 #endif
466
467 FX_ENTRY GrContext_t FX_CALL
468 grSstWinOpen(
469              HWND                 hWnd,
470              GrScreenResolution_t screen_resolution,
471              GrScreenRefresh_t    refresh_rate,
472              GrColorFormat_t      color_format,
473              GrOriginLocation_t   origin_location,
474              int                  nColBuffers,
475              int                  nAuxBuffers)
476 {
477   static int show_warning = 1;
478
479   // ZIGGY
480   // allocate static texture names
481   // the initial value should be big enough to support the maximal resolution
482   free_texture = 32*2048*2048;
483   default_texture = free_texture++;
484   color_texture = free_texture++;
485   depth_texture = free_texture++;
486
487   LOG("grSstWinOpen(%08lx, %d, %d, %d, %d, %d %d)\r\n", hWnd, screen_resolution&~0x80000000, refresh_rate, color_format, origin_location, nColBuffers, nAuxBuffers);
488
489 #ifdef _WIN32
490   if ((HWND)hWnd == NULL) hWnd = GetActiveWindow();
491   hwnd_win = (HWND)hWnd;
492 #endif // _WIN32
493   width = height = 0;
494
495   m64p_handle video_general_section;
496   printf("&ConfigOpenSection is %p\n", &ConfigOpenSection);
497   if (ConfigOpenSection("Video-General", &video_general_section) != M64ERR_SUCCESS)
498   {
499     printf("Could not open video settings");
500     return false;
501   }
502   width = ConfigGetParamInt(video_general_section, "ScreenWidth");
503   height = ConfigGetParamInt(video_general_section, "ScreenHeight");
504   fullscreen = ConfigGetParamBool(video_general_section, "Fullscreen");
505   int vsync = ConfigGetParamBool(video_general_section, "VerticalSync");
506   //viewport_offset = ((screen_resolution>>2) > 20) ? screen_resolution >> 2 : 20;
507   // ZIGGY viewport_offset is WIN32 specific, with SDL just set it to zero
508   viewport_offset = 0; //-10 //-20;
509
510   CoreVideo_Init();
511   CoreVideo_GL_SetAttribute(M64P_GL_DOUBLEBUFFER, 1);
512   CoreVideo_GL_SetAttribute(M64P_GL_SWAP_CONTROL, vsync);
513   CoreVideo_GL_SetAttribute(M64P_GL_BUFFER_SIZE, 16);
514   //   SDL_GL_SetAttribute(SDL_GL_BUFFER_SIZE, 32);
515   //   SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
516   //   SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
517   //   SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
518   //   SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
519   CoreVideo_GL_SetAttribute(M64P_GL_DEPTH_SIZE, 16);
520
521   printf("(II) Setting video mode %dx%d...\n", width, height);
522   if(CoreVideo_SetVideoMode(width, height, 0, fullscreen ? M64VIDEO_FULLSCREEN : M64VIDEO_WINDOWED, (m64p_video_flags) 0) != M64ERR_SUCCESS)
523   {
524     printf("(EE) Error setting videomode %dx%d\n", width, height);
525     return false;
526   }
527
528   char caption[500];
529 # ifdef _DEBUG
530   sprintf(caption, "Glide64mk2 debug");
531 # else // _DEBUG
532   sprintf(caption, "Glide64mk2");
533 # endif // _DEBUG
534   CoreVideo_SetCaption(caption);
535
536   glViewport(0, viewport_offset, width, height);
537   lfb_color_fmt = color_format;
538   if (origin_location != GR_ORIGIN_UPPER_LEFT) display_warning("origin must be in upper left corner");
539   if (nColBuffers != 2) display_warning("number of color buffer is not 2");
540   if (nAuxBuffers != 1) display_warning("number of auxiliary buffer is not 1");
541
542   if (isExtensionSupported("GL_ARB_texture_env_combine") == 0 &&
543     isExtensionSupported("GL_EXT_texture_env_combine") == 0 &&
544     show_warning)
545     display_warning("Your video card doesn't support GL_ARB_texture_env_combine extension");
546   if (isExtensionSupported("GL_ARB_multitexture") == 0 && show_warning)
547     display_warning("Your video card doesn't support GL_ARB_multitexture extension");
548   if (isExtensionSupported("GL_ARB_texture_mirrored_repeat") == 0 && show_warning)
549     display_warning("Your video card doesn't support GL_ARB_texture_mirrored_repeat extension");
550   show_warning = 0;
551
552 #ifdef _WIN32
553   glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC)wglGetProcAddress("glActiveTextureARB");
554   glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FARBPROC)wglGetProcAddress("glMultiTexCoord2fARB");
555 #endif // _WIN32
556
557   nbTextureUnits = 4;
558   //glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &nbTextureUnits);
559   if (nbTextureUnits == 1) display_warning("You need a video card that has at least 2 texture units");
560
561   nbAuxBuffers = 4;
562   //glGetIntegerv(GL_AUX_BUFFERS, &nbAuxBuffers);
563   if (nbAuxBuffers > 0)
564     printf("Congratulations, you have %d auxilliary buffers, we'll use them wisely !\n", nbAuxBuffers);
565 #ifdef VOODOO1
566   nbTextureUnits = 2;
567 #endif
568
569   blend_func_separate_support = 1;
570   packed_pixels_support = 0;
571 /*
572   if (isExtensionSupported("GL_EXT_blend_func_separate") == 0)
573     blend_func_separate_support = 0;
574   else
575     blend_func_separate_support = 1;
576
577   if (isExtensionSupported("GL_EXT_packed_pixels") == 0)
578     packed_pixels_support = 0;
579   else {
580     printf("packed pixels extension used\n");
581     packed_pixels_support = 1;
582   }
583 */
584
585   if (isExtensionSupported("GL_ARB_texture_non_power_of_two") == 0)
586     npot_support = 0;
587   else {
588     printf("NPOT extension used\n");
589     npot_support = 1;
590   }
591
592 #ifdef _WIN32
593   glBlendFuncSeparateEXT = (PFNGLBLENDFUNCSEPARATEEXTPROC)wglGetProcAddress("glBlendFuncSeparateEXT");
594 #endif // _WIN32
595
596   if (isExtensionSupported("GL_EXT_fog_coord") == 0)
597     fog_coord_support = 0;
598   else
599     fog_coord_support = 1;
600
601 #ifdef _WIN32
602   glFogCoordfEXT = (PFNGLFOGCOORDFPROC)wglGetProcAddress("glFogCoordfEXT");
603 #endif // _WIN32
604
605 #ifdef _WIN32
606   wglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)wglGetProcAddress("wglGetExtensionsStringARB");
607 #endif // _WIN32
608
609 #ifdef _WIN32
610   glBindFramebufferEXT = (PFNGLBINDFRAMEBUFFEREXTPROC)wglGetProcAddress("glBindFramebufferEXT");
611   glFramebufferTexture2DEXT = (PFNGLFRAMEBUFFERTEXTURE2DEXTPROC)wglGetProcAddress("glFramebufferTexture2DEXT");
612   glGenFramebuffersEXT = (PFNGLGENFRAMEBUFFERSEXTPROC)wglGetProcAddress("glGenFramebuffersEXT");
613   glCheckFramebufferStatusEXT = (PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC)wglGetProcAddress("glCheckFramebufferStatusEXT");
614   glDeleteFramebuffersEXT = (PFNGLDELETEFRAMEBUFFERSEXTPROC)wglGetProcAddress("glDeleteFramebuffersEXT");
615
616   glBindRenderbufferEXT = (PFNGLBINDRENDERBUFFEREXTPROC)wglGetProcAddress("glBindRenderbufferEXT");
617   glDeleteRenderbuffersEXT = (PFNGLDELETERENDERBUFFERSEXTPROC)wglGetProcAddress("glDeleteRenderbuffersEXT");
618   glGenRenderbuffersEXT = (PFNGLGENRENDERBUFFERSEXTPROC)wglGetProcAddress("glGenRenderbuffersEXT");
619   glRenderbufferStorageEXT = (PFNGLRENDERBUFFERSTORAGEEXTPROC)wglGetProcAddress("glRenderbufferStorageEXT");
620   glFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC)wglGetProcAddress("glFramebufferRenderbufferEXT");
621   use_fbo = config.fbo && (glFramebufferRenderbufferEXT != NULL);
622 #else
623   use_fbo = config.fbo;
624 #endif // _WIN32
625
626   LOGINFO("use_fbo %d\n", use_fbo);
627
628   if (isExtensionSupported("GL_ARB_shading_language_100") &&
629     isExtensionSupported("GL_ARB_shader_objects") &&
630     isExtensionSupported("GL_ARB_fragment_shader") &&
631     isExtensionSupported("GL_ARB_vertex_shader"))
632   {
633
634 #ifdef _WIN32
635     glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC)wglGetProcAddress("glCreateShaderObjectARB");
636     glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC)wglGetProcAddress("glShaderSourceARB");
637     glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC)wglGetProcAddress("glCompileShaderARB");
638     glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC)wglGetProcAddress("glCreateProgramObjectARB");
639     glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC)wglGetProcAddress("glAttachObjectARB");
640     glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC)wglGetProcAddress("glLinkProgramARB");
641     glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC)wglGetProcAddress("glUseProgramObjectARB");
642     glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC)wglGetProcAddress("glGetUniformLocationARB");
643     glUniform1iARB = (PFNGLUNIFORM1IARBPROC)wglGetProcAddress("glUniform1iARB");
644     glUniform4iARB = (PFNGLUNIFORM4IARBPROC)wglGetProcAddress("glUniform4iARB");
645     glUniform4fARB = (PFNGLUNIFORM4FARBPROC)wglGetProcAddress("glUniform4fARB");
646     glUniform1fARB = (PFNGLUNIFORM1FARBPROC)wglGetProcAddress("glUniform1fARB");
647     glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC)wglGetProcAddress("glDeleteObjectARB");
648     glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC)wglGetProcAddress("glGetInfoLogARB");
649     glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC)wglGetProcAddress("glGetObjectParameterivARB");
650
651     glSecondaryColor3f = (PFNGLSECONDARYCOLOR3FPROC)wglGetProcAddress("glSecondaryColor3f");
652 #endif // _WIN32
653   }
654
655   if (isExtensionSupported("GL_EXT_texture_compression_s3tc") == 0  && show_warning)
656     display_warning("Your video card doesn't support GL_EXT_texture_compression_s3tc extension");
657   if (isExtensionSupported("GL_3DFX_texture_compression_FXT1") == 0  && show_warning)
658     display_warning("Your video card doesn't support GL_3DFX_texture_compression_FXT1 extension");
659
660 #ifdef _WIN32
661   glCompressedTexImage2DARB = (PFNGLCOMPRESSEDTEXIMAGE2DPROC)wglGetProcAddress("glCompressedTexImage2DARB");
662 #endif
663 /*SEB*/
664   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
665   glPixelStorei(GL_PACK_ALIGNMENT, 1);
666
667
668 #ifdef _WIN32
669   glViewport(0, viewport_offset, width, height);
670   viewport_width = width;
671   viewport_height = height;
672   nvidia_viewport_hack = 1;
673 #else
674   glViewport(0, viewport_offset, width, height);
675   viewport_width = width;
676   viewport_height = height;
677 #endif // _WIN32
678
679   //   void do_benchmarks();
680   //   do_benchmarks();
681
682   // VP try to resolve z precision issues
683 //  glMatrixMode(GL_MODELVIEW);
684 //  glLoadIdentity();
685 //  glTranslatef(0, 0, 1-zscale);
686 //  glScalef(1, 1, zscale);
687
688   widtho = width/2;
689   heighto = height/2;
690
691   pBufferWidth = pBufferHeight = -1;
692
693   current_buffer = GL_BACK;
694
695   texture_unit = GL_TEXTURE0;
696
697   {
698     int i;
699     for (i=0; i<NB_TEXBUFS; i++)
700       texbufs[i].start = texbufs[i].end = 0xffffffff;
701   }
702
703   if (!use_fbo && nbAuxBuffers == 0) {
704     // create the framebuffer saving texture
705     int w = width, h = height;
706     glBindTexture(GL_TEXTURE_2D, color_texture);
707     if (!npot_support) {
708       w = h = 1;
709       while (w<width) w*=2;
710       while (h<height) h*=2;
711     }
712     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
713     glBindTexture(GL_TEXTURE_2D, 0);
714     save_w = save_h = 0;
715   }
716
717   void FindBestDepthBias();
718   FindBestDepthBias();
719
720   init_geometry();
721   init_textures();
722   init_combiner();
723
724 /*
725   // Aniso filter check
726   if (config.anisofilter > 0 )
727     glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &largest_supported_anisotropy);
728
729   // ATI hack - certain texture formats are slow on ATI?
730   // Hmm, perhaps the internal format need to be specified explicitly...
731   {
732     GLint ifmt;
733     glTexImage2D(GL_PROXY_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, NULL);
734     glGetTexLevelParameteriv(GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &ifmt);
735     if (ifmt != GL_RGB5_A1) {
736       display_warning("ATI SUCKS %x\n", ifmt);
737       ati_sucks = 1;
738     } else
739       ati_sucks = 0;
740   }
741 */
742
743   return 1;
744 }
745
746 FX_ENTRY void FX_CALL
747 grGlideShutdown( void )
748 {
749   LOG("grGlideShutdown\r\n");
750 }
751
752 FX_ENTRY FxBool FX_CALL
753 grSstWinClose( GrContext_t context )
754 {
755   int i, clear_texbuff = use_fbo;
756   LOG("grSstWinClose(%d)\r\n", context);
757
758   for (i=0; i<2; i++) {
759     tmu_usage[i].min = 0xfffffff;
760     tmu_usage[i].max = 0;
761     invtex[i] = 0;
762   }
763
764   free_combiners();
765 #ifndef WIN32
766   try // I don't know why, but opengl can be killed before this function call when emulator is closed (Gonetz).
767     // 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.
768   {
769     if (use_fbo)
770       glBindFramebuffer( GL_FRAMEBUFFER, 0 );
771   }
772   catch (...)
773   {
774     clear_texbuff = 0;
775   }
776
777   if (clear_texbuff)
778   {
779     for (i=0; i<nb_fb; i++)
780     {
781       glDeleteTextures( 1, &(fbs[i].texid) );
782       glDeleteFramebuffers( 1, &(fbs[i].fbid) );
783       glDeleteRenderbuffers( 1, &(fbs[i].zbid) );
784     }
785   }
786 #endif
787   nb_fb = 0;
788
789   free_textures();
790 #ifndef WIN32
791   // ZIGGY for some reasons, Pj64 doesn't like remove_tex on exit
792   remove_tex(0, 0xfffffff);
793 #endif
794
795   //*/
796 #ifdef _WIN32
797   if (hGLRC)
798   {
799     wglMakeCurrent(hDC,NULL);
800     wglDeleteContext(hGLRC);
801     hGLRC = NULL;
802   }
803   if (fullscreen)
804   {
805     ChangeDisplaySettings(NULL, 0);
806     SetWindowPos(hwnd_win, NULL,
807       windowedRect.left, windowedRect.top,
808       0, 0,
809       SWP_NOZORDER | SWP_NOSIZE);
810     SetWindowLong(hwnd_win, GWL_STYLE, windowedStyle);
811     SetWindowLong(hwnd_win, GWL_EXSTYLE, windowedExStyle);
812     if (windowedMenu) SetMenu(hwnd_win, windowedMenu);
813     fullscreen = 0;
814   }
815 #else
816   CoreVideo_Quit();
817   //SDL_QuitSubSystem(SDL_INIT_VIDEO);
818   //sleep(2);
819 #endif
820
821   CoreVideo_Quit();
822
823   return FXTRUE;
824 }
825
826 FX_ENTRY void FX_CALL grTextureBufferExt( GrChipID_t            tmu,
827                                          FxU32                          startAddress,
828                                          GrLOD_t                        lodmin,
829                                          GrLOD_t                        lodmax,
830                                          GrAspectRatio_t        aspect,
831                                          GrTextureFormat_t      fmt,
832                                          FxU32                          evenOdd)
833 {
834   int i;
835   static int fbs_init = 0;
836
837   LOG("grTextureBufferExt(%d, %d, %d, %d %d, %d, %d)\r\n", tmu, startAddress, lodmin, lodmax, aspect, fmt, evenOdd);
838   if (lodmin != lodmax) display_warning("grTextureBufferExt : loading more than one LOD");
839   if (!use_fbo) {
840
841     if (!render_to_texture) { //initialization
842       return;
843     }
844
845     render_to_texture = 2;
846
847     if (aspect < 0)
848     {
849       pBufferHeight = 1 << lodmin;
850       pBufferWidth = pBufferHeight >> -aspect;
851     }
852     else
853     {
854       pBufferWidth = 1 << lodmin;
855       pBufferHeight = pBufferWidth >> aspect;
856     }
857
858     if (curBufferAddr && startAddress+1 != curBufferAddr)
859       updateTexture();
860 #ifdef SAVE_CBUFFER
861     //printf("saving %dx%d\n", pBufferWidth, pBufferHeight);
862     // save color buffer
863     if (nbAuxBuffers > 0) {
864       //glDrawBuffer(GL_AUX0);
865       //current_buffer = GL_AUX0;
866     } else {
867       int tw, th;
868       if (pBufferWidth < screen_width)
869         tw = pBufferWidth;
870       else
871         tw = screen_width;
872       if (pBufferHeight < screen_height)
873         th = pBufferHeight;
874       else
875         th = screen_height;
876       //glReadBuffer(GL_BACK);
877       glActiveTexture(texture_unit);
878       glBindTexture(GL_TEXTURE_2D, color_texture);
879       // save incrementally the framebuffer
880       if (save_w) {
881         if (tw > save_w && th > save_h) {
882           glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, save_h,
883             0, viewport_offset+save_h, tw, th-save_h);
884           glCopyTexSubImage2D(GL_TEXTURE_2D, 0, save_w, 0,
885             save_w, viewport_offset, tw-save_w, save_h);
886           save_w = tw;
887           save_h = th;
888         } else if (tw > save_w) {
889           glCopyTexSubImage2D(GL_TEXTURE_2D, 0, save_w, 0,
890             save_w, viewport_offset, tw-save_w, save_h);
891           save_w = tw;
892         } else if (th > save_h) {
893           glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, save_h,
894             0, viewport_offset+save_h, save_w, th-save_h);
895           save_h = th;
896         }
897       } else {
898         glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
899           0, viewport_offset, tw, th);
900         save_w = tw;
901         save_h = th;
902       }
903       glBindTexture(GL_TEXTURE_2D, default_texture);
904     }
905 #endif
906
907     if (startAddress+1 != curBufferAddr ||
908       (curBufferAddr == 0L && nbAuxBuffers == 0))
909       buffer_cleared = 0;
910
911     curBufferAddr = pBufferAddress = startAddress+1;
912     pBufferFmt = fmt;
913
914     int rtmu = startAddress < grTexMinAddress(GR_TMU1)? 0 : 1;
915     int size = pBufferWidth*pBufferHeight*2; //grTexFormatSize(fmt);
916     if ((unsigned int) tmu_usage[rtmu].min > pBufferAddress)
917       tmu_usage[rtmu].min = pBufferAddress;
918     if ((unsigned int) tmu_usage[rtmu].max < pBufferAddress+size)
919       tmu_usage[rtmu].max = pBufferAddress+size;
920         //printf("tmu %d usage now %gMb - %gMb\n",
921     //      rtmu, tmu_usage[rtmu].min/1024.0f, tmu_usage[rtmu].max/1024.0f);
922
923
924     width = pBufferWidth;
925     height = pBufferHeight;
926
927     widtho = width/2;
928     heighto = height/2;
929
930     // this could be improved, but might be enough as long as the set of
931     // texture buffer addresses stay small
932     for (i=(texbuf_i-1)&(NB_TEXBUFS-1) ; i!=texbuf_i; i=(i-1)&(NB_TEXBUFS-1))
933       if (texbufs[i].start == pBufferAddress)
934         break;
935     texbufs[i].start = pBufferAddress;
936     texbufs[i].end = pBufferAddress + size;
937     texbufs[i].fmt = fmt;
938     if (i == texbuf_i)
939       texbuf_i = (texbuf_i+1)&(NB_TEXBUFS-1);
940         //printf("texbuf %x fmt %x\n", pBufferAddress, fmt);
941
942     // ZIGGY it speeds things up to not delete the buffers
943     // a better thing would be to delete them *sometimes*
944     //   remove_tex(pBufferAddress+1, pBufferAddress + size);
945     add_tex(pBufferAddress);
946
947         //printf("viewport %dx%d\n", width, height);
948     if (height > screen_height) {
949       glViewport( 0, viewport_offset + screen_height - height, width, height);
950     } else
951       glViewport( 0, viewport_offset, width, height);
952
953     glScissor(0, viewport_offset, width, height);
954
955
956   } else {
957     if (!render_to_texture) //initialization
958     {
959       if(!fbs_init)
960       {
961         for(i=0; i<100; i++) fbs[i].address = 0;
962         fbs_init = 1;
963         nb_fb = 0;
964       }
965       return; //no need to allocate FBO if render buffer is not texture buffer
966     }
967
968     render_to_texture = 2;
969
970     if (aspect < 0)
971     {
972       pBufferHeight = 1 << lodmin;
973       pBufferWidth = pBufferHeight >> -aspect;
974     }
975     else
976     {
977       pBufferWidth = 1 << lodmin;
978       pBufferHeight = pBufferWidth >> aspect;
979     }
980     pBufferAddress = startAddress+1;
981
982     width = pBufferWidth;
983     height = pBufferHeight;
984
985     widtho = width/2;
986     heighto = height/2;
987
988     for (i=0; i<nb_fb; i++)
989     {
990       if (fbs[i].address == pBufferAddress)
991       {
992 //        if (fbs[i].width == width && fbs[i].height == height) //select already allocated FBO
993         if (fbs[i].width >= width && fbs[i].height >= height) //select already allocated FBO, or large enough
994         {
995 //unsigned int tticks = ticksGetTicks();
996           glBindFramebuffer( GL_FRAMEBUFFER, 0 );
997           glBindFramebuffer( GL_FRAMEBUFFER, fbs[i].fbid );
998           glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbs[i].texid, 0 );
999           glBindRenderbuffer( GL_RENDERBUFFER, fbs[i].zbid );
1000           glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbs[i].zbid );
1001           glViewport( 0, 0, width, height);
1002           glScissor( 0, 0, width, height);
1003                   fbs[i].fb_width=width;
1004                   fbs[i].fb_height=height;
1005           if (fbs[i].buff_clear)
1006           {
1007             glDepthMask(1);
1008             glClear( GL_DEPTH_BUFFER_BIT ); //clear z-buffer only. we may need content, stored in the frame buffer
1009             fbs[i].buff_clear = 0;
1010           }
1011           CHECK_FRAMEBUFFER_STATUS();
1012           curBufferAddr = pBufferAddress;
1013 //printf("select existing fbo (%u ms)\n", ticksGetTicks()-tticks);
1014           return;
1015         }
1016         else //create new FBO at the same address, delete old one 
1017         {
1018 //unsigned int tticks = ticksGetTicks();
1019           glDeleteFramebuffers( 1, &(fbs[i].fbid) );
1020           glDeleteRenderbuffers( 1, &(fbs[i].zbid) );
1021           if (nb_fb > 1)
1022             memmove(&(fbs[i]), &(fbs[i+1]), sizeof(fb)*(nb_fb-i));
1023           nb_fb--;
1024 //printf("delete existing fbo (%u ms)\n", ticksGetTicks()-tticks);
1025           break;
1026         }
1027       }
1028     }
1029 //unsigned int tticks = ticksGetTicks();
1030     remove_tex(pBufferAddress, pBufferAddress + width*height*2/*grTexFormatSize(fmt)*/);
1031 //printf("delete texture (%u ms)\n", ticksGetTicks()-tticks);
1032     //create new FBO
1033     glGenFramebuffers( 1, &(fbs[nb_fb].fbid) );
1034     glGenRenderbuffers( 1, &(fbs[nb_fb].zbid) );
1035     glBindRenderbuffer( GL_RENDERBUFFER, fbs[nb_fb].zbid );
1036     glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
1037     fbs[nb_fb].address = pBufferAddress;
1038     fbs[nb_fb].width = width;
1039     fbs[nb_fb].height = height;
1040     fbs[nb_fb].fb_width = width;
1041     fbs[nb_fb].fb_height = height;
1042     fbs[nb_fb].texid = pBufferAddress;
1043     fbs[nb_fb].buff_clear = 0;
1044     add_tex(fbs[nb_fb].texid);
1045     glBindTexture(GL_TEXTURE_2D, fbs[nb_fb].texid);
1046     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0,
1047       GL_RGB, GL_UNSIGNED_BYTE, NULL);
1048     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
1049     glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
1050
1051     glBindFramebuffer( GL_FRAMEBUFFER, fbs[nb_fb].fbid);
1052     glFramebufferTexture2D(GL_FRAMEBUFFER,
1053       GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbs[nb_fb].texid, 0);
1054     glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbs[nb_fb].zbid );
1055     glViewport(0,0,width,height);
1056     glScissor(0,0,width,height);
1057     glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
1058     glDepthMask(1);
1059     glClear( GL_DEPTH_BUFFER_BIT );
1060     CHECK_FRAMEBUFFER_STATUS();
1061     curBufferAddr = pBufferAddress;
1062     nb_fb++;
1063 //printf("create new fbo=fb[%i] (%u ms)\n", nb_fb-1, ticksGetTicks()-tticks);
1064   }
1065 }
1066
1067 int CheckTextureBufferFormat(GrChipID_t tmu, FxU32 startAddress, GrTexInfo *info )
1068 {
1069   int found, i;
1070   if (!use_fbo) {
1071     for (found=i=0; i<2; i++)
1072       if ((FxU32) tmu_usage[i].min <= startAddress && (FxU32) tmu_usage[i].max > startAddress) {
1073         //printf("tmu %d == framebuffer %x\n", tmu, startAddress);
1074         found = 1;
1075         break;
1076       }
1077   } else {
1078     found = i = 0;
1079     while (i < nb_fb)
1080     {
1081       unsigned int end = fbs[i].address + fbs[i].fb_width*fbs[i].fb_height*2;
1082       if (startAddress >= fbs[i].address &&  startAddress < end)
1083       {
1084         found = 1;
1085         break;
1086       }
1087       i++;
1088     }
1089   }
1090
1091   if (!use_fbo && found) {
1092     int tw, th, rh, cw, ch;
1093     if (info->aspectRatioLog2 < 0)
1094     {
1095       th = 1 << info->largeLodLog2;
1096       tw = th >> -info->aspectRatioLog2;
1097     }
1098     else
1099     {
1100       tw = 1 << info->largeLodLog2;
1101       th = tw >> info->aspectRatioLog2;
1102     }
1103
1104     if (info->aspectRatioLog2 < 0)
1105     {
1106       ch = 256;
1107       cw = ch >> -info->aspectRatioLog2;
1108     }
1109     else
1110     {
1111       cw = 256;
1112       ch = cw >> info->aspectRatioLog2;
1113     }
1114
1115     if (use_fbo || th < screen_height)
1116       rh = th;
1117     else
1118       rh = screen_height;
1119
1120     //printf("th %d rh %d ch %d\n", th, rh, ch);
1121
1122     invtex[tmu] = 1.0f - (th - rh) / (float)th;
1123   } else
1124     invtex[tmu] = 0;
1125
1126   if (info->format == GR_TEXFMT_ALPHA_INTENSITY_88 ) {
1127     if (!found) {
1128       return 0;
1129     }
1130     if(tmu == 0)
1131     {
1132       if(blackandwhite1 != found)
1133       {
1134         blackandwhite1 = found;
1135         need_to_compile = 1;
1136       }
1137     }
1138     else
1139     {
1140       if(blackandwhite0 != found)
1141       {
1142         blackandwhite0 = found;
1143         need_to_compile = 1;
1144       }
1145     }
1146     return 1;
1147   }
1148   return 0;
1149
1150 }
1151
1152
1153 FX_ENTRY void FX_CALL
1154 grTextureAuxBufferExt( GrChipID_t tmu,
1155                       FxU32      startAddress,
1156                       GrLOD_t    thisLOD,
1157                       GrLOD_t    largeLOD,
1158                       GrAspectRatio_t aspectRatio,
1159                       GrTextureFormat_t format,
1160                       FxU32      odd_even_mask )
1161 {
1162   LOG("grTextureAuxBufferExt(%d, %d, %d, %d %d, %d, %d)\r\n", tmu, startAddress, thisLOD, largeLOD, aspectRatio, format, odd_even_mask);
1163   //display_warning("grTextureAuxBufferExt");
1164 }
1165
1166 FX_ENTRY void FX_CALL grAuxBufferExt( GrBuffer_t buffer );
1167
1168 FX_ENTRY GrProc FX_CALL
1169 grGetProcAddress( char *procName )
1170 {
1171   LOG("grGetProcAddress(%s)\r\n", procName);
1172   if(!strcmp(procName, "grSstWinOpenExt"))
1173     return (GrProc)grSstWinOpenExt;
1174   if(!strcmp(procName, "grTextureBufferExt"))
1175     return (GrProc)grTextureBufferExt;
1176   if(!strcmp(procName, "grChromaRangeExt"))
1177     return (GrProc)grChromaRangeExt;
1178   if(!strcmp(procName, "grChromaRangeModeExt"))
1179     return (GrProc)grChromaRangeModeExt;
1180   if(!strcmp(procName, "grTexChromaRangeExt"))
1181     return (GrProc)grTexChromaRangeExt;
1182   if(!strcmp(procName, "grTexChromaModeExt"))
1183     return (GrProc)grTexChromaModeExt;
1184   // ZIGGY framebuffer copy extension
1185   if(!strcmp(procName, "grFramebufferCopyExt"))
1186     return (GrProc)grFramebufferCopyExt;
1187   if(!strcmp(procName, "grColorCombineExt"))
1188     return (GrProc)grColorCombineExt;
1189   if(!strcmp(procName, "grAlphaCombineExt"))
1190     return (GrProc)grAlphaCombineExt;
1191   if(!strcmp(procName, "grTexColorCombineExt"))
1192     return (GrProc)grTexColorCombineExt;
1193   if(!strcmp(procName, "grTexAlphaCombineExt"))
1194     return (GrProc)grTexAlphaCombineExt;
1195   if(!strcmp(procName, "grConstantColorValueExt"))
1196     return (GrProc)grConstantColorValueExt;
1197   if(!strcmp(procName, "grTextureAuxBufferExt"))
1198     return (GrProc)grTextureAuxBufferExt;
1199   if(!strcmp(procName, "grAuxBufferExt"))
1200     return (GrProc)grAuxBufferExt;
1201   if(!strcmp(procName, "grWrapperFullScreenResolutionExt"))
1202     return (GrProc)grWrapperFullScreenResolutionExt;
1203   if(!strcmp(procName, "grConfigWrapperExt"))
1204     return (GrProc)grConfigWrapperExt;
1205   if(!strcmp(procName, "grKeyPressedExt"))
1206     return (GrProc)grKeyPressedExt;
1207   if(!strcmp(procName, "grQueryResolutionsExt"))
1208     return (GrProc)grQueryResolutionsExt;
1209   if(!strcmp(procName, "grGetGammaTableExt"))
1210     return (GrProc)grGetGammaTableExt;
1211   display_warning("grGetProcAddress : %s", procName);
1212   return 0;
1213 }
1214
1215 FX_ENTRY FxU32 FX_CALL
1216 grGet( FxU32 pname, FxU32 plength, FxI32 *params )
1217 {
1218   LOG("grGet(%d,%d)\r\n", pname, plength);
1219   switch(pname)
1220   {
1221   case GR_MAX_TEXTURE_SIZE:
1222     if (plength < 4 || params == NULL) return 0;
1223     params[0] = 2048;
1224     return 4;
1225     break;
1226   case GR_NUM_TMU:
1227     if (plength < 4 || params == NULL) return 0;
1228     if (!nbTextureUnits)
1229     {
1230       grSstWinOpen((unsigned long)NULL, GR_RESOLUTION_640x480 | 0x80000000, 0, GR_COLORFORMAT_ARGB,
1231         GR_ORIGIN_UPPER_LEFT, 2, 1);
1232       grSstWinClose(0);
1233     }
1234 #ifdef VOODOO1
1235     params[0] = 1;
1236 #else
1237     if (nbTextureUnits > 2)
1238       params[0] = 2;
1239     else
1240       params[0] = 1;
1241 #endif
1242     return 4;
1243     break;
1244   case GR_NUM_BOARDS:
1245   case GR_NUM_FB:
1246   case GR_REVISION_FB:
1247   case GR_REVISION_TMU:
1248     if (plength < 4 || params == NULL) return 0;
1249     params[0] = 1;
1250     return 4;
1251     break;
1252   case GR_MEMORY_FB:
1253     if (plength < 4 || params == NULL) return 0;
1254     params[0] = 16*1024*1024;
1255     return 4;
1256     break;
1257   case GR_MEMORY_TMU:
1258     if (plength < 4 || params == NULL) return 0;
1259     params[0] = 16*1024*1024;
1260     return 4;
1261     break;
1262   case GR_MEMORY_UMA:
1263     if (plength < 4 || params == NULL) return 0;
1264     params[0] = 16*1024*1024*nbTextureUnits;
1265     return 4;
1266     break;
1267   case GR_BITS_RGBA:
1268     if (plength < 16 || params == NULL) return 0;
1269     params[0] = 8;
1270     params[1] = 8;
1271     params[2] = 8;
1272     params[3] = 8;
1273     return 16;
1274     break;
1275   case GR_BITS_DEPTH:
1276     if (plength < 4 || params == NULL) return 0;
1277     params[0] = 16;
1278     return 4;
1279     break;
1280   case GR_BITS_GAMMA:
1281     if (plength < 4 || params == NULL) return 0;
1282     params[0] = 8;
1283     return 4;
1284     break;
1285   case GR_GAMMA_TABLE_ENTRIES:
1286     if (plength < 4 || params == NULL) return 0;
1287     params[0] = 256;
1288     return 4;
1289     break;
1290   case GR_FOG_TABLE_ENTRIES:
1291     if (plength < 4 || params == NULL) return 0;
1292     params[0] = 64;
1293     return 4;
1294     break;
1295   case GR_WDEPTH_MIN_MAX:
1296     if (plength < 8 || params == NULL) return 0;
1297     params[0] = 0;
1298     params[1] = 65528;
1299     return 8;
1300     break;
1301   case GR_ZDEPTH_MIN_MAX:
1302     if (plength < 8 || params == NULL) return 0;
1303     params[0] = 0;
1304     params[1] = 65535;
1305     return 8;
1306     break;
1307   case GR_LFB_PIXEL_PIPE:
1308     if (plength < 4 || params == NULL) return 0;
1309     params[0] = FXFALSE;
1310     return 4;
1311     break;
1312   case GR_MAX_TEXTURE_ASPECT_RATIO:
1313     if (plength < 4 || params == NULL) return 0;
1314     params[0] = 3;
1315     return 4;
1316     break;
1317   case GR_NON_POWER_OF_TWO_TEXTURES:
1318     if (plength < 4 || params == NULL) return 0;
1319     params[0] = FXFALSE;
1320     return 4;
1321     break;
1322   case GR_TEXTURE_ALIGN:
1323     if (plength < 4 || params == NULL) return 0;
1324     params[0] = 0;
1325     return 4;
1326     break;
1327   default:
1328     display_warning("unknown pname in grGet : %x", pname);
1329   }
1330   return 0;
1331 }
1332
1333 FX_ENTRY const char * FX_CALL
1334 grGetString( FxU32 pname )
1335 {
1336   LOG("grGetString(%d)\r\n", pname);
1337   switch(pname)
1338   {
1339   case GR_EXTENSION:
1340     {
1341       static char extension[] = "CHROMARANGE TEXCHROMA TEXMIRROR PALETTE6666 FOGCOORD EVOODOO TEXTUREBUFFER TEXUMA TEXFMT COMBINE GETGAMMA";
1342       return extension;
1343     }
1344     break;
1345   case GR_HARDWARE:
1346     {
1347       static char hardware[] = "Voodoo5 (tm)";
1348       return hardware;
1349     }
1350     break;
1351   case GR_VENDOR:
1352     {
1353       static char vendor[] = "3Dfx Interactive";
1354       return vendor;
1355     }
1356     break;
1357   case GR_RENDERER:
1358     {
1359       static char renderer[] = "Glide";
1360       return renderer;
1361     }
1362     break;
1363   case GR_VERSION:
1364     {
1365       static char version[] = "3.0";
1366       return version;
1367     }
1368     break;
1369   default:
1370     display_warning("unknown grGetString selector : %x", pname);
1371   }
1372   return NULL;
1373 }
1374
1375 static void render_rectangle(int texture_number,
1376                              int dst_x, int dst_y,
1377                              int src_width, int src_height,
1378                              int tex_width, int tex_height, int invert)
1379 {
1380   LOGINFO("render_rectangle(%d,%d,%d,%d,%d,%d,%d,%d)",texture_number,dst_x,dst_y,src_width,src_height,tex_width,tex_height,invert);
1381   int vertexOffset_location;
1382   int textureSizes_location;
1383   static float data[] = {
1384     ((int)dst_x),                             //X 0
1385     invert*-((int)dst_y),                     //Y 0 
1386     0.0f,                                     //U 0 
1387     0.0f,                                     //V 0
1388
1389     ((int)dst_x),                             //X 1
1390     invert*-((int)dst_y + (int)src_height),   //Y 1
1391     0.0f,                                     //U 1
1392     (float)src_height / (float)tex_height,    //V 1
1393
1394     ((int)dst_x + (int)src_width), 
1395     invert*-((int)dst_y + (int)src_height),
1396     (float)src_width / (float)tex_width,
1397     (float)src_height / (float)tex_height,
1398
1399     ((int)dst_x),
1400     invert*-((int)dst_y),
1401     0.0f,
1402     0.0f
1403   };
1404
1405   vbo_disable();
1406   glDisableVertexAttribArray(COLOUR_ATTR);
1407   glDisableVertexAttribArray(TEXCOORD_1_ATTR);
1408   glDisableVertexAttribArray(FOG_ATTR);
1409
1410   glVertexAttribPointer(POSITION_ATTR,2,GL_FLOAT,false,2,data); //Position
1411   glVertexAttribPointer(TEXCOORD_0_ATTR,2,GL_FLOAT,false,2,&data[2]); //Tex
1412
1413   glEnableVertexAttribArray(COLOUR_ATTR);
1414   glEnableVertexAttribArray(TEXCOORD_1_ATTR);
1415   glEnableVertexAttribArray(FOG_ATTR);
1416
1417
1418   disable_textureSizes();
1419
1420   glDrawArrays(GL_TRIANGLE_STRIP,0,4);
1421   vbo_enable();
1422
1423
1424 /*
1425   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1426   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1427   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1428   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1429   glBegin(GL_QUADS);
1430   glMultiTexCoord2fARB(texture_number, 0.0f, 0.0f);
1431   glVertex2f(((int)dst_x - widtho) / (float)(width/2),
1432     invert*-((int)dst_y - heighto) / (float)(height/2));
1433   glMultiTexCoord2fARB(texture_number, 0.0f, (float)src_height / (float)tex_height);
1434   glVertex2f(((int)dst_x - widtho) / (float)(width/2),
1435     invert*-((int)dst_y + (int)src_height - heighto) / (float)(height/2));
1436   glMultiTexCoord2fARB(texture_number, (float)src_width / (float)tex_width, (float)src_height / (float)tex_height);
1437   glVertex2f(((int)dst_x + (int)src_width - widtho) / (float)(width/2),
1438     invert*-((int)dst_y + (int)src_height - heighto) / (float)(height/2));
1439   glMultiTexCoord2fARB(texture_number, (float)src_width / (float)tex_width, 0.0f);
1440   glVertex2f(((int)dst_x + (int)src_width - widtho) / (float)(width/2),
1441     invert*-((int)dst_y - heighto) / (float)(height/2));
1442   glMultiTexCoord2fARB(texture_number, 0.0f, 0.0f);
1443   glVertex2f(((int)dst_x - widtho) / (float)(width/2),
1444     invert*-((int)dst_y - heighto) / (float)(height/2));
1445   glEnd();
1446 */
1447
1448   compile_shader();
1449
1450   glEnable(GL_DEPTH_TEST);
1451   glEnable(GL_BLEND);
1452 }
1453
1454 void reloadTexture()
1455 {
1456   if (use_fbo || !render_to_texture || buffer_cleared)
1457     return;
1458
1459   LOG("reload texture %dx%d\n", width, height);
1460   //printf("reload texture %dx%d\n", width, height);
1461
1462   buffer_cleared = 1;
1463
1464   //glPushAttrib(GL_ALL_ATTRIB_BITS);
1465   glActiveTexture(texture_unit);
1466   glBindTexture(GL_TEXTURE_2D, pBufferAddress);
1467   //glDisable(GL_ALPHA_TEST);
1468   //glDrawBuffer(current_buffer);
1469   glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1470   set_copy_shader();
1471   glDisable(GL_DEPTH_TEST);
1472   glDisable(GL_CULL_FACE);
1473   int w = 0, h = 0;
1474   if (height > screen_height) h = screen_height - height;
1475   render_rectangle(texture_unit,
1476     -w, -h,
1477     width,  height,
1478     width, height, -1);
1479   glBindTexture(GL_TEXTURE_2D, default_texture);
1480   //glPopAttrib();
1481 }
1482
1483 void updateTexture()
1484 {
1485   if (!use_fbo && render_to_texture == 2) {
1486     LOG("update texture %x\n", pBufferAddress);
1487     //printf("update texture %x\n", pBufferAddress);
1488
1489     // nothing changed, don't update the texture
1490     if (!buffer_cleared) {
1491       LOG("update cancelled\n", pBufferAddress);
1492       return;
1493     }
1494
1495     //glPushAttrib(GL_ALL_ATTRIB_BITS);
1496
1497     // save result of render to texture into actual texture
1498     //glReadBuffer(current_buffer);
1499     glActiveTexture(texture_unit);
1500     // ZIGGY
1501     // deleting the texture before resampling it increases speed on certain old
1502     // nvidia cards (geforce 2 for example), unfortunatly it slows down a lot
1503     // on newer cards.
1504     //glDeleteTextures( 1, &pBufferAddress );
1505     glBindTexture(GL_TEXTURE_2D, pBufferAddress);
1506     glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
1507       0, viewport_offset, width, height, 0);
1508
1509     glBindTexture(GL_TEXTURE_2D, default_texture);
1510     //glPopAttrib();
1511   }
1512 }
1513
1514 FX_ENTRY void FX_CALL grFramebufferCopyExt(int x, int y, int w, int h,
1515                                            int from, int to, int mode)
1516 {
1517   if (mode == GR_FBCOPY_MODE_DEPTH) {
1518
1519     int tw = 1, th = 1;
1520     if (npot_support) {
1521       tw = width; th = height;
1522     } else {
1523       while (tw < width) tw <<= 1;
1524       while (th < height) th <<= 1;
1525     }
1526
1527     if (from == GR_FBCOPY_BUFFER_BACK && to == GR_FBCOPY_BUFFER_FRONT) {
1528       //printf("save depth buffer %d\n", render_to_texture);
1529       // save the depth image in a texture
1530       //glReadBuffer(current_buffer);
1531       glBindTexture(GL_TEXTURE_2D, depth_texture);
1532       glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT,
1533         0, viewport_offset, tw, th, 0);
1534       glBindTexture(GL_TEXTURE_2D, default_texture);
1535       return;
1536     }
1537     if (from == GR_FBCOPY_BUFFER_FRONT && to == GR_FBCOPY_BUFFER_BACK) {
1538       //printf("writing to depth buffer %d\n", render_to_texture);
1539       //glPushAttrib(GL_ALL_ATTRIB_BITS);
1540       //glDisable(GL_ALPHA_TEST);
1541       //glDrawBuffer(current_buffer);
1542       glActiveTexture(texture_unit);
1543       glBindTexture(GL_TEXTURE_2D, depth_texture);
1544       glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1545       set_depth_shader();
1546       glEnable(GL_DEPTH_TEST);
1547       glDepthFunc(GL_ALWAYS);
1548       glDisable(GL_CULL_FACE);
1549       render_rectangle(texture_unit,
1550         0, 0,
1551         width,  height,
1552         tw, th, -1);
1553       glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1554       glBindTexture(GL_TEXTURE_2D, default_texture);
1555       //glPopAttrib();
1556       return;
1557     }
1558
1559   }
1560 }
1561
1562 FX_ENTRY void FX_CALL
1563 grRenderBuffer( GrBuffer_t buffer )
1564 {
1565 #ifdef _WIN32
1566   static HANDLE region = NULL;
1567   int realWidth = pBufferWidth, realHeight = pBufferHeight;
1568 #endif // _WIN32
1569   LOG("grRenderBuffer(%d)\r\n", buffer);
1570   //printf("grRenderBuffer(%d)\n", buffer);
1571
1572   switch(buffer)
1573   {
1574   case GR_BUFFER_BACKBUFFER:
1575     if(render_to_texture)
1576     {
1577       updateTexture();
1578
1579       // VP z fix
1580       //glMatrixMode(GL_MODELVIEW);
1581       //glLoadIdentity();
1582       //glTranslatef(0, 0, 1-zscale);
1583       //glScalef(1, 1, zscale);
1584       inverted_culling = 0;
1585       grCullMode(culling_mode);
1586
1587       width = savedWidth;
1588       height = savedHeight;
1589       widtho = savedWidtho;
1590       heighto = savedHeighto;
1591       if (use_fbo) {
1592         glBindFramebuffer(GL_FRAMEBUFFER, 0);
1593         glBindRenderbuffer( GL_RENDERBUFFER, 0 );
1594       }
1595       curBufferAddr = 0;
1596
1597       glViewport(0, viewport_offset, width, viewport_height);
1598       glScissor(0, viewport_offset, width, height);
1599
1600 #ifdef SAVE_CBUFFER
1601       if (!use_fbo && render_to_texture == 2) {
1602         // restore color buffer
1603         if (nbAuxBuffers > 0) {
1604           //glDrawBuffer(GL_BACK);
1605           current_buffer = GL_BACK;
1606         } else if (save_w) {
1607           int tw = 1, th = 1;
1608           //printf("restore %dx%d\n", save_w, save_h);
1609           if (npot_support) {
1610             tw = screen_width;
1611             th = screen_height;
1612           } else {
1613             while (tw < screen_width) tw <<= 1;
1614             while (th < screen_height) th <<= 1;
1615           }
1616
1617           //glPushAttrib(GL_ALL_ATTRIB_BITS);
1618           //glDisable(GL_ALPHA_TEST);
1619           //glDrawBuffer(GL_BACK);
1620           glActiveTexture(texture_unit);
1621           glBindTexture(GL_TEXTURE_2D, color_texture);
1622           glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1623           set_copy_shader();
1624           glDisable(GL_DEPTH_TEST);
1625           glDisable(GL_CULL_FACE);
1626           render_rectangle(texture_unit,
1627             0, 0,
1628             save_w,  save_h,
1629             tw, th, -1);
1630           glBindTexture(GL_TEXTURE_2D, default_texture);
1631           //glPopAttrib();
1632
1633           save_w = save_h = 0;
1634         }
1635       }
1636 #endif
1637       render_to_texture = 0;
1638     }
1639     //glDrawBuffer(GL_BACK);
1640     break;
1641   case 6: // RENDER TO TEXTURE
1642     if(!render_to_texture)
1643     {
1644       savedWidth = width;
1645       savedHeight = height;
1646       savedWidtho = widtho;
1647       savedHeighto = heighto;
1648     }
1649
1650     {
1651       if (!use_fbo) {
1652         //glMatrixMode(GL_MODELVIEW);
1653         //glLoadIdentity();
1654         //glTranslatef(0, 0, 1-zscale);
1655         //glScalef(1, 1, zscale);
1656         inverted_culling = 0;
1657       } else {
1658 /*
1659         float m[4*4] = {1.0f, 0.0f, 0.0f, 0.0f,
1660           0.0f,-1.0f, 0.0f, 0.0f,
1661           0.0f, 0.0f, 1.0f, 0.0f,
1662           0.0f, 0.0f, 0.0f, 1.0f};
1663         glMatrixMode(GL_MODELVIEW);
1664         glLoadMatrixf(m);
1665         // VP z fix
1666         glTranslatef(0, 0, 1-zscale);
1667         glScalef(1, 1*1, zscale);
1668 */
1669         inverted_culling = 1;
1670         grCullMode(culling_mode);
1671       }
1672     }
1673     render_to_texture = 1;
1674     break;
1675   default:
1676     display_warning("grRenderBuffer : unknown buffer : %x", buffer);
1677   }
1678 }
1679
1680 FX_ENTRY void FX_CALL
1681 grAuxBufferExt( GrBuffer_t buffer )
1682 {
1683   LOG("grAuxBufferExt(%d)\r\n", buffer);
1684   //display_warning("grAuxBufferExt");
1685
1686   if (buffer == GR_BUFFER_AUXBUFFER) {
1687     invtex[0] = 0;
1688     invtex[1] = 0;
1689     need_to_compile = 0;
1690     set_depth_shader();
1691     glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1692     glEnable(GL_DEPTH_TEST);
1693     glDepthFunc(GL_ALWAYS);
1694     glDisable(GL_CULL_FACE);
1695     //glDisable(GL_ALPHA_TEST);
1696     glDepthMask(GL_TRUE);
1697     grTexFilterMode(GR_TMU1, GR_TEXTUREFILTER_POINT_SAMPLED, GR_TEXTUREFILTER_POINT_SAMPLED);
1698   } else {
1699     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1700     need_to_compile = 1;
1701   }
1702 }
1703
1704 FX_ENTRY void FX_CALL
1705 grBufferClear( GrColor_t color, GrAlpha_t alpha, FxU32 depth )
1706 {
1707   vbo_draw();
1708   LOG("grBufferClear(%d,%d,%d)\r\n", color, alpha, depth);
1709   switch(lfb_color_fmt)
1710   {
1711   case GR_COLORFORMAT_ARGB:
1712     glClearColor(((color >> 16) & 0xFF) / 255.0f,
1713       ((color >>  8) & 0xFF) / 255.0f,
1714       ( color        & 0xFF) / 255.0f,
1715       alpha / 255.0f);
1716     break;
1717   case GR_COLORFORMAT_RGBA:
1718     glClearColor(((color >> 24) & 0xFF) / 255.0f,
1719       ((color >> 16) & 0xFF) / 255.0f,
1720       (color         & 0xFF) / 255.0f,
1721       alpha / 255.0f);
1722     break;
1723   default:
1724     display_warning("grBufferClear: unknown color format : %x", lfb_color_fmt);
1725   }
1726
1727   if (w_buffer_mode)
1728     glClearDepthf(1.0f - ((1.0f + (depth >> 4) / 4096.0f) * (1 << (depth & 0xF))) / 65528.0);
1729   else
1730     glClearDepthf(depth / 65535.0f);
1731   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1732
1733   // ZIGGY TODO check that color mask is on
1734   buffer_cleared = 1;
1735
1736 }
1737
1738 // #include <unistd.h>
1739 FX_ENTRY void FX_CALL
1740 grBufferSwap( FxU32 swap_interval )
1741 {
1742   vbo_draw();
1743 //      glFinish();
1744 //  printf("rendercallback is %p\n", renderCallback);
1745   if(renderCallback)
1746       (*renderCallback)(1);
1747   int i;
1748   LOG("grBufferSwap(%d)\r\n", swap_interval);
1749   //printf("swap\n");
1750   if (render_to_texture) {
1751     display_warning("swap while render_to_texture\n");
1752     return;
1753   }
1754
1755   CoreVideo_GL_SwapBuffers();
1756   for (i = 0; i < nb_fb; i++)
1757     fbs[i].buff_clear = 1;
1758
1759   // VP debugging
1760 #ifdef VPDEBUG
1761   dump_stop();
1762   SDL_Event event;
1763   while (SDL_PollEvent(&event)) {
1764     switch (event.type) {
1765 case SDL_KEYDOWN:
1766   switch (event.key.keysym.sym) {
1767 case 'd':
1768   printf("Dumping !\n");
1769   dump_start();
1770   break;
1771 case 'w': {
1772   static int wireframe;
1773   wireframe = !wireframe;
1774   glPolygonMode(GL_FRONT_AND_BACK, wireframe? GL_LINE : GL_FILL);
1775   break;
1776           }
1777   }
1778   break;
1779     }
1780   }
1781 #endif
1782 }
1783
1784 // frame buffer
1785
1786 FX_ENTRY FxBool FX_CALL
1787 grLfbLock( GrLock_t type, GrBuffer_t buffer, GrLfbWriteMode_t writeMode,
1788           GrOriginLocation_t origin, FxBool pixelPipeline,
1789           GrLfbInfo_t *info )
1790 {
1791   LOG("grLfbLock(%d,%d,%d,%d,%d)\r\n", type, buffer, writeMode, origin, pixelPipeline);
1792 printf("grLfbLock(%d,%d,%d,%d,%d)\r\n", type, buffer, writeMode, origin, pixelPipeline);
1793   if (type == GR_LFB_WRITE_ONLY)
1794   {
1795     display_warning("grLfbLock : write only");
1796   }
1797   else
1798   {
1799     unsigned char *buf;
1800     int i,j;
1801
1802     switch(buffer)
1803     {
1804     case GR_BUFFER_FRONTBUFFER:
1805       //glReadBuffer(GL_FRONT);
1806       break;
1807     case GR_BUFFER_BACKBUFFER:
1808       //glReadBuffer(GL_BACK);
1809       break;
1810     default:
1811       display_warning("grLfbLock : unknown buffer : %x", buffer);
1812     }
1813
1814     if(buffer != GR_BUFFER_AUXBUFFER)
1815     {
1816       if (writeMode == GR_LFBWRITEMODE_888) {
1817 /*SEB*/
1818         buf = (unsigned char*)malloc(width*height*4);
1819         //printf("LfbLock GR_LFBWRITEMODE_888\n");
1820         info->lfbPtr = frameBuffer;
1821         info->strideInBytes = width*4;
1822         info->writeMode = GR_LFBWRITEMODE_888;
1823         info->origin = origin;
1824         //glReadPixels(0, viewport_offset, width, height, GL_BGRA, GL_UNSIGNED_BYTE, frameBuffer);
1825         glReadPixels(0, viewport_offset, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buf);
1826
1827 /*SEB*/
1828             unsigned char *p=buf;
1829         for (j=0; j<height; j++)
1830         {
1831             short unsigned int *f=frameBuffer+(height-j-1)*width;
1832           for (i=0; i<width; i++)
1833           {
1834             *(f++) =
1835               (*(p)   <<24) |
1836               (*(p+1) <<16) |
1837               (*(p+2) << 8) |
1838                   (0xff);
1839               p+=4;
1840           }
1841         }
1842         free(buf);
1843       } else {
1844         buf = (unsigned char*)malloc(width*height*4);
1845
1846         info->lfbPtr = frameBuffer;
1847         info->strideInBytes = width*2;
1848         info->writeMode = GR_LFBWRITEMODE_565;
1849         info->origin = origin;
1850         glReadPixels(0, viewport_offset, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buf);
1851
1852 /*SEB*/
1853             unsigned char *p=buf;
1854         for (j=0; j<height; j++)
1855         {
1856               short unsigned int *f=frameBuffer+(height-j-1)*width;
1857           for (i=0; i<width; i++)
1858           {
1859 /*            frameBuffer[(height-j-1)*width+i] =
1860               ((buf[j*width*4+i*4+0] >> 3) << 11) |
1861               ((buf[j*width*4+i*4+1] >> 2) <<  5) |
1862               (buf[j*width*4+i*4+2] >> 3);*/
1863             *(f++) =
1864               ((*(p)   >> 3) << 11) |
1865               ((*(p+1) >> 2) <<  5) |
1866               (*(p+2)  >> 3);
1867               p+=4;
1868           }
1869         }
1870         free(buf);
1871       }
1872     }
1873     else
1874     {
1875       info->lfbPtr = depthBuffer;
1876       info->strideInBytes = width*2;
1877       info->writeMode = GR_LFBWRITEMODE_ZA16;
1878       info->origin = origin;
1879       //*SEB* *TODO* check alignment
1880       glReadPixels(0, viewport_offset, width, height, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, depthBuffer);
1881     }
1882   }
1883
1884   return FXTRUE;
1885 }
1886
1887 FX_ENTRY FxBool FX_CALL
1888 grLfbUnlock( GrLock_t type, GrBuffer_t buffer )
1889 {
1890   LOG("grLfbUnlock(%d,%d)\r\n", type, buffer);
1891   if (type == GR_LFB_WRITE_ONLY)
1892   {
1893     display_warning("grLfbUnlock : write only");
1894   }
1895   return FXTRUE;
1896 }
1897
1898 FX_ENTRY FxBool FX_CALL
1899 grLfbReadRegion( GrBuffer_t src_buffer,
1900                 FxU32 src_x, FxU32 src_y,
1901                 FxU32 src_width, FxU32 src_height,
1902                 FxU32 dst_stride, void *dst_data )
1903 {
1904   unsigned char *buf;
1905   unsigned int i,j;
1906   unsigned short *frameBuffer = (unsigned short*)dst_data;
1907   unsigned short *depthBuffer = (unsigned short*)dst_data;
1908   LOG("grLfbReadRegion(%d,%d,%d,%d,%d,%d)\r\n", src_buffer, src_x, src_y, src_width, src_height, dst_stride);
1909 //printf("grLfbReadRegion(%d,%d,%d,%d,%d,%d)\r\n", src_buffer, src_x, src_y, src_width, src_height, dst_stride);
1910
1911   switch(src_buffer)
1912   {
1913   case GR_BUFFER_FRONTBUFFER:
1914     //glReadBuffer(GL_FRONT);
1915     break;
1916   case GR_BUFFER_BACKBUFFER:
1917     //glReadBuffer(GL_BACK);
1918     break;
1919     /*case GR_BUFFER_AUXBUFFER:
1920     glReadBuffer(current_buffer);
1921     break;*/
1922   default:
1923     display_warning("grReadRegion : unknown buffer : %x", src_buffer);
1924   }
1925
1926   if(src_buffer != GR_BUFFER_AUXBUFFER)
1927   {
1928     buf = (unsigned char*)malloc(src_width*src_height*4);
1929
1930     glReadPixels(src_x, (viewport_offset)+height-src_y-src_height, src_width, src_height, GL_RGBA, GL_UNSIGNED_BYTE, buf);
1931     for (j=0; j<src_height; j++)
1932     {
1933 /*SEB*/
1934       unsigned char *p=buf+(src_height-j-1)*src_width*4;
1935       unsigned short *f=frameBuffer+(j*dst_stride/2);
1936       for (i=0; i<src_width; i++)
1937       {
1938 /*        frameBuffer[j*(dst_stride/2)+i] =
1939           ((buf[(src_height-j-1)*src_width*4+i*4+0] >> 3) << 11) |
1940           ((buf[(src_height-j-1)*src_width*4+i*4+1] >> 2) <<  5) |
1941           (buf[(src_height-j-1)*src_width*4+i*4+2] >> 3);*/
1942         *(f++) =
1943           ((*(p) >> 3) << 11) |
1944           ((*(p+1) >> 2) <<  5) |
1945           (*(p+2) >> 3);
1946           p+=4;
1947       }
1948     }
1949     free(buf);
1950   }
1951   else
1952   {
1953     buf = (unsigned char*)malloc(src_width*src_height*2);
1954 //*SEB read in buf, not depthBuffer.
1955     glReadPixels(src_x, (viewport_offset)+height-src_y-src_height, src_width, src_height, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, buf);
1956
1957     for (j=0;j<src_height; j++)
1958     {
1959 //*SEB*
1960       unsigned short *d=depthBuffer+j*dst_stride/2;
1961       unsigned short *p=(unsigned short*)buf+(src_height-j-1)*src_width; //orignal look fishy. why *4???
1962       for (i=0; i<src_width; i++)
1963       {
1964 /*        depthBuffer[j*(dst_stride/2)+i] =
1965           ((unsigned short*)buf)[(src_height-j-1)*src_width*4+i*4];*/
1966         *(d++) = *(p++); //why *4 (prob. GL_PACK was=4), plus transcoding to short, that make *8 ???
1967       }
1968     }
1969     free(buf);
1970   }
1971
1972   return FXTRUE;
1973 }
1974
1975 FX_ENTRY FxBool FX_CALL
1976 grLfbWriteRegion( GrBuffer_t dst_buffer,
1977                  FxU32 dst_x, FxU32 dst_y,
1978                  GrLfbSrcFmt_t src_format,
1979                  FxU32 src_width, FxU32 src_height,
1980                  FxBool pixelPipeline,
1981                  FxI32 src_stride, void *src_data )
1982 {
1983   unsigned char *buf;
1984   unsigned int i,j;
1985   unsigned short *frameBuffer = (unsigned short*)src_data;
1986   int texture_number;
1987   unsigned int tex_width = 1, tex_height = 1;
1988   LOG("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);
1989 //printf("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);
1990
1991   //glPushAttrib(GL_ALL_ATTRIB_BITS);
1992
1993   while (tex_width < src_width) tex_width <<= 1;
1994   while (tex_height < src_height) tex_height <<= 1;
1995
1996   switch(dst_buffer)
1997   {
1998   case GR_BUFFER_BACKBUFFER:
1999     //glDrawBuffer(GL_BACK);
2000     break;
2001   case GR_BUFFER_AUXBUFFER:
2002     //glDrawBuffer(current_buffer);
2003     break;
2004   default:
2005     display_warning("grLfbWriteRegion : unknown buffer : %x", dst_buffer);
2006   }
2007
2008   if(dst_buffer != GR_BUFFER_AUXBUFFER)
2009   {
2010     buf = (unsigned char*)malloc(tex_width*tex_height*4);
2011
2012     texture_number = GL_TEXTURE0;
2013     glActiveTexture(texture_number);
2014
2015     const unsigned int half_stride = src_stride / 2;
2016
2017     const int comp_stride = half_stride - src_width;
2018     const int comp_tex = (tex_width - src_width)*4;
2019     unsigned short *f=frameBuffer;
2020     unsigned char *p=buf;
2021
2022     switch(src_format)
2023     {
2024     case GR_LFB_SRC_FMT_1555:
2025       for (j=0; j<src_height; j++)
2026       {
2027         for (i=0; i<src_width; i++)
2028         {
2029 /*          const unsigned int col = frameBuffer[j*half_stride+i];
2030           buf[j*tex_width*4+i*4+0]=((col>>10)&0x1F)<<3;
2031           buf[j*tex_width*4+i*4+1]=((col>>5)&0x1F)<<3;
2032           buf[j*tex_width*4+i*4+2]=((col>>0)&0x1F)<<3;
2033           buf[j*tex_width*4+i*4+3]= (col>>15) ? 0xFF : 0;*/
2034           const unsigned int col = *(f++);
2035           *(p)=((col>>10)&0x1F)<<3;
2036           *(p+1)=((col>>5)&0x1F)<<3;
2037           *(p+2)=((col>>0)&0x1F)<<3;
2038           *(p+3)= (col>>15) ? 0xFF : 0;
2039           p+=4;
2040         }
2041         p+=comp_tex;
2042         f+=comp_stride;
2043       }
2044       break;
2045     case GR_LFBWRITEMODE_555:
2046       for (j=0; j<src_height; j++)
2047       {
2048         for (i=0; i<src_width; i++)
2049         {
2050 /*          const unsigned int col = frameBuffer[j*half_stride+i];
2051           buf[j*tex_width*4+i*4+0]=((col>>10)&0x1F)<<3;
2052           buf[j*tex_width*4+i*4+1]=((col>>5)&0x1F)<<3;
2053           buf[j*tex_width*4+i*4+2]=((col>>0)&0x1F)<<3;
2054           buf[j*tex_width*4+i*4+3]=0xFF;*/
2055           const unsigned int col = *(f++);
2056           *(p)=((col>>10)&0x1F)<<3;
2057           *(p+1)=((col>>5)&0x1F)<<3;
2058           *(p+2)=((col>>0)&0x1F)<<3;
2059           *(p+3)=0xFF;
2060           p+=4;
2061         }
2062         p+=comp_tex;
2063         f+=comp_stride;
2064       }
2065       break;
2066     case GR_LFBWRITEMODE_565:
2067       for (j=0; j<src_height; j++)
2068       {
2069         for (i=0; i<src_width; i++)
2070         {
2071 /*          const unsigned int col = frameBuffer[j*half_stride+i];
2072           buf[j*tex_width*4+i*4+0]=((col>>11)&0x1F)<<3;
2073           buf[j*tex_width*4+i*4+1]=((col>>5)&0x3F)<<2;
2074           buf[j*tex_width*4+i*4+2]=((col>>0)&0x1F)<<3;
2075           buf[j*tex_width*4+i*4+3]=0xFF;*/
2076           const unsigned int col = *(f++);
2077           *(p)=((col>>11)&0x1F)<<3;
2078           *(p+1)=((col>>5)&0x3F)<<2;
2079           *(p+2)=((col>>0)&0x1F)<<3;
2080           *(p+3)=0xFF;
2081           p+=4;
2082         }
2083         p+=comp_tex;
2084         f+=comp_stride;
2085       }
2086       break;
2087     default:
2088       display_warning("grLfbWriteRegion : unknown format : %d", src_format);
2089     }
2090
2091 #ifdef VPDEBUG
2092     if (dumping) {
2093       ilTexImage(tex_width, tex_height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, buf);
2094       char name[128];
2095       static int id;
2096       sprintf(name, "dump/writecolor%d.png", id++);
2097       ilSaveImage(name);
2098       //printf("dumped gdLfbWriteRegion %s\n", name);
2099     }
2100 #endif
2101
2102     glBindTexture(GL_TEXTURE_2D, default_texture);
2103     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_width, tex_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
2104     free(buf);
2105
2106     set_copy_shader();
2107
2108     glDisable(GL_DEPTH_TEST);
2109     glDisable(GL_BLEND);
2110     render_rectangle(texture_number,
2111       dst_x, dst_y,
2112       src_width,  src_height,
2113       tex_width,  tex_height, +1);
2114
2115   }
2116   else
2117   {
2118     float *buf = (float*)malloc(src_width*(src_height+(viewport_offset))*sizeof(float));
2119
2120     if (src_format != GR_LFBWRITEMODE_ZA16)
2121       display_warning("unknown depth buffer write format:%x", src_format);
2122
2123     if(dst_x || dst_y)
2124       display_warning("dst_x:%d, dst_y:%d\n",dst_x, dst_y);
2125
2126     for (j=0; j<src_height; j++)
2127     {
2128       for (i=0; i<src_width; i++)
2129       {
2130         buf[(j+(viewport_offset))*src_width+i] =
2131           (frameBuffer[(src_height-j-1)*(src_stride/2)+i]/(65536.0f*(2.0f/zscale)))+1-zscale/2.0f;
2132       }
2133     }
2134
2135 #ifdef VPDEBUG
2136     if (dumping) {
2137       unsigned char * buf2 = (unsigned char *)malloc(src_width*(src_height+(viewport_offset)));
2138       for (i=0; i<src_width*src_height ; i++)
2139         buf2[i] = buf[i]*255.0f;
2140       ilTexImage(src_width, src_height, 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, buf2);
2141       char name[128];
2142       static int id;
2143       sprintf(name, "dump/writedepth%d.png", id++);
2144       ilSaveImage(name);
2145       //printf("dumped gdLfbWriteRegion %s\n", name);
2146       free(buf2);
2147     }
2148 #endif
2149
2150     glEnable(GL_DEPTH_TEST);
2151     glDepthFunc(GL_ALWAYS);
2152
2153     //glDrawBuffer(GL_BACK);
2154     glClear( GL_DEPTH_BUFFER_BIT );
2155     glDepthMask(1);
2156     //glDrawPixels(src_width, src_height+(viewport_offset), GL_DEPTH_COMPONENT, GL_FLOAT, buf);
2157
2158     free(buf);
2159   }
2160   //glDrawBuffer(current_buffer);
2161   //glPopAttrib();
2162   return FXTRUE;
2163 }
2164
2165 /* wrapper-specific glide extensions */
2166
2167 FX_ENTRY char ** FX_CALL
2168 grQueryResolutionsExt(FxI32 * Size)
2169 {
2170   return 0;
2171 /*
2172   LOG("grQueryResolutionsExt\r\n");
2173   return g_FullScreenResolutions.getResolutionsList(Size);
2174 */
2175 }
2176
2177 FX_ENTRY GrScreenResolution_t FX_CALL grWrapperFullScreenResolutionExt(FxU32* width, FxU32* height)
2178 {
2179   return 0;
2180 /*
2181   LOG("grWrapperFullScreenResolutionExt\r\n");
2182   g_FullScreenResolutions.getResolution(config.res, width, height);
2183   return config.res;
2184 */
2185 }
2186
2187 FX_ENTRY FxBool FX_CALL grKeyPressedExt(FxU32 key)
2188 {
2189   return 0;
2190 /*
2191 #ifdef _WIN32
2192   return (GetAsyncKeyState(key) & 0x8000);
2193 #else
2194   if (key == 1) //LBUTTON
2195   {
2196     Uint8 mstate = SDL_GetMouseState(NULL, NULL);
2197     return (mstate & SDL_BUTTON_LMASK);
2198   }
2199   else
2200   {
2201     Uint8 *keystates = SDL_GetKeyState( NULL );
2202     if( keystates[ key ] )
2203     {
2204       return 1;
2205     }
2206     else
2207     {
2208       return 0;
2209     }
2210   }
2211 #endif
2212 */
2213 }
2214
2215 FX_ENTRY void FX_CALL grConfigWrapperExt(FxI32 resolution, FxI32 vram, FxBool fbo, FxBool aniso)
2216 {
2217   LOG("grConfigWrapperExt\r\n");
2218   config.res = resolution;
2219   config.vram_size = vram;
2220   config.fbo = fbo;
2221   config.anisofilter = aniso;
2222 }
2223
2224 // unused by glide64
2225
2226 FX_ENTRY FxI32 FX_CALL
2227 grQueryResolutions( const GrResolution *resTemplate, GrResolution *output )
2228 {
2229   int res_inf = 0;
2230   int res_sup = 0xf;
2231   int i;
2232   int n=0;
2233   LOG("grQueryResolutions\r\n");
2234   display_warning("grQueryResolutions");
2235   if ((unsigned int)resTemplate->resolution != GR_QUERY_ANY)
2236   {
2237     res_inf = res_sup = resTemplate->resolution;
2238   }
2239   if ((unsigned int)resTemplate->refresh == GR_QUERY_ANY) display_warning("querying any refresh rate");
2240   if ((unsigned int)resTemplate->numAuxBuffers == GR_QUERY_ANY) display_warning("querying any numAuxBuffers");
2241   if ((unsigned int)resTemplate->numColorBuffers == GR_QUERY_ANY) display_warning("querying any numColorBuffers");
2242
2243   if (output == NULL) return res_sup - res_inf + 1;
2244   for (i=res_inf; i<=res_sup; i++)
2245   {
2246     output[n].resolution = i;
2247     output[n].refresh = resTemplate->refresh;
2248     output[n].numAuxBuffers = resTemplate->numAuxBuffers;
2249     output[n].numColorBuffers = resTemplate->numColorBuffers;
2250     n++;
2251   }
2252   return res_sup - res_inf + 1;
2253 }
2254
2255 FX_ENTRY FxBool FX_CALL
2256 grReset( FxU32 what )
2257 {
2258   display_warning("grReset");
2259   return 1;
2260 }
2261
2262 FX_ENTRY void FX_CALL
2263 grEnable( GrEnableMode_t mode )
2264 {
2265   LOG("grEnable(%d)\r\n", mode);
2266   if (mode == GR_TEXTURE_UMA_EXT)
2267     UMAmode = 1;
2268 }
2269
2270 FX_ENTRY void FX_CALL
2271 grDisable( GrEnableMode_t mode )
2272 {
2273   LOG("grDisable(%d)\r\n", mode);
2274   if (mode == GR_TEXTURE_UMA_EXT)
2275     UMAmode = 0;
2276 }
2277
2278 FX_ENTRY void FX_CALL
2279 grDisableAllEffects( void )
2280 {
2281   display_warning("grDisableAllEffects");
2282 }
2283
2284 FX_ENTRY void FX_CALL
2285 grErrorSetCallback( GrErrorCallbackFnc_t fnc )
2286 {
2287   display_warning("grErrorSetCallback");
2288 }
2289
2290 FX_ENTRY void FX_CALL
2291 grFinish(void)
2292 {
2293   display_warning("grFinish");
2294 }
2295
2296 FX_ENTRY void FX_CALL
2297 grFlush(void)
2298 {
2299   display_warning("grFlush");
2300 }
2301
2302 FX_ENTRY void FX_CALL
2303 grTexMultibase( GrChipID_t tmu,
2304                FxBool     enable )
2305 {
2306   display_warning("grTexMultibase");
2307 }
2308
2309 FX_ENTRY void FX_CALL
2310 grTexMipMapMode( GrChipID_t     tmu,
2311                 GrMipMapMode_t mode,
2312                 FxBool         lodBlend )
2313 {
2314   display_warning("grTexMipMapMode");
2315 }
2316
2317 FX_ENTRY void FX_CALL
2318 grTexDownloadTablePartial( GrTexTable_t type,
2319                           void         *data,
2320                           int          start,
2321                           int          end )
2322 {
2323   display_warning("grTexDownloadTablePartial");
2324 }
2325
2326 FX_ENTRY void FX_CALL
2327 grTexDownloadTable( GrTexTable_t type,
2328                    void         *data )
2329 {
2330   display_warning("grTexDownloadTable");
2331 }
2332
2333 FX_ENTRY FxBool FX_CALL
2334 grTexDownloadMipMapLevelPartial( GrChipID_t        tmu,
2335                                 FxU32             startAddress,
2336                                 GrLOD_t           thisLod,
2337                                 GrLOD_t           largeLod,
2338                                 GrAspectRatio_t   aspectRatio,
2339                                 GrTextureFormat_t format,
2340                                 FxU32             evenOdd,
2341                                 void              *data,
2342                                 int               start,
2343                                 int               end )
2344 {
2345   display_warning("grTexDownloadMipMapLevelPartial");
2346   return 1;
2347 }
2348
2349 FX_ENTRY void FX_CALL
2350 grTexDownloadMipMapLevel( GrChipID_t        tmu,
2351                          FxU32             startAddress,
2352                          GrLOD_t           thisLod,
2353                          GrLOD_t           largeLod,
2354                          GrAspectRatio_t   aspectRatio,
2355                          GrTextureFormat_t format,
2356                          FxU32             evenOdd,
2357                          void              *data )
2358 {
2359   display_warning("grTexDownloadMipMapLevel");
2360 }
2361
2362 FX_ENTRY void FX_CALL
2363 grTexNCCTable( GrNCCTable_t table )
2364 {
2365   display_warning("grTexNCCTable");
2366 }
2367
2368 FX_ENTRY void FX_CALL
2369 grViewport( FxI32 x, FxI32 y, FxI32 width, FxI32 height )
2370 {
2371   display_warning("grViewport");
2372 }
2373
2374 FX_ENTRY void FX_CALL
2375 grDepthRange( FxFloat n, FxFloat f )
2376 {
2377   display_warning("grDepthRange");
2378 }
2379
2380 FX_ENTRY void FX_CALL
2381 grSplash(float x, float y, float width, float height, FxU32 frame)
2382 {
2383   display_warning("grSplash");
2384 }
2385
2386 FX_ENTRY FxBool FX_CALL
2387 grSelectContext( GrContext_t context )
2388 {
2389   display_warning("grSelectContext");
2390   return 1;
2391 }
2392
2393 FX_ENTRY void FX_CALL
2394 grAADrawTriangle(
2395                  const void *a, const void *b, const void *c,
2396                  FxBool ab_antialias, FxBool bc_antialias, FxBool ca_antialias
2397                  )
2398 {
2399   display_warning("grAADrawTriangle");
2400 }
2401
2402 FX_ENTRY void FX_CALL
2403 grAlphaControlsITRGBLighting( FxBool enable )
2404 {
2405   display_warning("grAlphaControlsITRGBLighting");
2406 }
2407
2408 FX_ENTRY void FX_CALL
2409 grGlideSetVertexLayout( const void *layout )
2410 {
2411   display_warning("grGlideSetVertexLayout");
2412 }
2413
2414 FX_ENTRY void FX_CALL
2415 grGlideGetVertexLayout( void *layout )
2416 {
2417   display_warning("grGlideGetVertexLayout");
2418 }
2419
2420 FX_ENTRY void FX_CALL
2421 grGlideSetState( const void *state )
2422 {
2423   display_warning("grGlideSetState");
2424 }
2425
2426 FX_ENTRY void FX_CALL
2427 grGlideGetState( void *state )
2428 {
2429   display_warning("grGlideGetState");
2430 }
2431
2432 FX_ENTRY void FX_CALL
2433 grLfbWriteColorFormat(GrColorFormat_t colorFormat)
2434 {
2435   display_warning("grLfbWriteColorFormat");
2436 }
2437
2438 FX_ENTRY void FX_CALL
2439 grLfbWriteColorSwizzle(FxBool swizzleBytes, FxBool swapWords)
2440 {
2441   display_warning("grLfbWriteColorSwizzle");
2442 }
2443
2444 FX_ENTRY void FX_CALL
2445 grLfbConstantDepth( FxU32 depth )
2446 {
2447   display_warning("grLfbConstantDepth");
2448 }
2449
2450 FX_ENTRY void FX_CALL
2451 grLfbConstantAlpha( GrAlpha_t alpha )
2452 {
2453   display_warning("grLfbConstantAlpha");
2454 }
2455
2456 FX_ENTRY void FX_CALL
2457 grTexMultibaseAddress( GrChipID_t       tmu,
2458                       GrTexBaseRange_t range,
2459                       FxU32            startAddress,
2460                       FxU32            evenOdd,
2461                       GrTexInfo        *info )
2462 {
2463   display_warning("grTexMultibaseAddress");
2464 }
2465
2466 /*
2467 inline void MySleep(FxU32 ms)
2468 {
2469 #ifdef _WIN32
2470   Sleep(ms);
2471 #else
2472   SDL_Delay(ms);
2473 #endif
2474 }
2475 */
2476
2477 #ifdef _WIN32
2478 static void CorrectGamma(LPVOID apGammaRamp)
2479 {
2480   HDC hdc = GetDC(NULL);
2481   if (hdc != NULL)
2482   {
2483     SetDeviceGammaRamp(hdc, apGammaRamp);
2484     ReleaseDC(NULL, hdc);
2485   }
2486 }
2487 #else
2488 static void CorrectGamma(const FxU16 aGammaRamp[3][256])
2489 {
2490   //TODO?
2491   //int res = SDL_SetGammaRamp(aGammaRamp[0], aGammaRamp[1], aGammaRamp[2]);
2492   //LOG("SDL_SetGammaRamp returned %d\r\n", res);
2493 }
2494 #endif
2495
2496 FX_ENTRY void FX_CALL
2497 grLoadGammaTable( FxU32 nentries, FxU32 *red, FxU32 *green, FxU32 *blue)
2498 {
2499   LOG("grLoadGammaTable\r\n");
2500   if (!fullscreen)
2501     return;
2502   FxU16 aGammaRamp[3][256];
2503   for (int i = 0; i < 256; i++)
2504   {
2505     aGammaRamp[0][i] = (FxU16)((red[i] << 8) & 0xFFFF);
2506     aGammaRamp[1][i] = (FxU16)((green[i] << 8) & 0xFFFF);
2507     aGammaRamp[2][i] = (FxU16)((blue[i] << 8) & 0xFFFF);
2508   }
2509   CorrectGamma(aGammaRamp);
2510   //MySleep(1000); //workaround for Mupen64
2511 }
2512
2513 FX_ENTRY void FX_CALL
2514 grGetGammaTableExt(FxU32 nentries, FxU32 *red, FxU32 *green, FxU32 *blue)
2515 {
2516   return;
2517   //TODO?
2518   /*
2519   LOG("grGetGammaTableExt()\r\n");
2520   FxU16 aGammaRamp[3][256];
2521 #ifdef _WIN32
2522   HDC hdc = GetDC(NULL);
2523   if (hdc == NULL)
2524     return;
2525   if (GetDeviceGammaRamp(hdc, aGammaRamp) == TRUE)
2526   {
2527     ReleaseDC(NULL, hdc);
2528 #else
2529   if (SDL_GetGammaRamp(aGammaRamp[0], aGammaRamp[1], aGammaRamp[2]) != -1)
2530   {
2531 #endif
2532     for (int i = 0; i < 256; i++)
2533     {
2534       red[i] = aGammaRamp[0][i] >> 8;
2535       green[i] = aGammaRamp[1][i] >> 8;
2536       blue[i] = aGammaRamp[2][i] >> 8;
2537     }
2538   }
2539   */
2540 }
2541
2542 FX_ENTRY void FX_CALL
2543 guGammaCorrectionRGB( FxFloat gammaR, FxFloat gammaG, FxFloat gammaB )
2544 {
2545   LOG("guGammaCorrectionRGB()\r\n");
2546   if (!fullscreen)
2547     return;
2548   FxU16 aGammaRamp[3][256];
2549   for (int i = 0; i < 256; i++)
2550   {
2551     aGammaRamp[0][i] = (((FxU16)((pow(i/255.0F, 1.0F/gammaR)) * 255.0F + 0.5F)) << 8) & 0xFFFF;
2552     aGammaRamp[1][i] = (((FxU16)((pow(i/255.0F, 1.0F/gammaG)) * 255.0F + 0.5F)) << 8) & 0xFFFF;
2553     aGammaRamp[2][i] = (((FxU16)((pow(i/255.0F, 1.0F/gammaB)) * 255.0F + 0.5F)) << 8) & 0xFFFF;
2554   }
2555   CorrectGamma(aGammaRamp);
2556 }
2557
2558 FX_ENTRY void FX_CALL
2559 grDitherMode( GrDitherMode_t mode )
2560 {
2561   display_warning("grDitherMode");
2562 }
2563
2564 void grChromaRangeExt(GrColor_t color0, GrColor_t color1, FxU32 mode)
2565 {
2566   display_warning("grChromaRangeExt");
2567 }
2568
2569 void grChromaRangeModeExt(GrChromakeyMode_t mode)
2570 {
2571   display_warning("grChromaRangeModeExt");
2572 }
2573
2574 void grTexChromaRangeExt(GrChipID_t tmu, GrColor_t color0, GrColor_t color1, GrTexChromakeyMode_t mode)
2575 {
2576   display_warning("grTexChromaRangeExt");
2577 }
2578
2579 void grTexChromaModeExt(GrChipID_t tmu, GrChromakeyMode_t mode)
2580 {
2581   display_warning("grTexChromaRangeModeExt");
2582 }
2583
2584 // VP debug
2585 #ifdef VPDEBUG
2586 int dumping = 0;
2587 static int tl_i;
2588 static int tl[10240];
2589
2590 void dump_start()
2591 {
2592   static int init;
2593   if (!init) {
2594     init = 1;
2595     ilInit();
2596     ilEnable(IL_FILE_OVERWRITE);
2597   }
2598   dumping = 1;
2599   tl_i = 0;
2600 }
2601
2602 void dump_stop()
2603 {
2604   if (!dumping) return;
2605
2606   int i, j;
2607   for (i=0; i<nb_fb; i++) {
2608     dump_tex(fbs[i].texid);
2609   }
2610   dump_tex(default_texture);
2611   dump_tex(depth_texture);
2612
2613   dumping = 0;
2614
2615   glReadBuffer(GL_FRONT);
2616   glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, frameBuffer);
2617   ilTexImage(width, height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, frameBuffer);
2618   ilSaveImage("dump/framecolor.png");
2619   glReadPixels(0, 0, width, height, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, depthBuffer);
2620   //   FILE * fp = fopen("glide_depth1.bin", "rb");
2621   //   fread(depthBuffer, 2, width*height, fp);
2622   //   fclose(fp);
2623   for (j=0; j<height; j++) {
2624     for (i=0; i<width; i++) {
2625       //uint16_t d = ( (uint16_t *)depthBuffer )[i+(height-1-j)*width]/2 + 0x8000;
2626       uint16_t d = ( (uint16_t *)depthBuffer )[i+j*width];
2627       uint32_t c = ( (uint32_t *)frameBuffer )[i+j*width];
2628       ( (unsigned char *)frameBuffer )[(i+j*width)*3] = d&0xff;
2629       ( (unsigned char *)frameBuffer )[(i+j*width)*3+1] = d>>8;
2630       ( (unsigned char *)frameBuffer )[(i+j*width)*3+2] = c&0xff;
2631     }
2632   }
2633   ilTexImage(width, height, 1, 3, IL_RGB, IL_UNSIGNED_BYTE, frameBuffer);
2634   ilSaveImage("dump/framedepth.png");
2635
2636   for (i=0; i<tl_i; i++) {
2637     glBindTexture(GL_TEXTURE_2D, tl[i]);
2638     GLint w, h, fmt;
2639     glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
2640     glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
2641     glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt);
2642     fprintf(stderr, "Texture %d %dx%d fmt %x\n", tl[i], (int)w, (int)h, (int) fmt);
2643
2644     uint32_t * pixels = (uint32_t *) malloc(w*h*4);
2645     // 0x1902 is another constant meaning GL_DEPTH_COMPONENT
2646     // (but isn't defined in gl's headers !!)
2647     if (fmt != GL_DEPTH_COMPONENT && fmt != 0x1902) {
2648       glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
2649       ilTexImage(w, h, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, pixels);
2650     } else {
2651       glGetTexImage(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, pixels);
2652       int i;
2653       for (i=0; i<w*h; i++)
2654         ((unsigned char *)frameBuffer)[i] = ((unsigned short *)pixels)[i]/256;
2655       ilTexImage(w, h, 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, frameBuffer);
2656     }
2657     char name[128];
2658     //     sprintf(name, "mkdir -p dump ; rm -f dump/tex%04d.png", i);
2659     //     system(name);
2660     sprintf(name, "dump/tex%04d.png", i);
2661     fprintf(stderr, "Writing '%s'\n", name);
2662     ilSaveImage(name);
2663
2664     //     SDL_FreeSurface(surf);
2665     free(pixels);
2666   }
2667   glBindTexture(GL_TEXTURE_2D, default_texture);
2668 }
2669
2670 void dump_tex(int id)
2671 {
2672   if (!dumping) return;
2673
2674   int n;
2675   // yes, it's inefficient
2676   for (n=0; n<tl_i; n++)
2677     if (tl[n] == id)
2678       return;
2679
2680   tl[tl_i++] = id;
2681
2682   int i = tl_i-1;
2683 }
2684
2685 #endif