98e75f2d |
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 | // ZIGGY not sure, but it might be better to let the system choose |
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 | return FXTRUE; |
821 | } |
822 | |
823 | FX_ENTRY void FX_CALL grTextureBufferExt( GrChipID_t tmu, |
824 | FxU32 startAddress, |
825 | GrLOD_t lodmin, |
826 | GrLOD_t lodmax, |
827 | GrAspectRatio_t aspect, |
828 | GrTextureFormat_t fmt, |
829 | FxU32 evenOdd) |
830 | { |
831 | int i; |
832 | static int fbs_init = 0; |
833 | |
834 | LOG("grTextureBufferExt(%d, %d, %d, %d %d, %d, %d)\r\n", tmu, startAddress, lodmin, lodmax, aspect, fmt, evenOdd); |
835 | if (lodmin != lodmax) display_warning("grTextureBufferExt : loading more than one LOD"); |
836 | if (!use_fbo) { |
837 | |
838 | if (!render_to_texture) { //initialization |
839 | return; |
840 | } |
841 | |
842 | render_to_texture = 2; |
843 | |
844 | if (aspect < 0) |
845 | { |
846 | pBufferHeight = 1 << lodmin; |
847 | pBufferWidth = pBufferHeight >> -aspect; |
848 | } |
849 | else |
850 | { |
851 | pBufferWidth = 1 << lodmin; |
852 | pBufferHeight = pBufferWidth >> aspect; |
853 | } |
854 | |
855 | if (curBufferAddr && startAddress+1 != curBufferAddr) |
856 | updateTexture(); |
857 | #ifdef SAVE_CBUFFER |
858 | //printf("saving %dx%d\n", pBufferWidth, pBufferHeight); |
859 | // save color buffer |
860 | if (nbAuxBuffers > 0) { |
861 | //glDrawBuffer(GL_AUX0); |
862 | //current_buffer = GL_AUX0; |
863 | } else { |
864 | int tw, th; |
865 | if (pBufferWidth < screen_width) |
866 | tw = pBufferWidth; |
867 | else |
868 | tw = screen_width; |
869 | if (pBufferHeight < screen_height) |
870 | th = pBufferHeight; |
871 | else |
872 | th = screen_height; |
873 | //glReadBuffer(GL_BACK); |
874 | glActiveTexture(texture_unit); |
875 | glBindTexture(GL_TEXTURE_2D, color_texture); |
876 | // save incrementally the framebuffer |
877 | if (save_w) { |
878 | if (tw > save_w && th > save_h) { |
879 | glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, save_h, |
880 | 0, viewport_offset+save_h, tw, th-save_h); |
881 | glCopyTexSubImage2D(GL_TEXTURE_2D, 0, save_w, 0, |
882 | save_w, viewport_offset, tw-save_w, save_h); |
883 | save_w = tw; |
884 | save_h = th; |
885 | } else if (tw > save_w) { |
886 | glCopyTexSubImage2D(GL_TEXTURE_2D, 0, save_w, 0, |
887 | save_w, viewport_offset, tw-save_w, save_h); |
888 | save_w = tw; |
889 | } else if (th > save_h) { |
890 | glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, save_h, |
891 | 0, viewport_offset+save_h, save_w, th-save_h); |
892 | save_h = th; |
893 | } |
894 | } else { |
895 | glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, |
896 | 0, viewport_offset, tw, th); |
897 | save_w = tw; |
898 | save_h = th; |
899 | } |
900 | glBindTexture(GL_TEXTURE_2D, default_texture); |
901 | } |
902 | #endif |
903 | |
904 | if (startAddress+1 != curBufferAddr || |
905 | (curBufferAddr == 0L && nbAuxBuffers == 0)) |
906 | buffer_cleared = 0; |
907 | |
908 | curBufferAddr = pBufferAddress = startAddress+1; |
909 | pBufferFmt = fmt; |
910 | |
911 | int rtmu = startAddress < grTexMinAddress(GR_TMU1)? 0 : 1; |
912 | int size = pBufferWidth*pBufferHeight*2; //grTexFormatSize(fmt); |
913 | if ((unsigned int) tmu_usage[rtmu].min > pBufferAddress) |
914 | tmu_usage[rtmu].min = pBufferAddress; |
915 | if ((unsigned int) tmu_usage[rtmu].max < pBufferAddress+size) |
916 | tmu_usage[rtmu].max = pBufferAddress+size; |
917 | //printf("tmu %d usage now %gMb - %gMb\n", |
918 | // rtmu, tmu_usage[rtmu].min/1024.0f, tmu_usage[rtmu].max/1024.0f); |
919 | |
920 | |
921 | width = pBufferWidth; |
922 | height = pBufferHeight; |
923 | |
924 | widtho = width/2; |
925 | heighto = height/2; |
926 | |
927 | // this could be improved, but might be enough as long as the set of |
928 | // texture buffer addresses stay small |
929 | for (i=(texbuf_i-1)&(NB_TEXBUFS-1) ; i!=texbuf_i; i=(i-1)&(NB_TEXBUFS-1)) |
930 | if (texbufs[i].start == pBufferAddress) |
931 | break; |
932 | texbufs[i].start = pBufferAddress; |
933 | texbufs[i].end = pBufferAddress + size; |
934 | texbufs[i].fmt = fmt; |
935 | if (i == texbuf_i) |
936 | texbuf_i = (texbuf_i+1)&(NB_TEXBUFS-1); |
937 | //printf("texbuf %x fmt %x\n", pBufferAddress, fmt); |
938 | |
939 | // ZIGGY it speeds things up to not delete the buffers |
940 | // a better thing would be to delete them *sometimes* |
941 | // remove_tex(pBufferAddress+1, pBufferAddress + size); |
942 | add_tex(pBufferAddress); |
943 | |
944 | //printf("viewport %dx%d\n", width, height); |
945 | if (height > screen_height) { |
946 | glViewport( 0, viewport_offset + screen_height - height, width, height); |
947 | } else |
948 | glViewport( 0, viewport_offset, width, height); |
949 | |
950 | glScissor(0, viewport_offset, width, height); |
951 | |
952 | |
953 | } else { |
954 | if (!render_to_texture) //initialization |
955 | { |
956 | if(!fbs_init) |
957 | { |
958 | for(i=0; i<100; i++) fbs[i].address = 0; |
959 | fbs_init = 1; |
960 | nb_fb = 0; |
961 | } |
962 | return; //no need to allocate FBO if render buffer is not texture buffer |
963 | } |
964 | |
965 | render_to_texture = 2; |
966 | |
967 | if (aspect < 0) |
968 | { |
969 | pBufferHeight = 1 << lodmin; |
970 | pBufferWidth = pBufferHeight >> -aspect; |
971 | } |
972 | else |
973 | { |
974 | pBufferWidth = 1 << lodmin; |
975 | pBufferHeight = pBufferWidth >> aspect; |
976 | } |
977 | pBufferAddress = startAddress+1; |
978 | |
979 | width = pBufferWidth; |
980 | height = pBufferHeight; |
981 | |
982 | widtho = width/2; |
983 | heighto = height/2; |
984 | |
985 | for (i=0; i<nb_fb; i++) |
986 | { |
987 | if (fbs[i].address == pBufferAddress) |
988 | { |
989 | // if (fbs[i].width == width && fbs[i].height == height) //select already allocated FBO |
990 | if (fbs[i].width >= width && fbs[i].height >= height) //select already allocated FBO, or large enough |
991 | { |
992 | //unsigned int tticks = ticksGetTicks(); |
993 | glBindFramebuffer( GL_FRAMEBUFFER, 0 ); |
994 | glBindFramebuffer( GL_FRAMEBUFFER, fbs[i].fbid ); |
995 | glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbs[i].texid, 0 ); |
996 | glBindRenderbuffer( GL_RENDERBUFFER, fbs[i].zbid ); |
997 | glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbs[i].zbid ); |
998 | glViewport( 0, 0, width, height); |
999 | glScissor( 0, 0, width, height); |
1000 | fbs[i].fb_width=width; |
1001 | fbs[i].fb_height=height; |
1002 | if (fbs[i].buff_clear) |
1003 | { |
1004 | glDepthMask(1); |
1005 | glClear( GL_DEPTH_BUFFER_BIT ); //clear z-buffer only. we may need content, stored in the frame buffer |
1006 | fbs[i].buff_clear = 0; |
1007 | } |
1008 | CHECK_FRAMEBUFFER_STATUS(); |
1009 | curBufferAddr = pBufferAddress; |
1010 | //printf("select existing fbo (%u ms)\n", ticksGetTicks()-tticks); |
1011 | return; |
1012 | } |
1013 | else //create new FBO at the same address, delete old one |
1014 | { |
1015 | //unsigned int tticks = ticksGetTicks(); |
1016 | glDeleteFramebuffers( 1, &(fbs[i].fbid) ); |
1017 | glDeleteRenderbuffers( 1, &(fbs[i].zbid) ); |
1018 | if (nb_fb > 1) |
1019 | memmove(&(fbs[i]), &(fbs[i+1]), sizeof(fb)*(nb_fb-i)); |
1020 | nb_fb--; |
1021 | //printf("delete existing fbo (%u ms)\n", ticksGetTicks()-tticks); |
1022 | break; |
1023 | } |
1024 | } |
1025 | } |
1026 | //unsigned int tticks = ticksGetTicks(); |
1027 | remove_tex(pBufferAddress, pBufferAddress + width*height*2/*grTexFormatSize(fmt)*/); |
1028 | //printf("delete texture (%u ms)\n", ticksGetTicks()-tticks); |
1029 | //create new FBO |
1030 | glGenFramebuffers( 1, &(fbs[nb_fb].fbid) ); |
1031 | glGenRenderbuffers( 1, &(fbs[nb_fb].zbid) ); |
1032 | glBindRenderbuffer( GL_RENDERBUFFER, fbs[nb_fb].zbid ); |
1033 | glRenderbufferStorage( GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height); |
1034 | fbs[nb_fb].address = pBufferAddress; |
1035 | fbs[nb_fb].width = width; |
1036 | fbs[nb_fb].height = height; |
1037 | fbs[nb_fb].fb_width = width; |
1038 | fbs[nb_fb].fb_height = height; |
1039 | fbs[nb_fb].texid = pBufferAddress; |
1040 | fbs[nb_fb].buff_clear = 0; |
1041 | add_tex(fbs[nb_fb].texid); |
1042 | glBindTexture(GL_TEXTURE_2D, fbs[nb_fb].texid); |
1043 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, |
1044 | GL_RGB, GL_UNSIGNED_BYTE, NULL); |
1045 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); |
1046 | glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); |
1047 | |
1048 | glBindFramebuffer( GL_FRAMEBUFFER, fbs[nb_fb].fbid); |
1049 | glFramebufferTexture2D(GL_FRAMEBUFFER, |
1050 | GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbs[nb_fb].texid, 0); |
1051 | glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbs[nb_fb].zbid ); |
1052 | glViewport(0,0,width,height); |
1053 | glScissor(0,0,width,height); |
1054 | glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); |
1055 | glDepthMask(1); |
1056 | glClear( GL_DEPTH_BUFFER_BIT ); |
1057 | CHECK_FRAMEBUFFER_STATUS(); |
1058 | curBufferAddr = pBufferAddress; |
1059 | nb_fb++; |
1060 | //printf("create new fbo=fb[%i] (%u ms)\n", nb_fb-1, ticksGetTicks()-tticks); |
1061 | } |
1062 | } |
1063 | |
1064 | int CheckTextureBufferFormat(GrChipID_t tmu, FxU32 startAddress, GrTexInfo *info ) |
1065 | { |
1066 | int found, i; |
1067 | if (!use_fbo) { |
1068 | for (found=i=0; i<2; i++) |
1069 | if ((FxU32) tmu_usage[i].min <= startAddress && (FxU32) tmu_usage[i].max > startAddress) { |
1070 | //printf("tmu %d == framebuffer %x\n", tmu, startAddress); |
1071 | found = 1; |
1072 | break; |
1073 | } |
1074 | } else { |
1075 | found = i = 0; |
1076 | while (i < nb_fb) |
1077 | { |
1078 | unsigned int end = fbs[i].address + fbs[i].fb_width*fbs[i].fb_height*2; |
1079 | if (startAddress >= fbs[i].address && startAddress < end) |
1080 | { |
1081 | found = 1; |
1082 | break; |
1083 | } |
1084 | i++; |
1085 | } |
1086 | } |
1087 | |
1088 | if (!use_fbo && found) { |
1089 | int tw, th, rh, cw, ch; |
1090 | if (info->aspectRatioLog2 < 0) |
1091 | { |
1092 | th = 1 << info->largeLodLog2; |
1093 | tw = th >> -info->aspectRatioLog2; |
1094 | } |
1095 | else |
1096 | { |
1097 | tw = 1 << info->largeLodLog2; |
1098 | th = tw >> info->aspectRatioLog2; |
1099 | } |
1100 | |
1101 | if (info->aspectRatioLog2 < 0) |
1102 | { |
1103 | ch = 256; |
1104 | cw = ch >> -info->aspectRatioLog2; |
1105 | } |
1106 | else |
1107 | { |
1108 | cw = 256; |
1109 | ch = cw >> info->aspectRatioLog2; |
1110 | } |
1111 | |
1112 | if (use_fbo || th < screen_height) |
1113 | rh = th; |
1114 | else |
1115 | rh = screen_height; |
1116 | |
1117 | //printf("th %d rh %d ch %d\n", th, rh, ch); |
1118 | |
1119 | invtex[tmu] = 1.0f - (th - rh) / (float)th; |
1120 | } else |
1121 | invtex[tmu] = 0; |
1122 | |
1123 | if (info->format == GR_TEXFMT_ALPHA_INTENSITY_88 ) { |
1124 | if (!found) { |
1125 | return 0; |
1126 | } |
1127 | if(tmu == 0) |
1128 | { |
1129 | if(blackandwhite1 != found) |
1130 | { |
1131 | blackandwhite1 = found; |
1132 | need_to_compile = 1; |
1133 | } |
1134 | } |
1135 | else |
1136 | { |
1137 | if(blackandwhite0 != found) |
1138 | { |
1139 | blackandwhite0 = found; |
1140 | need_to_compile = 1; |
1141 | } |
1142 | } |
1143 | return 1; |
1144 | } |
1145 | return 0; |
1146 | |
1147 | } |
1148 | |
1149 | |
1150 | FX_ENTRY void FX_CALL |
1151 | grTextureAuxBufferExt( GrChipID_t tmu, |
1152 | FxU32 startAddress, |
1153 | GrLOD_t thisLOD, |
1154 | GrLOD_t largeLOD, |
1155 | GrAspectRatio_t aspectRatio, |
1156 | GrTextureFormat_t format, |
1157 | FxU32 odd_even_mask ) |
1158 | { |
1159 | LOG("grTextureAuxBufferExt(%d, %d, %d, %d %d, %d, %d)\r\n", tmu, startAddress, thisLOD, largeLOD, aspectRatio, format, odd_even_mask); |
1160 | //display_warning("grTextureAuxBufferExt"); |
1161 | } |
1162 | |
1163 | FX_ENTRY void FX_CALL grAuxBufferExt( GrBuffer_t buffer ); |
1164 | |
1165 | FX_ENTRY GrProc FX_CALL |
1166 | grGetProcAddress( char *procName ) |
1167 | { |
1168 | LOG("grGetProcAddress(%s)\r\n", procName); |
1169 | if(!strcmp(procName, "grSstWinOpenExt")) |
1170 | return (GrProc)grSstWinOpenExt; |
1171 | if(!strcmp(procName, "grTextureBufferExt")) |
1172 | return (GrProc)grTextureBufferExt; |
1173 | if(!strcmp(procName, "grChromaRangeExt")) |
1174 | return (GrProc)grChromaRangeExt; |
1175 | if(!strcmp(procName, "grChromaRangeModeExt")) |
1176 | return (GrProc)grChromaRangeModeExt; |
1177 | if(!strcmp(procName, "grTexChromaRangeExt")) |
1178 | return (GrProc)grTexChromaRangeExt; |
1179 | if(!strcmp(procName, "grTexChromaModeExt")) |
1180 | return (GrProc)grTexChromaModeExt; |
1181 | // ZIGGY framebuffer copy extension |
1182 | if(!strcmp(procName, "grFramebufferCopyExt")) |
1183 | return (GrProc)grFramebufferCopyExt; |
1184 | if(!strcmp(procName, "grColorCombineExt")) |
1185 | return (GrProc)grColorCombineExt; |
1186 | if(!strcmp(procName, "grAlphaCombineExt")) |
1187 | return (GrProc)grAlphaCombineExt; |
1188 | if(!strcmp(procName, "grTexColorCombineExt")) |
1189 | return (GrProc)grTexColorCombineExt; |
1190 | if(!strcmp(procName, "grTexAlphaCombineExt")) |
1191 | return (GrProc)grTexAlphaCombineExt; |
1192 | if(!strcmp(procName, "grConstantColorValueExt")) |
1193 | return (GrProc)grConstantColorValueExt; |
1194 | if(!strcmp(procName, "grTextureAuxBufferExt")) |
1195 | return (GrProc)grTextureAuxBufferExt; |
1196 | if(!strcmp(procName, "grAuxBufferExt")) |
1197 | return (GrProc)grAuxBufferExt; |
1198 | if(!strcmp(procName, "grWrapperFullScreenResolutionExt")) |
1199 | return (GrProc)grWrapperFullScreenResolutionExt; |
1200 | if(!strcmp(procName, "grConfigWrapperExt")) |
1201 | return (GrProc)grConfigWrapperExt; |
1202 | if(!strcmp(procName, "grKeyPressedExt")) |
1203 | return (GrProc)grKeyPressedExt; |
1204 | if(!strcmp(procName, "grQueryResolutionsExt")) |
1205 | return (GrProc)grQueryResolutionsExt; |
1206 | if(!strcmp(procName, "grGetGammaTableExt")) |
1207 | return (GrProc)grGetGammaTableExt; |
1208 | display_warning("grGetProcAddress : %s", procName); |
1209 | return 0; |
1210 | } |
1211 | |
1212 | FX_ENTRY FxU32 FX_CALL |
1213 | grGet( FxU32 pname, FxU32 plength, FxI32 *params ) |
1214 | { |
1215 | LOG("grGet(%d,%d)\r\n", pname, plength); |
1216 | switch(pname) |
1217 | { |
1218 | case GR_MAX_TEXTURE_SIZE: |
1219 | if (plength < 4 || params == NULL) return 0; |
1220 | params[0] = 2048; |
1221 | return 4; |
1222 | break; |
1223 | case GR_NUM_TMU: |
1224 | if (plength < 4 || params == NULL) return 0; |
1225 | if (!nbTextureUnits) |
1226 | { |
1227 | grSstWinOpen((unsigned long)NULL, GR_RESOLUTION_640x480 | 0x80000000, 0, GR_COLORFORMAT_ARGB, |
1228 | GR_ORIGIN_UPPER_LEFT, 2, 1); |
1229 | grSstWinClose(0); |
1230 | } |
1231 | #ifdef VOODOO1 |
1232 | params[0] = 1; |
1233 | #else |
1234 | if (nbTextureUnits > 2) |
1235 | params[0] = 2; |
1236 | else |
1237 | params[0] = 1; |
1238 | #endif |
1239 | return 4; |
1240 | break; |
1241 | case GR_NUM_BOARDS: |
1242 | case GR_NUM_FB: |
1243 | case GR_REVISION_FB: |
1244 | case GR_REVISION_TMU: |
1245 | if (plength < 4 || params == NULL) return 0; |
1246 | params[0] = 1; |
1247 | return 4; |
1248 | break; |
1249 | case GR_MEMORY_FB: |
1250 | if (plength < 4 || params == NULL) return 0; |
1251 | params[0] = 16*1024*1024; |
1252 | return 4; |
1253 | break; |
1254 | case GR_MEMORY_TMU: |
1255 | if (plength < 4 || params == NULL) return 0; |
1256 | params[0] = 16*1024*1024; |
1257 | return 4; |
1258 | break; |
1259 | case GR_MEMORY_UMA: |
1260 | if (plength < 4 || params == NULL) return 0; |
1261 | params[0] = 16*1024*1024*nbTextureUnits; |
1262 | return 4; |
1263 | break; |
1264 | case GR_BITS_RGBA: |
1265 | if (plength < 16 || params == NULL) return 0; |
1266 | params[0] = 8; |
1267 | params[1] = 8; |
1268 | params[2] = 8; |
1269 | params[3] = 8; |
1270 | return 16; |
1271 | break; |
1272 | case GR_BITS_DEPTH: |
1273 | if (plength < 4 || params == NULL) return 0; |
1274 | params[0] = 16; |
1275 | return 4; |
1276 | break; |
1277 | case GR_BITS_GAMMA: |
1278 | if (plength < 4 || params == NULL) return 0; |
1279 | params[0] = 8; |
1280 | return 4; |
1281 | break; |
1282 | case GR_GAMMA_TABLE_ENTRIES: |
1283 | if (plength < 4 || params == NULL) return 0; |
1284 | params[0] = 256; |
1285 | return 4; |
1286 | break; |
1287 | case GR_FOG_TABLE_ENTRIES: |
1288 | if (plength < 4 || params == NULL) return 0; |
1289 | params[0] = 64; |
1290 | return 4; |
1291 | break; |
1292 | case GR_WDEPTH_MIN_MAX: |
1293 | if (plength < 8 || params == NULL) return 0; |
1294 | params[0] = 0; |
1295 | params[1] = 65528; |
1296 | return 8; |
1297 | break; |
1298 | case GR_ZDEPTH_MIN_MAX: |
1299 | if (plength < 8 || params == NULL) return 0; |
1300 | params[0] = 0; |
1301 | params[1] = 65535; |
1302 | return 8; |
1303 | break; |
1304 | case GR_LFB_PIXEL_PIPE: |
1305 | if (plength < 4 || params == NULL) return 0; |
1306 | params[0] = FXFALSE; |
1307 | return 4; |
1308 | break; |
1309 | case GR_MAX_TEXTURE_ASPECT_RATIO: |
1310 | if (plength < 4 || params == NULL) return 0; |
1311 | params[0] = 3; |
1312 | return 4; |
1313 | break; |
1314 | case GR_NON_POWER_OF_TWO_TEXTURES: |
1315 | if (plength < 4 || params == NULL) return 0; |
1316 | params[0] = FXFALSE; |
1317 | return 4; |
1318 | break; |
1319 | case GR_TEXTURE_ALIGN: |
1320 | if (plength < 4 || params == NULL) return 0; |
1321 | params[0] = 0; |
1322 | return 4; |
1323 | break; |
1324 | default: |
1325 | display_warning("unknown pname in grGet : %x", pname); |
1326 | } |
1327 | return 0; |
1328 | } |
1329 | |
1330 | FX_ENTRY const char * FX_CALL |
1331 | grGetString( FxU32 pname ) |
1332 | { |
1333 | LOG("grGetString(%d)\r\n", pname); |
1334 | switch(pname) |
1335 | { |
1336 | case GR_EXTENSION: |
1337 | { |
1338 | static char extension[] = "CHROMARANGE TEXCHROMA TEXMIRROR PALETTE6666 FOGCOORD EVOODOO TEXTUREBUFFER TEXUMA TEXFMT COMBINE GETGAMMA"; |
1339 | return extension; |
1340 | } |
1341 | break; |
1342 | case GR_HARDWARE: |
1343 | { |
1344 | static char hardware[] = "Voodoo5 (tm)"; |
1345 | return hardware; |
1346 | } |
1347 | break; |
1348 | case GR_VENDOR: |
1349 | { |
1350 | static char vendor[] = "3Dfx Interactive"; |
1351 | return vendor; |
1352 | } |
1353 | break; |
1354 | case GR_RENDERER: |
1355 | { |
1356 | static char renderer[] = "Glide"; |
1357 | return renderer; |
1358 | } |
1359 | break; |
1360 | case GR_VERSION: |
1361 | { |
1362 | static char version[] = "3.0"; |
1363 | return version; |
1364 | } |
1365 | break; |
1366 | default: |
1367 | display_warning("unknown grGetString selector : %x", pname); |
1368 | } |
1369 | return NULL; |
1370 | } |
1371 | |
1372 | static void render_rectangle(int texture_number, |
1373 | int dst_x, int dst_y, |
1374 | int src_width, int src_height, |
1375 | int tex_width, int tex_height, int invert) |
1376 | { |
1377 | 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); |
1378 | int vertexOffset_location; |
1379 | int textureSizes_location; |
1380 | static float data[] = { |
1381 | ((int)dst_x), //X 0 |
1382 | invert*-((int)dst_y), //Y 0 |
1383 | 0.0f, //U 0 |
1384 | 0.0f, //V 0 |
1385 | |
1386 | ((int)dst_x), //X 1 |
1387 | invert*-((int)dst_y + (int)src_height), //Y 1 |
1388 | 0.0f, //U 1 |
1389 | (float)src_height / (float)tex_height, //V 1 |
1390 | |
1391 | ((int)dst_x + (int)src_width), |
1392 | invert*-((int)dst_y + (int)src_height), |
1393 | (float)src_width / (float)tex_width, |
1394 | (float)src_height / (float)tex_height, |
1395 | |
1396 | ((int)dst_x), |
1397 | invert*-((int)dst_y), |
1398 | 0.0f, |
1399 | 0.0f |
1400 | }; |
1401 | |
1402 | vbo_disable(); |
1403 | glDisableVertexAttribArray(COLOUR_ATTR); |
1404 | glDisableVertexAttribArray(TEXCOORD_1_ATTR); |
1405 | glDisableVertexAttribArray(FOG_ATTR); |
1406 | |
1407 | glVertexAttribPointer(POSITION_ATTR,2,GL_FLOAT,false,2,data); //Position |
1408 | glVertexAttribPointer(TEXCOORD_0_ATTR,2,GL_FLOAT,false,2,&data[2]); //Tex |
1409 | |
1410 | glEnableVertexAttribArray(COLOUR_ATTR); |
1411 | glEnableVertexAttribArray(TEXCOORD_1_ATTR); |
1412 | glEnableVertexAttribArray(FOG_ATTR); |
1413 | |
1414 | |
1415 | disable_textureSizes(); |
1416 | |
1417 | glDrawArrays(GL_TRIANGLE_STRIP,0,4); |
1418 | vbo_enable(); |
1419 | |
1420 | |
1421 | /* |
1422 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
1423 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
1424 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
1425 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
1426 | glBegin(GL_QUADS); |
1427 | glMultiTexCoord2fARB(texture_number, 0.0f, 0.0f); |
1428 | glVertex2f(((int)dst_x - widtho) / (float)(width/2), |
1429 | invert*-((int)dst_y - heighto) / (float)(height/2)); |
1430 | glMultiTexCoord2fARB(texture_number, 0.0f, (float)src_height / (float)tex_height); |
1431 | glVertex2f(((int)dst_x - widtho) / (float)(width/2), |
1432 | invert*-((int)dst_y + (int)src_height - heighto) / (float)(height/2)); |
1433 | glMultiTexCoord2fARB(texture_number, (float)src_width / (float)tex_width, (float)src_height / (float)tex_height); |
1434 | glVertex2f(((int)dst_x + (int)src_width - 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, 0.0f); |
1437 | glVertex2f(((int)dst_x + (int)src_width - widtho) / (float)(width/2), |
1438 | invert*-((int)dst_y - heighto) / (float)(height/2)); |
1439 | glMultiTexCoord2fARB(texture_number, 0.0f, 0.0f); |
1440 | glVertex2f(((int)dst_x - widtho) / (float)(width/2), |
1441 | invert*-((int)dst_y - heighto) / (float)(height/2)); |
1442 | glEnd(); |
1443 | */ |
1444 | |
1445 | compile_shader(); |
1446 | |
1447 | glEnable(GL_DEPTH_TEST); |
1448 | glEnable(GL_BLEND); |
1449 | } |
1450 | |
1451 | void reloadTexture() |
1452 | { |
1453 | if (use_fbo || !render_to_texture || buffer_cleared) |
1454 | return; |
1455 | |
1456 | LOG("reload texture %dx%d\n", width, height); |
1457 | //printf("reload texture %dx%d\n", width, height); |
1458 | |
1459 | buffer_cleared = 1; |
1460 | |
1461 | //glPushAttrib(GL_ALL_ATTRIB_BITS); |
1462 | glActiveTexture(texture_unit); |
1463 | glBindTexture(GL_TEXTURE_2D, pBufferAddress); |
1464 | //glDisable(GL_ALPHA_TEST); |
1465 | //glDrawBuffer(current_buffer); |
1466 | glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); |
1467 | set_copy_shader(); |
1468 | glDisable(GL_DEPTH_TEST); |
1469 | glDisable(GL_CULL_FACE); |
1470 | int w = 0, h = 0; |
1471 | if (height > screen_height) h = screen_height - height; |
1472 | render_rectangle(texture_unit, |
1473 | -w, -h, |
1474 | width, height, |
1475 | width, height, -1); |
1476 | glBindTexture(GL_TEXTURE_2D, default_texture); |
1477 | //glPopAttrib(); |
1478 | } |
1479 | |
1480 | void updateTexture() |
1481 | { |
1482 | if (!use_fbo && render_to_texture == 2) { |
1483 | LOG("update texture %x\n", pBufferAddress); |
1484 | //printf("update texture %x\n", pBufferAddress); |
1485 | |
1486 | // nothing changed, don't update the texture |
1487 | if (!buffer_cleared) { |
1488 | LOG("update cancelled\n", pBufferAddress); |
1489 | return; |
1490 | } |
1491 | |
1492 | //glPushAttrib(GL_ALL_ATTRIB_BITS); |
1493 | |
1494 | // save result of render to texture into actual texture |
1495 | //glReadBuffer(current_buffer); |
1496 | glActiveTexture(texture_unit); |
1497 | // ZIGGY |
1498 | // deleting the texture before resampling it increases speed on certain old |
1499 | // nvidia cards (geforce 2 for example), unfortunatly it slows down a lot |
1500 | // on newer cards. |
1501 | //glDeleteTextures( 1, &pBufferAddress ); |
1502 | glBindTexture(GL_TEXTURE_2D, pBufferAddress); |
1503 | glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, |
1504 | 0, viewport_offset, width, height, 0); |
1505 | |
1506 | glBindTexture(GL_TEXTURE_2D, default_texture); |
1507 | //glPopAttrib(); |
1508 | } |
1509 | } |
1510 | |
1511 | FX_ENTRY void FX_CALL grFramebufferCopyExt(int x, int y, int w, int h, |
1512 | int from, int to, int mode) |
1513 | { |
1514 | if (mode == GR_FBCOPY_MODE_DEPTH) { |
1515 | |
1516 | int tw = 1, th = 1; |
1517 | if (npot_support) { |
1518 | tw = width; th = height; |
1519 | } else { |
1520 | while (tw < width) tw <<= 1; |
1521 | while (th < height) th <<= 1; |
1522 | } |
1523 | |
1524 | if (from == GR_FBCOPY_BUFFER_BACK && to == GR_FBCOPY_BUFFER_FRONT) { |
1525 | //printf("save depth buffer %d\n", render_to_texture); |
1526 | // save the depth image in a texture |
1527 | //glReadBuffer(current_buffer); |
1528 | glBindTexture(GL_TEXTURE_2D, depth_texture); |
1529 | glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, |
1530 | 0, viewport_offset, tw, th, 0); |
1531 | glBindTexture(GL_TEXTURE_2D, default_texture); |
1532 | return; |
1533 | } |
1534 | if (from == GR_FBCOPY_BUFFER_FRONT && to == GR_FBCOPY_BUFFER_BACK) { |
1535 | //printf("writing to depth buffer %d\n", render_to_texture); |
1536 | //glPushAttrib(GL_ALL_ATTRIB_BITS); |
1537 | //glDisable(GL_ALPHA_TEST); |
1538 | //glDrawBuffer(current_buffer); |
1539 | glActiveTexture(texture_unit); |
1540 | glBindTexture(GL_TEXTURE_2D, depth_texture); |
1541 | glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); |
1542 | set_depth_shader(); |
1543 | glEnable(GL_DEPTH_TEST); |
1544 | glDepthFunc(GL_ALWAYS); |
1545 | glDisable(GL_CULL_FACE); |
1546 | render_rectangle(texture_unit, |
1547 | 0, 0, |
1548 | width, height, |
1549 | tw, th, -1); |
1550 | glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); |
1551 | glBindTexture(GL_TEXTURE_2D, default_texture); |
1552 | //glPopAttrib(); |
1553 | return; |
1554 | } |
1555 | |
1556 | } |
1557 | } |
1558 | |
1559 | FX_ENTRY void FX_CALL |
1560 | grRenderBuffer( GrBuffer_t buffer ) |
1561 | { |
1562 | #ifdef _WIN32 |
1563 | static HANDLE region = NULL; |
1564 | int realWidth = pBufferWidth, realHeight = pBufferHeight; |
1565 | #endif // _WIN32 |
1566 | LOG("grRenderBuffer(%d)\r\n", buffer); |
1567 | //printf("grRenderBuffer(%d)\n", buffer); |
1568 | |
1569 | switch(buffer) |
1570 | { |
1571 | case GR_BUFFER_BACKBUFFER: |
1572 | if(render_to_texture) |
1573 | { |
1574 | updateTexture(); |
1575 | |
1576 | // VP z fix |
1577 | //glMatrixMode(GL_MODELVIEW); |
1578 | //glLoadIdentity(); |
1579 | //glTranslatef(0, 0, 1-zscale); |
1580 | //glScalef(1, 1, zscale); |
1581 | inverted_culling = 0; |
1582 | grCullMode(culling_mode); |
1583 | |
1584 | width = savedWidth; |
1585 | height = savedHeight; |
1586 | widtho = savedWidtho; |
1587 | heighto = savedHeighto; |
1588 | if (use_fbo) { |
1589 | glBindFramebuffer(GL_FRAMEBUFFER, 0); |
1590 | glBindRenderbuffer( GL_RENDERBUFFER, 0 ); |
1591 | } |
1592 | curBufferAddr = 0; |
1593 | |
1594 | glViewport(0, viewport_offset, width, viewport_height); |
1595 | glScissor(0, viewport_offset, width, height); |
1596 | |
1597 | #ifdef SAVE_CBUFFER |
1598 | if (!use_fbo && render_to_texture == 2) { |
1599 | // restore color buffer |
1600 | if (nbAuxBuffers > 0) { |
1601 | //glDrawBuffer(GL_BACK); |
1602 | current_buffer = GL_BACK; |
1603 | } else if (save_w) { |
1604 | int tw = 1, th = 1; |
1605 | //printf("restore %dx%d\n", save_w, save_h); |
1606 | if (npot_support) { |
1607 | tw = screen_width; |
1608 | th = screen_height; |
1609 | } else { |
1610 | while (tw < screen_width) tw <<= 1; |
1611 | while (th < screen_height) th <<= 1; |
1612 | } |
1613 | |
1614 | //glPushAttrib(GL_ALL_ATTRIB_BITS); |
1615 | //glDisable(GL_ALPHA_TEST); |
1616 | //glDrawBuffer(GL_BACK); |
1617 | glActiveTexture(texture_unit); |
1618 | glBindTexture(GL_TEXTURE_2D, color_texture); |
1619 | glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); |
1620 | set_copy_shader(); |
1621 | glDisable(GL_DEPTH_TEST); |
1622 | glDisable(GL_CULL_FACE); |
1623 | render_rectangle(texture_unit, |
1624 | 0, 0, |
1625 | save_w, save_h, |
1626 | tw, th, -1); |
1627 | glBindTexture(GL_TEXTURE_2D, default_texture); |
1628 | //glPopAttrib(); |
1629 | |
1630 | save_w = save_h = 0; |
1631 | } |
1632 | } |
1633 | #endif |
1634 | render_to_texture = 0; |
1635 | } |
1636 | //glDrawBuffer(GL_BACK); |
1637 | break; |
1638 | case 6: // RENDER TO TEXTURE |
1639 | if(!render_to_texture) |
1640 | { |
1641 | savedWidth = width; |
1642 | savedHeight = height; |
1643 | savedWidtho = widtho; |
1644 | savedHeighto = heighto; |
1645 | } |
1646 | |
1647 | { |
1648 | if (!use_fbo) { |
1649 | //glMatrixMode(GL_MODELVIEW); |
1650 | //glLoadIdentity(); |
1651 | //glTranslatef(0, 0, 1-zscale); |
1652 | //glScalef(1, 1, zscale); |
1653 | inverted_culling = 0; |
1654 | } else { |
1655 | /* |
1656 | float m[4*4] = {1.0f, 0.0f, 0.0f, 0.0f, |
1657 | 0.0f,-1.0f, 0.0f, 0.0f, |
1658 | 0.0f, 0.0f, 1.0f, 0.0f, |
1659 | 0.0f, 0.0f, 0.0f, 1.0f}; |
1660 | glMatrixMode(GL_MODELVIEW); |
1661 | glLoadMatrixf(m); |
1662 | // VP z fix |
1663 | glTranslatef(0, 0, 1-zscale); |
1664 | glScalef(1, 1*1, zscale); |
1665 | */ |
1666 | inverted_culling = 1; |
1667 | grCullMode(culling_mode); |
1668 | } |
1669 | } |
1670 | render_to_texture = 1; |
1671 | break; |
1672 | default: |
1673 | display_warning("grRenderBuffer : unknown buffer : %x", buffer); |
1674 | } |
1675 | } |
1676 | |
1677 | FX_ENTRY void FX_CALL |
1678 | grAuxBufferExt( GrBuffer_t buffer ) |
1679 | { |
1680 | LOG("grAuxBufferExt(%d)\r\n", buffer); |
1681 | //display_warning("grAuxBufferExt"); |
1682 | |
1683 | if (buffer == GR_BUFFER_AUXBUFFER) { |
1684 | invtex[0] = 0; |
1685 | invtex[1] = 0; |
1686 | need_to_compile = 0; |
1687 | set_depth_shader(); |
1688 | glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); |
1689 | glEnable(GL_DEPTH_TEST); |
1690 | glDepthFunc(GL_ALWAYS); |
1691 | glDisable(GL_CULL_FACE); |
1692 | //glDisable(GL_ALPHA_TEST); |
1693 | glDepthMask(GL_TRUE); |
1694 | grTexFilterMode(GR_TMU1, GR_TEXTUREFILTER_POINT_SAMPLED, GR_TEXTUREFILTER_POINT_SAMPLED); |
1695 | } else { |
1696 | glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); |
1697 | need_to_compile = 1; |
1698 | } |
1699 | } |
1700 | |
1701 | FX_ENTRY void FX_CALL |
1702 | grBufferClear( GrColor_t color, GrAlpha_t alpha, FxU32 depth ) |
1703 | { |
1704 | vbo_draw(); |
1705 | LOG("grBufferClear(%d,%d,%d)\r\n", color, alpha, depth); |
1706 | switch(lfb_color_fmt) |
1707 | { |
1708 | case GR_COLORFORMAT_ARGB: |
1709 | glClearColor(((color >> 16) & 0xFF) / 255.0f, |
1710 | ((color >> 8) & 0xFF) / 255.0f, |
1711 | ( color & 0xFF) / 255.0f, |
1712 | alpha / 255.0f); |
1713 | break; |
1714 | case GR_COLORFORMAT_RGBA: |
1715 | glClearColor(((color >> 24) & 0xFF) / 255.0f, |
1716 | ((color >> 16) & 0xFF) / 255.0f, |
1717 | (color & 0xFF) / 255.0f, |
1718 | alpha / 255.0f); |
1719 | break; |
1720 | default: |
1721 | display_warning("grBufferClear: unknown color format : %x", lfb_color_fmt); |
1722 | } |
1723 | |
1724 | if (w_buffer_mode) |
1725 | glClearDepthf(1.0f - ((1.0f + (depth >> 4) / 4096.0f) * (1 << (depth & 0xF))) / 65528.0); |
1726 | else |
1727 | glClearDepthf(depth / 65535.0f); |
1728 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
1729 | |
1730 | // ZIGGY TODO check that color mask is on |
1731 | buffer_cleared = 1; |
1732 | |
1733 | } |
1734 | |
1735 | // #include <unistd.h> |
1736 | FX_ENTRY void FX_CALL |
1737 | grBufferSwap( FxU32 swap_interval ) |
1738 | { |
1739 | vbo_draw(); |
1740 | // glFinish(); |
1741 | // printf("rendercallback is %p\n", renderCallback); |
1742 | if(renderCallback) |
1743 | (*renderCallback)(1); |
1744 | int i; |
1745 | LOG("grBufferSwap(%d)\r\n", swap_interval); |
1746 | //printf("swap\n"); |
1747 | if (render_to_texture) { |
1748 | display_warning("swap while render_to_texture\n"); |
1749 | return; |
1750 | } |
1751 | |
1752 | CoreVideo_GL_SwapBuffers(); |
1753 | for (i = 0; i < nb_fb; i++) |
1754 | fbs[i].buff_clear = 1; |
1755 | |
1756 | // VP debugging |
1757 | #ifdef VPDEBUG |
1758 | dump_stop(); |
1759 | SDL_Event event; |
1760 | while (SDL_PollEvent(&event)) { |
1761 | switch (event.type) { |
1762 | case SDL_KEYDOWN: |
1763 | switch (event.key.keysym.sym) { |
1764 | case 'd': |
1765 | printf("Dumping !\n"); |
1766 | dump_start(); |
1767 | break; |
1768 | case 'w': { |
1769 | static int wireframe; |
1770 | wireframe = !wireframe; |
1771 | glPolygonMode(GL_FRONT_AND_BACK, wireframe? GL_LINE : GL_FILL); |
1772 | break; |
1773 | } |
1774 | } |
1775 | break; |
1776 | } |
1777 | } |
1778 | #endif |
1779 | } |
1780 | |
1781 | // frame buffer |
1782 | |
1783 | FX_ENTRY FxBool FX_CALL |
1784 | grLfbLock( GrLock_t type, GrBuffer_t buffer, GrLfbWriteMode_t writeMode, |
1785 | GrOriginLocation_t origin, FxBool pixelPipeline, |
1786 | GrLfbInfo_t *info ) |
1787 | { |
1788 | LOG("grLfbLock(%d,%d,%d,%d,%d)\r\n", type, buffer, writeMode, origin, pixelPipeline); |
1789 | printf("grLfbLock(%d,%d,%d,%d,%d)\r\n", type, buffer, writeMode, origin, pixelPipeline); |
1790 | if (type == GR_LFB_WRITE_ONLY) |
1791 | { |
1792 | display_warning("grLfbLock : write only"); |
1793 | } |
1794 | else |
1795 | { |
1796 | unsigned char *buf; |
1797 | int i,j; |
1798 | |
1799 | switch(buffer) |
1800 | { |
1801 | case GR_BUFFER_FRONTBUFFER: |
1802 | //glReadBuffer(GL_FRONT); |
1803 | break; |
1804 | case GR_BUFFER_BACKBUFFER: |
1805 | //glReadBuffer(GL_BACK); |
1806 | break; |
1807 | default: |
1808 | display_warning("grLfbLock : unknown buffer : %x", buffer); |
1809 | } |
1810 | |
1811 | if(buffer != GR_BUFFER_AUXBUFFER) |
1812 | { |
1813 | if (writeMode == GR_LFBWRITEMODE_888) { |
1814 | /*SEB*/ |
1815 | buf = (unsigned char*)malloc(width*height*4); |
1816 | //printf("LfbLock GR_LFBWRITEMODE_888\n"); |
1817 | info->lfbPtr = frameBuffer; |
1818 | info->strideInBytes = width*4; |
1819 | info->writeMode = GR_LFBWRITEMODE_888; |
1820 | info->origin = origin; |
1821 | //glReadPixels(0, viewport_offset, width, height, GL_BGRA, GL_UNSIGNED_BYTE, frameBuffer); |
1822 | glReadPixels(0, viewport_offset, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buf); |
1823 | |
1824 | /*SEB*/ |
1825 | unsigned char *p=buf; |
1826 | for (j=0; j<height; j++) |
1827 | { |
1828 | short unsigned int *f=frameBuffer+(height-j-1)*width; |
1829 | for (i=0; i<width; i++) |
1830 | { |
1831 | *(f++) = |
1832 | (*(p) <<24) | |
1833 | (*(p+1) <<16) | |
1834 | (*(p+2) << 8) | |
1835 | (0xff); |
1836 | p+=4; |
1837 | } |
1838 | } |
1839 | free(buf); |
1840 | } else { |
1841 | buf = (unsigned char*)malloc(width*height*4); |
1842 | |
1843 | info->lfbPtr = frameBuffer; |
1844 | info->strideInBytes = width*2; |
1845 | info->writeMode = GR_LFBWRITEMODE_565; |
1846 | info->origin = origin; |
1847 | glReadPixels(0, viewport_offset, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buf); |
1848 | |
1849 | /*SEB*/ |
1850 | unsigned char *p=buf; |
1851 | for (j=0; j<height; j++) |
1852 | { |
1853 | short unsigned int *f=frameBuffer+(height-j-1)*width; |
1854 | for (i=0; i<width; i++) |
1855 | { |
1856 | /* frameBuffer[(height-j-1)*width+i] = |
1857 | ((buf[j*width*4+i*4+0] >> 3) << 11) | |
1858 | ((buf[j*width*4+i*4+1] >> 2) << 5) | |
1859 | (buf[j*width*4+i*4+2] >> 3);*/ |
1860 | *(f++) = |
1861 | ((*(p) >> 3) << 11) | |
1862 | ((*(p+1) >> 2) << 5) | |
1863 | (*(p+2) >> 3); |
1864 | p+=4; |
1865 | } |
1866 | } |
1867 | free(buf); |
1868 | } |
1869 | } |
1870 | else |
1871 | { |
1872 | info->lfbPtr = depthBuffer; |
1873 | info->strideInBytes = width*2; |
1874 | info->writeMode = GR_LFBWRITEMODE_ZA16; |
1875 | info->origin = origin; |
1876 | //*SEB* *TODO* check alignment |
1877 | glReadPixels(0, viewport_offset, width, height, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, depthBuffer); |
1878 | } |
1879 | } |
1880 | |
1881 | return FXTRUE; |
1882 | } |
1883 | |
1884 | FX_ENTRY FxBool FX_CALL |
1885 | grLfbUnlock( GrLock_t type, GrBuffer_t buffer ) |
1886 | { |
1887 | LOG("grLfbUnlock(%d,%d)\r\n", type, buffer); |
1888 | if (type == GR_LFB_WRITE_ONLY) |
1889 | { |
1890 | display_warning("grLfbUnlock : write only"); |
1891 | } |
1892 | return FXTRUE; |
1893 | } |
1894 | |
1895 | FX_ENTRY FxBool FX_CALL |
1896 | grLfbReadRegion( GrBuffer_t src_buffer, |
1897 | FxU32 src_x, FxU32 src_y, |
1898 | FxU32 src_width, FxU32 src_height, |
1899 | FxU32 dst_stride, void *dst_data ) |
1900 | { |
1901 | unsigned char *buf; |
1902 | unsigned int i,j; |
1903 | unsigned short *frameBuffer = (unsigned short*)dst_data; |
1904 | unsigned short *depthBuffer = (unsigned short*)dst_data; |
1905 | LOG("grLfbReadRegion(%d,%d,%d,%d,%d,%d)\r\n", src_buffer, src_x, src_y, src_width, src_height, dst_stride); |
1906 | //printf("grLfbReadRegion(%d,%d,%d,%d,%d,%d)\r\n", src_buffer, src_x, src_y, src_width, src_height, dst_stride); |
1907 | |
1908 | switch(src_buffer) |
1909 | { |
1910 | case GR_BUFFER_FRONTBUFFER: |
1911 | //glReadBuffer(GL_FRONT); |
1912 | break; |
1913 | case GR_BUFFER_BACKBUFFER: |
1914 | //glReadBuffer(GL_BACK); |
1915 | break; |
1916 | /*case GR_BUFFER_AUXBUFFER: |
1917 | glReadBuffer(current_buffer); |
1918 | break;*/ |
1919 | default: |
1920 | display_warning("grReadRegion : unknown buffer : %x", src_buffer); |
1921 | } |
1922 | |
1923 | if(src_buffer != GR_BUFFER_AUXBUFFER) |
1924 | { |
1925 | buf = (unsigned char*)malloc(src_width*src_height*4); |
1926 | |
1927 | glReadPixels(src_x, (viewport_offset)+height-src_y-src_height, src_width, src_height, GL_RGBA, GL_UNSIGNED_BYTE, buf); |
1928 | for (j=0; j<src_height; j++) |
1929 | { |
1930 | /*SEB*/ |
1931 | unsigned char *p=buf+(src_height-j-1)*src_width*4; |
1932 | unsigned short *f=frameBuffer+(j*dst_stride/2); |
1933 | for (i=0; i<src_width; i++) |
1934 | { |
1935 | /* frameBuffer[j*(dst_stride/2)+i] = |
1936 | ((buf[(src_height-j-1)*src_width*4+i*4+0] >> 3) << 11) | |
1937 | ((buf[(src_height-j-1)*src_width*4+i*4+1] >> 2) << 5) | |
1938 | (buf[(src_height-j-1)*src_width*4+i*4+2] >> 3);*/ |
1939 | *(f++) = |
1940 | ((*(p) >> 3) << 11) | |
1941 | ((*(p+1) >> 2) << 5) | |
1942 | (*(p+2) >> 3); |
1943 | p+=4; |
1944 | } |
1945 | } |
1946 | free(buf); |
1947 | } |
1948 | else |
1949 | { |
1950 | buf = (unsigned char*)malloc(src_width*src_height*2); |
1951 | //*SEB read in buf, not depthBuffer. |
1952 | glReadPixels(src_x, (viewport_offset)+height-src_y-src_height, src_width, src_height, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, buf); |
1953 | |
1954 | for (j=0;j<src_height; j++) |
1955 | { |
1956 | //*SEB* |
1957 | unsigned short *d=depthBuffer+j*dst_stride/2; |
1958 | unsigned short *p=(unsigned short*)buf+(src_height-j-1)*src_width; //orignal look fishy. why *4??? |
1959 | for (i=0; i<src_width; i++) |
1960 | { |
1961 | /* depthBuffer[j*(dst_stride/2)+i] = |
1962 | ((unsigned short*)buf)[(src_height-j-1)*src_width*4+i*4];*/ |
1963 | *(d++) = *(p++); //why *4 (prob. GL_PACK was=4), plus transcoding to short, that make *8 ??? |
1964 | } |
1965 | } |
1966 | free(buf); |
1967 | } |
1968 | |
1969 | return FXTRUE; |
1970 | } |
1971 | |
1972 | FX_ENTRY FxBool FX_CALL |
1973 | grLfbWriteRegion( GrBuffer_t dst_buffer, |
1974 | FxU32 dst_x, FxU32 dst_y, |
1975 | GrLfbSrcFmt_t src_format, |
1976 | FxU32 src_width, FxU32 src_height, |
1977 | FxBool pixelPipeline, |
1978 | FxI32 src_stride, void *src_data ) |
1979 | { |
1980 | unsigned char *buf; |
1981 | unsigned int i,j; |
1982 | unsigned short *frameBuffer = (unsigned short*)src_data; |
1983 | int texture_number; |
1984 | unsigned int tex_width = 1, tex_height = 1; |
1985 | 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); |
1986 | //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); |
1987 | |
1988 | //glPushAttrib(GL_ALL_ATTRIB_BITS); |
1989 | |
1990 | while (tex_width < src_width) tex_width <<= 1; |
1991 | while (tex_height < src_height) tex_height <<= 1; |
1992 | |
1993 | switch(dst_buffer) |
1994 | { |
1995 | case GR_BUFFER_BACKBUFFER: |
1996 | //glDrawBuffer(GL_BACK); |
1997 | break; |
1998 | case GR_BUFFER_AUXBUFFER: |
1999 | //glDrawBuffer(current_buffer); |
2000 | break; |
2001 | default: |
2002 | display_warning("grLfbWriteRegion : unknown buffer : %x", dst_buffer); |
2003 | } |
2004 | |
2005 | if(dst_buffer != GR_BUFFER_AUXBUFFER) |
2006 | { |
2007 | buf = (unsigned char*)malloc(tex_width*tex_height*4); |
2008 | |
2009 | texture_number = GL_TEXTURE0; |
2010 | glActiveTexture(texture_number); |
2011 | |
2012 | const unsigned int half_stride = src_stride / 2; |
2013 | |
2014 | const int comp_stride = half_stride - src_width; |
2015 | const int comp_tex = (tex_width - src_width)*4; |
2016 | unsigned short *f=frameBuffer; |
2017 | unsigned char *p=buf; |
2018 | |
2019 | switch(src_format) |
2020 | { |
2021 | case GR_LFB_SRC_FMT_1555: |
2022 | for (j=0; j<src_height; j++) |
2023 | { |
2024 | for (i=0; i<src_width; i++) |
2025 | { |
2026 | /* const unsigned int col = frameBuffer[j*half_stride+i]; |
2027 | buf[j*tex_width*4+i*4+0]=((col>>10)&0x1F)<<3; |
2028 | buf[j*tex_width*4+i*4+1]=((col>>5)&0x1F)<<3; |
2029 | buf[j*tex_width*4+i*4+2]=((col>>0)&0x1F)<<3; |
2030 | buf[j*tex_width*4+i*4+3]= (col>>15) ? 0xFF : 0;*/ |
2031 | const unsigned int col = *(f++); |
2032 | *(p)=((col>>10)&0x1F)<<3; |
2033 | *(p+1)=((col>>5)&0x1F)<<3; |
2034 | *(p+2)=((col>>0)&0x1F)<<3; |
2035 | *(p+3)= (col>>15) ? 0xFF : 0; |
2036 | p+=4; |
2037 | } |
2038 | p+=comp_tex; |
2039 | f+=comp_stride; |
2040 | } |
2041 | break; |
2042 | case GR_LFBWRITEMODE_555: |
2043 | for (j=0; j<src_height; j++) |
2044 | { |
2045 | for (i=0; i<src_width; i++) |
2046 | { |
2047 | /* const unsigned int col = frameBuffer[j*half_stride+i]; |
2048 | buf[j*tex_width*4+i*4+0]=((col>>10)&0x1F)<<3; |
2049 | buf[j*tex_width*4+i*4+1]=((col>>5)&0x1F)<<3; |
2050 | buf[j*tex_width*4+i*4+2]=((col>>0)&0x1F)<<3; |
2051 | buf[j*tex_width*4+i*4+3]=0xFF;*/ |
2052 | const unsigned int col = *(f++); |
2053 | *(p)=((col>>10)&0x1F)<<3; |
2054 | *(p+1)=((col>>5)&0x1F)<<3; |
2055 | *(p+2)=((col>>0)&0x1F)<<3; |
2056 | *(p+3)=0xFF; |
2057 | p+=4; |
2058 | } |
2059 | p+=comp_tex; |
2060 | f+=comp_stride; |
2061 | } |
2062 | break; |
2063 | case GR_LFBWRITEMODE_565: |
2064 | for (j=0; j<src_height; j++) |
2065 | { |
2066 | for (i=0; i<src_width; i++) |
2067 | { |
2068 | /* const unsigned int col = frameBuffer[j*half_stride+i]; |
2069 | buf[j*tex_width*4+i*4+0]=((col>>11)&0x1F)<<3; |
2070 | buf[j*tex_width*4+i*4+1]=((col>>5)&0x3F)<<2; |
2071 | buf[j*tex_width*4+i*4+2]=((col>>0)&0x1F)<<3; |
2072 | buf[j*tex_width*4+i*4+3]=0xFF;*/ |
2073 | const unsigned int col = *(f++); |
2074 | *(p)=((col>>11)&0x1F)<<3; |
2075 | *(p+1)=((col>>5)&0x3F)<<2; |
2076 | *(p+2)=((col>>0)&0x1F)<<3; |
2077 | *(p+3)=0xFF; |
2078 | p+=4; |
2079 | } |
2080 | p+=comp_tex; |
2081 | f+=comp_stride; |
2082 | } |
2083 | break; |
2084 | default: |
2085 | display_warning("grLfbWriteRegion : unknown format : %d", src_format); |
2086 | } |
2087 | |
2088 | #ifdef VPDEBUG |
2089 | if (dumping) { |
2090 | ilTexImage(tex_width, tex_height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, buf); |
2091 | char name[128]; |
2092 | static int id; |
2093 | sprintf(name, "dump/writecolor%d.png", id++); |
2094 | ilSaveImage(name); |
2095 | //printf("dumped gdLfbWriteRegion %s\n", name); |
2096 | } |
2097 | #endif |
2098 | |
2099 | glBindTexture(GL_TEXTURE_2D, default_texture); |
2100 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_width, tex_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf); |
2101 | free(buf); |
2102 | |
2103 | set_copy_shader(); |
2104 | |
2105 | glDisable(GL_DEPTH_TEST); |
2106 | glDisable(GL_BLEND); |
2107 | render_rectangle(texture_number, |
2108 | dst_x, dst_y, |
2109 | src_width, src_height, |
2110 | tex_width, tex_height, +1); |
2111 | |
2112 | } |
2113 | else |
2114 | { |
2115 | float *buf = (float*)malloc(src_width*(src_height+(viewport_offset))*sizeof(float)); |
2116 | |
2117 | if (src_format != GR_LFBWRITEMODE_ZA16) |
2118 | display_warning("unknown depth buffer write format:%x", src_format); |
2119 | |
2120 | if(dst_x || dst_y) |
2121 | display_warning("dst_x:%d, dst_y:%d\n",dst_x, dst_y); |
2122 | |
2123 | for (j=0; j<src_height; j++) |
2124 | { |
2125 | for (i=0; i<src_width; i++) |
2126 | { |
2127 | buf[(j+(viewport_offset))*src_width+i] = |
2128 | (frameBuffer[(src_height-j-1)*(src_stride/2)+i]/(65536.0f*(2.0f/zscale)))+1-zscale/2.0f; |
2129 | } |
2130 | } |
2131 | |
2132 | #ifdef VPDEBUG |
2133 | if (dumping) { |
2134 | unsigned char * buf2 = (unsigned char *)malloc(src_width*(src_height+(viewport_offset))); |
2135 | for (i=0; i<src_width*src_height ; i++) |
2136 | buf2[i] = buf[i]*255.0f; |
2137 | ilTexImage(src_width, src_height, 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, buf2); |
2138 | char name[128]; |
2139 | static int id; |
2140 | sprintf(name, "dump/writedepth%d.png", id++); |
2141 | ilSaveImage(name); |
2142 | //printf("dumped gdLfbWriteRegion %s\n", name); |
2143 | free(buf2); |
2144 | } |
2145 | #endif |
2146 | |
2147 | glEnable(GL_DEPTH_TEST); |
2148 | glDepthFunc(GL_ALWAYS); |
2149 | |
2150 | //glDrawBuffer(GL_BACK); |
2151 | glClear( GL_DEPTH_BUFFER_BIT ); |
2152 | glDepthMask(1); |
2153 | //glDrawPixels(src_width, src_height+(viewport_offset), GL_DEPTH_COMPONENT, GL_FLOAT, buf); |
2154 | |
2155 | free(buf); |
2156 | } |
2157 | //glDrawBuffer(current_buffer); |
2158 | //glPopAttrib(); |
2159 | return FXTRUE; |
2160 | } |
2161 | |
2162 | /* wrapper-specific glide extensions */ |
2163 | |
2164 | FX_ENTRY char ** FX_CALL |
2165 | grQueryResolutionsExt(FxI32 * Size) |
2166 | { |
2167 | return 0; |
2168 | /* |
2169 | LOG("grQueryResolutionsExt\r\n"); |
2170 | return g_FullScreenResolutions.getResolutionsList(Size); |
2171 | */ |
2172 | } |
2173 | |
2174 | FX_ENTRY GrScreenResolution_t FX_CALL grWrapperFullScreenResolutionExt(FxU32* width, FxU32* height) |
2175 | { |
2176 | return 0; |
2177 | /* |
2178 | LOG("grWrapperFullScreenResolutionExt\r\n"); |
2179 | g_FullScreenResolutions.getResolution(config.res, width, height); |
2180 | return config.res; |
2181 | */ |
2182 | } |
2183 | |
2184 | FX_ENTRY FxBool FX_CALL grKeyPressedExt(FxU32 key) |
2185 | { |
2186 | return 0; |
2187 | /* |
2188 | #ifdef _WIN32 |
2189 | return (GetAsyncKeyState(key) & 0x8000); |
2190 | #else |
2191 | if (key == 1) //LBUTTON |
2192 | { |
2193 | Uint8 mstate = SDL_GetMouseState(NULL, NULL); |
2194 | return (mstate & SDL_BUTTON_LMASK); |
2195 | } |
2196 | else |
2197 | { |
2198 | Uint8 *keystates = SDL_GetKeyState( NULL ); |
2199 | if( keystates[ key ] ) |
2200 | { |
2201 | return 1; |
2202 | } |
2203 | else |
2204 | { |
2205 | return 0; |
2206 | } |
2207 | } |
2208 | #endif |
2209 | */ |
2210 | } |
2211 | |
2212 | FX_ENTRY void FX_CALL grConfigWrapperExt(FxI32 resolution, FxI32 vram, FxBool fbo, FxBool aniso) |
2213 | { |
2214 | LOG("grConfigWrapperExt\r\n"); |
2215 | config.res = resolution; |
2216 | config.vram_size = vram; |
2217 | config.fbo = fbo; |
2218 | config.anisofilter = aniso; |
2219 | } |
2220 | |
2221 | // unused by glide64 |
2222 | |
2223 | FX_ENTRY FxI32 FX_CALL |
2224 | grQueryResolutions( const GrResolution *resTemplate, GrResolution *output ) |
2225 | { |
2226 | int res_inf = 0; |
2227 | int res_sup = 0xf; |
2228 | int i; |
2229 | int n=0; |
2230 | LOG("grQueryResolutions\r\n"); |
2231 | display_warning("grQueryResolutions"); |
2232 | if ((unsigned int)resTemplate->resolution != GR_QUERY_ANY) |
2233 | { |
2234 | res_inf = res_sup = resTemplate->resolution; |
2235 | } |
2236 | if ((unsigned int)resTemplate->refresh == GR_QUERY_ANY) display_warning("querying any refresh rate"); |
2237 | if ((unsigned int)resTemplate->numAuxBuffers == GR_QUERY_ANY) display_warning("querying any numAuxBuffers"); |
2238 | if ((unsigned int)resTemplate->numColorBuffers == GR_QUERY_ANY) display_warning("querying any numColorBuffers"); |
2239 | |
2240 | if (output == NULL) return res_sup - res_inf + 1; |
2241 | for (i=res_inf; i<=res_sup; i++) |
2242 | { |
2243 | output[n].resolution = i; |
2244 | output[n].refresh = resTemplate->refresh; |
2245 | output[n].numAuxBuffers = resTemplate->numAuxBuffers; |
2246 | output[n].numColorBuffers = resTemplate->numColorBuffers; |
2247 | n++; |
2248 | } |
2249 | return res_sup - res_inf + 1; |
2250 | } |
2251 | |
2252 | FX_ENTRY FxBool FX_CALL |
2253 | grReset( FxU32 what ) |
2254 | { |
2255 | display_warning("grReset"); |
2256 | return 1; |
2257 | } |
2258 | |
2259 | FX_ENTRY void FX_CALL |
2260 | grEnable( GrEnableMode_t mode ) |
2261 | { |
2262 | LOG("grEnable(%d)\r\n", mode); |
2263 | if (mode == GR_TEXTURE_UMA_EXT) |
2264 | UMAmode = 1; |
2265 | } |
2266 | |
2267 | FX_ENTRY void FX_CALL |
2268 | grDisable( GrEnableMode_t mode ) |
2269 | { |
2270 | LOG("grDisable(%d)\r\n", mode); |
2271 | if (mode == GR_TEXTURE_UMA_EXT) |
2272 | UMAmode = 0; |
2273 | } |
2274 | |
2275 | FX_ENTRY void FX_CALL |
2276 | grDisableAllEffects( void ) |
2277 | { |
2278 | display_warning("grDisableAllEffects"); |
2279 | } |
2280 | |
2281 | FX_ENTRY void FX_CALL |
2282 | grErrorSetCallback( GrErrorCallbackFnc_t fnc ) |
2283 | { |
2284 | display_warning("grErrorSetCallback"); |
2285 | } |
2286 | |
2287 | FX_ENTRY void FX_CALL |
2288 | grFinish(void) |
2289 | { |
2290 | display_warning("grFinish"); |
2291 | } |
2292 | |
2293 | FX_ENTRY void FX_CALL |
2294 | grFlush(void) |
2295 | { |
2296 | display_warning("grFlush"); |
2297 | } |
2298 | |
2299 | FX_ENTRY void FX_CALL |
2300 | grTexMultibase( GrChipID_t tmu, |
2301 | FxBool enable ) |
2302 | { |
2303 | display_warning("grTexMultibase"); |
2304 | } |
2305 | |
2306 | FX_ENTRY void FX_CALL |
2307 | grTexMipMapMode( GrChipID_t tmu, |
2308 | GrMipMapMode_t mode, |
2309 | FxBool lodBlend ) |
2310 | { |
2311 | display_warning("grTexMipMapMode"); |
2312 | } |
2313 | |
2314 | FX_ENTRY void FX_CALL |
2315 | grTexDownloadTablePartial( GrTexTable_t type, |
2316 | void *data, |
2317 | int start, |
2318 | int end ) |
2319 | { |
2320 | display_warning("grTexDownloadTablePartial"); |
2321 | } |
2322 | |
2323 | FX_ENTRY void FX_CALL |
2324 | grTexDownloadTable( GrTexTable_t type, |
2325 | void *data ) |
2326 | { |
2327 | display_warning("grTexDownloadTable"); |
2328 | } |
2329 | |
2330 | FX_ENTRY FxBool FX_CALL |
2331 | grTexDownloadMipMapLevelPartial( GrChipID_t tmu, |
2332 | FxU32 startAddress, |
2333 | GrLOD_t thisLod, |
2334 | GrLOD_t largeLod, |
2335 | GrAspectRatio_t aspectRatio, |
2336 | GrTextureFormat_t format, |
2337 | FxU32 evenOdd, |
2338 | void *data, |
2339 | int start, |
2340 | int end ) |
2341 | { |
2342 | display_warning("grTexDownloadMipMapLevelPartial"); |
2343 | return 1; |
2344 | } |
2345 | |
2346 | FX_ENTRY void FX_CALL |
2347 | grTexDownloadMipMapLevel( GrChipID_t tmu, |
2348 | FxU32 startAddress, |
2349 | GrLOD_t thisLod, |
2350 | GrLOD_t largeLod, |
2351 | GrAspectRatio_t aspectRatio, |
2352 | GrTextureFormat_t format, |
2353 | FxU32 evenOdd, |
2354 | void *data ) |
2355 | { |
2356 | display_warning("grTexDownloadMipMapLevel"); |
2357 | } |
2358 | |
2359 | FX_ENTRY void FX_CALL |
2360 | grTexNCCTable( GrNCCTable_t table ) |
2361 | { |
2362 | display_warning("grTexNCCTable"); |
2363 | } |
2364 | |
2365 | FX_ENTRY void FX_CALL |
2366 | grViewport( FxI32 x, FxI32 y, FxI32 width, FxI32 height ) |
2367 | { |
2368 | display_warning("grViewport"); |
2369 | } |
2370 | |
2371 | FX_ENTRY void FX_CALL |
2372 | grDepthRange( FxFloat n, FxFloat f ) |
2373 | { |
2374 | display_warning("grDepthRange"); |
2375 | } |
2376 | |
2377 | FX_ENTRY void FX_CALL |
2378 | grSplash(float x, float y, float width, float height, FxU32 frame) |
2379 | { |
2380 | display_warning("grSplash"); |
2381 | } |
2382 | |
2383 | FX_ENTRY FxBool FX_CALL |
2384 | grSelectContext( GrContext_t context ) |
2385 | { |
2386 | display_warning("grSelectContext"); |
2387 | return 1; |
2388 | } |
2389 | |
2390 | FX_ENTRY void FX_CALL |
2391 | grAADrawTriangle( |
2392 | const void *a, const void *b, const void *c, |
2393 | FxBool ab_antialias, FxBool bc_antialias, FxBool ca_antialias |
2394 | ) |
2395 | { |
2396 | display_warning("grAADrawTriangle"); |
2397 | } |
2398 | |
2399 | FX_ENTRY void FX_CALL |
2400 | grAlphaControlsITRGBLighting( FxBool enable ) |
2401 | { |
2402 | display_warning("grAlphaControlsITRGBLighting"); |
2403 | } |
2404 | |
2405 | FX_ENTRY void FX_CALL |
2406 | grGlideSetVertexLayout( const void *layout ) |
2407 | { |
2408 | display_warning("grGlideSetVertexLayout"); |
2409 | } |
2410 | |
2411 | FX_ENTRY void FX_CALL |
2412 | grGlideGetVertexLayout( void *layout ) |
2413 | { |
2414 | display_warning("grGlideGetVertexLayout"); |
2415 | } |
2416 | |
2417 | FX_ENTRY void FX_CALL |
2418 | grGlideSetState( const void *state ) |
2419 | { |
2420 | display_warning("grGlideSetState"); |
2421 | } |
2422 | |
2423 | FX_ENTRY void FX_CALL |
2424 | grGlideGetState( void *state ) |
2425 | { |
2426 | display_warning("grGlideGetState"); |
2427 | } |
2428 | |
2429 | FX_ENTRY void FX_CALL |
2430 | grLfbWriteColorFormat(GrColorFormat_t colorFormat) |
2431 | { |
2432 | display_warning("grLfbWriteColorFormat"); |
2433 | } |
2434 | |
2435 | FX_ENTRY void FX_CALL |
2436 | grLfbWriteColorSwizzle(FxBool swizzleBytes, FxBool swapWords) |
2437 | { |
2438 | display_warning("grLfbWriteColorSwizzle"); |
2439 | } |
2440 | |
2441 | FX_ENTRY void FX_CALL |
2442 | grLfbConstantDepth( FxU32 depth ) |
2443 | { |
2444 | display_warning("grLfbConstantDepth"); |
2445 | } |
2446 | |
2447 | FX_ENTRY void FX_CALL |
2448 | grLfbConstantAlpha( GrAlpha_t alpha ) |
2449 | { |
2450 | display_warning("grLfbConstantAlpha"); |
2451 | } |
2452 | |
2453 | FX_ENTRY void FX_CALL |
2454 | grTexMultibaseAddress( GrChipID_t tmu, |
2455 | GrTexBaseRange_t range, |
2456 | FxU32 startAddress, |
2457 | FxU32 evenOdd, |
2458 | GrTexInfo *info ) |
2459 | { |
2460 | display_warning("grTexMultibaseAddress"); |
2461 | } |
2462 | |
2463 | /* |
2464 | inline void MySleep(FxU32 ms) |
2465 | { |
2466 | #ifdef _WIN32 |
2467 | Sleep(ms); |
2468 | #else |
2469 | SDL_Delay(ms); |
2470 | #endif |
2471 | } |
2472 | */ |
2473 | |
2474 | #ifdef _WIN32 |
2475 | static void CorrectGamma(LPVOID apGammaRamp) |
2476 | { |
2477 | HDC hdc = GetDC(NULL); |
2478 | if (hdc != NULL) |
2479 | { |
2480 | SetDeviceGammaRamp(hdc, apGammaRamp); |
2481 | ReleaseDC(NULL, hdc); |
2482 | } |
2483 | } |
2484 | #else |
2485 | static void CorrectGamma(const FxU16 aGammaRamp[3][256]) |
2486 | { |
2487 | //TODO? |
2488 | //int res = SDL_SetGammaRamp(aGammaRamp[0], aGammaRamp[1], aGammaRamp[2]); |
2489 | //LOG("SDL_SetGammaRamp returned %d\r\n", res); |
2490 | } |
2491 | #endif |
2492 | |
2493 | FX_ENTRY void FX_CALL |
2494 | grLoadGammaTable( FxU32 nentries, FxU32 *red, FxU32 *green, FxU32 *blue) |
2495 | { |
2496 | LOG("grLoadGammaTable\r\n"); |
2497 | if (!fullscreen) |
2498 | return; |
2499 | FxU16 aGammaRamp[3][256]; |
2500 | for (int i = 0; i < 256; i++) |
2501 | { |
2502 | aGammaRamp[0][i] = (FxU16)((red[i] << 8) & 0xFFFF); |
2503 | aGammaRamp[1][i] = (FxU16)((green[i] << 8) & 0xFFFF); |
2504 | aGammaRamp[2][i] = (FxU16)((blue[i] << 8) & 0xFFFF); |
2505 | } |
2506 | CorrectGamma(aGammaRamp); |
2507 | //MySleep(1000); //workaround for Mupen64 |
2508 | } |
2509 | |
2510 | FX_ENTRY void FX_CALL |
2511 | grGetGammaTableExt(FxU32 nentries, FxU32 *red, FxU32 *green, FxU32 *blue) |
2512 | { |
2513 | return; |
2514 | //TODO? |
2515 | /* |
2516 | LOG("grGetGammaTableExt()\r\n"); |
2517 | FxU16 aGammaRamp[3][256]; |
2518 | #ifdef _WIN32 |
2519 | HDC hdc = GetDC(NULL); |
2520 | if (hdc == NULL) |
2521 | return; |
2522 | if (GetDeviceGammaRamp(hdc, aGammaRamp) == TRUE) |
2523 | { |
2524 | ReleaseDC(NULL, hdc); |
2525 | #else |
2526 | if (SDL_GetGammaRamp(aGammaRamp[0], aGammaRamp[1], aGammaRamp[2]) != -1) |
2527 | { |
2528 | #endif |
2529 | for (int i = 0; i < 256; i++) |
2530 | { |
2531 | red[i] = aGammaRamp[0][i] >> 8; |
2532 | green[i] = aGammaRamp[1][i] >> 8; |
2533 | blue[i] = aGammaRamp[2][i] >> 8; |
2534 | } |
2535 | } |
2536 | */ |
2537 | } |
2538 | |
2539 | FX_ENTRY void FX_CALL |
2540 | guGammaCorrectionRGB( FxFloat gammaR, FxFloat gammaG, FxFloat gammaB ) |
2541 | { |
2542 | LOG("guGammaCorrectionRGB()\r\n"); |
2543 | if (!fullscreen) |
2544 | return; |
2545 | FxU16 aGammaRamp[3][256]; |
2546 | for (int i = 0; i < 256; i++) |
2547 | { |
2548 | aGammaRamp[0][i] = (((FxU16)((pow(i/255.0F, 1.0F/gammaR)) * 255.0F + 0.5F)) << 8) & 0xFFFF; |
2549 | aGammaRamp[1][i] = (((FxU16)((pow(i/255.0F, 1.0F/gammaG)) * 255.0F + 0.5F)) << 8) & 0xFFFF; |
2550 | aGammaRamp[2][i] = (((FxU16)((pow(i/255.0F, 1.0F/gammaB)) * 255.0F + 0.5F)) << 8) & 0xFFFF; |
2551 | } |
2552 | CorrectGamma(aGammaRamp); |
2553 | } |
2554 | |
2555 | FX_ENTRY void FX_CALL |
2556 | grDitherMode( GrDitherMode_t mode ) |
2557 | { |
2558 | display_warning("grDitherMode"); |
2559 | } |
2560 | |
2561 | void grChromaRangeExt(GrColor_t color0, GrColor_t color1, FxU32 mode) |
2562 | { |
2563 | display_warning("grChromaRangeExt"); |
2564 | } |
2565 | |
2566 | void grChromaRangeModeExt(GrChromakeyMode_t mode) |
2567 | { |
2568 | display_warning("grChromaRangeModeExt"); |
2569 | } |
2570 | |
2571 | void grTexChromaRangeExt(GrChipID_t tmu, GrColor_t color0, GrColor_t color1, GrTexChromakeyMode_t mode) |
2572 | { |
2573 | display_warning("grTexChromaRangeExt"); |
2574 | } |
2575 | |
2576 | void grTexChromaModeExt(GrChipID_t tmu, GrChromakeyMode_t mode) |
2577 | { |
2578 | display_warning("grTexChromaRangeModeExt"); |
2579 | } |
2580 | |
2581 | // VP debug |
2582 | #ifdef VPDEBUG |
2583 | int dumping = 0; |
2584 | static int tl_i; |
2585 | static int tl[10240]; |
2586 | |
2587 | void dump_start() |
2588 | { |
2589 | static int init; |
2590 | if (!init) { |
2591 | init = 1; |
2592 | ilInit(); |
2593 | ilEnable(IL_FILE_OVERWRITE); |
2594 | } |
2595 | dumping = 1; |
2596 | tl_i = 0; |
2597 | } |
2598 | |
2599 | void dump_stop() |
2600 | { |
2601 | if (!dumping) return; |
2602 | |
2603 | int i, j; |
2604 | for (i=0; i<nb_fb; i++) { |
2605 | dump_tex(fbs[i].texid); |
2606 | } |
2607 | dump_tex(default_texture); |
2608 | dump_tex(depth_texture); |
2609 | |
2610 | dumping = 0; |
2611 | |
2612 | glReadBuffer(GL_FRONT); |
2613 | glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, frameBuffer); |
2614 | ilTexImage(width, height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, frameBuffer); |
2615 | ilSaveImage("dump/framecolor.png"); |
2616 | glReadPixels(0, 0, width, height, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, depthBuffer); |
2617 | // FILE * fp = fopen("glide_depth1.bin", "rb"); |
2618 | // fread(depthBuffer, 2, width*height, fp); |
2619 | // fclose(fp); |
2620 | for (j=0; j<height; j++) { |
2621 | for (i=0; i<width; i++) { |
2622 | //uint16_t d = ( (uint16_t *)depthBuffer )[i+(height-1-j)*width]/2 + 0x8000; |
2623 | uint16_t d = ( (uint16_t *)depthBuffer )[i+j*width]; |
2624 | uint32_t c = ( (uint32_t *)frameBuffer )[i+j*width]; |
2625 | ( (unsigned char *)frameBuffer )[(i+j*width)*3] = d&0xff; |
2626 | ( (unsigned char *)frameBuffer )[(i+j*width)*3+1] = d>>8; |
2627 | ( (unsigned char *)frameBuffer )[(i+j*width)*3+2] = c&0xff; |
2628 | } |
2629 | } |
2630 | ilTexImage(width, height, 1, 3, IL_RGB, IL_UNSIGNED_BYTE, frameBuffer); |
2631 | ilSaveImage("dump/framedepth.png"); |
2632 | |
2633 | for (i=0; i<tl_i; i++) { |
2634 | glBindTexture(GL_TEXTURE_2D, tl[i]); |
2635 | GLint w, h, fmt; |
2636 | glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w); |
2637 | glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h); |
2638 | glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt); |
2639 | fprintf(stderr, "Texture %d %dx%d fmt %x\n", tl[i], (int)w, (int)h, (int) fmt); |
2640 | |
2641 | uint32_t * pixels = (uint32_t *) malloc(w*h*4); |
2642 | // 0x1902 is another constant meaning GL_DEPTH_COMPONENT |
2643 | // (but isn't defined in gl's headers !!) |
2644 | if (fmt != GL_DEPTH_COMPONENT && fmt != 0x1902) { |
2645 | glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); |
2646 | ilTexImage(w, h, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, pixels); |
2647 | } else { |
2648 | glGetTexImage(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, pixels); |
2649 | int i; |
2650 | for (i=0; i<w*h; i++) |
2651 | ((unsigned char *)frameBuffer)[i] = ((unsigned short *)pixels)[i]/256; |
2652 | ilTexImage(w, h, 1, 1, IL_LUMINANCE, IL_UNSIGNED_BYTE, frameBuffer); |
2653 | } |
2654 | char name[128]; |
2655 | // sprintf(name, "mkdir -p dump ; rm -f dump/tex%04d.png", i); |
2656 | // system(name); |
2657 | sprintf(name, "dump/tex%04d.png", i); |
2658 | fprintf(stderr, "Writing '%s'\n", name); |
2659 | ilSaveImage(name); |
2660 | |
2661 | // SDL_FreeSurface(surf); |
2662 | free(pixels); |
2663 | } |
2664 | glBindTexture(GL_TEXTURE_2D, default_texture); |
2665 | } |
2666 | |
2667 | void dump_tex(int id) |
2668 | { |
2669 | if (!dumping) return; |
2670 | |
2671 | int n; |
2672 | // yes, it's inefficient |
2673 | for (n=0; n<tl_i; n++) |
2674 | if (tl[n] == id) |
2675 | return; |
2676 | |
2677 | tl[tl_i++] = id; |
2678 | |
2679 | int i = tl_i-1; |
2680 | } |
2681 | |
2682 | #endif |