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 | |
2d262872 |
510 | CoreVideo_Init(); |
98e75f2d |
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 |
2d262872 |
820 | |
821 | CoreVideo_Quit(); |
822 | |
98e75f2d |
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 |