| 
									
										
										
										
											2008-07-12 17:40:22 +00:00
										 |  |  | // Copyright (C) 2003-2008 Dolphin Project.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // This program is free software: you can redistribute it and/or modify
 | 
					
						
							|  |  |  | // it under the terms of the GNU General Public License as published by
 | 
					
						
							|  |  |  | // the Free Software Foundation, version 2.0.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // This program is distributed in the hope that it will be useful,
 | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					
						
							|  |  |  | // GNU General Public License 2.0 for more details.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // A copy of the GPL 2.0 should have been included with the program.
 | 
					
						
							|  |  |  | // If not, see http://www.gnu.org/licenses/
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Official SVN repository and contact information can be found at
 | 
					
						
							|  |  |  | // http://code.google.com/p/dolphin-emu/
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-17 09:18:03 +00:00
										 |  |  | #include "Globals.h"
 | 
					
						
							|  |  |  | #include <list>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "GLInit.h"
 | 
					
						
							|  |  |  | #include "Render.h"
 | 
					
						
							|  |  |  | #include "OpcodeDecoding.h"
 | 
					
						
							|  |  |  | #include "BPStructs.h"
 | 
					
						
							|  |  |  | #include "TextureMngr.h"
 | 
					
						
							|  |  |  | #include "rasterfont.h"
 | 
					
						
							|  |  |  | #include "VertexShader.h"
 | 
					
						
							| 
									
										
										
										
											2008-07-17 21:09:18 +00:00
										 |  |  | #include "PixelShaderManager.h"
 | 
					
						
							| 
									
										
										
										
											2008-07-17 09:18:03 +00:00
										 |  |  | #include "VertexLoader.h"
 | 
					
						
							| 
									
										
										
										
											2008-08-14 21:34:39 +00:00
										 |  |  | #include "XFB.h"
 | 
					
						
							| 
									
										
										
										
											2008-07-17 09:18:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #ifdef _WIN32
 | 
					
						
							| 
									
										
										
										
											2008-07-23 15:20:36 +00:00
										 |  |  | #include "OS\Win32.h"
 | 
					
						
							| 
									
										
										
										
											2008-07-17 09:18:03 +00:00
										 |  |  | #else
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct MESSAGE | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     MESSAGE() {} | 
					
						
							|  |  |  |     MESSAGE(const char* p, u32 dw) { strcpy(str, p); dwTimeStamp = dw; } | 
					
						
							|  |  |  |     char str[255]; | 
					
						
							|  |  |  |     u32 dwTimeStamp; | 
					
						
							|  |  |  | };	 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | CGcontext g_cgcontext; | 
					
						
							|  |  |  | CGprofile g_cgvProf, g_cgfProf; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int g_MaxTexWidth = 0, g_MaxTexHeight = 0; | 
					
						
							|  |  |  | static RasterFont* s_pfont = NULL; | 
					
						
							|  |  |  | static std::list<MESSAGE> s_listMsgs; | 
					
						
							|  |  |  | static bool s_bFullscreen = false; | 
					
						
							|  |  |  | static bool s_bOutputCgErrors = true; | 
					
						
							|  |  |  | static int nZBufferRender = 0; // if > 0, then using zbuffer render
 | 
					
						
							|  |  |  | static u32 s_uFramebuffer = 0; | 
					
						
							|  |  |  | static u32 s_RenderTargets[1] = {0}, s_DepthTarget = 0, s_ZBufferTarget = 0; | 
					
						
							| 
									
										
										
										
											2008-08-14 21:34:39 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-17 09:18:03 +00:00
										 |  |  | static bool s_bATIDrawBuffers = false, s_bHaveStencilBuffer = false; | 
					
						
							|  |  |  | static Renderer::RenderMode s_RenderMode = Renderer::RM_Normal; | 
					
						
							|  |  |  | static int s_nCurTarget = 0; | 
					
						
							|  |  |  | bool g_bBlendLogicOp = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void HandleCgError(CGcontext ctx, CGerror err, void* appdata); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Renderer::Create2()  | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     bool bSuccess = true; | 
					
						
							|  |  |  |     GLenum err = GL_NO_ERROR; | 
					
						
							|  |  |  |     g_cgcontext = cgCreateContext(); | 
					
						
							|  |  |  |     cgGetError(); | 
					
						
							|  |  |  |     cgSetErrorHandler(HandleCgError, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // fill the opengl extension map
 | 
					
						
							|  |  |  |     const char* ptoken = (const char*)glGetString( GL_EXTENSIONS ); | 
					
						
							|  |  |  |     if (ptoken == NULL) return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     __Log("Supported OpenGL Extensions:\n"); | 
					
						
							|  |  |  |     __Log(ptoken);     // write to the log file
 | 
					
						
							|  |  |  |     __Log("\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if( strstr(ptoken, "GL_EXT_blend_logic_op") != NULL ) | 
					
						
							|  |  |  |         g_bBlendLogicOp = true; | 
					
						
							|  |  |  |     if( strstr(ptoken, "ATI_draw_buffers") != NULL ) | 
					
						
							|  |  |  |         s_bATIDrawBuffers = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     s_bFullscreen = g_Config.bFullscreen; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (glewInit() != GLEW_OK) { | 
					
						
							|  |  |  |         ERROR_LOG("glewInit() failed!\n"); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!GLEW_EXT_framebuffer_object) { | 
					
						
							|  |  |  |         ERROR_LOG("*********\nGPU: ERROR: Need GL_EXT_framebufer_object for multiple render targets\nGPU: *********\n"); | 
					
						
							|  |  |  |         bSuccess = false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     if (!GLEW_EXT_secondary_color) { | 
					
						
							|  |  |  |         ERROR_LOG("*********\nGPU: OGL ERROR: Need GL_EXT_secondary_color\nGPU: *********\n"); | 
					
						
							|  |  |  |         bSuccess = false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int numvertexattribs=0; | 
					
						
							| 
									
										
										
										
											2008-08-06 21:07:31 +00:00
										 |  |  |     glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, (GLint *)&numvertexattribs); | 
					
						
							| 
									
										
										
										
											2008-07-17 09:18:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (numvertexattribs < 11) { | 
					
						
							|  |  |  |         ERROR_LOG("*********\nGPU: OGL ERROR: Number of attributes %d not enough\nGPU: *********\n", numvertexattribs); | 
					
						
							|  |  |  |         bSuccess = false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!bSuccess) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef _WIN32
 | 
					
						
							|  |  |  |     if (WGLEW_EXT_swap_control) | 
					
						
							|  |  |  |         wglSwapIntervalEXT(0); | 
					
						
							|  |  |  |     else | 
					
						
							|  |  |  |         ERROR_LOG("no support for SwapInterval (framerate clamped to monitor refresh rate)\n"); | 
					
						
							| 
									
										
										
										
											2008-08-13 00:00:39 +00:00
										 |  |  | #else
 | 
					
						
							|  |  |  | #ifdef __linux__
 | 
					
						
							| 
									
										
										
										
											2008-07-17 09:18:03 +00:00
										 |  |  |     if (glXSwapIntervalSGI) | 
					
						
							| 
									
										
										
										
											2008-08-06 21:07:31 +00:00
										 |  |  |        glXSwapIntervalSGI(0); | 
					
						
							| 
									
										
										
										
											2008-07-17 09:18:03 +00:00
										 |  |  |     else | 
					
						
							|  |  |  |         ERROR_LOG("no support for SwapInterval (framerate clamped to monitor refresh rate)\n"); | 
					
						
							| 
									
										
										
										
											2008-08-12 23:17:29 +00:00
										 |  |  | #else
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	//TODO
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-17 09:18:03 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2008-08-13 00:00:39 +00:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2008-07-17 09:18:03 +00:00
										 |  |  |     // check the max texture width and height
 | 
					
						
							| 
									
										
										
										
											2008-08-06 21:07:31 +00:00
										 |  |  |     glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *)&g_MaxTexWidth); | 
					
						
							| 
									
										
										
										
											2008-07-17 09:18:03 +00:00
										 |  |  |     g_MaxTexHeight = g_MaxTexWidth; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     GL_REPORT_ERROR(); | 
					
						
							|  |  |  |     if (err != GL_NO_ERROR) bSuccess = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (glDrawBuffers == NULL && !GLEW_ARB_draw_buffers) | 
					
						
							|  |  |  |         glDrawBuffers = glDrawBuffersARB; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-06 21:07:31 +00:00
										 |  |  |     glGenFramebuffersEXT( 1, (GLuint *)&s_uFramebuffer); | 
					
						
							| 
									
										
										
										
											2008-07-17 09:18:03 +00:00
										 |  |  |     if (s_uFramebuffer == 0) { | 
					
						
							|  |  |  |         ERROR_LOG("failed to create the renderbuffer\n"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     _assert_( glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT ); | 
					
						
							|  |  |  |     glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, s_uFramebuffer ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // create the framebuffer targets
 | 
					
						
							| 
									
										
										
										
											2008-08-06 21:38:18 +00:00
										 |  |  |     glGenTextures(ARRAYSIZE(s_RenderTargets), (GLuint *)s_RenderTargets); | 
					
						
							| 
									
										
										
										
											2008-07-17 09:18:03 +00:00
										 |  |  |     for(int i = 0; i < ARRAYSIZE(s_RenderTargets); ++i) { | 
					
						
							|  |  |  |         glBindTexture(GL_TEXTURE_RECTANGLE_NV, s_RenderTargets[i]); | 
					
						
							|  |  |  |         // initialize to default
 | 
					
						
							|  |  |  |         glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, 4, s_nTargetWidth, s_nTargetHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); | 
					
						
							|  |  |  |         glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 
					
						
							|  |  |  |         glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 
					
						
							|  |  |  |         if( glGetError() != GL_NO_ERROR) { | 
					
						
							|  |  |  |             glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP); | 
					
						
							|  |  |  |             glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP); | 
					
						
							|  |  |  |             GL_REPORT_ERROR(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | 
					
						
							|  |  |  |         glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     s_nCurTarget = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     GL_REPORT_ERROR(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int nMaxMRT = 0; | 
					
						
							| 
									
										
										
										
											2008-08-06 21:07:31 +00:00
										 |  |  |     glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, (GLint *)&nMaxMRT); | 
					
						
							| 
									
										
										
										
											2008-07-17 09:18:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if( nMaxMRT > 1 ) { | 
					
						
							|  |  |  |         // create zbuffer target
 | 
					
						
							| 
									
										
										
										
											2008-08-06 21:07:31 +00:00
										 |  |  |         glGenTextures(1, (GLuint *)&s_ZBufferTarget); | 
					
						
							| 
									
										
										
										
											2008-07-17 09:18:03 +00:00
										 |  |  |         glBindTexture(GL_TEXTURE_RECTANGLE_NV, s_ZBufferTarget); | 
					
						
							|  |  |  |         glTexImage2D(GL_TEXTURE_RECTANGLE_NV, 0, 4, s_nTargetWidth, s_nTargetHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | 
					
						
							|  |  |  |         glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | 
					
						
							|  |  |  |         if( glGetError() != GL_NO_ERROR) { | 
					
						
							|  |  |  |             glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_S, GL_CLAMP); | 
					
						
							|  |  |  |             glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_WRAP_T, GL_CLAMP); | 
					
						
							|  |  |  |             GL_REPORT_ERROR(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | 
					
						
							|  |  |  |         glTexParameteri(GL_TEXTURE_RECTANGLE_NV, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // create the depth buffer
 | 
					
						
							| 
									
										
										
										
											2008-08-06 21:07:31 +00:00
										 |  |  |     glGenRenderbuffersEXT( 1, (GLuint *)&s_DepthTarget); | 
					
						
							| 
									
										
										
										
											2008-07-17 09:18:03 +00:00
										 |  |  |     glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, s_DepthTarget); | 
					
						
							|  |  |  |     glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, s_nTargetWidth, s_nTargetHeight); | 
					
						
							|  |  |  |     if( glGetError() != GL_NO_ERROR ) { | 
					
						
							|  |  |  |         glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, s_nTargetWidth, s_nTargetHeight); | 
					
						
							|  |  |  |         s_bHaveStencilBuffer = false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else s_bHaveStencilBuffer = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     GL_REPORT_ERROR(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // set as render targets
 | 
					
						
							|  |  |  |     glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_NV, s_RenderTargets[s_nCurTarget], 0 ); | 
					
						
							|  |  |  |     glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, s_DepthTarget ); | 
					
						
							|  |  |  |     GL_REPORT_ERROR(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if( s_ZBufferTarget != 0 ) { | 
					
						
							|  |  |  |         // test to make sure it works
 | 
					
						
							|  |  |  |         glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_NV, s_ZBufferTarget, 0); | 
					
						
							|  |  |  |         bool bFailed = glGetError() != GL_NO_ERROR || glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT; | 
					
						
							|  |  |  |         glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_NV, 0, 0); | 
					
						
							|  |  |  |              | 
					
						
							|  |  |  |         if( bFailed ) { | 
					
						
							| 
									
										
										
										
											2008-08-06 21:07:31 +00:00
										 |  |  |             glDeleteTextures(1, (GLuint *)&s_ZBufferTarget); | 
					
						
							| 
									
										
										
										
											2008-07-17 09:18:03 +00:00
										 |  |  |             s_ZBufferTarget = 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if( s_ZBufferTarget == 0 ) | 
					
						
							|  |  |  |         ERROR_LOG("disabling ztarget mrt feature (max mrt=%d)\n", nMaxMRT); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     //glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, s_DepthTarget );
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); | 
					
						
							|  |  |  |     nZBufferRender = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     GL_REPORT_ERROR(); | 
					
						
							|  |  |  |     if (err != GL_NO_ERROR) bSuccess = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     s_pfont = new RasterFont(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     SetAA(g_Config.aa); | 
					
						
							|  |  |  |     GL_REPORT_ERROR(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // load the effect, find the best profiles (if any)
 | 
					
						
							|  |  |  |     if (cgGLIsProfileSupported(CG_PROFILE_ARBVP1) != CG_TRUE) { | 
					
						
							|  |  |  |         ERROR_LOG("arbvp1 not supported\n"); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (cgGLIsProfileSupported(CG_PROFILE_ARBFP1) != CG_TRUE) { | 
					
						
							|  |  |  |         ERROR_LOG("arbfp1 not supported\n"); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     g_cgvProf = cgGLGetLatestProfile(CG_GL_VERTEX); | 
					
						
							|  |  |  |     g_cgfProf = cgGLGetLatestProfile(CG_GL_FRAGMENT);//CG_PROFILE_ARBFP1;
 | 
					
						
							|  |  |  |     //cgGLSetOptimalOptions(g_cgvProf);
 | 
					
						
							|  |  |  |     //cgGLSetOptimalOptions(g_cgfProf);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     //ERROR_LOG("max buffer sizes: %d %d\n", cgGetProgramBufferMaxSize(g_cgvProf), cgGetProgramBufferMaxSize(g_cgfProf));
 | 
					
						
							|  |  |  |     int nenvvertparams, nenvfragparams, naddrregisters[2]; | 
					
						
							| 
									
										
										
										
											2008-08-06 21:07:31 +00:00
										 |  |  |     glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, (GLint *)&nenvvertparams); | 
					
						
							|  |  |  |     glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ENV_PARAMETERS_ARB, (GLint *)&nenvfragparams); | 
					
						
							|  |  |  |     glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB, (GLint *)&naddrregisters[0]); | 
					
						
							|  |  |  |     glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB, (GLint *)&naddrregisters[1]); | 
					
						
							| 
									
										
										
										
											2008-07-17 09:18:03 +00:00
										 |  |  |     __Log("max program env parameters: vert=%d, frag=%d\n", nenvvertparams, nenvfragparams); | 
					
						
							|  |  |  |     __Log("max program address register parameters: vert=%d, frag=%d\n", naddrregisters[0], naddrregisters[1]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if( nenvvertparams < 238 ) | 
					
						
							|  |  |  |         ERROR_LOG("not enough vertex shader environment constants!!\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef _DEBUG
 | 
					
						
							|  |  |  |     cgGLSetDebugMode(GL_FALSE); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if( cgGetError() != CG_NO_ERROR ) { | 
					
						
							|  |  |  |         ERROR_LOG("cg error\n"); | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     //glEnable(GL_POLYGON_OFFSET_FILL);
 | 
					
						
							|  |  |  |     //glEnable(GL_POLYGON_OFFSET_LINE);
 | 
					
						
							|  |  |  |     //glPolygonOffset(0, 1);
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!Initialize()) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-14 21:34:39 +00:00
										 |  |  | 	XFB_Init(); | 
					
						
							| 
									
										
										
										
											2008-07-17 09:18:03 +00:00
										 |  |  |     return glGetError() == GL_NO_ERROR && bSuccess; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Renderer::Shutdown(void) | 
					
						
							|  |  |  | {     | 
					
						
							| 
									
										
										
										
											2008-08-14 21:34:39 +00:00
										 |  |  |     delete s_pfont; | 
					
						
							|  |  |  | 	s_pfont = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	XFB_Shutdown(); | 
					
						
							| 
									
										
										
										
											2008-07-17 09:18:03 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-14 21:34:39 +00:00
										 |  |  |     if (g_cgcontext != 0) { | 
					
						
							| 
									
										
										
										
											2008-07-17 09:18:03 +00:00
										 |  |  |         cgDestroyContext(g_cgcontext); | 
					
						
							|  |  |  |         g_cgcontext = 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-14 21:34:39 +00:00
										 |  |  |     if (s_RenderTargets[0]) { | 
					
						
							| 
									
										
										
										
											2008-08-06 21:38:18 +00:00
										 |  |  |         glDeleteTextures(ARRAYSIZE(s_RenderTargets), (GLuint *)s_RenderTargets); | 
					
						
							| 
									
										
										
										
											2008-07-17 09:18:03 +00:00
										 |  |  |         memset(s_RenderTargets, 0, sizeof(s_RenderTargets)); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-08-14 21:34:39 +00:00
										 |  |  |     if (s_DepthTarget) { | 
					
						
							| 
									
										
										
										
											2008-08-06 21:07:31 +00:00
										 |  |  |         glDeleteRenderbuffersEXT(1, (GLuint *)&s_DepthTarget); s_DepthTarget = 0; | 
					
						
							| 
									
										
										
										
											2008-07-17 09:18:03 +00:00
										 |  |  |     } | 
					
						
							|  |  |  |     if (s_uFramebuffer != 0) { | 
					
						
							| 
									
										
										
										
											2008-08-06 21:07:31 +00:00
										 |  |  |         glDeleteFramebuffersEXT( 1, (GLuint *)&s_uFramebuffer); | 
					
						
							| 
									
										
										
										
											2008-07-17 09:18:03 +00:00
										 |  |  |         s_uFramebuffer = 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Renderer::Initialize() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     glStencilFunc(GL_ALWAYS, 0, 0); | 
					
						
							|  |  |  |     glBlendFunc(GL_ONE, GL_ONE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     glViewport(0,0,s_nTargetWidth,s_nTargetWidth);                     // Reset The Current Viewport
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     glMatrixMode(GL_PROJECTION); | 
					
						
							|  |  |  |     glLoadIdentity(); | 
					
						
							|  |  |  |     glMatrixMode(GL_MODELVIEW); | 
					
						
							|  |  |  |     glLoadIdentity(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     glShadeModel(GL_SMOOTH); | 
					
						
							|  |  |  |     glClearColor(0.0f, 0.0f, 0.0f, 0.0f); | 
					
						
							|  |  |  |     glClearDepth(1.0f); | 
					
						
							|  |  |  |     glEnable(GL_DEPTH_TEST); | 
					
						
							|  |  |  |     glDisable(GL_LIGHTING); | 
					
						
							|  |  |  |     glDepthFunc(GL_LEQUAL); | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);  // perspective correct interpolation of colors and tex coords
 | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     // setup the default vertex declaration
 | 
					
						
							|  |  |  |     glDisable(GL_STENCIL_TEST); | 
					
						
							|  |  |  |     glEnable(GL_SCISSOR_TEST); | 
					
						
							|  |  |  |     glScissor(0,0,nBackbufferWidth,nBackbufferHeight); | 
					
						
							|  |  |  |     glBlendColorEXT(0, 0, 0, 0.5f); | 
					
						
							|  |  |  |     glClearDepth(1.0f); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     glMatrixMode(GL_PROJECTION); | 
					
						
							|  |  |  |     glLoadIdentity(); | 
					
						
							|  |  |  |     glMatrixMode(GL_MODELVIEW); | 
					
						
							|  |  |  |     glLoadIdentity(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     //Renderer::SetZBufferRender();
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // legacy multitexturing: select texture channel only
 | 
					
						
							|  |  |  |     glActiveTexture(GL_TEXTURE0); | 
					
						
							|  |  |  |     glClientActiveTexture(GL_TEXTURE0); | 
					
						
							|  |  |  |     glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     s_RenderMode = Renderer::RM_Normal; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     GLenum err = GL_NO_ERROR; | 
					
						
							|  |  |  |     GL_REPORT_ERROR(); | 
					
						
							| 
									
										
										
										
											2008-08-10 21:06:03 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-17 09:18:03 +00:00
										 |  |  |     return err == GL_NO_ERROR; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Renderer::AddMessage(const char* pstr, u32 ms) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     s_listMsgs.push_back(MESSAGE(pstr, timeGetTime()+ms)); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Renderer::ProcessMessages() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2008-08-10 21:06:03 +00:00
										 |  |  | 	GLboolean wasEnabled = glIsEnabled(GL_BLEND); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(!wasEnabled) glEnable(GL_BLEND); | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  | 	if (s_listMsgs.size() > 0) { | 
					
						
							| 
									
										
										
										
											2008-07-17 09:18:03 +00:00
										 |  |  |         int left = 25, top = 15; | 
					
						
							|  |  |  |         list<MESSAGE>::iterator it = s_listMsgs.begin(); | 
					
						
							|  |  |  |          | 
					
						
							| 
									
										
										
										
											2008-08-08 22:04:02 +00:00
										 |  |  |         while( it != s_listMsgs.end() )  | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2008-08-10 21:06:03 +00:00
										 |  |  | 			int time_left = (int)(it->dwTimeStamp - timeGetTime()); | 
					
						
							|  |  |  | 			int alpha = 255; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if(time_left<1024) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				alpha=time_left>>2; | 
					
						
							|  |  |  | 				if(time_left<0) alpha=0; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			alpha<<=24; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             RenderText(it->str, left+1, top+1, 0x000000|alpha); | 
					
						
							|  |  |  |             RenderText(it->str, left, top, 0xffff30|alpha); | 
					
						
							| 
									
										
										
										
											2008-07-17 09:18:03 +00:00
										 |  |  |             top += 15; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-10 21:06:03 +00:00
										 |  |  |             if (time_left <= 0) | 
					
						
							| 
									
										
										
										
											2008-07-17 09:18:03 +00:00
										 |  |  |                 it = s_listMsgs.erase(it); | 
					
						
							|  |  |  |             else ++it; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-08-10 21:06:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if(!wasEnabled) glDisable(GL_BLEND); | 
					
						
							| 
									
										
										
										
											2008-07-17 09:18:03 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-10 21:06:03 +00:00
										 |  |  | void Renderer::RenderText(const char* pstr, int left, int top, u32 color) | 
					
						
							| 
									
										
										
										
											2008-07-17 09:18:03 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2008-08-10 21:06:03 +00:00
										 |  |  |     glColor4f( | 
					
						
							|  |  |  | 		((color>>16) & 0xff)/255.0f, | 
					
						
							|  |  |  | 		((color>> 8) & 0xff)/255.0f, | 
					
						
							|  |  |  | 		((color>> 0) & 0xff)/255.0f, | 
					
						
							|  |  |  | 		((color>>24) & 0xFF)/255.0f | 
					
						
							|  |  |  | 		); | 
					
						
							| 
									
										
										
										
											2008-08-09 09:16:59 +00:00
										 |  |  |     s_pfont->printMultilineText(pstr, left * 2.0f / (float)nBackbufferWidth - 1, 1 - top * 2.0f / (float)nBackbufferHeight,0,nBackbufferWidth,nBackbufferHeight); | 
					
						
							| 
									
										
										
										
											2008-07-17 09:18:03 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Renderer::SetAA(int aa) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Renderer::ReinitView(int nNewWidth, int nNewHeight) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int oldscreen = s_bFullscreen; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	OpenGL_Shutdown(); | 
					
						
							|  |  |  |     int oldwidth = nBackbufferWidth, oldheight = nBackbufferHeight; | 
					
						
							|  |  |  |     if (!OpenGL_Create(g_VideoInitialize, nNewWidth, nNewHeight)) {//nNewWidth&~7, nNewHeight&~7) ) {
 | 
					
						
							|  |  |  |         ERROR_LOG("Failed to recreate, reverting to old settings\n"); | 
					
						
							|  |  |  |         if (!OpenGL_Create(g_VideoInitialize, oldwidth, oldheight)) { | 
					
						
							|  |  |  |             SysMessage("Failed to revert, exiting...\n"); | 
					
						
							|  |  |  | 			// TODO - don't takedown the entire emu
 | 
					
						
							|  |  |  |             exit(0); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 	OpenGL_MakeCurrent(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (oldscreen && !g_Config.bFullscreen) { // if transitioning from full screen
 | 
					
						
							|  |  |  | #ifdef _WIN32
 | 
					
						
							|  |  |  |         RECT rc; | 
					
						
							|  |  |  |         rc.left = 0; rc.top = 0; | 
					
						
							|  |  |  |         rc.right = nNewWidth; rc.bottom = nNewHeight; | 
					
						
							|  |  |  |         AdjustWindowRect(&rc, EmuWindow::g_winstyle, FALSE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         RECT rcdesktop; | 
					
						
							|  |  |  |         GetWindowRect(GetDesktopWindow(), &rcdesktop); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         SetWindowLong( EmuWindow::GetWnd(), GWL_STYLE, EmuWindow::g_winstyle ); | 
					
						
							|  |  |  |         SetWindowPos(EmuWindow::GetWnd(), HWND_TOP, ((rcdesktop.right-rcdesktop.left)-(rc.right-rc.left))/2, | 
					
						
							|  |  |  |             ((rcdesktop.bottom-rcdesktop.top)-(rc.bottom-rc.top))/2, | 
					
						
							|  |  |  |             rc.right-rc.left, rc.bottom-rc.top, SWP_SHOWWINDOW); | 
					
						
							|  |  |  |         UpdateWindow(EmuWindow::GetWnd()); | 
					
						
							|  |  |  | #else // linux
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     nBackbufferWidth = nNewWidth > 16 ? nNewWidth : 16; | 
					
						
							|  |  |  |     nBackbufferHeight = nNewHeight > 16 ? nNewHeight : 16; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int Renderer::GetTargetWidth() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return s_nTargetWidth; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Renderer::CanBlendLogicOp() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return g_bBlendLogicOp; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int Renderer::GetTargetHeight() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return s_nTargetHeight; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Renderer::SetRenderTarget(u32 targ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_NV, targ!=0?targ:s_RenderTargets[s_nCurTarget], 0 ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Renderer::SetDepthTarget(u32 targ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     glFramebufferRenderbufferEXT( GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, targ != 0 ? targ : s_DepthTarget ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Renderer::SetFramebuffer(u32 fb) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fb != 0 ? fb : s_uFramebuffer ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | u32 Renderer::GetRenderTarget() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return s_RenderTargets[s_nCurTarget]; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Renderer::ResetGLState() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     glDisable(GL_SCISSOR_TEST); | 
					
						
							|  |  |  |     glDisable(GL_DEPTH_TEST); | 
					
						
							|  |  |  |     glDisable(GL_CULL_FACE); | 
					
						
							|  |  |  |     glDisable(GL_BLEND); | 
					
						
							|  |  |  |     glDepthMask(GL_FALSE); | 
					
						
							|  |  |  |     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     glDisable( GL_VERTEX_PROGRAM_ARB ); | 
					
						
							|  |  |  |     glDisable( GL_FRAGMENT_PROGRAM_ARB ); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Renderer::RestoreGLState() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     glEnable(GL_SCISSOR_TEST); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (bpmem.genMode.cullmode>0) glEnable(GL_CULL_FACE); | 
					
						
							|  |  |  |     if (bpmem.zmode.testenable) glEnable(GL_DEPTH_TEST); | 
					
						
							|  |  |  |     if (bpmem.blendmode.blendenable) glEnable(GL_BLEND); | 
					
						
							|  |  |  |     if(bpmem.zmode.updateenable) glDepthMask(GL_TRUE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     glEnable( GL_VERTEX_PROGRAM_ARB ); | 
					
						
							|  |  |  |     glEnable( GL_FRAGMENT_PROGRAM_ARB ); | 
					
						
							|  |  |  |     SetColorMask(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Renderer::IsUsingATIDrawBuffers() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return s_bATIDrawBuffers; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Renderer::HaveStencilBuffer() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return s_bHaveStencilBuffer; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Renderer::SetZBufferRender() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     nZBufferRender = 10; // give it 10 frames
 | 
					
						
							|  |  |  |     GLenum s_drawbuffers[2] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT}; | 
					
						
							|  |  |  |     glDrawBuffers(2, s_drawbuffers); | 
					
						
							|  |  |  |     glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_NV, s_ZBufferTarget, 0); | 
					
						
							|  |  |  |     _assert_(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Renderer::FlushZBufferAlphaToTarget() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ResetGLState(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     SetRenderTarget(0); | 
					
						
							|  |  |  |     glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); | 
					
						
							|  |  |  |     glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     glViewport(0, 0, GetTargetWidth()<<g_AAx, GetTargetHeight()<<g_AAy); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // texture map s_RenderTargets[s_curtarget] onto the main buffer
 | 
					
						
							|  |  |  |     glActiveTexture(GL_TEXTURE0); | 
					
						
							|  |  |  |     glBindTexture(GL_TEXTURE_RECTANGLE_NV, s_ZBufferTarget); | 
					
						
							|  |  |  |     TextureMngr::EnableTexRECT(0); | 
					
						
							|  |  |  |     // disable all other stages
 | 
					
						
							|  |  |  |     for(int i = 1; i < 8; ++i) TextureMngr::DisableStage(i); | 
					
						
							|  |  |  |     GL_REPORT_ERRORD(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // setup the stencil to only accept pixels that have been written
 | 
					
						
							|  |  |  |     glStencilFunc(GL_EQUAL, 1, 0xff); | 
					
						
							|  |  |  |     glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     glBegin(GL_QUADS); | 
					
						
							|  |  |  |     glTexCoord2f(0, 0); glVertex2f(-1,-1); | 
					
						
							|  |  |  |     glTexCoord2f(0, (float)(GetTargetHeight()<<g_AAy)); glVertex2f(-1,1); | 
					
						
							| 
									
										
										
										
											2008-08-14 21:34:39 +00:00
										 |  |  |     glTexCoord2f((float)(GetTargetWidth()<<g_AAx), (float)(GetTargetHeight()<<g_AAy)); glVertex2f(1,1); | 
					
						
							| 
									
										
										
										
											2008-07-17 09:18:03 +00:00
										 |  |  |     glTexCoord2f((float)(GetTargetWidth()<<g_AAx), 0); glVertex2f(1,-1); | 
					
						
							|  |  |  |     glEnd(); | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     GL_REPORT_ERRORD(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     glBindTexture(GL_TEXTURE_RECTANGLE_NV, 0); | 
					
						
							|  |  |  |     RestoreGLState(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Renderer::SetRenderMode(RenderMode mode) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if( !s_bHaveStencilBuffer && mode == RM_ZBufferAlpha ) | 
					
						
							|  |  |  |         mode = RM_ZBufferOnly; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if( s_RenderMode == mode ) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if( mode == RM_Normal ) { | 
					
						
							|  |  |  |         // flush buffers
 | 
					
						
							|  |  |  |         if( s_RenderMode == RM_ZBufferAlpha ) { | 
					
						
							|  |  |  |             FlushZBufferAlphaToTarget(); | 
					
						
							|  |  |  |             glDisable(GL_STENCIL_TEST); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         SetColorMask(); | 
					
						
							|  |  |  |         SetRenderTarget(0); | 
					
						
							|  |  |  |         SetZBufferRender(); | 
					
						
							|  |  |  |         GL_REPORT_ERRORD(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if( s_RenderMode == RM_Normal ) { | 
					
						
							|  |  |  |         // setup buffers
 | 
					
						
							|  |  |  |         _assert_(GetZBufferTarget() && bpmem.zmode.updateenable); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if( mode == RM_ZBufferAlpha ) { | 
					
						
							|  |  |  |             glEnable(GL_STENCIL_TEST); | 
					
						
							|  |  |  |             glClearStencil(0); | 
					
						
							|  |  |  |             glClear(GL_STENCIL_BUFFER_BIT); | 
					
						
							|  |  |  |             glStencilFunc(GL_ALWAYS, 1, 0xff); | 
					
						
							|  |  |  |             glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); | 
					
						
							|  |  |  |         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); | 
					
						
							|  |  |  |         GL_REPORT_ERRORD(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |         _assert_(GetZBufferTarget()); | 
					
						
							|  |  |  |         _assert_(s_bHaveStencilBuffer); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if( mode == RM_ZBufferOnly ) { | 
					
						
							|  |  |  |             // flush and remove stencil
 | 
					
						
							|  |  |  |             _assert_(s_RenderMode==RM_ZBufferAlpha); | 
					
						
							|  |  |  |             FlushZBufferAlphaToTarget(); | 
					
						
							|  |  |  |             glDisable(GL_STENCIL_TEST); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             SetRenderTarget(s_ZBufferTarget); | 
					
						
							|  |  |  |             glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); | 
					
						
							|  |  |  |             GL_REPORT_ERRORD(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else { | 
					
						
							|  |  |  |             _assert_(mode == RM_ZBufferAlpha&&s_RenderMode==RM_ZBufferOnly); | 
					
						
							|  |  |  |              | 
					
						
							|  |  |  |             // setup stencil
 | 
					
						
							|  |  |  |             glEnable(GL_STENCIL_TEST); | 
					
						
							|  |  |  |             glClearStencil(0); | 
					
						
							|  |  |  |             glClear(GL_STENCIL_BUFFER_BIT); | 
					
						
							|  |  |  |             glStencilFunc(GL_ALWAYS, 1, 0xff); | 
					
						
							|  |  |  |             glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     s_RenderMode = mode; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Renderer::RenderMode Renderer::GetRenderMode() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return s_RenderMode; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | u32 Renderer::GetZBufferTarget() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     return nZBufferRender > 0 ? s_ZBufferTarget : 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Renderer::Swap(const TRectangle& rc) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     OpenGL_Update(); // just updates the render window position and the backbuffer size
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     DVProfileFunc _pf("Renderer::Swap"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Renderer::SetRenderMode(Renderer::RM_Normal); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // render to the real buffer now 
 | 
					
						
							|  |  |  |     glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 ); // switch to the backbuffer
 | 
					
						
							|  |  |  |     glViewport(0, 0, nBackbufferWidth, nBackbufferHeight); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ResetGLState(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // texture map s_RenderTargets[s_curtarget] onto the main buffer
 | 
					
						
							|  |  |  |     glActiveTexture(GL_TEXTURE0); | 
					
						
							|  |  |  |     glBindTexture(GL_TEXTURE_RECTANGLE_NV, s_RenderTargets[s_nCurTarget]); | 
					
						
							|  |  |  |     TextureMngr::EnableTexRECT(0); | 
					
						
							|  |  |  |     // disable all other stages
 | 
					
						
							|  |  |  |     for(int i = 1; i < 8; ++i) TextureMngr::DisableStage(i); | 
					
						
							|  |  |  |     GL_REPORT_ERRORD(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     float FactorW  = (float)s_nTargetWidth / (float)nBackbufferWidth; | 
					
						
							|  |  |  |     float FactorH  = (float)s_nTargetHeight / (float)nBackbufferHeight; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     float Max = (FactorW < FactorH) ? FactorH : FactorW; | 
					
						
							|  |  |  |     float Temp = 1 / Max; | 
					
						
							|  |  |  |     FactorW *= Temp; | 
					
						
							|  |  |  |     FactorH *= Temp; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     glBegin(GL_QUADS); | 
					
						
							|  |  |  |     glTexCoord2f(0, 0);                                             glVertex2f(-FactorW,-FactorH); | 
					
						
							|  |  |  |     glTexCoord2f(0, (float)s_nTargetHeight);                        glVertex2f(-FactorW,FactorH); | 
					
						
							|  |  |  |     glTexCoord2f((float)s_nTargetWidth, (float)s_nTargetHeight);    glVertex2f(FactorW,FactorH); | 
					
						
							|  |  |  |     glTexCoord2f((float)s_nTargetWidth, 0);                         glVertex2f(FactorW,-FactorH); | 
					
						
							|  |  |  |     glEnd(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     glBindTexture(GL_TEXTURE_RECTANGLE_NV, 0); | 
					
						
							|  |  |  |     TextureMngr::DisableStage(0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //    static int fpscount = 0;
 | 
					
						
							|  |  |  | //    static float s_fps = 0;
 | 
					
						
							|  |  |  | //    static u32 lasttime = timeGetTime();
 | 
					
						
							|  |  |  | //    
 | 
					
						
							|  |  |  | //    if( ++fpscount >= 16 ) {
 | 
					
						
							|  |  |  | //        s_fps = 16*1000.0f/(float)(timeGetTime() - lasttime);
 | 
					
						
							|  |  |  | //        lasttime = timeGetTime();
 | 
					
						
							|  |  |  | //        fpscount = 0;
 | 
					
						
							|  |  |  | //    }
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | //    char strfps[25];
 | 
					
						
							|  |  |  | //    sprintf(strfps, "fps: %2.1f\n", s_fps);
 | 
					
						
							| 
									
										
										
										
											2008-08-10 21:06:03 +00:00
										 |  |  | //    Renderer::RenderText(strfps, 20, 20, 0xFF00FFFF);
 | 
					
						
							| 
									
										
										
										
											2008-07-17 09:18:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (g_Config.bOverlayStats) { | 
					
						
							|  |  |  |         char st[2048]; | 
					
						
							|  |  |  |         char *p = st; | 
					
						
							|  |  |  |         p+=sprintf(p,"Num textures created: %i\n",stats.numTexturesCreated); | 
					
						
							| 
									
										
										
										
											2008-08-08 22:17:03 +00:00
										 |  |  |         p+=sprintf(p,"Num textures alive:   %i\n",stats.numTexturesAlive); | 
					
						
							| 
									
										
										
										
											2008-07-17 09:18:03 +00:00
										 |  |  |         p+=sprintf(p,"Num pshaders created: %i\n",stats.numPixelShadersCreated); | 
					
						
							| 
									
										
										
										
											2008-08-08 22:17:03 +00:00
										 |  |  |         p+=sprintf(p,"Num pshaders alive:   %i\n",stats.numPixelShadersAlive); | 
					
						
							| 
									
										
										
										
											2008-07-17 09:18:03 +00:00
										 |  |  |         p+=sprintf(p,"Num vshaders created: %i\n",stats.numVertexShadersCreated); | 
					
						
							| 
									
										
										
										
											2008-08-08 22:17:03 +00:00
										 |  |  |         p+=sprintf(p,"Num vshaders alive:   %i\n",stats.numVertexShadersAlive); | 
					
						
							| 
									
										
										
										
											2008-08-08 23:39:48 +00:00
										 |  |  |         p+=sprintf(p,"Num dlists called:         %i\n",stats.numDListsCalled); | 
					
						
							|  |  |  |         p+=sprintf(p,"Num dlists called (frame): %i\n",stats.thisFrame.numDListsCalled); | 
					
						
							| 
									
										
										
										
											2008-08-08 23:22:27 +00:00
										 |  |  | 		// not used.
 | 
					
						
							|  |  |  |         //p+=sprintf(p,"Num dlists created:  %i\n",stats.numDListsCreated);
 | 
					
						
							|  |  |  |         //p+=sprintf(p,"Num dlists alive:    %i\n",stats.numDListsAlive);
 | 
					
						
							|  |  |  |         //p+=sprintf(p,"Num strip joins:     %i\n",stats.numJoins);
 | 
					
						
							|  |  |  |         p+=sprintf(p,"Num primitives:       %i\n",stats.thisFrame.numPrims); | 
					
						
							|  |  |  |         p+=sprintf(p,"Num primitives (DL):  %i\n",stats.thisFrame.numDLPrims); | 
					
						
							|  |  |  |         p+=sprintf(p,"Num bad commands:     %i%s\n",stats.thisFrame.numBadCommands,stats.thisFrame.numBadCommands?"!!!":""); | 
					
						
							| 
									
										
										
										
											2008-08-08 23:32:29 +00:00
										 |  |  |         p+=sprintf(p,"Num XF loads:      %i\n",stats.thisFrame.numXFLoads); | 
					
						
							|  |  |  |         p+=sprintf(p,"Num XF loads (DL): %i\n",stats.thisFrame.numXFLoadsInDL); | 
					
						
							|  |  |  |         p+=sprintf(p,"Num CP loads:      %i\n",stats.thisFrame.numCPLoads); | 
					
						
							|  |  |  |         p+=sprintf(p,"Num CP loads (DL): %i\n",stats.thisFrame.numCPLoadsInDL); | 
					
						
							|  |  |  |         p+=sprintf(p,"Num BP loads:      %i\n",stats.thisFrame.numBPLoads); | 
					
						
							|  |  |  |         p+=sprintf(p,"Num BP loads (DL): %i\n",stats.thisFrame.numBPLoadsInDL); | 
					
						
							| 
									
										
										
										
											2008-08-08 23:22:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-10 21:06:03 +00:00
										 |  |  | 		Renderer::RenderText(st, 20, 20, 0xFF00FFFF); | 
					
						
							| 
									
										
										
										
											2008-07-17 09:18:03 +00:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-10 21:06:03 +00:00
										 |  |  | 	Renderer::ProcessMessages(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-17 09:18:03 +00:00
										 |  |  | #if defined(DVPROFILE)
 | 
					
						
							|  |  |  |     if (g_bWriteProfile) { | 
					
						
							|  |  |  |         //g_bWriteProfile = 0;
 | 
					
						
							|  |  |  |         static int framenum = 0; | 
					
						
							|  |  |  |         const int UPDATE_FRAMES = 8; | 
					
						
							|  |  |  |         if (++framenum >= UPDATE_FRAMES) { | 
					
						
							|  |  |  |             DVProfWrite("prof.txt", UPDATE_FRAMES); | 
					
						
							|  |  |  |             DVProfClear(); | 
					
						
							|  |  |  |             framenum = 0; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // copy the rendered from to the real window
 | 
					
						
							|  |  |  | 	OpenGL_SwapBuffers(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-10 21:06:03 +00:00
										 |  |  | 	glClearColor(0,0,0,0); | 
					
						
							|  |  |  | 	glClear(GL_COLOR_BUFFER_BIT); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-07-17 09:18:03 +00:00
										 |  |  |     GL_REPORT_ERRORD(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     //clean out old stuff from caches
 | 
					
						
							|  |  |  |     frameCount++; | 
					
						
							|  |  |  |     PixelShaderMngr::Cleanup(); | 
					
						
							|  |  |  |     TextureMngr::Cleanup(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // New frame
 | 
					
						
							|  |  |  |     stats.ResetFrame(); | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, s_uFramebuffer ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //    s_nCurTarget = !s_nCurTarget;
 | 
					
						
							|  |  |  | //    SetRenderTarget(0);
 | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     if( nZBufferRender > 0 ) { | 
					
						
							|  |  |  |         if( --nZBufferRender == 0 ) { | 
					
						
							|  |  |  |             // turn off
 | 
					
						
							|  |  |  |             nZBufferRender = 0; | 
					
						
							|  |  |  |             glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); | 
					
						
							|  |  |  |             glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_NV, 0, 0); | 
					
						
							|  |  |  |             Renderer::SetRenderMode(RM_Normal); // turn off any zwrites
 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     RestoreGLState(); | 
					
						
							|  |  |  |     GL_REPORT_ERRORD(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     g_Config.iSaveTargetId = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // for testing zbuffer targets
 | 
					
						
							|  |  |  |     //Renderer::SetZBufferRender();
 | 
					
						
							|  |  |  |     //SaveTexture("tex.tga", GL_TEXTURE_RECTANGLE_NV, s_ZBufferTarget, GetTargetWidth(), GetTargetHeight());
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool Renderer::SaveRenderTarget(const char* filename, int jpeg) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     bool bflip = true; | 
					
						
							|  |  |  |     vector<u32> data(s_nTargetWidth*s_nTargetHeight); | 
					
						
							|  |  |  |     glReadPixels(0, 0, s_nTargetWidth, s_nTargetHeight, GL_BGRA, GL_UNSIGNED_BYTE, &data[0]); | 
					
						
							|  |  |  |     if (glGetError() != GL_NO_ERROR) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (bflip) { | 
					
						
							|  |  |  |         // swap scanlines
 | 
					
						
							|  |  |  |         vector<u32> scanline(s_nTargetWidth); | 
					
						
							|  |  |  |         for(u32 i = 0; i < s_nTargetHeight/2; ++i) { | 
					
						
							|  |  |  |             memcpy(&scanline[0], &data[i*s_nTargetWidth], s_nTargetWidth*4); | 
					
						
							|  |  |  |             memcpy(&data[i*s_nTargetWidth], &data[(s_nTargetHeight-i-1)*s_nTargetWidth], s_nTargetWidth*4); | 
					
						
							|  |  |  |             memcpy(&data[(s_nTargetHeight-i-1)*s_nTargetWidth], &scanline[0], s_nTargetWidth*4); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (jpeg) return SaveJPEG(filename, s_nTargetWidth, s_nTargetHeight, &data[0], 70); | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     return SaveTGA(filename, s_nTargetWidth, s_nTargetHeight, &data[0]); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void Renderer::SetCgErrorOutput(bool bOutput) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     s_bOutputCgErrors = bOutput; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void HandleGLError() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const GLubyte* pstr = glGetString(GL_PROGRAM_ERROR_STRING_ARB); | 
					
						
							|  |  |  |     if (pstr != NULL && pstr[0] != 0 ) { | 
					
						
							|  |  |  |         GLint loc=0; | 
					
						
							|  |  |  |         glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &loc); | 
					
						
							|  |  |  |         ERROR_LOG("program error at %d: ", loc); | 
					
						
							|  |  |  |         ERROR_LOG((char*)pstr); | 
					
						
							|  |  |  |         ERROR_LOG("\n"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // check the error status of this framebuffer */
 | 
					
						
							|  |  |  |     GLenum error = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // if error != GL_FRAMEBUFFER_COMPLETE_EXT, there's an error of some sort 
 | 
					
						
							|  |  |  |     if (error != 0) { | 
					
						
							|  |  |  |         int w, h; | 
					
						
							|  |  |  |         GLint fmt; | 
					
						
							|  |  |  |         glGetRenderbufferParameterivEXT(GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_INTERNAL_FORMAT_EXT, &fmt); | 
					
						
							| 
									
										
										
										
											2008-08-06 21:07:31 +00:00
										 |  |  |         glGetRenderbufferParameterivEXT(GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_WIDTH_EXT, (GLint *)&w); | 
					
						
							|  |  |  |         glGetRenderbufferParameterivEXT(GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_HEIGHT_EXT, (GLint *)&h); | 
					
						
							| 
									
										
										
										
											2008-07-17 09:18:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         switch(error) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             case GL_FRAMEBUFFER_COMPLETE_EXT: | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: | 
					
						
							|  |  |  |                 ERROR_LOG("Error! missing a required image/buffer attachment!\n"); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: | 
					
						
							|  |  |  |                 ERROR_LOG("Error! has no images/buffers attached!\n"); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  | //            case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT:
 | 
					
						
							|  |  |  | //                ERROR_LOG("Error! has an image/buffer attached in multiple locations!\n");
 | 
					
						
							|  |  |  | //                break;
 | 
					
						
							|  |  |  |             case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: | 
					
						
							|  |  |  |                 ERROR_LOG("Error! has mismatched image/buffer dimensions!\n"); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: | 
					
						
							|  |  |  |                 ERROR_LOG("Error! colorbuffer attachments have different types!\n"); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: | 
					
						
							|  |  |  |                 ERROR_LOG("Error! trying to draw to non-attached color buffer!\n"); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: | 
					
						
							|  |  |  |                 ERROR_LOG("Error! trying to read from a non-attached color buffer!\n"); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case GL_FRAMEBUFFER_UNSUPPORTED_EXT: | 
					
						
							|  |  |  |                 ERROR_LOG("Error! format is not supported by current graphics card/driver!\n"); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  |                 ERROR_LOG("*UNKNOWN ERROR* reported from glCheckFramebufferStatusEXT()!\n"); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void HandleCgError(CGcontext ctx, CGerror err, void* appdata) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if( s_bOutputCgErrors ) { | 
					
						
							|  |  |  |         ERROR_LOG("Cg error: %s\n", cgGetErrorString(err)); | 
					
						
							|  |  |  |         const char* listing = cgGetLastListing(g_cgcontext); | 
					
						
							|  |  |  |         if (listing != NULL) { | 
					
						
							|  |  |  |             ERROR_LOG("    last listing: %s\n", listing); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     //    glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &loc);
 | 
					
						
							|  |  |  |     //    printf("pos: %d\n", loc);
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } |