9 //// paulscode, added for SDL linkage:
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
28 #include "ShaderCombiner.h"
34 #include "FrameSkipper.h"
36 //#include "ae_bridge.h"
38 //// paulscode, function prototype missing from Yongzh's code
39 void OGL_UpdateDepthUpdate();
42 #ifdef TEXTURECACHE_TEST
43 int TextureCacheTime = 0;
47 #ifdef RENDERSTATE_TEST
56 int TotalDrawTime = 0;
57 int TotalTriangles = 0;
58 int 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);
68 const 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" \
73 "gl_Position = vec4(aPosition.x, aPosition.y, 0.0, 1.0);\n\t" \
74 "vTexCoord = aTexCoord; \n\t" \
77 const char _default_fsh[] = " \n\t" \
78 "uniform sampler2D uTex; \n\t" \
79 "varying mediump vec2 vTexCoord; \n\t" \
81 "gl_FragColor = texture2D(uTex, vTexCoord); \n\t" \
85 void OGL_EnableRunfast()
88 static const unsigned int x = 0x04086060;
89 static const unsigned int y = 0x03000000;
92 "fmrx %0, fpscr \n\t" //r0 = FPSCR
93 "and %0, %0, %1 \n\t" //r0 = r0 & 0x04086060
94 "orr %0, %0, %2 \n\t" //r0 = r0 | 0x03000000
95 "fmxr fpscr, %0 \n\t" //FPSCR = r0
102 int OGL_IsExtSupported( const char *extension )
104 const GLubyte *extensions = NULL;
105 const GLubyte *start;
106 GLubyte *where, *terminator;
108 where = (GLubyte *) strchr(extension, ' ');
109 if (where || *extension == '\0')
112 extensions = glGetString(GL_EXTENSIONS);
114 if (!extensions) return 0;
119 where = (GLubyte *) strstr((const char *) start, extension);
123 terminator = where + strlen(extension);
124 if (where == start || *(where - 1) == ' ')
125 if (*terminator == ' ' || *terminator == '\0')
134 extern void _glcompiler_error(GLint shader);
136 void OGL_InitStates()
140 glEnable( GL_CULL_FACE );
141 glEnableVertexAttribArray( SC_POSITION );
142 glEnable( GL_DEPTH_TEST );
143 glDepthFunc( GL_ALWAYS );
144 glDepthMask( GL_FALSE );
145 glEnable( GL_SCISSOR_TEST );
147 ///// paulscode, fixes missing graphics on Qualcomm, Adreno:
148 glDepthRangef(0.0f, 1.0f);
150 // default values (only seem to work on OMAP!)
151 glPolygonOffset(0.2f, 0.2f);
153 //// paulscode, added for different configurations based on hardware
154 // (part of the missing shadows and stars bug fix)
155 /* int hardwareType = Android_JNI_GetHardwareType();
157 Android_JNI_GetPolygonOffset(hardwareType, 1, &f1, &f2);
158 glPolygonOffset( f1, f2 );
161 // some other settings that have been tried, which do not work:
162 //glDepthRangef(1.0f, 0.0f); // reverses depth-order on OMAP3 chipsets
163 //glPolygonOffset(-0.2f, -0.2f);
164 //glDepthRangef( 0.09f, (float)0x7FFF ); // should work, but not on Adreno
165 //glPolygonOffset( -0.2f, 0.2f );
166 //glDepthRangef(0.0f, (float)0x7FFF); // what Yongzh used, broken on Adreno
167 //glPolygonOffset(0.2f, 0.2f);
171 glViewport(config.framebuffer.xpos, config.framebuffer.ypos, config.framebuffer.width, config.framebuffer.height);
173 //create default shader program
174 LOG( LOG_VERBOSE, "Generate Default Shader Program.\n" );
177 src[0] = _default_fsh;
178 OGL.defaultFragShader = glCreateShader( GL_FRAGMENT_SHADER );
179 glShaderSource( OGL.defaultFragShader, 1, (const char**) src, NULL );
180 glCompileShader( OGL.defaultFragShader );
181 glGetShaderiv( OGL.defaultFragShader, GL_COMPILE_STATUS, &success );
184 LOG(LOG_ERROR, "Failed to produce default fragment shader.\n");
187 src[0] = _default_vsh;
188 OGL.defaultVertShader = glCreateShader( GL_VERTEX_SHADER );
189 glShaderSource( OGL.defaultVertShader, 1, (const char**) src, NULL );
190 glCompileShader( OGL.defaultVertShader );
191 glGetShaderiv( OGL.defaultVertShader, GL_COMPILE_STATUS, &success );
194 LOG( LOG_ERROR, "Failed to produce default vertex shader.\n" );
195 _glcompiler_error( OGL.defaultVertShader );
198 OGL.defaultProgram = glCreateProgram();
199 glBindAttribLocation( OGL.defaultProgram, 0, "aPosition" );
200 glBindAttribLocation( OGL.defaultProgram, 1, "aTexCoord" );
201 glAttachShader( OGL.defaultProgram, OGL.defaultFragShader );
202 glAttachShader( OGL.defaultProgram, OGL.defaultVertShader );
203 glLinkProgram( OGL.defaultProgram );
204 glGetProgramiv( OGL.defaultProgram, GL_LINK_STATUS, &success );
207 LOG( LOG_ERROR, "Failed to link default program.\n" );
208 _glcompiler_error( OGL.defaultFragShader );
210 glUniform1i( glGetUniformLocation( OGL.defaultProgram, "uTex" ), 0 );
211 glUseProgram( OGL.defaultProgram );
215 void OGL_UpdateScale()
217 OGL.scaleX = (float)config.framebuffer.width / (float)VI.width;
218 OGL.scaleY = (float)config.framebuffer.height / (float)VI.height;
221 void OGL_ResizeWindow(int x, int y, int width, int height)
223 config.window.xpos = x;
224 config.window.ypos = y;
225 config.window.width = width;
226 config.window.height = height;
228 if (config.framebuffer.enable!=1) {
229 config.framebuffer.xpos = x;
230 config.framebuffer.ypos = y;
231 config.framebuffer.width = width;
232 config.framebuffer.height = height;
236 glViewport(config.framebuffer.xpos, config.framebuffer.ypos,
237 config.framebuffer.width, config.framebuffer.height);
240 ////// paulscode, added for SDL linkage
245 LOG(LOG_MINIMAL, "Initializing SDL video subsystem...\n" );
246 if (SDL_InitSubSystem( SDL_INIT_VIDEO ) == -1)
248 LOG(LOG_ERROR, "Error initializing SDL video subsystem: %s\n", SDL_GetError() );
252 int current_w = config.window.width;
253 int current_h = config.window.height;
257 /* Set the video mode */
258 LOG(LOG_MINIMAL, "Setting video mode %dx%d...\n", current_w, current_h );
260 // TODO: I should actually check what the pixelformat is, rather than assuming 16 bpp (RGB_565) or 32 bpp (RGBA_8888):
261 //// paulscode, added for switching between modes RGBA8888 and RGB565
262 // (part of the color banding fix)
264 /*if( Android_JNI_UseRGBA8888() )
270 // TODO: Replace SDL_SetVideoMode with something that is SDL 2.0 compatible
271 // Better yet, eliminate all SDL calls by using the Mupen64Plus core api
272 if (!(OGL.hScreen = SDL_SetVideoMode( current_w, current_h, bitsPP, SDL_HWSURFACE | SDL_FULLSCREEN )))
274 LOG(LOG_ERROR, "Problem setting videomode %dx%d: %s\n", current_w, current_h, SDL_GetError() );
275 SDL_QuitSubSystem( SDL_INIT_VIDEO );
279 //// paulscode, fixes the screen-size problem
280 const float ratio = ( config.romPAL ? 9.0f/11.0f : 0.75f );
281 int videoWidth = config.window.refwidth;
282 int videoHeight = config.window.refheight;
286 //re-scale width and height on per-rom basis
287 float width = /*(float)videoWidth * (float)config.window.refwidth /*/ 800.f;
288 float height = /*(float)videoHeight * (float)config.window.refheight / */480.f;
290 if (!config.stretchVideo) {
291 /* if ((float)videoWith*480.0f/(float)videoHeight/800.0f>1.0f) {
296 videoWidth = (int) (height / ratio);
297 if (videoWidth > width) {
299 videoHeight = (int) (width * ratio);
305 x = (width - videoWidth) / 2;
306 y = (height - videoHeight) / 2;
309 config.window.xpos = x;
310 config.window.ypos = y;
312 //set width and height
313 config.window.width = (int)videoWidth;
314 config.window.height = (int)videoHeight;
315 if (config.framebuffer.enable!=1) {
316 config.framebuffer.xpos = x;
317 config.framebuffer.ypos = y;
318 config.framebuffer.width = (int)videoWidth;
319 config.framebuffer.height = (int)videoHeight;
331 void Android_JNI_SwapWindow()
339 // paulscode, initialize SDL
341 if (!OGL_SDL_Start())
349 /////// paulscode, graphics bug-fixes
350 float depth = gDP.fillColor.z ;
351 glDisable( GL_SCISSOR_TEST );
352 glDepthMask( GL_TRUE ); // fixes side-bar graphics glitches
353 // glClearDepthf( depth ); // broken on Qualcomm Adreno
354 glClearDepthf( 1.0f ); // fixes missing graphics on Qualcomm Adreno
355 glClearColor( 0, 0, 0, 1 );
356 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
358 Android_JNI_SwapWindow(); // paulscode, fix for black-screen bug
359 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
361 OGL_UpdateDepthUpdate();
362 glEnable( GL_SCISSOR_TEST );
367 if (config.framebuffer.enable)
369 LOG(LOG_VERBOSE, "Create offscreen framebuffer. \n");
370 if (config.framebuffer.width == config.window.width && config.framebuffer.height == config.window.height)
372 LOG(LOG_WARNING, "There's no point in using a offscreen framebuffer when the window and screen dimensions are the same\n");
375 glGenFramebuffers(1, &OGL.framebuffer.fb);
376 glGenTextures(1, &OGL.framebuffer.color_buffer);
377 glBindTexture(GL_TEXTURE_2D, OGL.framebuffer.color_buffer);
378 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, config.framebuffer.width, config.framebuffer.height, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL);
379 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
380 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
381 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
382 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
383 glBindTexture(GL_TEXTURE_2D, 0);
384 glGenRenderbuffers(1, &OGL.framebuffer.depth_buffer);
385 glBindRenderbuffer(GL_RENDERBUFFER, OGL.framebuffer.depth_buffer);
386 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24_OES, config.framebuffer.width, config.framebuffer.height);
387 glBindFramebuffer(GL_FRAMEBUFFER, OGL.framebuffer.fb);
388 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, OGL.framebuffer.color_buffer, 0);
389 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, OGL.framebuffer.depth_buffer);
391 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
393 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
395 LOG(LOG_ERROR, "Incomplete Framebuffer Object: ");
396 switch(glCheckFramebufferStatus(GL_FRAMEBUFFER))
398 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
399 printf("Incomplete Attachment. \n"); break;
400 case GL_FRAMEBUFFER_UNSUPPORTED:
401 printf("Framebuffer Unsupported. \n"); break;
402 case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
403 printf("Incomplete Dimensions. \n"); break;
405 config.framebuffer.enable = 0;
406 glBindFramebuffer(GL_FRAMEBUFFER, 0);
411 if ((config.texture.maxAnisotropy>0) && !OGL_IsExtSupported("GL_EXT_texture_filter_anistropic"))
413 LOG(LOG_WARNING, "Anistropic Filtering is not supported.\n");
414 config.texture.maxAnisotropy = 0;
418 glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &f);
419 if (config.texture.maxAnisotropy > ((int)f))
421 LOG(LOG_WARNING, "Clamping max anistropy to %ix.\n", (int)f);
422 config.texture.maxAnisotropy = (int)f;
426 LOG(LOG_VERBOSE, "Width: %i Height:%i \n", config.framebuffer.width, config.framebuffer.height);
427 LOG(LOG_VERBOSE, "[gles2n64]: Enable Runfast... \n");
432 //We must have a shader bound before binding any textures:
433 ShaderCombiner_Init();
434 ShaderCombiner_Set(EncodeCombineMode(0, 0, 0, TEXEL0, 0, 0, 0, TEXEL0, 0, 0, 0, TEXEL0, 0, 0, 0, TEXEL0));
435 ShaderCombiner_Set(EncodeCombineMode(0, 0, 0, SHADE, 0, 0, 0, 1, 0, 0, 0, SHADE, 0, 0, 0, 1));
439 memset(OGL.triangles.vertices, 0, VERTBUFF_SIZE * sizeof(SPVertex));
440 memset(OGL.triangles.elements, 0, ELEMBUFF_SIZE * sizeof(GLubyte));
441 OGL.triangles.num = 0;
443 #ifdef __TRIBUFFER_OPT
447 OGL.frameSkipped = 0;
448 for(int i = 0; i < OGL_FRAMETIME_NUM; i++) OGL.frameTime[i] = 0;
450 OGL.renderingToTexture = false;
451 OGL.renderState = RS_NONE;
452 gSP.changed = gDP.changed = 0xFFFFFFFF;
461 LOG(LOG_MINIMAL, "Stopping OpenGL\n");
465 SDL_QuitSubSystem( SDL_INIT_VIDEO );
468 if (config.framebuffer.enable)
470 glDeleteFramebuffers(1, &OGL.framebuffer.fb);
471 glDeleteTextures(1, &OGL.framebuffer.color_buffer);
472 glDeleteRenderbuffers(1, &OGL.framebuffer.depth_buffer);
475 glDeleteShader(OGL.defaultFragShader);
476 glDeleteShader(OGL.defaultVertShader);
477 glDeleteProgram(OGL.defaultProgram);
479 ShaderCombiner_Destroy();
480 TextureCache_Destroy();
483 void OGL_UpdateCullFace()
485 if (config.enableFaceCulling && (gSP.geometryMode & G_CULL_BOTH))
487 glEnable( GL_CULL_FACE );
488 if ((gSP.geometryMode & G_CULL_BACK) && (gSP.geometryMode & G_CULL_FRONT))
489 glCullFace(GL_FRONT_AND_BACK);
490 else if (gSP.geometryMode & G_CULL_BACK)
493 glCullFace(GL_FRONT);
496 glDisable(GL_CULL_FACE);
499 void OGL_UpdateViewport()
502 x = config.framebuffer.xpos + (int)(gSP.viewport.x * OGL.scaleX);
503 y = config.framebuffer.ypos + (int)((VI.height - (gSP.viewport.y + gSP.viewport.height)) * OGL.scaleY);
504 w = (int)(gSP.viewport.width * OGL.scaleX);
505 h = (int)(gSP.viewport.height * OGL.scaleY);
507 glViewport(x, y, w, h);
510 void OGL_UpdateDepthUpdate()
512 if (gDP.otherMode.depthUpdate)
513 glDepthMask(GL_TRUE);
515 glDepthMask(GL_FALSE);
518 void OGL_UpdateScissor()
521 x = config.framebuffer.xpos + (int)(gDP.scissor.ulx * OGL.scaleX);
522 y = config.framebuffer.ypos + (int)((VI.height - gDP.scissor.lry) * OGL.scaleY);
523 w = (int)((gDP.scissor.lrx - gDP.scissor.ulx) * OGL.scaleX);
524 h = (int)((gDP.scissor.lry - gDP.scissor.uly) * OGL.scaleY);
525 glScissor(x, y, w, h);
528 //copied from RICE VIDEO
529 void OGL_SetBlendMode()
532 u32 blender = gDP.otherMode.l >> 16;
533 u32 blendmode_1 = blender&0xcccc;
534 u32 blendmode_2 = blender&0x3333;
537 switch(gDP.otherMode.cycleType)
544 glBlendFunc(GL_ONE, GL_ZERO);
548 if (gDP.otherMode.forceBlender && gDP.otherMode.depthCompare)
550 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
554 switch(blendmode_1+blendmode_2)
556 case BLEND_PASS+(BLEND_PASS>>2): // In * 0 + In * 1
557 case BLEND_FOG_APRIM+(BLEND_PASS>>2):
558 case BLEND_FOG_MEM_FOG_MEM + (BLEND_OPA>>2):
559 case BLEND_FOG_APRIM + (BLEND_OPA>>2):
560 case BLEND_FOG_ASHADE + (BLEND_OPA>>2):
561 case BLEND_BI_AFOG + (BLEND_OPA>>2):
562 case BLEND_FOG_ASHADE + (BLEND_NOOP>>2):
563 case BLEND_NOOP + (BLEND_OPA>>2):
564 case BLEND_NOOP4 + (BLEND_NOOP>>2):
565 case BLEND_FOG_ASHADE+(BLEND_PASS>>2):
566 case BLEND_FOG_3+(BLEND_PASS>>2):
570 case BLEND_PASS+(BLEND_OPA>>2):
571 if (gDP.otherMode.cvgXAlpha && gDP.otherMode.alphaCvgSel)
572 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
577 case BLEND_PASS + (BLEND_XLU>>2):
578 case BLEND_FOG_ASHADE + (BLEND_XLU>>2):
579 case BLEND_FOG_APRIM + (BLEND_XLU>>2):
580 case BLEND_FOG_MEM_FOG_MEM + (BLEND_PASS>>2):
581 case BLEND_XLU + (BLEND_XLU>>2):
582 case BLEND_BI_AFOG + (BLEND_XLU>>2):
583 case BLEND_XLU + (BLEND_FOG_MEM_IN_MEM>>2):
584 case BLEND_PASS + (BLEND_FOG_MEM_IN_MEM>>2):
585 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
588 case BLEND_FOG_ASHADE+0x0301:
589 glBlendFunc(GL_SRC_ALPHA, GL_ZERO);
593 glBlendFunc(GL_ZERO, GL_DST_ALPHA);
597 if (blendmode_2 == (BLEND_PASS>>2))
600 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
607 if (gDP.otherMode.forceBlender && gDP.otherMode.depthCompare && blendmode_1 != BLEND_FOG_ASHADE )
609 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
618 case BLEND_FOG_MEM_IN_MEM:
619 case BLEND_BLENDCOLOR:
621 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
624 case BLEND_MEM_ALPHA_IN:
625 glBlendFunc(GL_ZERO, GL_DST_ALPHA);
629 //if( options.enableHackForGames == HACK_FOR_MARIO_TENNIS )
631 // glBlendFunc(BLEND_SRCALPHA, BLEND_INVSRCALPHA);
639 case BLEND_FOG_ASHADE:
640 case BLEND_FOG_MEM_3:
645 case BLEND_FOG_APRIM:
646 glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_ZERO);
652 glBlendFunc(GL_ZERO, GL_ONE);
656 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
662 void OGL_UpdateStates()
664 if (gDP.otherMode.cycleType == G_CYC_COPY)
665 ShaderCombiner_Set(EncodeCombineMode(0, 0, 0, TEXEL0, 0, 0, 0, TEXEL0, 0, 0, 0, TEXEL0, 0, 0, 0, TEXEL0));
666 else if (gDP.otherMode.cycleType == G_CYC_FILL)
667 ShaderCombiner_Set(EncodeCombineMode(0, 0, 0, SHADE, 0, 0, 0, 1, 0, 0, 0, SHADE, 0, 0, 0, 1));
669 ShaderCombiner_Set(gDP.combine.mux);
672 ProgramSwaps += scProgramChanged;
675 if (gSP.changed & CHANGED_GEOMETRYMODE)
677 OGL_UpdateCullFace();
679 if (gSP.geometryMode & G_ZBUFFER)
680 glEnable(GL_DEPTH_TEST);
682 glDisable(GL_DEPTH_TEST);
686 if (gDP.changed & CHANGED_CONVERT)
688 SC_SetUniform1f(uK4, gDP.convert.k4);
689 SC_SetUniform1f(uK5, gDP.convert.k5);
692 if (gDP.changed & CHANGED_RENDERMODE || gDP.changed & CHANGED_CYCLETYPE)
694 if (gDP.otherMode.cycleType == G_CYC_1CYCLE || gDP.otherMode.cycleType == G_CYC_2CYCLE)
696 //glDepthFunc((gDP.otherMode.depthCompare) ? GL_GEQUAL : GL_ALWAYS);
697 glDepthFunc((gDP.otherMode.depthCompare) ? GL_LESS : GL_ALWAYS);
698 glDepthMask((gDP.otherMode.depthUpdate) ? GL_TRUE : GL_FALSE);
700 if (gDP.otherMode.depthMode == ZMODE_DEC)
701 glEnable(GL_POLYGON_OFFSET_FILL);
703 glDisable(GL_POLYGON_OFFSET_FILL);
707 glDepthFunc(GL_ALWAYS);
708 glDepthMask(GL_FALSE);
712 if ((gDP.changed & CHANGED_BLENDCOLOR) || (gDP.changed & CHANGED_RENDERMODE))
713 SC_SetUniform1f(uAlphaRef, (gDP.otherMode.cvgXAlpha) ? 0.5f : gDP.blendColor.a);
715 if (gDP.changed & CHANGED_SCISSOR)
718 if (gSP.changed & CHANGED_VIEWPORT)
719 OGL_UpdateViewport();
721 if (gSP.changed & CHANGED_FOGPOSITION)
723 SC_SetUniform1f(uFogMultiplier, (float) gSP.fog.multiplier / 255.0f);
724 SC_SetUniform1f(uFogOffset, (float) gSP.fog.offset / 255.0f);
727 if (gSP.changed & CHANGED_TEXTURESCALE)
729 if (scProgramCurrent->usesT0 || scProgramCurrent->usesT1)
730 SC_SetUniform2f(uTexScale, gSP.texture.scales, gSP.texture.scalet);
733 if ((gSP.changed & CHANGED_TEXTURE) || (gDP.changed & CHANGED_TILE) || (gDP.changed & CHANGED_TMEM))
735 //For some reason updating the texture cache on the first frame of LOZ:OOT causes a NULL Pointer exception...
736 if (scProgramCurrent)
738 if (scProgramCurrent->usesT0)
740 #ifdef TEXTURECACHE_TEST
741 unsigned t = ticksGetTicks();
742 TextureCache_Update(0);
743 TextureCacheTime += (ticksGetTicks() - t);
745 TextureCache_Update(0);
747 SC_ForceUniform2f(uTexOffset[0], gSP.textureTile[0]->fuls, gSP.textureTile[0]->fult);
748 SC_ForceUniform2f(uCacheShiftScale[0], cache.current[0]->shiftScaleS, cache.current[0]->shiftScaleT);
749 SC_ForceUniform2f(uCacheScale[0], cache.current[0]->scaleS, cache.current[0]->scaleT);
750 SC_ForceUniform2f(uCacheOffset[0], cache.current[0]->offsetS, cache.current[0]->offsetT);
752 //else TextureCache_ActivateDummy(0);
754 //Note: enabling dummies makes some F-zero X textures flicker.... strange.
756 if (scProgramCurrent->usesT1)
758 #ifdef TEXTURECACHE_TEST
759 unsigned t = ticksGetTicks();
760 TextureCache_Update(1);
761 TextureCacheTime += (ticksGetTicks() - t);
763 TextureCache_Update(1);
765 SC_ForceUniform2f(uTexOffset[1], gSP.textureTile[1]->fuls, gSP.textureTile[1]->fult);
766 SC_ForceUniform2f(uCacheShiftScale[1], cache.current[1]->shiftScaleS, cache.current[1]->shiftScaleT);
767 SC_ForceUniform2f(uCacheScale[1], cache.current[1]->scaleS, cache.current[1]->scaleT);
768 SC_ForceUniform2f(uCacheOffset[1], cache.current[1]->offsetS, cache.current[1]->offsetT);
770 //else TextureCache_ActivateDummy(1);
774 if ((gDP.changed & CHANGED_FOGCOLOR) && config.enableFog)
775 SC_SetUniform4fv(uFogColor, &gDP.fogColor.r );
777 if (gDP.changed & CHANGED_ENV_COLOR)
778 SC_SetUniform4fv(uEnvColor, &gDP.envColor.r);
780 if (gDP.changed & CHANGED_PRIM_COLOR)
782 SC_SetUniform4fv(uPrimColor, &gDP.primColor.r);
783 SC_SetUniform1f(uPrimLODFrac, gDP.primColor.l);
786 if ((gDP.changed & CHANGED_RENDERMODE) || (gDP.changed & CHANGED_CYCLETYPE))
788 #ifndef OLD_BLENDMODE
791 if ((gDP.otherMode.forceBlender) &&
792 (gDP.otherMode.cycleType != G_CYC_COPY) &&
793 (gDP.otherMode.cycleType != G_CYC_FILL) &&
794 !(gDP.otherMode.alphaCvgSel))
796 glEnable( GL_BLEND );
798 switch (gDP.otherMode.l >> 16)
802 glBlendFunc( GL_ONE, GL_ONE );
804 case 0x0C08: // 1080 Sky
805 case 0x0F0A: // Used LOTS of places
806 glBlendFunc( GL_ONE, GL_ZERO );
809 case 0x0040: // Fzero
810 case 0xC810: // Blends fog
811 case 0xC811: // Blends fog
812 case 0x0C18: // Standard interpolated blend
813 case 0x0C19: // Used for antialiasing
814 case 0x0050: // Standard interpolated blend
815 case 0x0055: // Used for antialiasing
816 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
819 case 0x0FA5: // Seems to be doing just blend color - maybe combiner can be used for this?
820 case 0x5055: // Used in Paper Mario intro, I'm not sure if this is right...
821 glBlendFunc( GL_ZERO, GL_ONE );
825 LOG(LOG_VERBOSE, "Unhandled blend mode=%x", gDP.otherMode.l >> 16);
826 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
832 glDisable( GL_BLEND );
835 if (gDP.otherMode.cycleType == G_CYC_FILL)
837 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
838 glEnable( GL_BLEND );
843 gDP.changed &= CHANGED_TILE | CHANGED_TMEM;
844 gSP.changed &= CHANGED_TEXTURE | CHANGED_MATRIX;
847 void OGL_DrawTriangle(SPVertex *vertices, int v0, int v1, int v2)
852 void OGL_AddTriangle(int v0, int v1, int v2)
854 OGL.triangles.elements[OGL.triangles.num++] = v0;
855 OGL.triangles.elements[OGL.triangles.num++] = v1;
856 OGL.triangles.elements[OGL.triangles.num++] = v2;
859 void OGL_SetColorArray()
861 if (scProgramCurrent->usesCol)
862 glEnableVertexAttribArray(SC_COLOR);
864 glDisableVertexAttribArray(SC_COLOR);
867 void OGL_SetTexCoordArrays()
869 if (scProgramCurrent->usesT0)
870 glEnableVertexAttribArray(SC_TEXCOORD0);
872 glDisableVertexAttribArray(SC_TEXCOORD0);
874 if (scProgramCurrent->usesT1)
875 glEnableVertexAttribArray(SC_TEXCOORD1);
877 glDisableVertexAttribArray(SC_TEXCOORD1);
880 void OGL_DrawTriangles()
882 if (OGL.renderingToTexture && config.ignoreOffscreenRendering)
884 OGL.triangles.num = 0;
888 if (OGL.triangles.num == 0) return;
890 if ((config.updateMode == SCREEN_UPDATE_AT_1ST_PRIMITIVE) && OGL.screenUpdate)
893 if (gSP.changed || gDP.changed)
896 if (OGL.renderState != RS_TRIANGLE || scProgramChanged)
899 OGL_SetTexCoordArrays();
900 glDisableVertexAttribArray(SC_TEXCOORD1);
901 SC_ForceUniform1f(uRenderState, RS_TRIANGLE);
904 if (OGL.renderState != RS_TRIANGLE)
906 #ifdef RENDERSTATE_TEST
909 glVertexAttribPointer(SC_POSITION, 4, GL_FLOAT, GL_FALSE, sizeof(SPVertex), &OGL.triangles.vertices[0].x);
910 glVertexAttribPointer(SC_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(SPVertex), &OGL.triangles.vertices[0].r);
911 glVertexAttribPointer(SC_TEXCOORD0, 2, GL_FLOAT, GL_FALSE, sizeof(SPVertex), &OGL.triangles.vertices[0].s);
913 OGL_UpdateCullFace();
914 OGL_UpdateViewport();
915 glEnable(GL_SCISSOR_TEST);
916 OGL.renderState = RS_TRIANGLE;
919 glDrawElements(GL_TRIANGLES, OGL.triangles.num, GL_UNSIGNED_BYTE, OGL.triangles.elements);
920 OGL.triangles.num = 0;
922 #ifdef __TRIBUFFER_OPT
927 void OGL_DrawLine(int v0, int v1, float width )
929 if (OGL.renderingToTexture && config.ignoreOffscreenRendering) return;
931 if ((config.updateMode == SCREEN_UPDATE_AT_1ST_PRIMITIVE) && OGL.screenUpdate)
934 if (gSP.changed || gDP.changed)
937 if (OGL.renderState != RS_LINE || scProgramChanged)
939 #ifdef RENDERSTATE_TEST
943 glDisableVertexAttribArray(SC_TEXCOORD0);
944 glDisableVertexAttribArray(SC_TEXCOORD1);
945 glVertexAttribPointer(SC_POSITION, 4, GL_FLOAT, GL_FALSE, sizeof(SPVertex), &OGL.triangles.vertices[0].x);
946 glVertexAttribPointer(SC_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(SPVertex), &OGL.triangles.vertices[0].r);
948 SC_ForceUniform1f(uRenderState, RS_LINE);
949 OGL_UpdateCullFace();
950 OGL_UpdateViewport();
951 OGL.renderState = RS_LINE;
954 unsigned short elem[2];
957 glLineWidth( width * OGL.scaleX );
958 glDrawElements(GL_LINES, 2, GL_UNSIGNED_SHORT, elem);
961 void OGL_DrawRect( int ulx, int uly, int lrx, int lry, float *color)
963 if (OGL.renderingToTexture && config.ignoreOffscreenRendering) return;
965 if ((config.updateMode == SCREEN_UPDATE_AT_1ST_PRIMITIVE) && OGL.screenUpdate)
968 if (gSP.changed || gDP.changed)
971 if (OGL.renderState != RS_RECT || scProgramChanged)
973 glDisableVertexAttribArray(SC_COLOR);
974 glDisableVertexAttribArray(SC_TEXCOORD0);
975 glDisableVertexAttribArray(SC_TEXCOORD1);
976 SC_ForceUniform1f(uRenderState, RS_RECT);
979 if (OGL.renderState != RS_RECT)
981 #ifdef RENDERSTATE_TEST
984 glVertexAttrib4f(SC_POSITION, 0, 0, gSP.viewport.nearz, 1.0);
985 glVertexAttribPointer(SC_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(GLVertex), &OGL.rect[0].x);
986 OGL.renderState = RS_RECT;
989 glViewport(config.framebuffer.xpos, config.framebuffer.ypos, config.framebuffer.width, config.framebuffer.height );
990 glDisable(GL_SCISSOR_TEST);
991 glDisable(GL_CULL_FACE);
993 OGL.rect[0].x = (float) ulx * (2.0f * VI.rwidth) - 1.0;
994 OGL.rect[0].y = (float) uly * (-2.0f * VI.rheight) + 1.0;
995 OGL.rect[1].x = (float) (lrx+1) * (2.0f * VI.rwidth) - 1.0;
996 OGL.rect[1].y = OGL.rect[0].y;
997 OGL.rect[2].x = OGL.rect[0].x;
998 OGL.rect[2].y = (float) (lry+1) * (-2.0f * VI.rheight) + 1.0;
999 OGL.rect[3].x = OGL.rect[1].x;
1000 OGL.rect[3].y = OGL.rect[2].y;
1002 glVertexAttrib4fv(SC_COLOR, color);
1003 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1004 glEnable(GL_SCISSOR_TEST);
1005 OGL_UpdateViewport();
1009 void OGL_DrawTexturedRect( float ulx, float uly, float lrx, float lry, float uls, float ult, float lrs, float lrt, bool flip )
1011 if (config.hackBanjoTooie)
1013 if (gDP.textureImage.width == gDP.colorImage.width &&
1014 gDP.textureImage.format == G_IM_FMT_CI &&
1015 gDP.textureImage.size == G_IM_SIZ_8b)
1021 if (OGL.renderingToTexture && config.ignoreOffscreenRendering) return;
1023 if ((config.updateMode == SCREEN_UPDATE_AT_1ST_PRIMITIVE) && OGL.screenUpdate)
1026 if (gSP.changed || gDP.changed)
1029 if (OGL.renderState != RS_TEXTUREDRECT || scProgramChanged)
1031 glDisableVertexAttribArray(SC_COLOR);
1032 OGL_SetTexCoordArrays();
1033 SC_ForceUniform1f(uRenderState, RS_TEXTUREDRECT);
1036 if (OGL.renderState != RS_TEXTUREDRECT)
1038 #ifdef RENDERSTATE_TEST
1041 glVertexAttrib4f(SC_COLOR, 0, 0, 0, 0);
1042 glVertexAttrib4f(SC_POSITION, 0, 0, (gDP.otherMode.depthSource == G_ZS_PRIM) ? gDP.primDepth.z : gSP.viewport.nearz, 1.0);
1043 glVertexAttribPointer(SC_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(GLVertex), &OGL.rect[0].x);
1044 glVertexAttribPointer(SC_TEXCOORD0, 2, GL_FLOAT, GL_FALSE, sizeof(GLVertex), &OGL.rect[0].s0);
1045 glVertexAttribPointer(SC_TEXCOORD1, 2, GL_FLOAT, GL_FALSE, sizeof(GLVertex), &OGL.rect[0].s1);
1046 OGL.renderState = RS_TEXTUREDRECT;
1049 glViewport(config.framebuffer.xpos, config.framebuffer.ypos, config.framebuffer.width, config.framebuffer.height);
1050 glDisable(GL_CULL_FACE);
1052 OGL.rect[0].x = (float) ulx * (2.0f * VI.rwidth) - 1.0f;
1053 OGL.rect[0].y = (float) uly * (-2.0f * VI.rheight) + 1.0f;
1054 OGL.rect[1].x = (float) (lrx) * (2.0f * VI.rwidth) - 1.0f;
1055 OGL.rect[1].y = OGL.rect[0].y;
1056 OGL.rect[2].x = OGL.rect[0].x;
1057 OGL.rect[2].y = (float) (lry) * (-2.0f * VI.rheight) + 1.0f;
1058 OGL.rect[3].x = OGL.rect[1].x;
1059 OGL.rect[3].y = OGL.rect[2].y;
1061 if (scProgramCurrent->usesT0 && cache.current[0] && gSP.textureTile[0])
1063 OGL.rect[0].s0 = uls * cache.current[0]->shiftScaleS - gSP.textureTile[0]->fuls;
1064 OGL.rect[0].t0 = ult * cache.current[0]->shiftScaleT - gSP.textureTile[0]->fult;
1065 OGL.rect[3].s0 = (lrs + 1.0f) * cache.current[0]->shiftScaleS - gSP.textureTile[0]->fuls;
1066 OGL.rect[3].t0 = (lrt + 1.0f) * cache.current[0]->shiftScaleT - gSP.textureTile[0]->fult;
1068 if ((cache.current[0]->maskS) && !(cache.current[0]->mirrorS) && (fmod( OGL.rect[0].s0, cache.current[0]->width ) == 0.0f))
1070 OGL.rect[3].s0 -= OGL.rect[0].s0;
1071 OGL.rect[0].s0 = 0.0f;
1074 if ((cache.current[0]->maskT) && !(cache.current[0]->mirrorT) && (fmod( OGL.rect[0].t0, cache.current[0]->height ) == 0.0f))
1076 OGL.rect[3].t0 -= OGL.rect[0].t0;
1077 OGL.rect[0].t0 = 0.0f;
1080 glActiveTexture( GL_TEXTURE0);
1081 if ((OGL.rect[0].s0 >= 0.0f) && (OGL.rect[3].s0 <= cache.current[0]->width))
1082 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
1084 if ((OGL.rect[0].t0 >= 0.0f) && (OGL.rect[3].t0 <= cache.current[0]->height))
1085 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
1087 OGL.rect[0].s0 *= cache.current[0]->scaleS;
1088 OGL.rect[0].t0 *= cache.current[0]->scaleT;
1089 OGL.rect[3].s0 *= cache.current[0]->scaleS;
1090 OGL.rect[3].t0 *= cache.current[0]->scaleT;
1093 if (scProgramCurrent->usesT1 && cache.current[1] && gSP.textureTile[1])
1095 OGL.rect[0].s1 = uls * cache.current[1]->shiftScaleS - gSP.textureTile[1]->fuls;
1096 OGL.rect[0].t1 = ult * cache.current[1]->shiftScaleT - gSP.textureTile[1]->fult;
1097 OGL.rect[3].s1 = (lrs + 1.0f) * cache.current[1]->shiftScaleS - gSP.textureTile[1]->fuls;
1098 OGL.rect[3].t1 = (lrt + 1.0f) * cache.current[1]->shiftScaleT - gSP.textureTile[1]->fult;
1100 if ((cache.current[1]->maskS) && (fmod( OGL.rect[0].s1, cache.current[1]->width ) == 0.0f) && !(cache.current[1]->mirrorS))
1102 OGL.rect[3].s1 -= OGL.rect[0].s1;
1103 OGL.rect[0].s1 = 0.0f;
1106 if ((cache.current[1]->maskT) && (fmod( OGL.rect[0].t1, cache.current[1]->height ) == 0.0f) && !(cache.current[1]->mirrorT))
1108 OGL.rect[3].t1 -= OGL.rect[0].t1;
1109 OGL.rect[0].t1 = 0.0f;
1112 glActiveTexture( GL_TEXTURE1);
1113 if ((OGL.rect[0].s1 == 0.0f) && (OGL.rect[3].s1 <= cache.current[1]->width))
1114 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
1116 if ((OGL.rect[0].t1 == 0.0f) && (OGL.rect[3].t1 <= cache.current[1]->height))
1117 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
1119 OGL.rect[0].s1 *= cache.current[1]->scaleS;
1120 OGL.rect[0].t1 *= cache.current[1]->scaleT;
1121 OGL.rect[3].s1 *= cache.current[1]->scaleS;
1122 OGL.rect[3].t1 *= cache.current[1]->scaleT;
1125 if ((gDP.otherMode.cycleType == G_CYC_COPY) && !config.texture.forceBilinear)
1127 glActiveTexture(GL_TEXTURE0);
1128 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
1129 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
1134 OGL.rect[1].s0 = OGL.rect[0].s0;
1135 OGL.rect[1].t0 = OGL.rect[3].t0;
1136 OGL.rect[1].s1 = OGL.rect[0].s1;
1137 OGL.rect[1].t1 = OGL.rect[3].t1;
1138 OGL.rect[2].s0 = OGL.rect[3].s0;
1139 OGL.rect[2].t0 = OGL.rect[0].t0;
1140 OGL.rect[2].s1 = OGL.rect[3].s1;
1141 OGL.rect[2].t1 = OGL.rect[0].t1;
1145 OGL.rect[1].s0 = OGL.rect[3].s0;
1146 OGL.rect[1].t0 = OGL.rect[0].t0;
1147 OGL.rect[1].s1 = OGL.rect[3].s1;
1148 OGL.rect[1].t1 = OGL.rect[0].t1;
1149 OGL.rect[2].s0 = OGL.rect[0].s0;
1150 OGL.rect[2].t0 = OGL.rect[3].t0;
1151 OGL.rect[2].s1 = OGL.rect[0].s1;
1152 OGL.rect[2].t1 = OGL.rect[3].t1;
1155 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1156 OGL_UpdateViewport();
1159 void OGL_ClearDepthBuffer()
1161 if (OGL.renderingToTexture && config.ignoreOffscreenRendering) return;
1163 if ((config.updateMode == SCREEN_UPDATE_AT_1ST_PRIMITIVE) && OGL.screenUpdate)
1166 //float depth = 1.0 - (gDP.fillColor.z / ((float)0x3FFF)); // broken on OMAP3
1167 float depth = gDP.fillColor.z ;
1169 /////// paulscode, graphics bug-fixes
1170 glDisable( GL_SCISSOR_TEST );
1171 glDepthMask( GL_TRUE ); // fixes side-bar graphics glitches
1172 // glClearDepthf( depth ); // broken on Qualcomm Adreno
1173 glClearDepthf( 1.0f ); // fixes missing graphics on Qualcomm Adreno
1174 glClearColor( 0, 0, 0, 1 );
1175 glClear( GL_DEPTH_BUFFER_BIT );
1176 OGL_UpdateDepthUpdate();
1177 glEnable( GL_SCISSOR_TEST );
1181 void OGL_ClearColorBuffer( float *color )
1183 if (OGL.renderingToTexture && config.ignoreOffscreenRendering) return;
1185 if ((config.updateMode == SCREEN_UPDATE_AT_1ST_PRIMITIVE) && OGL.screenUpdate)
1188 glScissor(config.framebuffer.xpos, config.framebuffer.ypos, config.framebuffer.width, config.framebuffer.height);
1189 glClearColor( color[0], color[1], color[2], color[3] );
1190 glClear( GL_COLOR_BUFFER_BIT );
1191 OGL_UpdateScissor();
1195 int OGL_CheckError()
1197 GLenum e = glGetError();
1198 if (e != GL_NO_ERROR)
1200 printf("GL Error: ");
1203 case GL_INVALID_ENUM: printf("INVALID ENUM"); break;
1204 case GL_INVALID_VALUE: printf("INVALID VALUE"); break;
1205 case GL_INVALID_OPERATION: printf("INVALID OPERATION"); break;
1206 case GL_OUT_OF_MEMORY: printf("OUT OF MEMORY"); break;
1214 void OGL_UpdateFrameTime()
1216 unsigned ticks = ticksGetTicks();
1217 static unsigned lastFrameTicks = 0;
1218 for(int i = OGL_FRAMETIME_NUM-1; i > 0; i--) OGL.frameTime[i] = OGL.frameTime[i-1];
1219 OGL.frameTime[0] = ticks - lastFrameTicks;
1220 lastFrameTicks = ticks;
1223 void OGL_SwapBuffers()
1225 //OGL_DrawTriangles();
1226 scProgramChanged = 0;
1228 static int frames = 0;
1229 static unsigned lastTicks = 0;
1230 unsigned ticks = ticksGetTicks();
1233 if (ticks >= (lastTicks + 1000))
1236 float fps = 1000.0f * (float) frames / (ticks - lastTicks);
1237 LOG(LOG_MINIMAL, "fps = %.2f \n", fps);
1238 LOG(LOG_MINIMAL, "skipped frame = %i of %i \n", OGL.frameSkipped, frames + OGL.frameSkipped);
1240 OGL.frameSkipped = 0;
1243 LOG(LOG_MINIMAL, "time spent in draw calls per frame = %.2f ms\n", (float)TotalDrawTime / frames);
1244 LOG(LOG_MINIMAL, "average draw calls per frame = %.0f\n", (float)TotalDrawCalls / frames);
1245 LOG(LOG_MINIMAL, "average vertices per draw call = %.2f\n", (float)TotalTriangles / TotalDrawCalls);
1252 LOG(LOG_MINIMAL, "average shader changes per frame = %f\n", (float)ProgramSwaps / frames);
1256 #ifdef TEXTURECACHE_TEST
1257 LOG(LOG_MINIMAL, "texture cache time per frame: %.2f ms\n", (float)TextureCacheTime/ frames);
1258 LOG(LOG_MINIMAL, "texture cache per frame: hits=%.2f misses=%.2f\n", (float)cache.hits / frames,
1259 (float)cache.misses / frames);
1260 cache.hits = cache.misses = 0;
1261 TextureCacheTime = 0;
1271 u32 profileTicks = ticksGetTicks();
1272 static u32 profileLastTicks = 0;
1273 if (profileTicks >= (profileLastTicks + 5000))
1275 LOG(LOG_MINIMAL, "GBI PROFILE DATA: %i ms \n", profileTicks - profileLastTicks);
1276 LOG(LOG_MINIMAL, "=========================================================\n");
1277 GBI_ProfilePrint(stdout);
1278 LOG(LOG_MINIMAL, "=========================================================\n");
1280 profileLastTicks = profileTicks;
1284 // if emulator defined a render callback function, call it before
1286 if (renderCallback) (*renderCallback)();
1288 if (config.framebuffer.enable)
1290 glBindFramebuffer(GL_FRAMEBUFFER, 0);
1291 glClearColor( 0, 0, 0, 1 );
1292 glClear( GL_COLOR_BUFFER_BIT );
1294 glUseProgram(OGL.defaultProgram);
1295 glDisable(GL_SCISSOR_TEST);
1296 glDisable(GL_DEPTH_TEST);
1297 glDisable(GL_CULL_FACE); //*SEB*
1298 glViewport(config.window.xpos, config.window.ypos, config.window.width, config.window.height);
1300 static const float vert[] =
1302 -1.0, -1.0, +0.0, +0.0,
1303 +1.0, -1.0, +1.0, +0.0,
1304 -1.0, +1.0, +0.0, +1.0,
1305 +1.0, +1.0, +1.0, +1.0
1308 glActiveTexture(GL_TEXTURE0);
1309 glBindTexture(GL_TEXTURE_2D, OGL.framebuffer.color_buffer);
1310 if (config.framebuffer.bilinear)
1312 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1313 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1317 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1318 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1321 glEnableVertexAttribArray(0);
1322 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (float*)vert);
1323 glEnableVertexAttribArray(1);
1324 glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (float*)vert + 2);
1325 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1327 Android_JNI_SwapWindow(); // paulscode, fix for black-screen bug
1329 glBindFramebuffer(GL_FRAMEBUFFER, OGL.framebuffer.fb);
1330 OGL_UpdateViewport();
1331 OGL_UpdateCullFace();
1332 if (scProgramCurrent) glUseProgram(scProgramCurrent->program);
1333 OGL.renderState = RS_NONE;
1337 Android_JNI_SwapWindow(); // paulscode, fix for black-screen bug
1340 OGL.screenUpdate = false;
1342 if (config.forceBufferClear)
1344 /////// paulscode, graphics bug-fixes
1345 float depth = gDP.fillColor.z ;
1346 glDisable( GL_SCISSOR_TEST );
1347 glDepthMask( GL_TRUE ); // fixes side-bar graphics glitches
1348 // glClearDepthf( depth ); // broken on Qualcomm Adreno
1349 glClearDepthf( 1.0f ); // fixes missing graphics on Qualcomm Adreno
1350 glClearColor( 0, 0, 0, 1 );
1351 glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT );
1352 OGL_UpdateDepthUpdate();
1353 glEnable( GL_SCISSOR_TEST );
1359 void OGL_ReadScreen( void *dest, int *width, int *height )
1362 *width = config.framebuffer.width;
1364 *height = config.framebuffer.height;
1369 glReadPixels( config.framebuffer.xpos, config.framebuffer.ypos,
1370 config.framebuffer.width, config.framebuffer.height,
1371 GL_RGBA, GL_UNSIGNED_BYTE, dest );