Some printf and Correct aspect ratio for Rice(s)
[mupen64plus-pandora.git] / source / gles2n64 / src / OpenGL.cpp
CommitLineData
34cf4058 1
2#include <stdlib.h>
3#include <stdio.h>
4#include <math.h>
5#include <string.h>
6#include <time.h>
7#include <unistd.h>
8
9//// paulscode, added for SDL linkage:
10#ifdef USE_SDL
11 #include <SDL.h>
12 // TODO: Remove this bandaid for SDL 2.0 compatibility (needed for SDL_SetVideoMode)
13 #if SDL_VERSION_ATLEAST(2,0,0)
14 #include "sdl2_compat.h" // Slightly hacked version of core/vidext_sdl2_compat.h
15 #endif
16 #include "eglport.h"
17#endif
18////
19
20#include "Common.h"
21#include "gles2N64.h"
22#include "OpenGL.h"
23#include "Types.h"
24#include "N64.h"
25#include "gSP.h"
26#include "gDP.h"
27#include "Textures.h"
28#include "ShaderCombiner.h"
29#include "VI.h"
30#include "RSP.h"
31#include "Config.h"
32#include "ticks.h"
33
34#include "FrameSkipper.h"
35
36//#include "ae_bridge.h"
37
38//// paulscode, function prototype missing from Yongzh's code
39void OGL_UpdateDepthUpdate();
40////
41
42#ifdef TEXTURECACHE_TEST
43int TextureCacheTime = 0;
44#endif
45
46
47#ifdef RENDERSTATE_TEST
48int StateChanges = 0;
49#endif
50
51#ifdef SHADER_TEST
52int ProgramSwaps = 0;
53#endif
54
55#ifdef BATCH_TEST
56int TotalDrawTime = 0;
57int TotalTriangles = 0;
58int TotalDrawCalls = 0;
59#define glDrawElements(A,B,C,D) \
60 TotalTriangles += B; TotalDrawCalls++; int t = ticksGetTicks(); glDrawElements(A,B,C,D); TotalDrawTime += (ticksGetTicks() - t);
61#define glDrawArrays(A,B,C) \
62 TotalTriangles += C; TotalDrawCalls++; int t = ticksGetTicks(); glDrawArrays(A,B,C); TotalDrawTime += (ticksGetTicks() - t);
63
64#endif
65
66GLInfo OGL;
67
68const char _default_vsh[] = " \n\t" \
69"attribute highp vec2 aPosition; \n\t" \
70"attribute highp vec2 aTexCoord; \n\t" \
71"varying mediump vec2 vTexCoord; \n\t" \
72"void main(){ \n\t" \
73"gl_Position = vec4(aPosition.x, aPosition.y, 0.0, 1.0);\n\t" \
74"vTexCoord = aTexCoord; \n\t" \
75"} \n\t";
76
77const char _default_fsh[] = " \n\t" \
78"uniform sampler2D uTex; \n\t" \
79"varying mediump vec2 vTexCoord; \n\t" \
80"void main(){ \n\t" \
81"gl_FragColor = texture2D(uTex, vTexCoord); \n\t" \
82"} \n\t";
83
84void OGL_EnableRunfast()
85{
86#ifdef ARM_ASM
87 static const unsigned int x = 0x04086060;
88 static const unsigned int y = 0x03000000;
89 int r;
90 asm volatile (
91 "fmrx %0, fpscr \n\t" //r0 = FPSCR
92 "and %0, %0, %1 \n\t" //r0 = r0 & 0x04086060
93 "orr %0, %0, %2 \n\t" //r0 = r0 | 0x03000000
94 "fmxr fpscr, %0 \n\t" //FPSCR = r0
95 : "=r"(r)
96 : "r"(x), "r"(y)
97 );
98#endif
99}
100
101int OGL_IsExtSupported( const char *extension )
102{
103 const GLubyte *extensions = NULL;
104 const GLubyte *start;
105 GLubyte *where, *terminator;
106
107 where = (GLubyte *) strchr(extension, ' ');
108 if (where || *extension == '\0')
109 return 0;
110
111 extensions = glGetString(GL_EXTENSIONS);
112
113 if (!extensions) return 0;
114
115 start = extensions;
116 for (;;)
117 {
118 where = (GLubyte *) strstr((const char *) start, extension);
119 if (!where)
120 break;
121
122 terminator = where + strlen(extension);
123 if (where == start || *(where - 1) == ' ')
124 if (*terminator == ' ' || *terminator == '\0')
125 return 1;
126
127 start = terminator;
128 }
129
130 return 0;
131}
132
133extern void _glcompiler_error(GLint shader);
134
135void OGL_InitStates()
136{
137 GLint success;
138
139 glEnable( GL_CULL_FACE );
140 glEnableVertexAttribArray( SC_POSITION );
141 glEnable( GL_DEPTH_TEST );
142 glDepthFunc( GL_ALWAYS );
143 glDepthMask( GL_FALSE );
144 glEnable( GL_SCISSOR_TEST );
145
146///// paulscode, fixes missing graphics on Qualcomm, Adreno:
147 glDepthRangef(0.0f, 1.0f);
148
149 // default values (only seem to work on OMAP!)
150 glPolygonOffset(0.2f, 0.2f);
151
152 //// paulscode, added for different configurations based on hardware
153 // (part of the missing shadows and stars bug fix)
154/* int hardwareType = Android_JNI_GetHardwareType();
155 float f1, f2;
156 Android_JNI_GetPolygonOffset(hardwareType, 1, &f1, &f2);
157 glPolygonOffset( f1, f2 );
158*/ ////
159
160// some other settings that have been tried, which do not work:
161 //glDepthRangef(1.0f, 0.0f); // reverses depth-order on OMAP3 chipsets
162 //glPolygonOffset(-0.2f, -0.2f);
163 //glDepthRangef( 0.09f, (float)0x7FFF ); // should work, but not on Adreno
164 //glPolygonOffset( -0.2f, 0.2f );
165 //glDepthRangef(0.0f, (float)0x7FFF); // what Yongzh used, broken on Adreno
166 //glPolygonOffset(0.2f, 0.2f);
167/////
168
169
170 glViewport(config.framebuffer.xpos, config.framebuffer.ypos, config.framebuffer.width, config.framebuffer.height);
171
172 //create default shader program
173 LOG( LOG_VERBOSE, "Generate Default Shader Program.\n" );
174
175 const char *src[1];
176 src[0] = _default_fsh;
177 OGL.defaultFragShader = glCreateShader( GL_FRAGMENT_SHADER );
178 glShaderSource( OGL.defaultFragShader, 1, (const char**) src, NULL );
179 glCompileShader( OGL.defaultFragShader );
180 glGetShaderiv( OGL.defaultFragShader, GL_COMPILE_STATUS, &success );
181 if (!success)
182 {
183 LOG(LOG_ERROR, "Failed to produce default fragment shader.\n");
184 }
185
186 src[0] = _default_vsh;
187 OGL.defaultVertShader = glCreateShader( GL_VERTEX_SHADER );
188 glShaderSource( OGL.defaultVertShader, 1, (const char**) src, NULL );
189 glCompileShader( OGL.defaultVertShader );
190 glGetShaderiv( OGL.defaultVertShader, GL_COMPILE_STATUS, &success );
191 if( !success )
192 {
193 LOG( LOG_ERROR, "Failed to produce default vertex shader.\n" );
194 _glcompiler_error( OGL.defaultVertShader );
195 }
196
197 OGL.defaultProgram = glCreateProgram();
198 glBindAttribLocation( OGL.defaultProgram, 0, "aPosition" );
199 glBindAttribLocation( OGL.defaultProgram, 1, "aTexCoord" );
200 glAttachShader( OGL.defaultProgram, OGL.defaultFragShader );
201 glAttachShader( OGL.defaultProgram, OGL.defaultVertShader );
202 glLinkProgram( OGL.defaultProgram );
203 glGetProgramiv( OGL.defaultProgram, GL_LINK_STATUS, &success );
204 if( !success )
205 {
206 LOG( LOG_ERROR, "Failed to link default program.\n" );
207 _glcompiler_error( OGL.defaultFragShader );
208 }
209 glUniform1i( glGetUniformLocation( OGL.defaultProgram, "uTex" ), 0 );
210 glUseProgram( OGL.defaultProgram );
211
212}
213
214void OGL_UpdateScale()
215{
216 OGL.scaleX = (float)config.framebuffer.width / (float)VI.width;
217 OGL.scaleY = (float)config.framebuffer.height / (float)VI.height;
218}
219
220void OGL_ResizeWindow(int x, int y, int width, int height)
221{
222 config.window.xpos = x;
223 config.window.ypos = y;
224 config.window.width = width;
225 config.window.height = height;
226
227 config.framebuffer.xpos = x;
228 config.framebuffer.ypos = y;
229 config.framebuffer.width = width;
230 config.framebuffer.height = height;
231 OGL_UpdateScale();
232
233 glViewport(config.framebuffer.xpos, config.framebuffer.ypos,
234 config.framebuffer.width, config.framebuffer.height);
235}
236
237////// paulscode, added for SDL linkage
238#ifdef USE_SDL
239bool OGL_SDL_Start()
240{
241 /* Initialize SDL */
242 LOG(LOG_MINIMAL, "Initializing SDL video subsystem...\n" );
243 if (SDL_InitSubSystem( SDL_INIT_VIDEO ) == -1)
244 {
245 LOG(LOG_ERROR, "Error initializing SDL video subsystem: %s\n", SDL_GetError() );
246 return FALSE;
247 }
248/*SEB*
249 int current_w = config.window.width;
250 int current_h = config.window.height;
251*/
252 int current_w = 800;
253 int current_h = 480;
254 /* Set the video mode */
255 LOG(LOG_MINIMAL, "Setting video mode %dx%d...\n", current_w, current_h );
256
257// TODO: I should actually check what the pixelformat is, rather than assuming 16 bpp (RGB_565) or 32 bpp (RGBA_8888):
258//// paulscode, added for switching between modes RGBA8888 and RGB565
259// (part of the color banding fix)
260int bitsPP;
261/*if( Android_JNI_UseRGBA8888() )
262 bitsPP = 32;
263else*/
264 bitsPP = 16;
265////
266
267 // TODO: Replace SDL_SetVideoMode with something that is SDL 2.0 compatible
268 // Better yet, eliminate all SDL calls by using the Mupen64Plus core api
ac4f8e43 269 if (!(OGL.hScreen = SDL_SetVideoMode( current_w, current_h, bitsPP, SDL_HWSURFACE | SDL_FULLSCREEN )))
34cf4058 270 {
271 LOG(LOG_ERROR, "Problem setting videomode %dx%d: %s\n", current_w, current_h, SDL_GetError() );
272 SDL_QuitSubSystem( SDL_INIT_VIDEO );
273 return FALSE;
274 }
275
276//// paulscode, fixes the screen-size problem
277 const float ratio = ( config.romPAL ? 9.0f/11.0f : 0.75f );
278 int videoWidth = config.window.refwidth;
279 int videoHeight = config.window.refheight;
280 int x = 0;
281 int y = 0;
282
283 //re-scale width and height on per-rom basis
284 float width = /*(float)videoWidth * (float)config.window.refwidth /*/ 800.f;
285 float height = /*(float)videoHeight * (float)config.window.refheight / */480.f;
286
287 if (!config.stretchVideo) {
288/* if ((float)videoWith*480.0f/(float)videoHeight/800.0f>1.0f) {
289 //scale by Width
290 } else {
291 //scale by Height
292 }*/
293 videoWidth = (int) (height / ratio);
294 if (videoWidth > width) {
295 videoWidth = width;
296 videoHeight = (int) (width * ratio);
297 }
298 } else {
299 videoWidth=800;
300 videoHeight=480;
301 }
302 x = (width - videoWidth) / 2;
303 y = (height - videoHeight) / 2;
304
305 //set xpos and ypos
306 config.window.xpos = x;
307 config.window.ypos = y;
308 config.framebuffer.xpos = x;
309 config.framebuffer.ypos = y;
310
311 //set width and height
312 config.window.width = (int)videoWidth;
313 config.window.height = (int)videoHeight;
314 config.framebuffer.width = (int)videoWidth;
315 config.framebuffer.height = (int)videoHeight;
316
317 EGL_Open(800, 480);
318////
319 return true;
320}
321#endif
322//////
323
324#ifdef USE_SDL
325void Android_JNI_SwapWindow()
326{
327 EGL_SwapBuffers();
328}
329#endif
330
331
332bool OGL_Start()
333{
334// paulscode, initialize SDL
335#ifdef USE_SDL
336 if (!OGL_SDL_Start())
337 return false;
338#endif
339//
340
341 OGL_InitStates();
342
343#ifdef USE_SDL
344/////// paulscode, graphics bug-fixes
345 float depth = gDP.fillColor.z ;
346 glDisable( GL_SCISSOR_TEST );
347 glDepthMask( GL_TRUE ); // fixes side-bar graphics glitches
348// glClearDepthf( depth ); // broken on Qualcomm Adreno
349 glClearDepthf( 1.0f ); // fixes missing graphics on Qualcomm Adreno
350 glClearColor( 0, 0, 0, 1 );
351 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
352 glFinish();
353 Android_JNI_SwapWindow(); // paulscode, fix for black-screen bug
354 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
355 glFinish();
356 OGL_UpdateDepthUpdate();
357 glEnable( GL_SCISSOR_TEST );
358////////
359#endif
360
361 //create framebuffer
362 if (config.framebuffer.enable)
363 {
364 LOG(LOG_VERBOSE, "Create offscreen framebuffer. \n");
365 if (config.framebuffer.width == config.window.width && config.framebuffer.height == config.window.height)
366 {
367 LOG(LOG_WARNING, "There's no point in using a offscreen framebuffer when the window and screen dimensions are the same\n");
368 }
369
370 glGenFramebuffers(1, &OGL.framebuffer.fb);
371 glGenRenderbuffers(1, &OGL.framebuffer.depth_buffer);
372 glGenTextures(1, &OGL.framebuffer.color_buffer);
373 glBindRenderbuffer(GL_RENDERBUFFER, OGL.framebuffer.depth_buffer);
374 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24_OES, config.framebuffer.width, config.framebuffer.height);
375 glBindTexture(GL_TEXTURE_2D, OGL.framebuffer.color_buffer);
376 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, config.framebuffer.width, config.framebuffer.height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL);
377 glBindFramebuffer(GL_FRAMEBUFFER, OGL.framebuffer.fb);
378 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, OGL.framebuffer.color_buffer, 0);
379 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, OGL.framebuffer.depth_buffer);
380
381 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
382
383 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
384 {
385 LOG(LOG_ERROR, "Incomplete Framebuffer Object: ");
386 switch(glCheckFramebufferStatus(GL_FRAMEBUFFER))
387 {
388 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
389 printf("Incomplete Attachment. \n"); break;
390 case GL_FRAMEBUFFER_UNSUPPORTED:
391 printf("Framebuffer Unsupported. \n"); break;
392 case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
393 printf("Incomplete Dimensions. \n"); break;
394 }
395 config.framebuffer.enable = 0;
396 glBindFramebuffer(GL_FRAMEBUFFER, 0);
397 }
398 }
399
400 //check extensions
401 if ((config.texture.maxAnisotropy>0) && !OGL_IsExtSupported("GL_EXT_texture_filter_anistropic"))
402 {
403 LOG(LOG_WARNING, "Anistropic Filtering is not supported.\n");
404 config.texture.maxAnisotropy = 0;
405 }
406
407 float f = 0;
408 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &f);
409 if (config.texture.maxAnisotropy > ((int)f))
410 {
411 LOG(LOG_WARNING, "Clamping max anistropy to %ix.\n", (int)f);
412 config.texture.maxAnisotropy = (int)f;
413 }
414
415 //Print some info
416 LOG(LOG_VERBOSE, "Width: %i Height:%i \n", config.framebuffer.width, config.framebuffer.height);
417 LOG(LOG_VERBOSE, "[gles2n64]: Enable Runfast... \n");
418
419 OGL_EnableRunfast();
420 OGL_UpdateScale();
421
422 //We must have a shader bound before binding any textures:
423 ShaderCombiner_Init();
424 ShaderCombiner_Set(EncodeCombineMode(0, 0, 0, TEXEL0, 0, 0, 0, TEXEL0, 0, 0, 0, TEXEL0, 0, 0, 0, TEXEL0));
425 ShaderCombiner_Set(EncodeCombineMode(0, 0, 0, SHADE, 0, 0, 0, 1, 0, 0, 0, SHADE, 0, 0, 0, 1));
426
427 TextureCache_Init();
428
429 memset(OGL.triangles.vertices, 0, VERTBUFF_SIZE * sizeof(SPVertex));
430 memset(OGL.triangles.elements, 0, ELEMBUFF_SIZE * sizeof(GLubyte));
431 OGL.triangles.num = 0;
432
433#ifdef __TRIBUFFER_OPT
434 __indexmap_init();
435#endif
436
437 OGL.frameSkipped = 0;
438 for(int i = 0; i < OGL_FRAMETIME_NUM; i++) OGL.frameTime[i] = 0;
439
440 OGL.renderingToTexture = false;
441 OGL.renderState = RS_NONE;
442 gSP.changed = gDP.changed = 0xFFFFFFFF;
443 VI.displayNum = 0;
444 glGetError();
445
446 return TRUE;
447}
448
449void OGL_Stop()
450{
451 LOG(LOG_MINIMAL, "Stopping OpenGL\n");
452
453#ifdef USE_SDL
454 EGL_Close();
455 SDL_QuitSubSystem( SDL_INIT_VIDEO );
456#endif
457
458 if (config.framebuffer.enable)
459 {
460 glDeleteFramebuffers(1, &OGL.framebuffer.fb);
461 glDeleteTextures(1, &OGL.framebuffer.color_buffer);
462 glDeleteRenderbuffers(1, &OGL.framebuffer.depth_buffer);
463 }
464
465 glDeleteShader(OGL.defaultFragShader);
466 glDeleteShader(OGL.defaultVertShader);
467 glDeleteProgram(OGL.defaultProgram);
468
469 ShaderCombiner_Destroy();
470 TextureCache_Destroy();
471}
472
473void OGL_UpdateCullFace()
474{
475 if (config.enableFaceCulling && (gSP.geometryMode & G_CULL_BOTH))
476 {
477 glEnable( GL_CULL_FACE );
478 if ((gSP.geometryMode & G_CULL_BACK) && (gSP.geometryMode & G_CULL_FRONT))
479 glCullFace(GL_FRONT_AND_BACK);
480 else if (gSP.geometryMode & G_CULL_BACK)
481 glCullFace(GL_BACK);
482 else
483 glCullFace(GL_FRONT);
484 }
485 else
486 glDisable(GL_CULL_FACE);
487}
488
489void OGL_UpdateViewport()
490{
491 int x, y, w, h;
492 x = config.framebuffer.xpos + (int)(gSP.viewport.x * OGL.scaleX);
493 y = config.framebuffer.ypos + (int)((VI.height - (gSP.viewport.y + gSP.viewport.height)) * OGL.scaleY);
494 w = (int)(gSP.viewport.width * OGL.scaleX);
495 h = (int)(gSP.viewport.height * OGL.scaleY);
496
497 glViewport(x, y, w, h);
498}
499
500void OGL_UpdateDepthUpdate()
501{
502 if (gDP.otherMode.depthUpdate)
503 glDepthMask(GL_TRUE);
504 else
505 glDepthMask(GL_FALSE);
506}
507
508void OGL_UpdateScissor()
509{
510 int x, y, w, h;
511 x = config.framebuffer.xpos + (int)(gDP.scissor.ulx * OGL.scaleX);
512 y = config.framebuffer.ypos + (int)((VI.height - gDP.scissor.lry) * OGL.scaleY);
513 w = (int)((gDP.scissor.lrx - gDP.scissor.ulx) * OGL.scaleX);
514 h = (int)((gDP.scissor.lry - gDP.scissor.uly) * OGL.scaleY);
515 glScissor(x, y, w, h);
516}
517
518//copied from RICE VIDEO
519void OGL_SetBlendMode()
520{
521
522 u32 blender = gDP.otherMode.l >> 16;
523 u32 blendmode_1 = blender&0xcccc;
524 u32 blendmode_2 = blender&0x3333;
525
526 glEnable(GL_BLEND);
527 switch(gDP.otherMode.cycleType)
528 {
529 case G_CYC_FILL:
530 glDisable(GL_BLEND);
531 break;
532
533 case G_CYC_COPY:
534 glBlendFunc(GL_ONE, GL_ZERO);
535 break;
536
537 case G_CYC_2CYCLE:
538 if (gDP.otherMode.forceBlender && gDP.otherMode.depthCompare)
539 {
540 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
541 break;
542 }
543
544 switch(blendmode_1+blendmode_2)
545 {
546 case BLEND_PASS+(BLEND_PASS>>2): // In * 0 + In * 1
547 case BLEND_FOG_APRIM+(BLEND_PASS>>2):
548 case BLEND_FOG_MEM_FOG_MEM + (BLEND_OPA>>2):
549 case BLEND_FOG_APRIM + (BLEND_OPA>>2):
550 case BLEND_FOG_ASHADE + (BLEND_OPA>>2):
551 case BLEND_BI_AFOG + (BLEND_OPA>>2):
552 case BLEND_FOG_ASHADE + (BLEND_NOOP>>2):
553 case BLEND_NOOP + (BLEND_OPA>>2):
554 case BLEND_NOOP4 + (BLEND_NOOP>>2):
555 case BLEND_FOG_ASHADE+(BLEND_PASS>>2):
556 case BLEND_FOG_3+(BLEND_PASS>>2):
557 glDisable(GL_BLEND);
558 break;
559
560 case BLEND_PASS+(BLEND_OPA>>2):
561 if (gDP.otherMode.cvgXAlpha && gDP.otherMode.alphaCvgSel)
562 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
563 else
564 glDisable(GL_BLEND);
565 break;
566
567 case BLEND_PASS + (BLEND_XLU>>2):
568 case BLEND_FOG_ASHADE + (BLEND_XLU>>2):
569 case BLEND_FOG_APRIM + (BLEND_XLU>>2):
570 case BLEND_FOG_MEM_FOG_MEM + (BLEND_PASS>>2):
571 case BLEND_XLU + (BLEND_XLU>>2):
572 case BLEND_BI_AFOG + (BLEND_XLU>>2):
573 case BLEND_XLU + (BLEND_FOG_MEM_IN_MEM>>2):
574 case BLEND_PASS + (BLEND_FOG_MEM_IN_MEM>>2):
575 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
576 break;
577
578 case BLEND_FOG_ASHADE+0x0301:
579 glBlendFunc(GL_SRC_ALPHA, GL_ZERO);
580 break;
581
582 case 0x0c08+0x1111:
583 glBlendFunc(GL_ZERO, GL_DST_ALPHA);
584 break;
585
586 default:
587 if (blendmode_2 == (BLEND_PASS>>2))
588 glDisable(GL_BLEND);
589 else
590 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
591 break;
592 }
593 break;
594
595 default:
596
597 if (gDP.otherMode.forceBlender && gDP.otherMode.depthCompare && blendmode_1 != BLEND_FOG_ASHADE )
598 {
599 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
600 break;
601 }
602
603 switch (blendmode_1)
604 {
605 case BLEND_XLU:
606 case BLEND_BI_AIN:
607 case BLEND_FOG_MEM:
608 case BLEND_FOG_MEM_IN_MEM:
609 case BLEND_BLENDCOLOR:
610 case 0x00c0:
611 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
612 break;
613
614 case BLEND_MEM_ALPHA_IN:
615 glBlendFunc(GL_ZERO, GL_DST_ALPHA);
616 break;
617
618 case BLEND_OPA:
619 //if( options.enableHackForGames == HACK_FOR_MARIO_TENNIS )
620 //{
621 // glBlendFunc(BLEND_SRCALPHA, BLEND_INVSRCALPHA);
622 //}
623
624 glDisable(GL_BLEND);
625 break;
626
627 case BLEND_PASS:
628 case BLEND_NOOP:
629 case BLEND_FOG_ASHADE:
630 case BLEND_FOG_MEM_3:
631 case BLEND_BI_AFOG:
632 glDisable(GL_BLEND);
633 break;
634
635 case BLEND_FOG_APRIM:
636 glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_ZERO);
637 break;
638
639 case BLEND_NOOP3:
640 case BLEND_NOOP5:
641 case BLEND_MEM:
642 glBlendFunc(GL_ZERO, GL_ONE);
643 break;
644
645 default:
646 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
647 }
648 }
649
650}
651
652void OGL_UpdateStates()
653{
654 if (gDP.otherMode.cycleType == G_CYC_COPY)
655 ShaderCombiner_Set(EncodeCombineMode(0, 0, 0, TEXEL0, 0, 0, 0, TEXEL0, 0, 0, 0, TEXEL0, 0, 0, 0, TEXEL0));
656 else if (gDP.otherMode.cycleType == G_CYC_FILL)
657 ShaderCombiner_Set(EncodeCombineMode(0, 0, 0, SHADE, 0, 0, 0, 1, 0, 0, 0, SHADE, 0, 0, 0, 1));
658 else
659 ShaderCombiner_Set(gDP.combine.mux);
660
661#ifdef SHADER_TEST
662 ProgramSwaps += scProgramChanged;
663#endif
664
665 if (gSP.changed & CHANGED_GEOMETRYMODE)
666 {
667 OGL_UpdateCullFace();
668
669 if (gSP.geometryMode & G_ZBUFFER)
670 glEnable(GL_DEPTH_TEST);
671 else
672 glDisable(GL_DEPTH_TEST);
673
674 }
675
676 if (gDP.changed & CHANGED_CONVERT)
677 {
678 SC_SetUniform1f(uK4, gDP.convert.k4);
679 SC_SetUniform1f(uK5, gDP.convert.k5);
680 }
681
682 if (gDP.changed & CHANGED_RENDERMODE || gDP.changed & CHANGED_CYCLETYPE)
683 {
684 if (gDP.otherMode.cycleType == G_CYC_1CYCLE || gDP.otherMode.cycleType == G_CYC_2CYCLE)
685 {
686 //glDepthFunc((gDP.otherMode.depthCompare) ? GL_GEQUAL : GL_ALWAYS);
687 glDepthFunc((gDP.otherMode.depthCompare) ? GL_LESS : GL_ALWAYS);
688 glDepthMask((gDP.otherMode.depthUpdate) ? GL_TRUE : GL_FALSE);
689
690 if (gDP.otherMode.depthMode == ZMODE_DEC)
691 glEnable(GL_POLYGON_OFFSET_FILL);
692 else
693 glDisable(GL_POLYGON_OFFSET_FILL);
694 }
695 else
696 {
697 glDepthFunc(GL_ALWAYS);
698 glDepthMask(GL_FALSE);
699 }
700 }
701
702 if ((gDP.changed & CHANGED_BLENDCOLOR) || (gDP.changed & CHANGED_RENDERMODE))
703 SC_SetUniform1f(uAlphaRef, (gDP.otherMode.cvgXAlpha) ? 0.5f : gDP.blendColor.a);
704
705 if (gDP.changed & CHANGED_SCISSOR)
706 OGL_UpdateScissor();
707
708 if (gSP.changed & CHANGED_VIEWPORT)
709 OGL_UpdateViewport();
710
711 if (gSP.changed & CHANGED_FOGPOSITION)
712 {
713 SC_SetUniform1f(uFogMultiplier, (float) gSP.fog.multiplier / 255.0f);
714 SC_SetUniform1f(uFogOffset, (float) gSP.fog.offset / 255.0f);
715 }
716
717 if (gSP.changed & CHANGED_TEXTURESCALE)
718 {
719 if (scProgramCurrent->usesT0 || scProgramCurrent->usesT1)
720 SC_SetUniform2f(uTexScale, gSP.texture.scales, gSP.texture.scalet);
721 }
722
723 if ((gSP.changed & CHANGED_TEXTURE) || (gDP.changed & CHANGED_TILE) || (gDP.changed & CHANGED_TMEM))
724 {
725 //For some reason updating the texture cache on the first frame of LOZ:OOT causes a NULL Pointer exception...
726 if (scProgramCurrent)
727 {
728 if (scProgramCurrent->usesT0)
729 {
730#ifdef TEXTURECACHE_TEST
731 unsigned t = ticksGetTicks();
732 TextureCache_Update(0);
733 TextureCacheTime += (ticksGetTicks() - t);
734#else
735 TextureCache_Update(0);
736#endif
737 SC_ForceUniform2f(uTexOffset[0], gSP.textureTile[0]->fuls, gSP.textureTile[0]->fult);
738 SC_ForceUniform2f(uCacheShiftScale[0], cache.current[0]->shiftScaleS, cache.current[0]->shiftScaleT);
739 SC_ForceUniform2f(uCacheScale[0], cache.current[0]->scaleS, cache.current[0]->scaleT);
740 SC_ForceUniform2f(uCacheOffset[0], cache.current[0]->offsetS, cache.current[0]->offsetT);
741 }
742 //else TextureCache_ActivateDummy(0);
743
744 //Note: enabling dummies makes some F-zero X textures flicker.... strange.
745
746 if (scProgramCurrent->usesT1)
747 {
748#ifdef TEXTURECACHE_TEST
749 unsigned t = ticksGetTicks();
750 TextureCache_Update(1);
751 TextureCacheTime += (ticksGetTicks() - t);
752#else
753 TextureCache_Update(1);
754#endif
755 SC_ForceUniform2f(uTexOffset[1], gSP.textureTile[1]->fuls, gSP.textureTile[1]->fult);
756 SC_ForceUniform2f(uCacheShiftScale[1], cache.current[1]->shiftScaleS, cache.current[1]->shiftScaleT);
757 SC_ForceUniform2f(uCacheScale[1], cache.current[1]->scaleS, cache.current[1]->scaleT);
758 SC_ForceUniform2f(uCacheOffset[1], cache.current[1]->offsetS, cache.current[1]->offsetT);
759 }
760 //else TextureCache_ActivateDummy(1);
761 }
762 }
763
764 if ((gDP.changed & CHANGED_FOGCOLOR) && config.enableFog)
765 SC_SetUniform4fv(uFogColor, &gDP.fogColor.r );
766
767 if (gDP.changed & CHANGED_ENV_COLOR)
768 SC_SetUniform4fv(uEnvColor, &gDP.envColor.r);
769
770 if (gDP.changed & CHANGED_PRIM_COLOR)
771 {
772 SC_SetUniform4fv(uPrimColor, &gDP.primColor.r);
773 SC_SetUniform1f(uPrimLODFrac, gDP.primColor.l);
774 }
775
776 if ((gDP.changed & CHANGED_RENDERMODE) || (gDP.changed & CHANGED_CYCLETYPE))
777 {
778#ifndef OLD_BLENDMODE
779 OGL_SetBlendMode();
780#else
781 if ((gDP.otherMode.forceBlender) &&
782 (gDP.otherMode.cycleType != G_CYC_COPY) &&
783 (gDP.otherMode.cycleType != G_CYC_FILL) &&
784 !(gDP.otherMode.alphaCvgSel))
785 {
786 glEnable( GL_BLEND );
787
788 switch (gDP.otherMode.l >> 16)
789 {
790 case 0x0448: // Add
791 case 0x055A:
792 glBlendFunc( GL_ONE, GL_ONE );
793 break;
794 case 0x0C08: // 1080 Sky
795 case 0x0F0A: // Used LOTS of places
796 glBlendFunc( GL_ONE, GL_ZERO );
797 break;
798
799 case 0x0040: // Fzero
800 case 0xC810: // Blends fog
801 case 0xC811: // Blends fog
802 case 0x0C18: // Standard interpolated blend
803 case 0x0C19: // Used for antialiasing
804 case 0x0050: // Standard interpolated blend
805 case 0x0055: // Used for antialiasing
806 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
807 break;
808
809 case 0x0FA5: // Seems to be doing just blend color - maybe combiner can be used for this?
810 case 0x5055: // Used in Paper Mario intro, I'm not sure if this is right...
811 glBlendFunc( GL_ZERO, GL_ONE );
812 break;
813
814 default:
815 LOG(LOG_VERBOSE, "Unhandled blend mode=%x", gDP.otherMode.l >> 16);
816 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
817 break;
818 }
819 }
820 else
821 {
822 glDisable( GL_BLEND );
823 }
824
825 if (gDP.otherMode.cycleType == G_CYC_FILL)
826 {
827 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
828 glEnable( GL_BLEND );
829 }
830#endif
831 }
832
833 gDP.changed &= CHANGED_TILE | CHANGED_TMEM;
834 gSP.changed &= CHANGED_TEXTURE | CHANGED_MATRIX;
835}
836
837void OGL_DrawTriangle(SPVertex *vertices, int v0, int v1, int v2)
838{
839
840}
841
842void OGL_AddTriangle(int v0, int v1, int v2)
843{
844 OGL.triangles.elements[OGL.triangles.num++] = v0;
845 OGL.triangles.elements[OGL.triangles.num++] = v1;
846 OGL.triangles.elements[OGL.triangles.num++] = v2;
847}
848
849void OGL_SetColorArray()
850{
851 if (scProgramCurrent->usesCol)
852 glEnableVertexAttribArray(SC_COLOR);
853 else
854 glDisableVertexAttribArray(SC_COLOR);
855}
856
857void OGL_SetTexCoordArrays()
858{
859 if (scProgramCurrent->usesT0)
860 glEnableVertexAttribArray(SC_TEXCOORD0);
861 else
862 glDisableVertexAttribArray(SC_TEXCOORD0);
863
864 if (scProgramCurrent->usesT1)
865 glEnableVertexAttribArray(SC_TEXCOORD1);
866 else
867 glDisableVertexAttribArray(SC_TEXCOORD1);
868}
869
870void OGL_DrawTriangles()
871{
872 if (OGL.renderingToTexture && config.ignoreOffscreenRendering)
873 {
874 OGL.triangles.num = 0;
875 return;
876 }
877
878 if (OGL.triangles.num == 0) return;
879
880 if ((config.updateMode == SCREEN_UPDATE_AT_1ST_PRIMITIVE) && OGL.screenUpdate)
881 OGL_SwapBuffers();
882
883 if (gSP.changed || gDP.changed)
884 OGL_UpdateStates();
885
886 if (OGL.renderState != RS_TRIANGLE || scProgramChanged)
887 {
888 OGL_SetColorArray();
889 OGL_SetTexCoordArrays();
890 glDisableVertexAttribArray(SC_TEXCOORD1);
891 SC_ForceUniform1f(uRenderState, RS_TRIANGLE);
892 }
893
894 if (OGL.renderState != RS_TRIANGLE)
895 {
896#ifdef RENDERSTATE_TEST
897 StateChanges++;
898#endif
899 glVertexAttribPointer(SC_POSITION, 4, GL_FLOAT, GL_FALSE, sizeof(SPVertex), &OGL.triangles.vertices[0].x);
900 glVertexAttribPointer(SC_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(SPVertex), &OGL.triangles.vertices[0].r);
901 glVertexAttribPointer(SC_TEXCOORD0, 2, GL_FLOAT, GL_FALSE, sizeof(SPVertex), &OGL.triangles.vertices[0].s);
902
903 OGL_UpdateCullFace();
904 OGL_UpdateViewport();
905 glEnable(GL_SCISSOR_TEST);
906 OGL.renderState = RS_TRIANGLE;
907 }
908
909 glDrawElements(GL_TRIANGLES, OGL.triangles.num, GL_UNSIGNED_BYTE, OGL.triangles.elements);
910 OGL.triangles.num = 0;
911
912#ifdef __TRIBUFFER_OPT
913 __indexmap_clear();
914#endif
915}
916
917void OGL_DrawLine(int v0, int v1, float width )
918{
919 if (OGL.renderingToTexture && config.ignoreOffscreenRendering) return;
920
921 if ((config.updateMode == SCREEN_UPDATE_AT_1ST_PRIMITIVE) && OGL.screenUpdate)
922 OGL_SwapBuffers();
923
924 if (gSP.changed || gDP.changed)
925 OGL_UpdateStates();
926
927 if (OGL.renderState != RS_LINE || scProgramChanged)
928 {
929#ifdef RENDERSTATE_TEST
930 StateChanges++;
931#endif
932 OGL_SetColorArray();
933 glDisableVertexAttribArray(SC_TEXCOORD0);
934 glDisableVertexAttribArray(SC_TEXCOORD1);
935 glVertexAttribPointer(SC_POSITION, 4, GL_FLOAT, GL_FALSE, sizeof(SPVertex), &OGL.triangles.vertices[0].x);
936 glVertexAttribPointer(SC_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(SPVertex), &OGL.triangles.vertices[0].r);
937
938 SC_ForceUniform1f(uRenderState, RS_LINE);
939 OGL_UpdateCullFace();
940 OGL_UpdateViewport();
941 OGL.renderState = RS_LINE;
942 }
943
944 unsigned short elem[2];
945 elem[0] = v0;
946 elem[1] = v1;
947 glLineWidth( width * OGL.scaleX );
948 glDrawElements(GL_LINES, 2, GL_UNSIGNED_SHORT, elem);
949}
950
951void OGL_DrawRect( int ulx, int uly, int lrx, int lry, float *color)
952{
953 if (OGL.renderingToTexture && config.ignoreOffscreenRendering) return;
954
955 if ((config.updateMode == SCREEN_UPDATE_AT_1ST_PRIMITIVE) && OGL.screenUpdate)
956 OGL_SwapBuffers();
957
958 if (gSP.changed || gDP.changed)
959 OGL_UpdateStates();
960
961 if (OGL.renderState != RS_RECT || scProgramChanged)
962 {
963 glDisableVertexAttribArray(SC_COLOR);
964 glDisableVertexAttribArray(SC_TEXCOORD0);
965 glDisableVertexAttribArray(SC_TEXCOORD1);
966 SC_ForceUniform1f(uRenderState, RS_RECT);
967 }
968
969 if (OGL.renderState != RS_RECT)
970 {
971#ifdef RENDERSTATE_TEST
972 StateChanges++;
973#endif
974 glVertexAttrib4f(SC_POSITION, 0, 0, gSP.viewport.nearz, 1.0);
975 glVertexAttribPointer(SC_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(GLVertex), &OGL.rect[0].x);
976 OGL.renderState = RS_RECT;
977 }
978
979 glViewport(config.framebuffer.xpos, config.framebuffer.ypos, config.framebuffer.width, config.framebuffer.height );
980 glDisable(GL_SCISSOR_TEST);
981 glDisable(GL_CULL_FACE);
982
983 OGL.rect[0].x = (float) ulx * (2.0f * VI.rwidth) - 1.0;
984 OGL.rect[0].y = (float) uly * (-2.0f * VI.rheight) + 1.0;
985 OGL.rect[1].x = (float) (lrx+1) * (2.0f * VI.rwidth) - 1.0;
986 OGL.rect[1].y = OGL.rect[0].y;
987 OGL.rect[2].x = OGL.rect[0].x;
988 OGL.rect[2].y = (float) (lry+1) * (-2.0f * VI.rheight) + 1.0;
989 OGL.rect[3].x = OGL.rect[1].x;
990 OGL.rect[3].y = OGL.rect[2].y;
991
992 glVertexAttrib4fv(SC_COLOR, color);
993 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
994 glEnable(GL_SCISSOR_TEST);
995 OGL_UpdateViewport();
996
997}
998
999void OGL_DrawTexturedRect( float ulx, float uly, float lrx, float lry, float uls, float ult, float lrs, float lrt, bool flip )
1000{
1001 if (config.hackBanjoTooie)
1002 {
1003 if (gDP.textureImage.width == gDP.colorImage.width &&
1004 gDP.textureImage.format == G_IM_FMT_CI &&
1005 gDP.textureImage.size == G_IM_SIZ_8b)
1006 {
1007 return;
1008 }
1009 }
1010
1011 if (OGL.renderingToTexture && config.ignoreOffscreenRendering) return;
1012
1013 if ((config.updateMode == SCREEN_UPDATE_AT_1ST_PRIMITIVE) && OGL.screenUpdate)
1014 OGL_SwapBuffers();
1015
1016 if (gSP.changed || gDP.changed)
1017 OGL_UpdateStates();
1018
1019 if (OGL.renderState != RS_TEXTUREDRECT || scProgramChanged)
1020 {
1021 glDisableVertexAttribArray(SC_COLOR);
1022 OGL_SetTexCoordArrays();
1023 SC_ForceUniform1f(uRenderState, RS_TEXTUREDRECT);
1024 }
1025
1026 if (OGL.renderState != RS_TEXTUREDRECT)
1027 {
1028#ifdef RENDERSTATE_TEST
1029 StateChanges++;
1030#endif
1031 glVertexAttrib4f(SC_COLOR, 0, 0, 0, 0);
1032 glVertexAttrib4f(SC_POSITION, 0, 0, (gDP.otherMode.depthSource == G_ZS_PRIM) ? gDP.primDepth.z : gSP.viewport.nearz, 1.0);
1033 glVertexAttribPointer(SC_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(GLVertex), &OGL.rect[0].x);
1034 glVertexAttribPointer(SC_TEXCOORD0, 2, GL_FLOAT, GL_FALSE, sizeof(GLVertex), &OGL.rect[0].s0);
1035 glVertexAttribPointer(SC_TEXCOORD1, 2, GL_FLOAT, GL_FALSE, sizeof(GLVertex), &OGL.rect[0].s1);
1036 OGL.renderState = RS_TEXTUREDRECT;
1037 }
1038
1039 glViewport(config.framebuffer.xpos, config.framebuffer.ypos, config.framebuffer.width, config.framebuffer.height);
1040 glDisable(GL_CULL_FACE);
1041
1042 OGL.rect[0].x = (float) ulx * (2.0f * VI.rwidth) - 1.0f;
1043 OGL.rect[0].y = (float) uly * (-2.0f * VI.rheight) + 1.0f;
1044 OGL.rect[1].x = (float) (lrx) * (2.0f * VI.rwidth) - 1.0f;
1045 OGL.rect[1].y = OGL.rect[0].y;
1046 OGL.rect[2].x = OGL.rect[0].x;
1047 OGL.rect[2].y = (float) (lry) * (-2.0f * VI.rheight) + 1.0f;
1048 OGL.rect[3].x = OGL.rect[1].x;
1049 OGL.rect[3].y = OGL.rect[2].y;
1050
1051 if (scProgramCurrent->usesT0 && cache.current[0] && gSP.textureTile[0])
1052 {
1053 OGL.rect[0].s0 = uls * cache.current[0]->shiftScaleS - gSP.textureTile[0]->fuls;
1054 OGL.rect[0].t0 = ult * cache.current[0]->shiftScaleT - gSP.textureTile[0]->fult;
1055 OGL.rect[3].s0 = (lrs + 1.0f) * cache.current[0]->shiftScaleS - gSP.textureTile[0]->fuls;
1056 OGL.rect[3].t0 = (lrt + 1.0f) * cache.current[0]->shiftScaleT - gSP.textureTile[0]->fult;
1057
1058 if ((cache.current[0]->maskS) && !(cache.current[0]->mirrorS) && (fmod( OGL.rect[0].s0, cache.current[0]->width ) == 0.0f))
1059 {
1060 OGL.rect[3].s0 -= OGL.rect[0].s0;
1061 OGL.rect[0].s0 = 0.0f;
1062 }
1063
1064 if ((cache.current[0]->maskT) && !(cache.current[0]->mirrorT) && (fmod( OGL.rect[0].t0, cache.current[0]->height ) == 0.0f))
1065 {
1066 OGL.rect[3].t0 -= OGL.rect[0].t0;
1067 OGL.rect[0].t0 = 0.0f;
1068 }
1069
1070 glActiveTexture( GL_TEXTURE0);
1071 if ((OGL.rect[0].s0 >= 0.0f) && (OGL.rect[3].s0 <= cache.current[0]->width))
1072 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
1073
1074 if ((OGL.rect[0].t0 >= 0.0f) && (OGL.rect[3].t0 <= cache.current[0]->height))
1075 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
1076
1077 OGL.rect[0].s0 *= cache.current[0]->scaleS;
1078 OGL.rect[0].t0 *= cache.current[0]->scaleT;
1079 OGL.rect[3].s0 *= cache.current[0]->scaleS;
1080 OGL.rect[3].t0 *= cache.current[0]->scaleT;
1081 }
1082
1083 if (scProgramCurrent->usesT1 && cache.current[1] && gSP.textureTile[1])
1084 {
1085 OGL.rect[0].s1 = uls * cache.current[1]->shiftScaleS - gSP.textureTile[1]->fuls;
1086 OGL.rect[0].t1 = ult * cache.current[1]->shiftScaleT - gSP.textureTile[1]->fult;
1087 OGL.rect[3].s1 = (lrs + 1.0f) * cache.current[1]->shiftScaleS - gSP.textureTile[1]->fuls;
1088 OGL.rect[3].t1 = (lrt + 1.0f) * cache.current[1]->shiftScaleT - gSP.textureTile[1]->fult;
1089
1090 if ((cache.current[1]->maskS) && (fmod( OGL.rect[0].s1, cache.current[1]->width ) == 0.0f) && !(cache.current[1]->mirrorS))
1091 {
1092 OGL.rect[3].s1 -= OGL.rect[0].s1;
1093 OGL.rect[0].s1 = 0.0f;
1094 }
1095
1096 if ((cache.current[1]->maskT) && (fmod( OGL.rect[0].t1, cache.current[1]->height ) == 0.0f) && !(cache.current[1]->mirrorT))
1097 {
1098 OGL.rect[3].t1 -= OGL.rect[0].t1;
1099 OGL.rect[0].t1 = 0.0f;
1100 }
1101
1102 glActiveTexture( GL_TEXTURE1);
1103 if ((OGL.rect[0].s1 == 0.0f) && (OGL.rect[3].s1 <= cache.current[1]->width))
1104 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
1105
1106 if ((OGL.rect[0].t1 == 0.0f) && (OGL.rect[3].t1 <= cache.current[1]->height))
1107 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
1108
1109 OGL.rect[0].s1 *= cache.current[1]->scaleS;
1110 OGL.rect[0].t1 *= cache.current[1]->scaleT;
1111 OGL.rect[3].s1 *= cache.current[1]->scaleS;
1112 OGL.rect[3].t1 *= cache.current[1]->scaleT;
1113 }
1114
1115 if ((gDP.otherMode.cycleType == G_CYC_COPY) && !config.texture.forceBilinear)
1116 {
1117 glActiveTexture(GL_TEXTURE0);
1118 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
1119 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
1120 }
1121
1122 if (flip)
1123 {
1124 OGL.rect[1].s0 = OGL.rect[0].s0;
1125 OGL.rect[1].t0 = OGL.rect[3].t0;
1126 OGL.rect[1].s1 = OGL.rect[0].s1;
1127 OGL.rect[1].t1 = OGL.rect[3].t1;
1128 OGL.rect[2].s0 = OGL.rect[3].s0;
1129 OGL.rect[2].t0 = OGL.rect[0].t0;
1130 OGL.rect[2].s1 = OGL.rect[3].s1;
1131 OGL.rect[2].t1 = OGL.rect[0].t1;
1132 }
1133 else
1134 {
1135 OGL.rect[1].s0 = OGL.rect[3].s0;
1136 OGL.rect[1].t0 = OGL.rect[0].t0;
1137 OGL.rect[1].s1 = OGL.rect[3].s1;
1138 OGL.rect[1].t1 = OGL.rect[0].t1;
1139 OGL.rect[2].s0 = OGL.rect[0].s0;
1140 OGL.rect[2].t0 = OGL.rect[3].t0;
1141 OGL.rect[2].s1 = OGL.rect[0].s1;
1142 OGL.rect[2].t1 = OGL.rect[3].t1;
1143 }
1144
1145 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1146 OGL_UpdateViewport();
1147}
1148
1149void OGL_ClearDepthBuffer()
1150{
1151 if (OGL.renderingToTexture && config.ignoreOffscreenRendering) return;
1152
1153 if ((config.updateMode == SCREEN_UPDATE_AT_1ST_PRIMITIVE) && OGL.screenUpdate)
1154 OGL_SwapBuffers();
1155
1156 //float depth = 1.0 - (gDP.fillColor.z / ((float)0x3FFF)); // broken on OMAP3
1157 float depth = gDP.fillColor.z ;
1158
1159/////// paulscode, graphics bug-fixes
1160 glDisable( GL_SCISSOR_TEST );
1161 glDepthMask( GL_TRUE ); // fixes side-bar graphics glitches
1162// glClearDepthf( depth ); // broken on Qualcomm Adreno
1163 glClearDepthf( 1.0f ); // fixes missing graphics on Qualcomm Adreno
1164 glClearColor( 0, 0, 0, 1 );
1165 glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT );
1166 OGL_UpdateDepthUpdate();
1167 glEnable( GL_SCISSOR_TEST );
1168////////
1169}
1170
1171void OGL_ClearColorBuffer( float *color )
1172{
1173 if (OGL.renderingToTexture && config.ignoreOffscreenRendering) return;
1174
1175 if ((config.updateMode == SCREEN_UPDATE_AT_1ST_PRIMITIVE) && OGL.screenUpdate)
1176 OGL_SwapBuffers();
1177
1178 glScissor(config.framebuffer.xpos, config.framebuffer.ypos, config.framebuffer.width, config.framebuffer.height);
1179 glClearColor( color[0], color[1], color[2], color[3] );
1180 glClear( GL_COLOR_BUFFER_BIT );
1181 OGL_UpdateScissor();
1182
1183}
1184
1185int OGL_CheckError()
1186{
1187 GLenum e = glGetError();
1188 if (e != GL_NO_ERROR)
1189 {
1190 printf("GL Error: ");
1191 switch(e)
1192 {
1193 case GL_INVALID_ENUM: printf("INVALID ENUM"); break;
1194 case GL_INVALID_VALUE: printf("INVALID VALUE"); break;
1195 case GL_INVALID_OPERATION: printf("INVALID OPERATION"); break;
1196 case GL_OUT_OF_MEMORY: printf("OUT OF MEMORY"); break;
1197 }
1198 printf("\n");
1199 return 1;
1200 }
1201 return 0;
1202}
1203
1204void OGL_UpdateFrameTime()
1205{
1206 unsigned ticks = ticksGetTicks();
1207 static unsigned lastFrameTicks = 0;
1208 for(int i = OGL_FRAMETIME_NUM-1; i > 0; i--) OGL.frameTime[i] = OGL.frameTime[i-1];
1209 OGL.frameTime[0] = ticks - lastFrameTicks;
1210 lastFrameTicks = ticks;
1211}
1212
1213void OGL_SwapBuffers()
1214{
1215 //OGL_DrawTriangles();
1216 scProgramChanged = 0;
1217#if 0
1218 static int frames = 0;
1219 static unsigned lastTicks = 0;
1220 unsigned ticks = ticksGetTicks();
1221
1222 frames++;
1223 if (ticks >= (lastTicks + 1000))
1224 {
1225
1226 float fps = 1000.0f * (float) frames / (ticks - lastTicks);
1227 LOG(LOG_MINIMAL, "fps = %.2f \n", fps);
1228 LOG(LOG_MINIMAL, "skipped frame = %i of %i \n", OGL.frameSkipped, frames + OGL.frameSkipped);
1229
1230 OGL.frameSkipped = 0;
1231
1232#ifdef BATCH_TEST
1233 LOG(LOG_MINIMAL, "time spent in draw calls per frame = %.2f ms\n", (float)TotalDrawTime / frames);
1234 LOG(LOG_MINIMAL, "average draw calls per frame = %.0f\n", (float)TotalDrawCalls / frames);
1235 LOG(LOG_MINIMAL, "average vertices per draw call = %.2f\n", (float)TotalTriangles / TotalDrawCalls);
1236 TotalDrawCalls = 0;
1237 TotalTriangles = 0;
1238 TotalDrawTime = 0;
1239#endif
1240
1241#ifdef SHADER_TEST
1242 LOG(LOG_MINIMAL, "average shader changes per frame = %f\n", (float)ProgramSwaps / frames);
1243 ProgramSwaps = 0;
1244#endif
1245
1246#ifdef TEXTURECACHE_TEST
1247 LOG(LOG_MINIMAL, "texture cache time per frame: %.2f ms\n", (float)TextureCacheTime/ frames);
1248 LOG(LOG_MINIMAL, "texture cache per frame: hits=%.2f misses=%.2f\n", (float)cache.hits / frames,
1249 (float)cache.misses / frames);
1250 cache.hits = cache.misses = 0;
1251 TextureCacheTime = 0;
1252
1253#endif
1254 frames = 0;
1255 lastTicks = ticks;
1256 }
1257#endif
1258
1259
1260#ifdef PROFILE_GBI
1261 u32 profileTicks = ticksGetTicks();
1262 static u32 profileLastTicks = 0;
1263 if (profileTicks >= (profileLastTicks + 5000))
1264 {
1265 LOG(LOG_MINIMAL, "GBI PROFILE DATA: %i ms \n", profileTicks - profileLastTicks);
1266 LOG(LOG_MINIMAL, "=========================================================\n");
1267 GBI_ProfilePrint(stdout);
1268 LOG(LOG_MINIMAL, "=========================================================\n");
1269 GBI_ProfileReset();
1270 profileLastTicks = profileTicks;
1271 }
1272#endif
1273
1274 if (config.framebuffer.enable)
1275 {
1276 glBindFramebuffer(GL_FRAMEBUFFER, 0);
1277 glClearColor( 0, 0, 0, 1 );
1278 glClear( GL_COLOR_BUFFER_BIT );
1279
1280 glUseProgram(OGL.defaultProgram);
1281 glDisable(GL_SCISSOR_TEST);
1282 glDisable(GL_DEPTH_TEST);
1283 glViewport(config.window.xpos, config.window.ypos, config.window.width, config.window.height);
1284
1285 static const float vert[] =
1286 {
1287 -1.0, -1.0, +0.0, +0.0,
1288 +1.0, -1.0, +1.0, +0.0,
1289 -1.0, +1.0, +0.0, +1.0,
1290 +1.0, +1.0, +1.0, +1.0
1291 };
1292
1293 glActiveTexture(GL_TEXTURE0);
1294 glBindTexture(GL_TEXTURE_2D, OGL.framebuffer.color_buffer);
1295 if (config.framebuffer.bilinear)
1296 {
1297 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1298 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1299 }
1300 else
1301 {
1302 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1303 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1304 }
1305
1306 glEnableVertexAttribArray(0);
1307 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (float*)vert);
1308 glEnableVertexAttribArray(1);
1309 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (float*)vert + 2);
1310 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1311
1312 Android_JNI_SwapWindow(); // paulscode, fix for black-screen bug
1313
1314 glBindFramebuffer(GL_FRAMEBUFFER, OGL.framebuffer.fb);
1315 OGL_UpdateViewport();
1316 if (scProgramCurrent) glUseProgram(scProgramCurrent->program);
1317 OGL.renderState = RS_NONE;
1318 }
1319 else
1320 {
1321 Android_JNI_SwapWindow(); // paulscode, fix for black-screen bug
1322 }
1323
1324 // if emulator defined a render callback function, call it before
1325 // buffer swap
1326 if (renderCallback) (*renderCallback)();
1327
1328 OGL.screenUpdate = false;
1329
1330 if (config.forceBufferClear)
1331 {
1332/////// paulscode, graphics bug-fixes
1333 float depth = gDP.fillColor.z ;
1334 glDisable( GL_SCISSOR_TEST );
1335 glDepthMask( GL_TRUE ); // fixes side-bar graphics glitches
1336// glClearDepthf( depth ); // broken on Qualcomm Adreno
1337 glClearDepthf( 1.0f ); // fixes missing graphics on Qualcomm Adreno
1338 glClearColor( 0, 0, 0, 1 );
1339 glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT );
1340 OGL_UpdateDepthUpdate();
1341 glEnable( GL_SCISSOR_TEST );
1342///////
1343 }
1344
1345}
1346
1347void OGL_ReadScreen( void *dest, int *width, int *height )
1348{
1349 if (width)
1350 *width = config.framebuffer.width;
1351 if (height)
1352 *height = config.framebuffer.height;
1353
1354 if (dest == NULL)
1355 return;
1356
1357 glReadPixels( config.framebuffer.xpos, config.framebuffer.ypos,
1358 config.framebuffer.width, config.framebuffer.height,
1359 GL_RGBA, GL_UNSIGNED_BYTE, dest );
1360}
1361