1 /*
2 	Copyright (C) 2006 yopyop
3 	Copyright (C) 2006-2007 shash
4 	Copyright (C) 2008-2016 DeSmuME team
5 
6 	This file is free software: you can redistribute it and/or modify
7 	it under the terms of the GNU General Public License as published by
8 	the Free Software Foundation, either version 2 of the License, or
9 	(at your option) any later version.
10 
11 	This file is distributed in the hope that it will be useful,
12 	but WITHOUT ANY WARRANTY; without even the implied warranty of
13 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 	GNU General Public License for more details.
15 
16 	You should have received a copy of the GNU General Public License
17 	along with the this software.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include "OGLRender.h"
21 
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <algorithm>
26 
27 #include "common.h"
28 #include "debug.h"
29 #include "gfx3d.h"
30 #include "NDSSystem.h"
31 #include "texcache.h"
32 
33 #ifdef ENABLE_SSE2
34 #include <emmintrin.h>
35 #endif
36 
37 #ifdef ENABLE_SSSE3
38 #include <tmmintrin.h>
39 #endif
40 
41 typedef struct
42 {
43 	unsigned int major;
44 	unsigned int minor;
45 	unsigned int revision;
46 } OGLVersion;
47 
48 static OGLVersion _OGLDriverVersion = {0, 0, 0};
49 
50 // Lookup Tables
51 static CACHE_ALIGN GLfloat material_8bit_to_float[256] = {0};
52 CACHE_ALIGN const GLfloat divide5bitBy31_LUT[32]	= {0.0, 0.03225806451613, 0.06451612903226, 0.09677419354839,
53 													   0.1290322580645, 0.1612903225806, 0.1935483870968, 0.2258064516129,
54 													   0.2580645161290, 0.2903225806452, 0.3225806451613, 0.3548387096774,
55 													   0.3870967741935, 0.4193548387097, 0.4516129032258, 0.4838709677419,
56 													   0.5161290322581, 0.5483870967742, 0.5806451612903, 0.6129032258065,
57 													   0.6451612903226, 0.6774193548387, 0.7096774193548, 0.7419354838710,
58 													   0.7741935483871, 0.8064516129032, 0.8387096774194, 0.8709677419355,
59 													   0.9032258064516, 0.9354838709677, 0.9677419354839, 1.0};
60 
61 const GLfloat PostprocessVtxBuffer[16]	= {-1.0f, -1.0f,  1.0f, -1.0f,  1.0f,  1.0f, -1.0f,  1.0f,
62 										    0.0f,  0.0f,  1.0f,  0.0f,  1.0f,  1.0f,  0.0f,  1.0f};
63 const GLubyte PostprocessElementBuffer[6] = {0, 1, 2, 2, 3, 0};
64 
65 const GLenum RenderDrawList[4] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_COLOR_ATTACHMENT3_EXT};
66 
BEGINGL()67 bool BEGINGL()
68 {
69 	if(oglrender_beginOpenGL)
70 		return oglrender_beginOpenGL();
71 	else return true;
72 }
73 
ENDGL()74 void ENDGL()
75 {
76 	if(oglrender_endOpenGL)
77 		oglrender_endOpenGL();
78 }
79 
80 // Function Pointers
81 bool (*oglrender_init)() = NULL;
82 bool (*oglrender_beginOpenGL)() = NULL;
83 void (*oglrender_endOpenGL)() = NULL;
84 bool (*oglrender_framebufferDidResizeCallback)(size_t w, size_t h) = NULL;
85 void (*OGLLoadEntryPoints_3_2_Func)() = NULL;
86 void (*OGLCreateRenderer_3_2_Func)(OpenGLRenderer **rendererPtr) = NULL;
87 
OGLLoadEntryPoints_Legacy()88 static void OGLLoadEntryPoints_Legacy()
89 {
90 }
91 
92 // Vertex Shader GLSL 1.00
93 static const char *vertexShader_100 = {"\
94 	attribute vec4 inPosition; \n\
95 	attribute vec2 inTexCoord0; \n\
96 	attribute vec3 inColor; \n\
97 	\n\
98 	uniform float polyAlpha; \n\
99 	uniform vec2 polyTexScale; \n\
100 	\n\
101 	varying vec4 vtxPosition; \n\
102 	varying vec2 vtxTexCoord; \n\
103 	varying vec4 vtxColor; \n\
104 	\n\
105 	void main() \n\
106 	{ \n\
107 		mat2 texScaleMtx	= mat2(	vec2(polyTexScale.x,            0.0), \n\
108 									vec2(           0.0, polyTexScale.y)); \n\
109 		\n\
110 		vtxPosition = inPosition; \n\
111 		vtxTexCoord = texScaleMtx * inTexCoord0; \n\
112 		vtxColor = vec4(inColor * 4.0, polyAlpha); \n\
113 		\n\
114 		gl_Position = vtxPosition; \n\
115 	} \n\
116 "};
117 
118 // Fragment Shader GLSL 1.00
119 static const char *fragmentShader_100 = {"\
120 	varying vec4 vtxPosition; \n\
121 	varying vec2 vtxTexCoord; \n\
122 	varying vec4 vtxColor; \n\
123 	\n\
124 	uniform sampler2D texRenderObject; \n\
125 	uniform sampler1D texToonTable; \n\
126 	\n\
127 	uniform int stateToonShadingMode; \n\
128 	uniform bool stateEnableAlphaTest; \n\
129 	uniform bool stateEnableAntialiasing;\n\
130 	uniform bool stateEnableEdgeMarking;\n\
131 	uniform bool stateUseWDepth; \n\
132 	uniform float stateAlphaTestRef; \n\
133 	\n\
134 	uniform int polyMode; \n\
135 	uniform bool polyEnableDepthWrite;\n\
136 	uniform bool polySetNewDepthForTranslucent;\n\
137 	uniform int polyID; \n\
138 	\n\
139 	uniform bool polyEnableTexture; \n\
140 	uniform bool polyEnableFog;\n\
141 	\n\
142 	vec3 packVec3FromFloat(const float value)\n\
143 	{\n\
144 		float expandedValue = value * 16777215.0;\n\
145 		vec3 packedValue = vec3( fract(expandedValue/256.0), fract(((expandedValue/256.0) - fract(expandedValue/256.0)) / 256.0), fract(((expandedValue/65536.0) - fract(expandedValue/65536.0)) / 256.0) );\n\
146 		return packedValue;\n\
147 	}\n\
148 	\n\
149 	void main() \n\
150 	{ \n\
151 		vec4 mainTexColor = (polyEnableTexture) ? texture2D(texRenderObject, vtxTexCoord) : vec4(1.0, 1.0, 1.0, 1.0); \n\
152 		vec4 newFragColor = mainTexColor * vtxColor; \n\
153 		\n\
154 		if(polyMode == 1) \n\
155 		{ \n\
156 			newFragColor.rgb = (polyEnableTexture) ? mix(vtxColor.rgb, mainTexColor.rgb, mainTexColor.a) : vtxColor.rgb; \n\
157 			newFragColor.a = vtxColor.a; \n\
158 		} \n\
159 		else if(polyMode == 2) \n\
160 		{ \n\
161 			vec3 toonColor = vec3(texture1D(texToonTable, vtxColor.r).rgb); \n\
162 			newFragColor.rgb = (stateToonShadingMode == 0) ? mainTexColor.rgb * toonColor.rgb : min((mainTexColor.rgb * vtxColor.r) + toonColor.rgb, 1.0); \n\
163 		} \n\
164 		else if(polyMode == 3) \n\
165 		{ \n\
166 			if (polyID != 0) \n\
167 			{ \n\
168 				newFragColor = vtxColor; \n\
169 			} \n\
170 		} \n\
171 		\n\
172 		if (newFragColor.a == 0.0 || (stateEnableAlphaTest && newFragColor.a < stateAlphaTestRef)) \n\
173 		{ \n\
174 			discard; \n\
175 		} \n\
176 		\n\
177 		float vertW = (vtxPosition.w == 0.0) ? 0.00000001 : vtxPosition.w; \n\
178 		// hack: when using z-depth, drop some LSBs so that the overworld map in Dragon Quest IV shows up correctly\n\
179 		float newFragDepth = (stateUseWDepth) ? vtxPosition.w/4096.0 : clamp( (floor((((vtxPosition.z/vertW) * 0.5 + 0.5) * 16777215.0) / 4.0) * 4.0) / 16777215.0, 0.0, 1.0); \n\
180 		\n\
181 		gl_FragData[0] = newFragColor;\n\
182 		gl_FragData[1] = vec4( packVec3FromFloat(newFragDepth), float(polyEnableDepthWrite && (newFragColor.a > 0.999 || polySetNewDepthForTranslucent)));\n\
183 		gl_FragData[2] = vec4(float(polyID)/63.0, 0.0, 0.0, float(newFragColor.a > 0.999));\n\
184 		gl_FragData[3] = vec4( float(polyEnableFog), 0.0, 0.0, float(newFragColor.a > 0.999 || !polyEnableFog));\n\
185 		gl_FragDepth = newFragDepth;\n\
186 	} \n\
187 "};
188 
189 // Vertex shader for applying edge marking, GLSL 1.00
190 static const char *EdgeMarkVtxShader_100 = {"\
191 	attribute vec2 inPosition;\n\
192 	attribute vec2 inTexCoord0;\n\
193 	uniform vec2 framebufferSize;\n\
194 	varying vec2 texCoord[5];\n\
195 	\n\
196 	void main()\n\
197 	{\n\
198 		vec2 texInvScale = vec2(1.0/framebufferSize.x, 1.0/framebufferSize.y);\n\
199 		\n\
200 		texCoord[0] = inTexCoord0; // Center\n\
201 		texCoord[1] = inTexCoord0 + (vec2( 1.0, 0.0) * texInvScale); // Right\n\
202 		texCoord[2] = inTexCoord0 + (vec2( 0.0, 1.0) * texInvScale); // Down\n\
203 		texCoord[3] = inTexCoord0 + (vec2(-1.0, 0.0) * texInvScale); // Left\n\
204 		texCoord[4] = inTexCoord0 + (vec2( 0.0,-1.0) * texInvScale); // Up\n\
205 		\n\
206 		gl_Position = vec4(inPosition, 0.0, 1.0);\n\
207 	}\n\
208 "};
209 
210 // Fragment shader for applying edge marking, GLSL 1.00
211 static const char *EdgeMarkFragShader_100 = {"\
212 	varying vec2 texCoord[5];\n\
213 	\n\
214 	uniform sampler2D texInFragDepth;\n\
215 	uniform sampler2D texInPolyID;\n\
216 	uniform vec4 stateEdgeColor[8];\n\
217 	\n\
218 	float unpackFloatFromVec3(const vec3 value)\n\
219 	{\n\
220 		const vec3 unpackRatio = vec3(256.0, 65536.0, 16777216.0);\n\
221 		return (dot(value, unpackRatio) / 16777215.0);\n\
222 	}\n\
223 	\n\
224 	void main()\n\
225 	{\n\
226 		int polyID[5];\n\
227 		polyID[0] = int((texture2D(texInPolyID, texCoord[0]).r * 63.0) + 0.5);\n\
228 		polyID[1] = int((texture2D(texInPolyID, texCoord[1]).r * 63.0) + 0.5);\n\
229 		polyID[2] = int((texture2D(texInPolyID, texCoord[2]).r * 63.0) + 0.5);\n\
230 		polyID[3] = int((texture2D(texInPolyID, texCoord[3]).r * 63.0) + 0.5);\n\
231 		polyID[4] = int((texture2D(texInPolyID, texCoord[4]).r * 63.0) + 0.5);\n\
232 		\n\
233 		float depth[5];\n\
234 		depth[0] = unpackFloatFromVec3(texture2D(texInFragDepth, texCoord[0]).rgb);\n\
235 		depth[1] = unpackFloatFromVec3(texture2D(texInFragDepth, texCoord[1]).rgb);\n\
236 		depth[2] = unpackFloatFromVec3(texture2D(texInFragDepth, texCoord[2]).rgb);\n\
237 		depth[3] = unpackFloatFromVec3(texture2D(texInFragDepth, texCoord[3]).rgb);\n\
238 		depth[4] = unpackFloatFromVec3(texture2D(texInFragDepth, texCoord[4]).rgb);\n\
239 		\n\
240 		vec4 edgeColor = vec4(0.0, 0.0, 0.0, 0.0);\n\
241 		\n\
242 		for (int i = 1; i < 5; i++)\n\
243 		{\n\
244 			if (polyID[0] != polyID[i] && depth[0] >= depth[i])\n\
245 			{\n\
246 				edgeColor = stateEdgeColor[polyID[i]/8];\n\
247 				break;\n\
248 			}\n\
249 		}\n\
250 		\n\
251 		gl_FragData[0] = edgeColor;\n\
252 	}\n\
253 "};
254 
255 // Vertex shader for applying fog, GLSL 1.00
256 static const char *FogVtxShader_100 = {"\
257 	attribute vec2 inPosition;\n\
258 	attribute vec2 inTexCoord0;\n\
259 	varying vec2 texCoord;\n\
260 	\n\
261 	void main() \n\
262 	{ \n\
263 		texCoord = inTexCoord0; \n\
264 		gl_Position = vec4(inPosition, 0.0, 1.0);\n\
265 	}\n\
266 "};
267 
268 // Fragment shader for applying fog, GLSL 1.00
269 static const char *FogFragShader_100 = {"\
270 	varying vec2 texCoord;\n\
271 	\n\
272 	uniform sampler2D texInFragColor;\n\
273 	uniform sampler2D texInFragDepth;\n\
274 	uniform sampler2D texInFogAttributes;\n\
275 	uniform bool stateEnableFogAlphaOnly;\n\
276 	uniform vec4 stateFogColor;\n\
277 	uniform float stateFogDensity[32];\n\
278 	uniform float stateFogOffset;\n\
279 	uniform float stateFogStep;\n\
280 	\n\
281 	float unpackFloatFromVec3(const vec3 value)\n\
282 	{\n\
283 		const vec3 unpackRatio = vec3(256.0, 65536.0, 16777216.0);\n\
284 		return (dot(value, unpackRatio) / 16777215.0);\n\
285 	}\n\
286 	\n\
287 	void main()\n\
288 	{\n\
289 		vec4 inFragColor = texture2D(texInFragColor, texCoord);\n\
290 		vec4 inFogAttributes = texture2D(texInFogAttributes, texCoord);\n\
291 		bool polyEnableFog = bool(inFogAttributes.r);\n\
292 		vec4 newFoggedColor = inFragColor;\n\
293 		\n\
294 		if (polyEnableFog)\n\
295 		{\n\
296 			float inFragDepth = unpackFloatFromVec3(texture2D(texInFragDepth, texCoord).rgb);\n\
297 			float fogMixWeight = 0.0;\n\
298 			\n\
299 			if (inFragDepth <= min(stateFogOffset + stateFogStep, 1.0))\n\
300 			{\n\
301 				fogMixWeight = stateFogDensity[0];\n\
302 			}\n\
303 			else if (inFragDepth >= min(stateFogOffset + (stateFogStep*32.0), 1.0))\n\
304 			{\n\
305 				fogMixWeight = stateFogDensity[31];\n\
306 			}\n\
307 			else\n\
308 			{\n\
309 				for (int i = 1; i < 32; i++)\n\
310 				{\n\
311 					float currentFogStep = min(stateFogOffset + (stateFogStep * float(i+1)), 1.0);\n\
312 					if (inFragDepth <= currentFogStep)\n\
313 					{\n\
314 						float previousFogStep = min(stateFogOffset + (stateFogStep * float(i)), 1.0);\n\
315 						fogMixWeight = mix(stateFogDensity[i-1], stateFogDensity[i], (inFragDepth - previousFogStep) / (currentFogStep - previousFogStep));\n\
316 						break;\n\
317 					}\n\
318 				}\n\
319 			}\n\
320 			\n\
321 			newFoggedColor = mix(inFragColor, (stateEnableFogAlphaOnly) ? vec4(inFragColor.rgb, stateFogColor.a) : stateFogColor, fogMixWeight);\n\
322 		}\n\
323 		\n\
324 		gl_FragData[0] = newFoggedColor;\n\
325 	}\n\
326 "};
327 
328 // Vertex shader for the final framebuffer, GLSL 1.00
329 static const char *FramebufferOutputVtxShader_100 = {"\
330 	attribute vec2 inPosition;\n\
331 	attribute vec2 inTexCoord0;\n\
332 	varying vec2 texCoord;\n\
333 	\n\
334 	void main()\n\
335 	{\n\
336 		texCoord = inTexCoord0;\n\
337 		gl_Position = vec4(inPosition, 0.0, 1.0);\n\
338 	}\n\
339 "};
340 
341 // Fragment shader for the final RGBA6665 formatted framebuffer, GLSL 1.00
342 static const char *FramebufferOutputRGBA6665FragShader_100 = {"\
343 	varying vec2 texCoord;\n\
344 	\n\
345 	uniform sampler2D texInFragColor;\n\
346 	\n\
347 	void main()\n\
348 	{\n\
349 		// Note that we swap B and R since pixel readbacks are done in BGRA format for fastest\n\
350 		// performance. The final color is still in RGBA format.\n\
351 		vec4 colorRGBA6665 = texture2D(texInFragColor, texCoord).bgra;\n\
352 		colorRGBA6665     = floor((colorRGBA6665 * 255.0) + 0.5);\n\
353 		colorRGBA6665.rgb = floor(colorRGBA6665.rgb / 4.0);\n\
354 		colorRGBA6665.a   = floor(colorRGBA6665.a   / 8.0);\n\
355 		\n\
356 		gl_FragData[0] = (colorRGBA6665 / 255.0);\n\
357 	}\n\
358 "};
359 
360 // Fragment shader for the final RGBA8888 formatted framebuffer, GLSL 1.00
361 static const char *FramebufferOutputRGBA8888FragShader_100 = {"\
362 	varying vec2 texCoord;\n\
363 	\n\
364 	uniform sampler2D texInFragColor;\n\
365 	\n\
366 	void main()\n\
367 	{\n\
368 		gl_FragData[0] = texture2D(texInFragColor, texCoord).bgra;\n\
369 	}\n\
370 "};
371 
BGRA8888_32_To_RGBA6665_32(const u32 srcPix)372 FORCEINLINE u32 BGRA8888_32_To_RGBA6665_32(const u32 srcPix)
373 {
374 	const u32 dstPix = (srcPix >> 2);
375 
376 	return	 (dstPix & 0x00003F00) << 16 |		// R
377 			 (dstPix & 0x003F0000)       |		// G
378 			 (dstPix & 0x3F000000) >> 16 |		// B
379 			((dstPix >> 1) & 0x0000001F);		// A
380 }
381 
BGRA8888_32Rev_To_RGBA6665_32Rev(const u32 srcPix)382 FORCEINLINE u32 BGRA8888_32Rev_To_RGBA6665_32Rev(const u32 srcPix)
383 {
384 	const u32 dstPix = (srcPix >> 2);
385 
386 	return	 (dstPix & 0x003F0000) >> 16 |		// R
387 			 (dstPix & 0x00003F00)       |		// G
388 			 (dstPix & 0x0000003F) << 16 |		// B
389 			((dstPix >> 1) & 0x1F000000);		// A
390 }
391 
BGRA8888_32_To_RGBA6665_32(const FragmentColor src)392 FORCEINLINE FragmentColor BGRA8888_32_To_RGBA6665_32(const FragmentColor src)
393 {
394 	FragmentColor dst = src;
395 	dst.r = src.b >> 2;
396 	dst.g = src.g >> 2;
397 	dst.b = src.r >> 2;
398 	dst.a = src.a >> 3;
399 
400 	return dst;
401 }
402 
BGRA8888_32Rev_To_RGBA6665_32Rev(const FragmentColor src)403 FORCEINLINE FragmentColor BGRA8888_32Rev_To_RGBA6665_32Rev(const FragmentColor src)
404 {
405 	FragmentColor dst = src;
406 	dst.r = src.b >> 2;
407 	dst.g = src.g >> 2;
408 	dst.b = src.r >> 2;
409 	dst.a = src.a >> 3;
410 
411 	return dst;
412 }
413 
BGRA8888_32_To_RGBA5551_16(const FragmentColor src)414 FORCEINLINE u16 BGRA8888_32_To_RGBA5551_16(const FragmentColor src)
415 {
416 	return R5G5B5TORGB15( (src.b >> 3),
417 	                      (src.g >> 3),
418 	                      (src.r >> 3)) |
419 	                     ((src.a == 0) ? 0x0000 : 0x8000);
420 }
421 
BGRA8888_32Rev_To_RGBA5551_16Rev(const FragmentColor src)422 FORCEINLINE u16 BGRA8888_32Rev_To_RGBA5551_16Rev(const FragmentColor src)
423 {
424 	return R5G5B5TORGB15( (src.b >> 3),
425 	                      (src.g >> 3),
426 	                      (src.r >> 3)) |
427 	                     ((src.a == 0) ? 0x0000 : 0x8000);
428 }
429 
430 #ifdef ENABLE_SSSE3
431 
BGRA8888_32Rev_To_RGBA6665_32Rev(const __m128i src)432 FORCEINLINE __m128i BGRA8888_32Rev_To_RGBA6665_32Rev(const __m128i src)
433 {
434 	const __m128i rgb = _mm_srli_epi32(_mm_and_si128(src, _mm_set1_epi32(0x00FCFCFC)), 2);
435 	const __m128i a   = _mm_srli_epi32(_mm_and_si128(src, _mm_set1_epi32(0xF8000000)), 3);
436 
437 	return _mm_shuffle_epi8(_mm_or_si128(rgb, a), _mm_set_epi8(15, 12, 13, 14, 11, 8, 9, 10, 7, 4, 5, 6, 3, 0, 1, 2)); // Swizzle RGBA to BGRA
438 }
439 
BGRA8888_32Rev_To_RGBA5551_16Rev(const __m128i src)440 FORCEINLINE __m128i BGRA8888_32Rev_To_RGBA5551_16Rev(const __m128i src)
441 {
442 	__m128i b = _mm_and_si128(src, _mm_set1_epi32(0x000000F8));		// Read from R
443 	b = _mm_slli_epi32(b, 7);										// Shift to B
444 
445 	__m128i g = _mm_and_si128(src, _mm_set1_epi32(0x0000F800));		// Read from G
446 	g = _mm_srli_epi32(g, 6);										// Shift in G
447 
448 	__m128i r = _mm_and_si128(src, _mm_set1_epi32(0x00F80000));		// Read from B
449 	r = _mm_srli_epi32(r, 19);										// Shift to R
450 
451 	__m128i a = _mm_and_si128(src, _mm_set1_epi32(0xFF000000));		// Read from A
452 	a = _mm_cmpeq_epi32(a, _mm_setzero_si128());					// Determine A
453 	a = _mm_andnot_si128(a, _mm_set1_epi32(0x00008000));			// Mask to A
454 
455 	// All the colors are currently placed on 32 bit boundaries, so we need to swizzle them
456 	// to the lower 64 bits of our vector before we store them back to memory.
457 	// Note: Do not attempt to use packssdw here since packing with the 0x8000 bit set will
458 	// result in values of 0x7FFF, which are incorrect values in this case.
459 	return _mm_shuffle_epi8(_mm_or_si128(_mm_or_si128(_mm_or_si128(b, g), r), a), _mm_set_epi8(15, 14, 11, 10, 7, 6, 3, 2, 13, 12, 9, 8, 5, 4, 1, 0));
460 }
461 
462 #endif
463 
IsVersionSupported(unsigned int checkVersionMajor,unsigned int checkVersionMinor,unsigned int checkVersionRevision)464 bool IsVersionSupported(unsigned int checkVersionMajor, unsigned int checkVersionMinor, unsigned int checkVersionRevision)
465 {
466 	bool result = false;
467 
468 	if ( (_OGLDriverVersion.major > checkVersionMajor) ||
469 		 (_OGLDriverVersion.major >= checkVersionMajor && _OGLDriverVersion.minor > checkVersionMinor) ||
470 		 (_OGLDriverVersion.major >= checkVersionMajor && _OGLDriverVersion.minor >= checkVersionMinor && _OGLDriverVersion.revision >= checkVersionRevision) )
471 	{
472 		result = true;
473 	}
474 
475 	return result;
476 }
477 
OGLGetDriverVersion(const char * oglVersionString,unsigned int * versionMajor,unsigned int * versionMinor,unsigned int * versionRevision)478 static void OGLGetDriverVersion(const char *oglVersionString,
479 								unsigned int *versionMajor,
480 								unsigned int *versionMinor,
481 								unsigned int *versionRevision)
482 {
483 	size_t versionStringLength = 0;
484 
485 	if (oglVersionString == NULL)
486 		return;
487 
488 	// First, check for the dot in the revision string. There should be at
489 	// least one present.
490 	const char *versionStrEnd = strstr(oglVersionString, ".");
491 	if (versionStrEnd == NULL)
492 		return;
493 
494 	// Next, check for the space before the vendor-specific info (if present).
495 	versionStrEnd = strstr(oglVersionString, " ");
496 	if (versionStrEnd == NULL)
497 	{
498 		// If a space was not found, then the vendor-specific info is not present,
499 		// and therefore the entire string must be the version number.
500 		versionStringLength = strlen(oglVersionString);
501 	}
502 	else
503 	{
504 		// If a space was found, then the vendor-specific info is present,
505 		// and therefore the version number is everything before the space.
506 		versionStringLength = versionStrEnd - oglVersionString;
507 	}
508 
509 	// Copy the version substring and parse it.
510 	char *versionSubstring = (char *)malloc(versionStringLength * sizeof(char));
511 	strncpy(versionSubstring, oglVersionString, versionStringLength);
512 
513 	unsigned int major = 0;
514 	unsigned int minor = 0;
515 	unsigned int revision = 0;
516 
517 	sscanf(versionSubstring, "%u.%u.%u", &major, &minor, &revision);
518 
519 	free(versionSubstring);
520 	versionSubstring = NULL;
521 
522 	if (versionMajor != NULL)
523 		*versionMajor = major;
524 
525 	if (versionMinor != NULL)
526 		*versionMinor = minor;
527 
528 	if (versionRevision != NULL)
529 		*versionRevision = revision;
530 }
531 
texDeleteCallback(TexCacheItem * texItem,void * param1,void * param2)532 void texDeleteCallback(TexCacheItem *texItem, void *param1, void *param2)
533 {
534 	OpenGLRenderer *oglRenderer = (OpenGLRenderer *)param1;
535 	oglRenderer->DeleteTexture(texItem);
536 }
537 
538 template<bool require_profile, bool enable_3_2>
OpenGLRendererCreate()539 static Render3D* OpenGLRendererCreate()
540 {
541 	OpenGLRenderer *newRenderer = NULL;
542 	Render3DError error = OGLERROR_NOERR;
543 
544 	if (oglrender_init == NULL)
545 		return NULL;
546 
547 	if (!oglrender_init())
548 		return NULL;
549 
550 	if (!BEGINGL())
551 	{
552 		INFO("OpenGL<%s,%s>: Could not initialize -- BEGINGL() failed.\n",require_profile?"force":"auto",enable_3_2?"3_2":"old");
553 		return NULL;
554 	}
555 
556 	// Get OpenGL info
557 	const char *oglVersionString = (const char *)glGetString(GL_VERSION);
558 	const char *oglVendorString = (const char *)glGetString(GL_VENDOR);
559 	const char *oglRendererString = (const char *)glGetString(GL_RENDERER);
560 
561 	// Writing to gl_FragDepth causes the driver to fail miserably on systems equipped
562 	// with a Intel G965 graphic card. Warn the user and fail gracefully.
563 	// http://forums.desmume.org/viewtopic.php?id=9286
564 	if(!strcmp(oglVendorString,"Intel") && strstr(oglRendererString,"965"))
565 	{
566 		INFO("OpenGL: Incompatible graphic card detected. Disabling OpenGL support.\n");
567 
568 		ENDGL();
569 		return newRenderer;
570 	}
571 
572 	// Check the driver's OpenGL version
573 	OGLGetDriverVersion(oglVersionString, &_OGLDriverVersion.major, &_OGLDriverVersion.minor, &_OGLDriverVersion.revision);
574 
575 	if (!IsVersionSupported(OGLRENDER_MINIMUM_DRIVER_VERSION_REQUIRED_MAJOR, OGLRENDER_MINIMUM_DRIVER_VERSION_REQUIRED_MINOR, OGLRENDER_MINIMUM_DRIVER_VERSION_REQUIRED_REVISION))
576 	{
577 		INFO("OpenGL: Driver does not support OpenGL v%u.%u.%u or later. Disabling 3D renderer.\n[ Driver Info -\n    Version: %s\n    Vendor: %s\n    Renderer: %s ]\n",
578 			 OGLRENDER_MINIMUM_DRIVER_VERSION_REQUIRED_MAJOR, OGLRENDER_MINIMUM_DRIVER_VERSION_REQUIRED_MINOR, OGLRENDER_MINIMUM_DRIVER_VERSION_REQUIRED_REVISION,
579 			 oglVersionString, oglVendorString, oglRendererString);
580 
581 		ENDGL();
582 		return newRenderer;
583 	}
584 
585 	// Create new OpenGL rendering object
586 	if (enable_3_2)
587 	{
588 		if (OGLLoadEntryPoints_3_2_Func != NULL && OGLCreateRenderer_3_2_Func != NULL)
589 		{
590 			OGLLoadEntryPoints_3_2_Func();
591 			OGLLoadEntryPoints_Legacy(); //zero 04-feb-2013 - this seems to be necessary as well
592 			OGLCreateRenderer_3_2_Func(&newRenderer);
593 		}
594 		else
595 		{
596 			if(require_profile)
597 			{
598 				ENDGL();
599 				return newRenderer;
600 			}
601 		}
602 	}
603 
604 	// If the renderer doesn't initialize with OpenGL v3.2 or higher, fall back
605 	// to one of the lower versions.
606 	if (newRenderer == NULL)
607 	{
608 		OGLLoadEntryPoints_Legacy();
609 
610 		if (IsVersionSupported(2, 1, 0))
611 		{
612 			newRenderer = new OpenGLRenderer_2_1;
613 			newRenderer->SetVersion(2, 1, 0);
614 		}
615 		else if (IsVersionSupported(2, 0, 0))
616 		{
617 			newRenderer = new OpenGLRenderer_2_0;
618 			newRenderer->SetVersion(2, 0, 0);
619 		}
620 		else if (IsVersionSupported(1, 5, 0))
621 		{
622 			newRenderer = new OpenGLRenderer_1_5;
623 			newRenderer->SetVersion(1, 5, 0);
624 		}
625 		else if (IsVersionSupported(1, 4, 0))
626 		{
627 			newRenderer = new OpenGLRenderer_1_4;
628 			newRenderer->SetVersion(1, 4, 0);
629 		}
630 		else if (IsVersionSupported(1, 3, 0))
631 		{
632 			newRenderer = new OpenGLRenderer_1_3;
633 			newRenderer->SetVersion(1, 3, 0);
634 		}
635 		else if (IsVersionSupported(1, 2, 0))
636 		{
637 			newRenderer = new OpenGLRenderer_1_2;
638 			newRenderer->SetVersion(1, 2, 0);
639 		}
640 	}
641 
642 	if (newRenderer == NULL)
643 	{
644 		INFO("OpenGL: Renderer did not initialize. Disabling 3D renderer.\n[ Driver Info -\n    Version: %s\n    Vendor: %s\n    Renderer: %s ]\n",
645 			 oglVersionString, oglVendorString, oglRendererString);
646 
647 		ENDGL();
648 		return newRenderer;
649 	}
650 
651 	// Initialize OpenGL extensions
652 	error = newRenderer->InitExtensions();
653 	if (error != OGLERROR_NOERR)
654 	{
655 		if ( IsVersionSupported(2, 0, 0) &&
656 			(error == OGLERROR_SHADER_CREATE_ERROR ||
657 			 error == OGLERROR_VERTEX_SHADER_PROGRAM_LOAD_ERROR ||
658 			 error == OGLERROR_FRAGMENT_SHADER_PROGRAM_LOAD_ERROR) )
659 		{
660 			INFO("OpenGL: Shaders are not working, even though they should be. Disabling 3D renderer.\n");
661 			delete newRenderer;
662 			newRenderer = NULL;
663 
664 			ENDGL();
665 			return newRenderer;
666 		}
667 		else if (IsVersionSupported(3, 0, 0) && error == OGLERROR_FBO_CREATE_ERROR && OGLLoadEntryPoints_3_2_Func != NULL)
668 		{
669 			INFO("OpenGL: FBOs are not working, even though they should be. Disabling 3D renderer.\n");
670 			delete newRenderer;
671 			newRenderer = NULL;
672 
673 			ENDGL();
674 			return newRenderer;
675 		}
676 	}
677 
678 	ENDGL();
679 
680 	// Initialization finished -- reset the renderer
681 	newRenderer->Reset();
682 
683 	unsigned int major = 0;
684 	unsigned int minor = 0;
685 	unsigned int revision = 0;
686 	newRenderer->GetVersion(&major, &minor, &revision);
687 
688 	INFO("OpenGL: Renderer initialized successfully (v%u.%u.%u).\n[ Driver Info -\n    Version: %s\n    Vendor: %s\n    Renderer: %s ]\n",
689 		 major, minor, revision, oglVersionString, oglVendorString, oglRendererString);
690 
691 	return newRenderer;
692 }
693 
OpenGLRendererDestroy()694 static void OpenGLRendererDestroy()
695 {
696 	if(!BEGINGL())
697 		return;
698 
699 	if (CurrentRenderer != BaseRenderer)
700 	{
701 		OpenGLRenderer *oldRenderer = (OpenGLRenderer *)CurrentRenderer;
702 		CurrentRenderer = BaseRenderer;
703 		delete oldRenderer;
704 	}
705 
706 	ENDGL();
707 }
708 
709 //automatically select 3.2 or old profile depending on whether 3.2 is available
710 GPU3DInterface gpu3Dgl = {
711 	"OpenGL",
712 	OpenGLRendererCreate<false,true>,
713 	OpenGLRendererDestroy
714 };
715 
716 //forcibly use old profile
717 GPU3DInterface gpu3DglOld = {
718 	"OpenGL Old",
719 	OpenGLRendererCreate<true,false>,
720 	OpenGLRendererDestroy
721 };
722 
723 //forcibly use new profile
724 GPU3DInterface gpu3Dgl_3_2 = {
725 	"OpenGL 3.2",
726 	OpenGLRendererCreate<true,true>,
727 	OpenGLRendererDestroy
728 };
729 
OpenGLRenderer()730 OpenGLRenderer::OpenGLRenderer()
731 {
732 	_renderID = RENDERID_OPENGL_AUTO;
733 	_renderName = "OpenGL";
734 	_internalRenderingFormat = NDSColorFormat_BGR888_Rev;
735 
736 	versionMajor = 0;
737 	versionMinor = 0;
738 	versionRevision = 0;
739 
740 	isVBOSupported = false;
741 	isPBOSupported = false;
742 	isFBOSupported = false;
743 	isMultisampledFBOSupported = false;
744 	isShaderSupported = false;
745 	isVAOSupported = false;
746 	willFlipFramebufferOnGPU = false;
747 	willConvertFramebufferOnGPU = false;
748 
749 	// Init OpenGL rendering states
750 	ref = new OGLRenderRef;
751 	ref->fboRenderID = 0;
752 	ref->fboMSIntermediateRenderID = 0;
753 	ref->fboPostprocessID = 0;
754 	ref->selectedRenderingFBO = 0;
755 
756 	currTexture = NULL;
757 	_mappedFramebuffer = NULL;
758 	_pixelReadNeedsFinish = false;
759 	_currentPolyIndex = 0;
760 	_shadowPolyID.reserve(POLYLIST_SIZE);
761 }
762 
~OpenGLRenderer()763 OpenGLRenderer::~OpenGLRenderer()
764 {
765 	free_aligned(_framebufferColor);
766 
767 	// Destroy OpenGL rendering states
768 	delete ref;
769 	ref = NULL;
770 }
771 
IsExtensionPresent(const std::set<std::string> * oglExtensionSet,const std::string extensionName) const772 bool OpenGLRenderer::IsExtensionPresent(const std::set<std::string> *oglExtensionSet, const std::string extensionName) const
773 {
774 	if (oglExtensionSet == NULL || oglExtensionSet->size() == 0)
775 		return false;
776 
777 	return (oglExtensionSet->find(extensionName) != oglExtensionSet->end());
778 }
779 
ValidateShaderCompile(GLuint theShader) const780 bool OpenGLRenderer::ValidateShaderCompile(GLuint theShader) const
781 {
782 	bool isCompileValid = false;
783 	GLint status = GL_FALSE;
784 
785 	glGetShaderiv(theShader, GL_COMPILE_STATUS, &status);
786 	if(status == GL_TRUE)
787 	{
788 		isCompileValid = true;
789 	}
790 	else
791 	{
792 		GLint logSize;
793 		GLchar *log = NULL;
794 
795 		glGetShaderiv(theShader, GL_INFO_LOG_LENGTH, &logSize);
796 		log = new GLchar[logSize];
797 		glGetShaderInfoLog(theShader, logSize, &logSize, log);
798 
799 		INFO("OpenGL: SEVERE - FAILED TO COMPILE SHADER : %s\n", log);
800 		delete[] log;
801 	}
802 
803 	return isCompileValid;
804 }
805 
ValidateShaderProgramLink(GLuint theProgram) const806 bool OpenGLRenderer::ValidateShaderProgramLink(GLuint theProgram) const
807 {
808 	bool isLinkValid = false;
809 	GLint status = GL_FALSE;
810 
811 	glGetProgramiv(theProgram, GL_LINK_STATUS, &status);
812 	if(status == GL_TRUE)
813 	{
814 		isLinkValid = true;
815 	}
816 	else
817 	{
818 		GLint logSize;
819 		GLchar *log = NULL;
820 
821 		glGetProgramiv(theProgram, GL_INFO_LOG_LENGTH, &logSize);
822 		log = new GLchar[logSize];
823 		glGetProgramInfoLog(theProgram, logSize, &logSize, log);
824 
825 		INFO("OpenGL: SEVERE - FAILED TO LINK SHADER PROGRAM : %s\n", log);
826 		delete[] log;
827 	}
828 
829 	return isLinkValid;
830 }
831 
GetVersion(unsigned int * major,unsigned int * minor,unsigned int * revision) const832 void OpenGLRenderer::GetVersion(unsigned int *major, unsigned int *minor, unsigned int *revision) const
833 {
834 	*major = this->versionMajor;
835 	*minor = this->versionMinor;
836 	*revision = this->versionRevision;
837 }
838 
SetVersion(unsigned int major,unsigned int minor,unsigned int revision)839 void OpenGLRenderer::SetVersion(unsigned int major, unsigned int minor, unsigned int revision)
840 {
841 	this->versionMajor = major;
842 	this->versionMinor = minor;
843 	this->versionRevision = revision;
844 }
845 
_FlushFramebufferConvertOnCPU(const FragmentColor * __restrict srcFramebuffer,FragmentColor * __restrict dstFramebuffer,u16 * __restrict dstRGBA5551)846 Render3DError OpenGLRenderer::_FlushFramebufferConvertOnCPU(const FragmentColor *__restrict srcFramebuffer, FragmentColor *__restrict dstFramebuffer, u16 *__restrict dstRGBA5551)
847 {
848 	if ( ((dstFramebuffer == NULL) && (dstRGBA5551 == NULL)) || (srcFramebuffer == NULL) )
849 		return RENDER3DERROR_NOERR;
850 
851 	// Convert from 32-bit BGRA8888 format to 32-bit RGBA6665 reversed format. OpenGL
852 	// stores pixels using a flipped Y-coordinate, so this needs to be flipped back
853 	// to the DS Y-coordinate.
854 
855 	size_t i = 0;
856 	const size_t pixCount = this->_framebufferWidth;
857 
858 #ifdef ENABLE_SSSE3
859 	const size_t ssePixCount = pixCount - (pixCount % 4);
860 #endif
861 
862 	if (this->willFlipFramebufferOnGPU)
863 	{
864 		if (this->_outputFormat == NDSColorFormat_BGR666_Rev)
865 		{
866 			if ( (dstFramebuffer != NULL) && (dstRGBA5551 != NULL) )
867 			{
868 #ifdef ENABLE_SSSE3
869 				for (; i < ssePixCount; i += 4)
870 				{
871 					const __m128i srcColor = _mm_load_si128((__m128i *)(srcFramebuffer + i));
872 					const __m128i color6665 = BGRA8888_32Rev_To_RGBA6665_32Rev(srcColor);
873 					const __m128i color5551 = BGRA8888_32Rev_To_RGBA5551_16Rev(srcColor);
874 					_mm_store_si128((__m128i *)(dstFramebuffer + i), color6665);
875 					_mm_storel_epi64((__m128i *)(dstRGBA5551 + i), color5551);
876 				}
877 #endif
878 				for (; i < pixCount; i++)
879 				{
880 #ifdef MSB_FIRST
881 					dstFramebuffer[i] = BGRA8888_32_To_RGBA6665_32(srcFramebuffer[i]);
882 					dstRGBA5551[i]    = BGRA8888_32_To_RGBA5551_16(srcFramebuffer[i]);
883 #else
884 					dstFramebuffer[i] = BGRA8888_32Rev_To_RGBA6665_32Rev(srcFramebuffer[i]);
885 					dstRGBA5551[i]    = BGRA8888_32Rev_To_RGBA5551_16Rev(srcFramebuffer[i]);
886 #endif
887 				}
888 			}
889 			else if (dstFramebuffer != NULL)
890 			{
891 #ifdef ENABLE_SSSE3
892 				for (; i < ssePixCount; i += 4)
893 				{
894 					const __m128i srcColor = _mm_load_si128((__m128i *)(srcFramebuffer + i));
895 					const __m128i color6665 = BGRA8888_32Rev_To_RGBA6665_32Rev(srcColor);
896 					_mm_store_si128((__m128i *)(dstFramebuffer + i), color6665);
897 				}
898 #endif
899 				for (; i < pixCount; i++)
900 				{
901 #ifdef MSB_FIRST
902 					dstFramebuffer[i] = BGRA8888_32_To_RGBA6665_32(srcFramebuffer[i]);
903 #else
904 					dstFramebuffer[i] = BGRA8888_32Rev_To_RGBA6665_32Rev(srcFramebuffer[i]);
905 #endif
906 				}
907 			}
908 			else
909 			{
910 #ifdef ENABLE_SSSE3
911 				for (; i < ssePixCount; i += 4)
912 				{
913 					const __m128i srcColor = _mm_load_si128((__m128i *)(srcFramebuffer + i));
914 					const __m128i color5551 = BGRA8888_32Rev_To_RGBA5551_16Rev(srcColor);
915 					_mm_storel_epi64((__m128i *)(dstRGBA5551 + i), color5551);
916 				}
917 #endif
918 				for (; i < pixCount; i++)
919 				{
920 #ifdef MSB_FIRST
921 					dstRGBA5551[i]    = BGRA8888_32_To_RGBA5551_16(srcFramebuffer[i]);
922 #else
923 					dstRGBA5551[i]    = BGRA8888_32Rev_To_RGBA5551_16Rev(srcFramebuffer[i]);
924 #endif
925 				}
926 			}
927 		}
928 		else if (this->_outputFormat == NDSColorFormat_BGR888_Rev)
929 		{
930 			if ( (dstFramebuffer != NULL) && (dstRGBA5551 != NULL) )
931 			{
932 #ifdef ENABLE_SSSE3
933 				for (; i < ssePixCount; i += 4)
934 				{
935 					const __m128i srcColor = _mm_load_si128((__m128i *)(srcFramebuffer + i));
936 					const __m128i color5551 = BGRA8888_32Rev_To_RGBA5551_16Rev(srcColor);
937 					_mm_store_si128((__m128i *)(dstFramebuffer + i), srcColor);
938 					_mm_storel_epi64((__m128i *)(dstRGBA5551 + i), color5551);
939 				}
940 #endif
941 				for (; i < pixCount; i++)
942 				{
943 					dstFramebuffer[i] = srcFramebuffer[i];
944 #ifdef MSB_FIRST
945 					dstRGBA5551[i]    = BGRA8888_32_To_RGBA5551_16(srcFramebuffer[i]);
946 #else
947 					dstRGBA5551[i]    = BGRA8888_32Rev_To_RGBA5551_16Rev(srcFramebuffer[i]);
948 #endif
949 				}
950 			}
951 			else if (dstFramebuffer != NULL)
952 			{
953 				memcpy(dstFramebuffer, srcFramebuffer, this->_framebufferWidth * this->_framebufferHeight * sizeof(FragmentColor));
954 			}
955 			else
956 			{
957 #ifdef ENABLE_SSSE3
958 				for (; i < ssePixCount; i += 4)
959 				{
960 					const __m128i srcColor = _mm_load_si128((__m128i *)(srcFramebuffer + i));
961 					const __m128i color5551 = BGRA8888_32Rev_To_RGBA5551_16Rev(srcColor);
962 					_mm_storel_epi64((__m128i *)(dstRGBA5551 + i), color5551);
963 				}
964 #endif
965 				for (; i < pixCount; i++)
966 				{
967 #ifdef MSB_FIRST
968 					dstRGBA5551[i]    = BGRA8888_32_To_RGBA5551_16(srcFramebuffer[i]);
969 #else
970 					dstRGBA5551[i]    = BGRA8888_32Rev_To_RGBA5551_16Rev(srcFramebuffer[i]);
971 #endif
972 				}
973 			}
974 		}
975 	}
976 	else // In the case where OpenGL couldn't flip the framebuffer on the GPU, we'll instead need to flip the framebuffer during conversion.
977 	{
978 		if (this->_outputFormat == NDSColorFormat_BGR666_Rev)
979 		{
980 			if ( (dstFramebuffer != NULL) && (dstRGBA5551 != NULL) )
981 			{
982 				for (size_t y = 0, ir = 0, iw = ((this->_framebufferHeight - 1) * this->_framebufferWidth); y < this->_framebufferHeight; y++, iw -= (this->_framebufferWidth * 2))
983 				{
984 					size_t x = 0;
985 #ifdef ENABLE_SSSE3
986 					for (; x < ssePixCount; x += 4, ir += 4, iw += 4)
987 					{
988 						const __m128i srcColor = _mm_load_si128((__m128i *)(srcFramebuffer + ir));
989 						const __m128i color6665 = BGRA8888_32Rev_To_RGBA6665_32Rev(srcColor);
990 						const __m128i color5551 = BGRA8888_32Rev_To_RGBA5551_16Rev(srcColor);
991 						_mm_store_si128((__m128i *)(dstFramebuffer + iw), color6665);
992 						_mm_storel_epi64((__m128i *)(dstFramebuffer + iw), color5551);
993 					}
994 #endif
995 					for (; x < pixCount; x++, ir++, iw++)
996 					{
997 #ifdef MSB_FIRST
998 						dstFramebuffer[iw] = BGRA8888_32_To_RGBA6665_32(srcFramebuffer[ir]);
999 						dstRGBA5551[iw]    = BGRA8888_32_To_RGBA5551_16(srcFramebuffer[ir]);
1000 #else
1001 						dstFramebuffer[iw] = BGRA8888_32Rev_To_RGBA6665_32Rev(srcFramebuffer[ir]);
1002 						dstRGBA5551[iw]    = BGRA8888_32Rev_To_RGBA5551_16Rev(srcFramebuffer[ir]);
1003 #endif
1004 					}
1005 				}
1006 			}
1007 			else if (dstFramebuffer != NULL)
1008 			{
1009 				for (size_t y = 0, ir = 0, iw = ((this->_framebufferHeight - 1) * this->_framebufferWidth); y < this->_framebufferHeight; y++, iw -= (this->_framebufferWidth * 2))
1010 				{
1011 					size_t x = 0;
1012 #ifdef ENABLE_SSSE3
1013 					for (; x < ssePixCount; x += 4, ir += 4, iw += 4)
1014 					{
1015 						const __m128i srcColor = _mm_load_si128((__m128i *)(srcFramebuffer + ir));
1016 						const __m128i color6665 = BGRA8888_32Rev_To_RGBA6665_32Rev(srcColor);
1017 						_mm_store_si128((__m128i *)(dstFramebuffer + iw), color6665);
1018 					}
1019 #endif
1020 					for (; x < pixCount; x++, ir++, iw++)
1021 					{
1022 #ifdef MSB_FIRST
1023 						dstFramebuffer[iw] = BGRA8888_32_To_RGBA6665_32(srcFramebuffer[ir]);
1024 #else
1025 						dstFramebuffer[iw] = BGRA8888_32Rev_To_RGBA6665_32Rev(srcFramebuffer[ir]);
1026 #endif
1027 					}
1028 				}
1029 			}
1030 			else
1031 			{
1032 				for (size_t y = 0, ir = 0, iw = ((this->_framebufferHeight - 1) * this->_framebufferWidth); y < this->_framebufferHeight; y++, iw -= (this->_framebufferWidth * 2))
1033 				{
1034 					size_t x = 0;
1035 #ifdef ENABLE_SSSE3
1036 					for (; x < ssePixCount; x += 4, ir += 4, iw += 4)
1037 					{
1038 						const __m128i srcColor = _mm_load_si128((__m128i *)(srcFramebuffer + ir));
1039 						const __m128i color5551 = BGRA8888_32Rev_To_RGBA5551_16Rev(srcColor);
1040 						_mm_storel_epi64((__m128i *)(dstFramebuffer + iw), color5551);
1041 					}
1042 #endif
1043 					for (; x < pixCount; x++, ir++, iw++)
1044 					{
1045 #ifdef MSB_FIRST
1046 						dstRGBA5551[iw]    = BGRA8888_32_To_RGBA5551_16(srcFramebuffer[ir]);
1047 #else
1048 						dstRGBA5551[iw]    = BGRA8888_32Rev_To_RGBA5551_16Rev(srcFramebuffer[ir]);
1049 #endif
1050 					}
1051 				}
1052 			}
1053 		}
1054 		else if (this->_outputFormat == NDSColorFormat_BGR888_Rev)
1055 		{
1056 			if ( (dstFramebuffer != NULL) && (dstRGBA5551 != NULL) )
1057 			{
1058 				for (size_t y = 0, ir = 0, iw = ((this->_framebufferHeight - 1) * this->_framebufferWidth); y < this->_framebufferHeight; y++, iw -= (this->_framebufferWidth * 2))
1059 				{
1060 					size_t x = 0;
1061 #ifdef ENABLE_SSSE3
1062 					for (; x < ssePixCount; x += 4, ir += 4, iw += 4)
1063 					{
1064 						const __m128i srcColor = _mm_load_si128((__m128i *)(srcFramebuffer + ir));
1065 						const __m128i color5551 = BGRA8888_32Rev_To_RGBA5551_16Rev(srcColor);
1066 						_mm_store_si128((__m128i *)(dstFramebuffer + iw), srcColor);
1067 						_mm_storel_epi64((__m128i *)(dstFramebuffer + iw), color5551);
1068 					}
1069 #endif
1070 					for (; x < pixCount; x++, ir++, iw++)
1071 					{
1072 						dstFramebuffer[iw] = srcFramebuffer[ir];
1073 #ifdef MSB_FIRST
1074 						dstRGBA5551[iw]    = BGRA8888_32_To_RGBA5551_16(srcFramebuffer[ir]);
1075 #else
1076 						dstRGBA5551[iw]    = BGRA8888_32Rev_To_RGBA5551_16Rev(srcFramebuffer[ir]);
1077 #endif
1078 					}
1079 				}
1080 			}
1081 			else if (dstFramebuffer != NULL)
1082 			{
1083 				const size_t lineBytes = this->_framebufferWidth * sizeof(FragmentColor);
1084 				const FragmentColor *__restrict srcPtr = srcFramebuffer;
1085 				FragmentColor *__restrict dstPtr = dstFramebuffer + ((this->_framebufferHeight - 1) * this->_framebufferWidth);
1086 
1087 				for (size_t y = 0; y < this->_framebufferHeight; y++)
1088 				{
1089 					memcpy(dstPtr, srcPtr, lineBytes);
1090 					srcPtr += this->_framebufferWidth;
1091 					dstPtr -= this->_framebufferWidth;
1092 				}
1093 			}
1094 			else
1095 			{
1096 				for (size_t y = 0, ir = 0, iw = ((this->_framebufferHeight - 1) * this->_framebufferWidth); y < this->_framebufferHeight; y++, iw -= (this->_framebufferWidth * 2))
1097 				{
1098 					size_t x = 0;
1099 #ifdef ENABLE_SSSE3
1100 					for (; x < ssePixCount; x += 4, ir += 4, iw += 4)
1101 					{
1102 						const __m128i srcColor = _mm_load_si128((__m128i *)(srcFramebuffer + ir));
1103 						const __m128i color5551 = BGRA8888_32Rev_To_RGBA5551_16Rev(srcColor);
1104 						_mm_storel_epi64((__m128i *)(dstFramebuffer + iw), color5551);
1105 					}
1106 #endif
1107 					for (; x < pixCount; x++, ir++, iw++)
1108 					{
1109 #ifdef MSB_FIRST
1110 						dstRGBA5551[iw]    = BGRA8888_32_To_RGBA5551_16(srcFramebuffer[ir]);
1111 #else
1112 						dstRGBA5551[iw]    = BGRA8888_32Rev_To_RGBA5551_16Rev(srcFramebuffer[ir]);
1113 #endif
1114 					}
1115 				}
1116 			}
1117 		}
1118 	}
1119 
1120 	return RENDER3DERROR_NOERR;
1121 }
1122 
FlushFramebuffer(const FragmentColor * __restrict srcFramebuffer,FragmentColor * __restrict dstFramebuffer,u16 * __restrict dstRGBA5551)1123 Render3DError OpenGLRenderer::FlushFramebuffer(const FragmentColor *__restrict srcFramebuffer, FragmentColor *__restrict dstFramebuffer, u16 *__restrict dstRGBA5551)
1124 {
1125 	if (this->willConvertFramebufferOnGPU)
1126 	{
1127 #ifdef ENABLE_SSE2
1128 		return Render3D_SSE2::FlushFramebuffer(srcFramebuffer, NULL, dstRGBA5551);
1129 #else
1130 		return Render3D::FlushFramebuffer(srcFramebuffer, NULL, dstRGBA5551);
1131 #endif
1132 	}
1133 
1134    return this->_FlushFramebufferConvertOnCPU(srcFramebuffer, dstFramebuffer, dstRGBA5551);
1135 }
1136 
GetFramebuffer()1137 FragmentColor* OpenGLRenderer::GetFramebuffer()
1138 {
1139 	return (this->willConvertFramebufferOnGPU) ? this->_mappedFramebuffer : GPU->GetEngineMain()->Get3DFramebufferRGBA6665();
1140 }
1141 
~OpenGLRenderer_1_2()1142 OpenGLRenderer_1_2::~OpenGLRenderer_1_2()
1143 {
1144 	glFinish();
1145 
1146 	_pixelReadNeedsFinish = false;
1147 
1148 	delete[] ref->color4fBuffer;
1149 	ref->color4fBuffer = NULL;
1150 
1151 	delete[] ref->vertIndexBuffer;
1152 	ref->vertIndexBuffer = NULL;
1153 
1154 	DestroyGeometryProgram();
1155 	DestroyPostprocessingPrograms();
1156 	DestroyVAOs();
1157 	DestroyVBOs();
1158 	DestroyPBOs();
1159 	DestroyFBOs();
1160 	DestroyMultisampledFBO();
1161 
1162 	// Kill the texture cache now before all of our texture IDs disappear.
1163 	TexCache_Reset();
1164 
1165 	while(!ref->freeTextureIDs.empty())
1166 	{
1167 		GLuint temp = ref->freeTextureIDs.front();
1168 		ref->freeTextureIDs.pop();
1169 		glDeleteTextures(1, &temp);
1170 	}
1171 
1172 	glFinish();
1173 }
1174 
InitExtensions()1175 Render3DError OpenGLRenderer_1_2::InitExtensions()
1176 {
1177 	Render3DError error = OGLERROR_NOERR;
1178 
1179 	// Get OpenGL extensions
1180 	std::set<std::string> oglExtensionSet;
1181 	this->GetExtensionSet(&oglExtensionSet);
1182 
1183 	// Initialize OpenGL
1184 	this->InitTables();
1185 
1186 	this->isShaderSupported	= this->IsExtensionPresent(&oglExtensionSet, "GL_ARB_shader_objects") &&
1187 							  this->IsExtensionPresent(&oglExtensionSet, "GL_ARB_vertex_shader") &&
1188 							  this->IsExtensionPresent(&oglExtensionSet, "GL_ARB_fragment_shader") &&
1189 							  this->IsExtensionPresent(&oglExtensionSet, "GL_ARB_vertex_program");
1190 	if (this->isShaderSupported)
1191 	{
1192 		std::string vertexShaderProgram;
1193 		std::string fragmentShaderProgram;
1194 
1195 		error = this->LoadGeometryShaders(vertexShaderProgram, fragmentShaderProgram);
1196 		if (error == OGLERROR_NOERR)
1197 		{
1198 			error = this->InitGeometryProgram(vertexShaderProgram, fragmentShaderProgram);
1199 			if (error == OGLERROR_NOERR)
1200 			{
1201 				std::string edgeMarkVtxShaderString = std::string(EdgeMarkVtxShader_100);
1202 				std::string edgeMarkFragShaderString = std::string(EdgeMarkFragShader_100);
1203 				std::string fogVtxShaderString = std::string(FogVtxShader_100);
1204 				std::string fogFragShaderString = std::string(FogFragShader_100);
1205 				std::string framebufferOutputVtxShaderString = std::string(FramebufferOutputVtxShader_100);
1206 				std::string framebufferOutputRGBA6665FragShaderString = std::string(FramebufferOutputRGBA6665FragShader_100);
1207 				std::string framebufferOutputRGBA8888FragShaderString = std::string(FramebufferOutputRGBA8888FragShader_100);
1208 				error = this->InitPostprocessingPrograms(edgeMarkVtxShaderString,
1209 														 edgeMarkFragShaderString,
1210 														 fogVtxShaderString,
1211 														 fogFragShaderString,
1212 														 framebufferOutputVtxShaderString,
1213 														 framebufferOutputRGBA6665FragShaderString,
1214 														 framebufferOutputRGBA8888FragShaderString);
1215 				if (error != OGLERROR_NOERR)
1216 				{
1217 					INFO("OpenGL: Edge mark and fog require OpenGL v2.0 or later. These features will be disabled.\n");
1218 				}
1219 			}
1220 			else
1221 			{
1222 				this->isShaderSupported = false;
1223 			}
1224 		}
1225 		else
1226 		{
1227 			this->isShaderSupported = false;
1228 		}
1229 	}
1230 	else
1231 	{
1232 		INFO("OpenGL: Shaders are unsupported. Disabling shaders and using fixed-function pipeline. Some emulation features will be disabled.\n");
1233 	}
1234 
1235 	this->isVBOSupported = this->IsExtensionPresent(&oglExtensionSet, "GL_ARB_vertex_buffer_object");
1236 	if (this->isVBOSupported)
1237 	{
1238 		this->CreateVBOs();
1239 	}
1240 
1241 	this->isPBOSupported	= this->isVBOSupported &&
1242 							 (this->IsExtensionPresent(&oglExtensionSet, "GL_ARB_pixel_buffer_object") ||
1243 							  this->IsExtensionPresent(&oglExtensionSet, "GL_EXT_pixel_buffer_object"));
1244 	if (this->isPBOSupported)
1245 	{
1246 		this->CreatePBOs();
1247 	}
1248 
1249 	this->isVAOSupported	= this->isShaderSupported &&
1250 							  this->isVBOSupported &&
1251 							 (this->IsExtensionPresent(&oglExtensionSet, "GL_ARB_vertex_array_object") ||
1252 							  this->IsExtensionPresent(&oglExtensionSet, "GL_APPLE_vertex_array_object"));
1253 	if (this->isVAOSupported)
1254 	{
1255 		this->CreateVAOs();
1256 	}
1257 
1258 	// Don't use ARB versions since we're using the EXT versions for backwards compatibility.
1259 	this->isFBOSupported	= this->IsExtensionPresent(&oglExtensionSet, "GL_EXT_framebuffer_object") &&
1260 							  this->IsExtensionPresent(&oglExtensionSet, "GL_EXT_framebuffer_blit") &&
1261 							  this->IsExtensionPresent(&oglExtensionSet, "GL_EXT_packed_depth_stencil");
1262 	if (this->isFBOSupported)
1263 	{
1264 		this->willFlipFramebufferOnGPU = true;
1265 		this->willConvertFramebufferOnGPU = (this->isShaderSupported && this->isVAOSupported && this->isPBOSupported && this->isFBOSupported);
1266 
1267 		error = this->CreateFBOs();
1268 		if (error != OGLERROR_NOERR)
1269 		{
1270 			this->isFBOSupported = false;
1271 		}
1272 	}
1273 	else
1274 	{
1275 		INFO("OpenGL: FBOs are unsupported. Some emulation features will be disabled.\n");
1276 	}
1277 
1278 	// Set these again after FBO creation just in case FBO creation fails.
1279 	this->willFlipFramebufferOnGPU = this->isFBOSupported;
1280 	this->willConvertFramebufferOnGPU = (this->isShaderSupported && this->isVAOSupported && this->isPBOSupported && this->isFBOSupported);
1281 
1282 	// Don't use ARB versions since we're using the EXT versions for backwards compatibility.
1283 	this->isMultisampledFBOSupported	= this->isFBOSupported &&
1284 										  this->IsExtensionPresent(&oglExtensionSet, "GL_EXT_framebuffer_multisample");
1285 	if (this->isMultisampledFBOSupported)
1286 	{
1287 		error = this->CreateMultisampledFBO();
1288 		if (error != OGLERROR_NOERR)
1289 		{
1290 			this->isMultisampledFBOSupported = false;
1291 		}
1292 	}
1293 	else
1294 	{
1295 		INFO("OpenGL: Multisampled FBOs are unsupported. Multisample antialiasing will be disabled.\n");
1296 	}
1297 
1298 	this->InitTextures();
1299 	this->InitFinalRenderStates(&oglExtensionSet); // This must be done last
1300 
1301 	return OGLERROR_NOERR;
1302 }
1303 
CreateVBOs()1304 Render3DError OpenGLRenderer_1_2::CreateVBOs()
1305 {
1306 	OGLRenderRef &OGLRef = *this->ref;
1307 
1308 	glGenBuffersARB(1, &OGLRef.vboGeometryVtxID);
1309 	glGenBuffersARB(1, &OGLRef.iboGeometryIndexID);
1310 	glGenBuffersARB(1, &OGLRef.vboPostprocessVtxID);
1311 	glGenBuffersARB(1, &OGLRef.iboPostprocessIndexID);
1312 
1313 	glBindBufferARB(GL_ARRAY_BUFFER_ARB, OGLRef.vboGeometryVtxID);
1314 	glBufferDataARB(GL_ARRAY_BUFFER_ARB, VERTLIST_SIZE * sizeof(VERT), NULL, GL_STREAM_DRAW_ARB);
1315 	glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, OGLRef.iboGeometryIndexID);
1316 	glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, OGLRENDER_VERT_INDEX_BUFFER_COUNT * sizeof(GLushort), NULL, GL_STREAM_DRAW_ARB);
1317 
1318 	glBindBufferARB(GL_ARRAY_BUFFER_ARB, OGLRef.vboPostprocessVtxID);
1319 	glBufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(PostprocessVtxBuffer), PostprocessVtxBuffer, GL_STATIC_DRAW_ARB);
1320 	glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, OGLRef.iboPostprocessIndexID);
1321 	glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, sizeof(PostprocessElementBuffer), PostprocessElementBuffer, GL_STATIC_DRAW_ARB);
1322 
1323 	glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1324 	glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1325 
1326 	return OGLERROR_NOERR;
1327 }
1328 
DestroyVBOs()1329 void OpenGLRenderer_1_2::DestroyVBOs()
1330 {
1331 	if (!this->isVBOSupported)
1332 		return;
1333 
1334 	OGLRenderRef &OGLRef = *this->ref;
1335 
1336 	glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1337 	glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1338 
1339 	glDeleteBuffersARB(1, &OGLRef.vboGeometryVtxID);
1340 	glDeleteBuffersARB(1, &OGLRef.iboGeometryIndexID);
1341 	glDeleteBuffersARB(1, &OGLRef.vboPostprocessVtxID);
1342 	glDeleteBuffersARB(1, &OGLRef.iboPostprocessIndexID);
1343 
1344 	this->isVBOSupported = false;
1345 }
1346 
CreatePBOs()1347 Render3DError OpenGLRenderer_1_2::CreatePBOs()
1348 {
1349 	OGLRenderRef &OGLRef = *this->ref;
1350 
1351 	glGenBuffersARB(1, &OGLRef.pboRenderDataID);
1352 	glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, OGLRef.pboRenderDataID);
1353 	glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, this->_framebufferColorSizeBytes, NULL, GL_STREAM_READ_ARB);
1354 
1355 	return OGLERROR_NOERR;
1356 }
1357 
DestroyPBOs()1358 void OpenGLRenderer_1_2::DestroyPBOs()
1359 {
1360 	if (!this->isPBOSupported)
1361 	{
1362 		return;
1363 	}
1364 
1365 	glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
1366 	glDeleteBuffersARB(1, &this->ref->pboRenderDataID);
1367 
1368 	this->isPBOSupported = false;
1369 }
1370 
LoadGeometryShaders(std::string & outVertexShaderProgram,std::string & outFragmentShaderProgram)1371 Render3DError OpenGLRenderer_1_2::LoadGeometryShaders(std::string &outVertexShaderProgram, std::string &outFragmentShaderProgram)
1372 {
1373 	outVertexShaderProgram.clear();
1374 	outFragmentShaderProgram.clear();
1375 
1376 	outVertexShaderProgram += std::string(vertexShader_100);
1377 	outFragmentShaderProgram += std::string(fragmentShader_100);
1378 
1379 	return OGLERROR_NOERR;
1380 }
1381 
InitGeometryProgramBindings()1382 Render3DError OpenGLRenderer_1_2::InitGeometryProgramBindings()
1383 {
1384 	OGLRenderRef &OGLRef = *this->ref;
1385 
1386 	glBindAttribLocation(OGLRef.programGeometryID, OGLVertexAttributeID_Position, "inPosition");
1387 	glBindAttribLocation(OGLRef.programGeometryID, OGLVertexAttributeID_TexCoord0, "inTexCoord0");
1388 	glBindAttribLocation(OGLRef.programGeometryID, OGLVertexAttributeID_Color, "inColor");
1389 
1390 	return OGLERROR_NOERR;
1391 }
1392 
InitGeometryProgramShaderLocations()1393 Render3DError OpenGLRenderer_1_2::InitGeometryProgramShaderLocations()
1394 {
1395 	OGLRenderRef &OGLRef = *this->ref;
1396 
1397 	glUseProgram(OGLRef.programGeometryID);
1398 
1399 	const GLint uniformTexRenderObject			= glGetUniformLocation(OGLRef.programGeometryID, "texRenderObject");
1400 	const GLint uniformTexToonTable				= glGetUniformLocation(OGLRef.programGeometryID, "texToonTable");
1401 	glUniform1i(uniformTexRenderObject, 0);
1402 	glUniform1i(uniformTexToonTable, OGLTextureUnitID_ToonTable);
1403 
1404 	OGLRef.uniformStateToonShadingMode			= glGetUniformLocation(OGLRef.programGeometryID, "stateToonShadingMode");
1405 	OGLRef.uniformStateEnableAlphaTest			= glGetUniformLocation(OGLRef.programGeometryID, "stateEnableAlphaTest");
1406 	OGLRef.uniformStateEnableAntialiasing		= glGetUniformLocation(OGLRef.programGeometryID, "stateEnableAntialiasing");
1407 	OGLRef.uniformStateEnableEdgeMarking		= glGetUniformLocation(OGLRef.programGeometryID, "stateEnableEdgeMarking");
1408 	OGLRef.uniformStateUseWDepth				= glGetUniformLocation(OGLRef.programGeometryID, "stateUseWDepth");
1409 	OGLRef.uniformStateAlphaTestRef				= glGetUniformLocation(OGLRef.programGeometryID, "stateAlphaTestRef");
1410 
1411 	OGLRef.uniformPolyTexScale					= glGetUniformLocation(OGLRef.programGeometryID, "polyTexScale");
1412 	OGLRef.uniformPolyMode						= glGetUniformLocation(OGLRef.programGeometryID, "polyMode");
1413 	OGLRef.uniformPolyEnableDepthWrite			= glGetUniformLocation(OGLRef.programGeometryID, "polyEnableDepthWrite");
1414 	OGLRef.uniformPolySetNewDepthForTranslucent	= glGetUniformLocation(OGLRef.programGeometryID, "polySetNewDepthForTranslucent");
1415 	OGLRef.uniformPolyAlpha						= glGetUniformLocation(OGLRef.programGeometryID, "polyAlpha");
1416 	OGLRef.uniformPolyID						= glGetUniformLocation(OGLRef.programGeometryID, "polyID");
1417 
1418 	OGLRef.uniformPolyEnableTexture				= glGetUniformLocation(OGLRef.programGeometryID, "polyEnableTexture");
1419 	OGLRef.uniformPolyEnableFog					= glGetUniformLocation(OGLRef.programGeometryID, "polyEnableFog");
1420 
1421 	return OGLERROR_NOERR;
1422 }
1423 
InitGeometryProgram(const std::string & vertexShaderProgram,const std::string & fragmentShaderProgram)1424 Render3DError OpenGLRenderer_1_2::InitGeometryProgram(const std::string &vertexShaderProgram, const std::string &fragmentShaderProgram)
1425 {
1426 	OGLRenderRef &OGLRef = *this->ref;
1427 
1428 	OGLRef.vertexGeometryShaderID = glCreateShader(GL_VERTEX_SHADER);
1429 	if(!OGLRef.vertexGeometryShaderID)
1430 	{
1431 		INFO("OpenGL: Failed to create the vertex shader. Disabling shaders and using fixed-function pipeline. Some emulation features will be disabled.\n");
1432 		return OGLERROR_SHADER_CREATE_ERROR;
1433 	}
1434 
1435 	const char *vertexShaderProgramChar = vertexShaderProgram.c_str();
1436 	glShaderSource(OGLRef.vertexGeometryShaderID, 1, (const GLchar **)&vertexShaderProgramChar, NULL);
1437 	glCompileShader(OGLRef.vertexGeometryShaderID);
1438 	if (!this->ValidateShaderCompile(OGLRef.vertexGeometryShaderID))
1439 	{
1440 		glDeleteShader(OGLRef.vertexGeometryShaderID);
1441 		INFO("OpenGL: Failed to compile the vertex shader. Disabling shaders and using fixed-function pipeline. Some emulation features will be disabled.\n");
1442 		return OGLERROR_SHADER_CREATE_ERROR;
1443 	}
1444 
1445 	OGLRef.fragmentGeometryShaderID = glCreateShader(GL_FRAGMENT_SHADER);
1446 	if(!OGLRef.fragmentGeometryShaderID)
1447 	{
1448 		glDeleteShader(OGLRef.vertexGeometryShaderID);
1449 		INFO("OpenGL: Failed to create the fragment shader. Disabling shaders and using fixed-function pipeline. Some emulation features will be disabled.\n");
1450 		return OGLERROR_SHADER_CREATE_ERROR;
1451 	}
1452 
1453 	const char *fragmentShaderProgramChar = fragmentShaderProgram.c_str();
1454 	glShaderSource(OGLRef.fragmentGeometryShaderID, 1, (const GLchar **)&fragmentShaderProgramChar, NULL);
1455 	glCompileShader(OGLRef.fragmentGeometryShaderID);
1456 	if (!this->ValidateShaderCompile(OGLRef.fragmentGeometryShaderID))
1457 	{
1458 		glDeleteShader(OGLRef.vertexGeometryShaderID);
1459 		glDeleteShader(OGLRef.fragmentGeometryShaderID);
1460 		INFO("OpenGL: Failed to compile the fragment shader. Disabling shaders and using fixed-function pipeline. Some emulation features will be disabled.\n");
1461 		return OGLERROR_SHADER_CREATE_ERROR;
1462 	}
1463 
1464 	OGLRef.programGeometryID = glCreateProgram();
1465 	if(!OGLRef.programGeometryID)
1466 	{
1467 		glDeleteShader(OGLRef.vertexGeometryShaderID);
1468 		glDeleteShader(OGLRef.fragmentGeometryShaderID);
1469 		INFO("OpenGL: Failed to create the shader program. Disabling shaders and using fixed-function pipeline. Some emulation features will be disabled.\n");
1470 		return OGLERROR_SHADER_CREATE_ERROR;
1471 	}
1472 
1473 	glAttachShader(OGLRef.programGeometryID, OGLRef.vertexGeometryShaderID);
1474 	glAttachShader(OGLRef.programGeometryID, OGLRef.fragmentGeometryShaderID);
1475 
1476 	this->InitGeometryProgramBindings();
1477 
1478 	glLinkProgram(OGLRef.programGeometryID);
1479 	if (!this->ValidateShaderProgramLink(OGLRef.programGeometryID))
1480 	{
1481 		glDetachShader(OGLRef.programGeometryID, OGLRef.vertexGeometryShaderID);
1482 		glDetachShader(OGLRef.programGeometryID, OGLRef.fragmentGeometryShaderID);
1483 		glDeleteProgram(OGLRef.programGeometryID);
1484 		glDeleteShader(OGLRef.vertexGeometryShaderID);
1485 		glDeleteShader(OGLRef.fragmentGeometryShaderID);
1486 		INFO("OpenGL: Failed to link the shader program. Disabling shaders and using fixed-function pipeline. Some emulation features will be disabled.\n");
1487 		return OGLERROR_SHADER_CREATE_ERROR;
1488 	}
1489 
1490 	glValidateProgram(OGLRef.programGeometryID);
1491 
1492 	this->InitGeometryProgramShaderLocations();
1493 
1494 	INFO("OpenGL: Successfully created shaders.\n");
1495 
1496 	this->CreateToonTable();
1497 
1498 	return OGLERROR_NOERR;
1499 }
1500 
DestroyGeometryProgram()1501 void OpenGLRenderer_1_2::DestroyGeometryProgram()
1502 {
1503 	if(!this->isShaderSupported)
1504 	{
1505 		return;
1506 	}
1507 
1508 	OGLRenderRef &OGLRef = *this->ref;
1509 
1510 	glUseProgram(0);
1511 
1512 	glDetachShader(OGLRef.programGeometryID, OGLRef.vertexGeometryShaderID);
1513 	glDetachShader(OGLRef.programGeometryID, OGLRef.fragmentGeometryShaderID);
1514 
1515 	glDeleteProgram(OGLRef.programGeometryID);
1516 	glDeleteShader(OGLRef.vertexGeometryShaderID);
1517 	glDeleteShader(OGLRef.fragmentGeometryShaderID);
1518 
1519 	this->DestroyToonTable();
1520 
1521 	this->isShaderSupported = false;
1522 }
1523 
CreateVAOs()1524 Render3DError OpenGLRenderer_1_2::CreateVAOs()
1525 {
1526 	OGLRenderRef &OGLRef = *this->ref;
1527 
1528 	glGenVertexArrays(1, &OGLRef.vaoGeometryStatesID);
1529 	glGenVertexArrays(1, &OGLRef.vaoPostprocessStatesID);
1530 
1531 	glBindVertexArray(OGLRef.vaoGeometryStatesID);
1532 	glBindBufferARB(GL_ARRAY_BUFFER_ARB, OGLRef.vboGeometryVtxID);
1533 	glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, OGLRef.iboGeometryIndexID);
1534 
1535 	glEnableVertexAttribArray(OGLVertexAttributeID_Position);
1536 	glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0);
1537 	glEnableVertexAttribArray(OGLVertexAttributeID_Color);
1538 	glVertexAttribPointer(OGLVertexAttributeID_Position, 4, GL_FLOAT, GL_FALSE, sizeof(VERT), (const GLvoid *)offsetof(VERT, coord));
1539 	glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(VERT), (const GLvoid *)offsetof(VERT, texcoord));
1540 	glVertexAttribPointer(OGLVertexAttributeID_Color, 3, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(VERT), (const GLvoid *)offsetof(VERT, color));
1541 
1542 	glBindVertexArray(0);
1543 
1544 	glBindVertexArray(OGLRef.vaoPostprocessStatesID);
1545 	glBindBufferARB(GL_ARRAY_BUFFER_ARB, OGLRef.vboPostprocessVtxID);
1546 	glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, OGLRef.iboPostprocessIndexID);
1547 
1548 	glEnableVertexAttribArray(OGLVertexAttributeID_Position);
1549 	glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0);
1550 	glVertexAttribPointer(OGLVertexAttributeID_Position, 2, GL_FLOAT, GL_FALSE, 0, 0);
1551 	glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *)(sizeof(GLfloat) * 8));
1552 
1553 	glBindVertexArray(0);
1554 
1555 	return OGLERROR_NOERR;
1556 }
1557 
DestroyVAOs()1558 void OpenGLRenderer_1_2::DestroyVAOs()
1559 {
1560 	OGLRenderRef &OGLRef = *this->ref;
1561 
1562 	if (!this->isVAOSupported)
1563 	{
1564 		return;
1565 	}
1566 
1567 	glBindVertexArray(0);
1568 	glDeleteVertexArrays(1, &OGLRef.vaoGeometryStatesID);
1569 	glDeleteVertexArrays(1, &OGLRef.vaoPostprocessStatesID);
1570 
1571 	this->isVAOSupported = false;
1572 }
1573 
CreateFBOs()1574 Render3DError OpenGLRenderer_1_2::CreateFBOs()
1575 {
1576 	OGLRenderRef &OGLRef = *this->ref;
1577 
1578 	// Set up FBO render targets
1579 	glGenTextures(1, &OGLRef.texCIColorID);
1580 	glGenTextures(1, &OGLRef.texCIDepthID);
1581 	glGenTextures(1, &OGLRef.texCIFogAttrID);
1582 	glGenTextures(1, &OGLRef.texCIPolyID);
1583 	glGenTextures(1, &OGLRef.texCIDepthStencilID);
1584 
1585 	glGenTextures(1, &OGLRef.texFinalColorID);
1586 	glGenTextures(1, &OGLRef.texGColorID);
1587 	glGenTextures(1, &OGLRef.texGDepthID);
1588 	glGenTextures(1, &OGLRef.texGFogAttrID);
1589 	glGenTextures(1, &OGLRef.texGPolyID);
1590 	glGenTextures(1, &OGLRef.texGDepthStencilID);
1591 	glGenTextures(1, &OGLRef.texPostprocessFogID);
1592 
1593 	if (this->willFlipFramebufferOnGPU)
1594 	{
1595 		glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_FinalColor);
1596 		glBindTexture(GL_TEXTURE_2D, OGLRef.texFinalColorID);
1597 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1598 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1599 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1600 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1601 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
1602 	}
1603 
1604 	glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GColor);
1605 	glBindTexture(GL_TEXTURE_2D, OGLRef.texGDepthStencilID);
1606 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1607 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1608 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1609 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1610 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
1611 	glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8_EXT, this->_framebufferWidth, this->_framebufferHeight, 0, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, NULL);
1612 
1613 	glBindTexture(GL_TEXTURE_2D, OGLRef.texGColorID);
1614 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1615 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1616 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1617 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1618 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
1619 
1620 	glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GDepth);
1621 	glBindTexture(GL_TEXTURE_2D, OGLRef.texGDepthID);
1622 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1623 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1624 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1625 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1626 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
1627 
1628 	glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GPolyID);
1629 	glBindTexture(GL_TEXTURE_2D, OGLRef.texGPolyID);
1630 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1631 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1632 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1633 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1634 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
1635 
1636 	glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_FogAttr);
1637 	glBindTexture(GL_TEXTURE_2D, OGLRef.texGFogAttrID);
1638 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1639 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1640 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1641 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1642 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
1643 
1644 	glActiveTexture(GL_TEXTURE0);
1645 
1646 	glBindTexture(GL_TEXTURE_2D, OGLRef.texPostprocessFogID);
1647 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1648 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1649 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1650 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1651 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
1652 
1653 	glBindTexture(GL_TEXTURE_2D, OGLRef.texCIColorID);
1654 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1655 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1656 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1657 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1658 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
1659 
1660 	glBindTexture(GL_TEXTURE_2D, OGLRef.texCIDepthStencilID);
1661 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1662 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1663 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1664 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1665 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE);
1666 	glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8_EXT, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, 0, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, NULL);
1667 
1668 	glBindTexture(GL_TEXTURE_2D, OGLRef.texCIDepthID);
1669 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1670 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1671 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1672 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1673 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
1674 
1675 	glBindTexture(GL_TEXTURE_2D, OGLRef.texCIPolyID);
1676 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1677 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1678 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1679 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1680 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
1681 
1682 	glBindTexture(GL_TEXTURE_2D, OGLRef.texCIFogAttrID);
1683 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1684 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1685 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1686 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1687 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
1688 
1689 	glBindTexture(GL_TEXTURE_2D, 0);
1690 
1691 	// Set up RBOs
1692 	if (this->willConvertFramebufferOnGPU)
1693 	{
1694 		glGenRenderbuffersEXT(1, &OGLRef.rboFramebufferRGBA6665ID);
1695 		glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboFramebufferRGBA6665ID);
1696 		glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight);
1697 	}
1698 
1699 	// Set up FBOs
1700 	glGenFramebuffersEXT(1, &OGLRef.fboClearImageID);
1701 	glGenFramebuffersEXT(1, &OGLRef.fboRenderID);
1702 	glGenFramebuffersEXT(1, &OGLRef.fboPostprocessID);
1703 
1704 	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboClearImageID);
1705 	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, OGLRef.texCIColorID, 0);
1706 	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, OGLRef.texCIDepthID, 0);
1707 	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_TEXTURE_2D, OGLRef.texCIPolyID, 0);
1708 	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT3_EXT, GL_TEXTURE_2D, OGLRef.texCIFogAttrID, 0);
1709 	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, OGLRef.texCIDepthStencilID, 0);
1710 	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, OGLRef.texCIDepthStencilID, 0);
1711 
1712 	if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT)
1713 	{
1714 		INFO("OpenGL: Failed to created FBOs. Some emulation features will be disabled.\n");
1715 
1716 		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1717 		glDeleteFramebuffersEXT(1, &OGLRef.fboClearImageID);
1718 		glDeleteFramebuffersEXT(1, &OGLRef.fboRenderID);
1719 		glDeleteFramebuffersEXT(1, &OGLRef.fboPostprocessID);
1720 		glDeleteTextures(1, &OGLRef.texCIColorID);
1721 		glDeleteTextures(1, &OGLRef.texCIDepthID);
1722 		glDeleteTextures(1, &OGLRef.texCIFogAttrID);
1723 		glDeleteTextures(1, &OGLRef.texCIPolyID);
1724 		glDeleteTextures(1, &OGLRef.texCIDepthStencilID);
1725 		glDeleteTextures(1, &OGLRef.texGColorID);
1726 		glDeleteTextures(1, &OGLRef.texGDepthID);
1727 		glDeleteTextures(1, &OGLRef.texGPolyID);
1728 		glDeleteTextures(1, &OGLRef.texGFogAttrID);
1729 		glDeleteTextures(1, &OGLRef.texGDepthStencilID);
1730 		glDeleteTextures(1, &OGLRef.texPostprocessFogID);
1731 		glDeleteTextures(1, &OGLRef.texFinalColorID);
1732 		glDeleteRenderbuffersEXT(1, &OGLRef.rboFramebufferRGBA6665ID);
1733 
1734 		OGLRef.fboClearImageID = 0;
1735 		OGLRef.fboRenderID = 0;
1736 		OGLRef.fboPostprocessID = 0;
1737 
1738 		this->isFBOSupported = false;
1739 		return OGLERROR_FBO_CREATE_ERROR;
1740 	}
1741 
1742 	glDrawBuffers(4, RenderDrawList);
1743 	glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
1744 
1745 	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID);
1746 	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, OGLRef.texGColorID, 0);
1747 	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, OGLRef.texGDepthID, 0);
1748 	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_TEXTURE_2D, OGLRef.texGPolyID, 0);
1749 	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT3_EXT, GL_TEXTURE_2D, OGLRef.texGFogAttrID, 0);
1750 	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, OGLRef.texGDepthStencilID, 0);
1751 	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_TEXTURE_2D, OGLRef.texGDepthStencilID, 0);
1752 
1753 	if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT)
1754 	{
1755 		INFO("OpenGL: Failed to created FBOs. Some emulation features will be disabled.\n");
1756 
1757 		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1758 		glDeleteFramebuffersEXT(1, &OGLRef.fboClearImageID);
1759 		glDeleteFramebuffersEXT(1, &OGLRef.fboRenderID);
1760 		glDeleteFramebuffersEXT(1, &OGLRef.fboPostprocessID);
1761 		glDeleteTextures(1, &OGLRef.texCIColorID);
1762 		glDeleteTextures(1, &OGLRef.texCIDepthID);
1763 		glDeleteTextures(1, &OGLRef.texCIFogAttrID);
1764 		glDeleteTextures(1, &OGLRef.texCIPolyID);
1765 		glDeleteTextures(1, &OGLRef.texCIDepthStencilID);
1766 		glDeleteTextures(1, &OGLRef.texGColorID);
1767 		glDeleteTextures(1, &OGLRef.texGDepthID);
1768 		glDeleteTextures(1, &OGLRef.texGPolyID);
1769 		glDeleteTextures(1, &OGLRef.texGFogAttrID);
1770 		glDeleteTextures(1, &OGLRef.texGDepthStencilID);
1771 		glDeleteTextures(1, &OGLRef.texPostprocessFogID);
1772 		glDeleteTextures(1, &OGLRef.texFinalColorID);
1773 		glDeleteRenderbuffersEXT(1, &OGLRef.rboFramebufferRGBA6665ID);
1774 
1775 		OGLRef.fboClearImageID = 0;
1776 		OGLRef.fboRenderID = 0;
1777 		OGLRef.fboPostprocessID = 0;
1778 
1779 		this->isFBOSupported = false;
1780 		return OGLERROR_FBO_CREATE_ERROR;
1781 	}
1782 
1783 	glDrawBuffers(4, RenderDrawList);
1784 	glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
1785 
1786 	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboPostprocessID);
1787 	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, OGLRef.texPostprocessFogID, 0);
1788 
1789 	if (this->willFlipFramebufferOnGPU)
1790 	{
1791 		glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, OGLRef.texFinalColorID, 0);
1792 	}
1793 
1794 	if (this->willConvertFramebufferOnGPU)
1795 	{
1796 		glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_RENDERBUFFER_EXT, OGLRef.rboFramebufferRGBA6665ID);
1797 	}
1798 
1799 	if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT)
1800 	{
1801 		INFO("OpenGL: Failed to created FBOs. Some emulation features will be disabled.\n");
1802 
1803 		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1804 		glDeleteFramebuffersEXT(1, &OGLRef.fboClearImageID);
1805 		glDeleteFramebuffersEXT(1, &OGLRef.fboRenderID);
1806 		glDeleteFramebuffersEXT(1, &OGLRef.fboPostprocessID);
1807 		glDeleteTextures(1, &OGLRef.texCIColorID);
1808 		glDeleteTextures(1, &OGLRef.texCIDepthID);
1809 		glDeleteTextures(1, &OGLRef.texCIFogAttrID);
1810 		glDeleteTextures(1, &OGLRef.texCIPolyID);
1811 		glDeleteTextures(1, &OGLRef.texCIDepthStencilID);
1812 		glDeleteTextures(1, &OGLRef.texGColorID);
1813 		glDeleteTextures(1, &OGLRef.texGDepthID);
1814 		glDeleteTextures(1, &OGLRef.texGPolyID);
1815 		glDeleteTextures(1, &OGLRef.texGFogAttrID);
1816 		glDeleteTextures(1, &OGLRef.texGDepthStencilID);
1817 		glDeleteTextures(1, &OGLRef.texPostprocessFogID);
1818 		glDeleteTextures(1, &OGLRef.texFinalColorID);
1819 		glDeleteRenderbuffersEXT(1, &OGLRef.rboFramebufferRGBA6665ID);
1820 
1821 		OGLRef.fboClearImageID = 0;
1822 		OGLRef.fboRenderID = 0;
1823 		OGLRef.fboPostprocessID = 0;
1824 
1825 		this->isFBOSupported = false;
1826 		return OGLERROR_FBO_CREATE_ERROR;
1827 	}
1828 
1829 	glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
1830 	glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
1831 
1832 	OGLRef.selectedRenderingFBO = OGLRef.fboRenderID;
1833 	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.selectedRenderingFBO);
1834 	INFO("OpenGL: Successfully created FBOs.\n");
1835 
1836 	return OGLERROR_NOERR;
1837 }
1838 
DestroyFBOs()1839 void OpenGLRenderer_1_2::DestroyFBOs()
1840 {
1841 	if (!this->isFBOSupported)
1842 	{
1843 		return;
1844 	}
1845 
1846 	OGLRenderRef &OGLRef = *this->ref;
1847 
1848 	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1849 	glDeleteFramebuffersEXT(1, &OGLRef.fboClearImageID);
1850 	glDeleteFramebuffersEXT(1, &OGLRef.fboRenderID);
1851 	glDeleteFramebuffersEXT(1, &OGLRef.fboPostprocessID);
1852 	glDeleteTextures(1, &OGLRef.texCIColorID);
1853 	glDeleteTextures(1, &OGLRef.texCIDepthID);
1854 	glDeleteTextures(1, &OGLRef.texCIFogAttrID);
1855 	glDeleteTextures(1, &OGLRef.texCIPolyID);
1856 	glDeleteTextures(1, &OGLRef.texCIDepthStencilID);
1857 	glDeleteTextures(1, &OGLRef.texGColorID);
1858 	glDeleteTextures(1, &OGLRef.texGDepthID);
1859 	glDeleteTextures(1, &OGLRef.texGPolyID);
1860 	glDeleteTextures(1, &OGLRef.texGFogAttrID);
1861 	glDeleteTextures(1, &OGLRef.texGDepthStencilID);
1862 	glDeleteTextures(1, &OGLRef.texPostprocessFogID);
1863 	glDeleteTextures(1, &OGLRef.texFinalColorID);
1864 	glDeleteRenderbuffersEXT(1, &OGLRef.rboFramebufferRGBA6665ID);
1865 
1866 	OGLRef.fboClearImageID = 0;
1867 	OGLRef.fboRenderID = 0;
1868 	OGLRef.fboPostprocessID = 0;
1869 
1870 	this->isFBOSupported = false;
1871 }
1872 
CreateMultisampledFBO()1873 Render3DError OpenGLRenderer_1_2::CreateMultisampledFBO()
1874 {
1875 	// Check the maximum number of samples that the driver supports and use that.
1876 	// Since our target resolution is only 256x192 pixels, using the most samples
1877 	// possible is the best thing to do.
1878 	GLint maxSamples = 0;
1879 	glGetIntegerv(GL_MAX_SAMPLES_EXT, &maxSamples);
1880 
1881 	if (maxSamples < 2)
1882 	{
1883 		INFO("OpenGL: Driver does not support at least 2x multisampled FBOs. Multisample antialiasing will be disabled.\n");
1884 		return OGLERROR_FEATURE_UNSUPPORTED;
1885 	}
1886 	else if (maxSamples > OGLRENDER_MAX_MULTISAMPLES)
1887 	{
1888 		maxSamples = OGLRENDER_MAX_MULTISAMPLES;
1889 	}
1890 
1891 	OGLRenderRef &OGLRef = *this->ref;
1892 
1893 	// Set up FBO render targets
1894 	glGenRenderbuffersEXT(1, &OGLRef.rboMSGColorID);
1895 	glGenRenderbuffersEXT(1, &OGLRef.rboMSGDepthID);
1896 	glGenRenderbuffersEXT(1, &OGLRef.rboMSGPolyID);
1897 	glGenRenderbuffersEXT(1, &OGLRef.rboMSGFogAttrID);
1898 	glGenRenderbuffersEXT(1, &OGLRef.rboMSGDepthStencilID);
1899 
1900 	glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGColorID);
1901 	glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight);
1902 	glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGDepthID);
1903 	glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight);
1904 	glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGPolyID);
1905 	glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight);
1906 	glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGFogAttrID);
1907 	glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_RGBA, this->_framebufferWidth, this->_framebufferHeight);
1908 	glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGDepthStencilID);
1909 	glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_DEPTH24_STENCIL8_EXT, this->_framebufferWidth, this->_framebufferHeight);
1910 
1911 	// Set up multisampled rendering FBO
1912 	glGenFramebuffersEXT(1, &OGLRef.fboMSIntermediateRenderID);
1913 
1914 	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboMSIntermediateRenderID);
1915 	glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, OGLRef.rboMSGColorID);
1916 	glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_RENDERBUFFER_EXT, OGLRef.rboMSGDepthID);
1917 	glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, GL_RENDERBUFFER_EXT, OGLRef.rboMSGPolyID);
1918 	glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT3_EXT, GL_RENDERBUFFER_EXT, OGLRef.rboMSGFogAttrID);
1919 	glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, OGLRef.rboMSGDepthStencilID);
1920 	glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, OGLRef.rboMSGDepthStencilID);
1921 
1922 	if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT)
1923 	{
1924 		INFO("OpenGL: Failed to create multisampled FBO. Multisample antialiasing will be disabled.\n");
1925 
1926 		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1927 		glDeleteFramebuffersEXT(1, &OGLRef.fboMSIntermediateRenderID);
1928 		glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGColorID);
1929 		glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGDepthID);
1930 		glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGPolyID);
1931 		glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGFogAttrID);
1932 		glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGDepthStencilID);
1933 
1934 		return OGLERROR_FBO_CREATE_ERROR;
1935 	}
1936 
1937 	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID);
1938 	INFO("OpenGL: Successfully created multisampled FBO.\n");
1939 
1940 	return OGLERROR_NOERR;
1941 }
1942 
DestroyMultisampledFBO()1943 void OpenGLRenderer_1_2::DestroyMultisampledFBO()
1944 {
1945 	if (!this->isMultisampledFBOSupported)
1946 	{
1947 		return;
1948 	}
1949 
1950 	OGLRenderRef &OGLRef = *this->ref;
1951 
1952 	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1953 	glDeleteFramebuffersEXT(1, &OGLRef.fboMSIntermediateRenderID);
1954 	glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGColorID);
1955 	glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGDepthID);
1956 	glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGPolyID);
1957 	glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGFogAttrID);
1958 	glDeleteRenderbuffersEXT(1, &OGLRef.rboMSGDepthStencilID);
1959 
1960 	this->isMultisampledFBOSupported = false;
1961 }
1962 
InitFinalRenderStates(const std::set<std::string> * oglExtensionSet)1963 Render3DError OpenGLRenderer_1_2::InitFinalRenderStates(const std::set<std::string> *oglExtensionSet)
1964 {
1965 	OGLRenderRef &OGLRef = *this->ref;
1966 
1967 	bool isTexMirroredRepeatSupported = this->IsExtensionPresent(oglExtensionSet, "GL_ARB_texture_mirrored_repeat");
1968 	bool isBlendFuncSeparateSupported = this->IsExtensionPresent(oglExtensionSet, "GL_EXT_blend_func_separate");
1969 	bool isBlendEquationSeparateSupported = this->IsExtensionPresent(oglExtensionSet, "GL_EXT_blend_equation_separate");
1970 
1971 	// Blending Support
1972 	if (isBlendFuncSeparateSupported)
1973 	{
1974 		if (isBlendEquationSeparateSupported)
1975 		{
1976 			// we want to use alpha destination blending so we can track the last-rendered alpha value
1977 			// test: new super mario brothers renders the stormclouds at the beginning
1978 			glBlendFuncSeparateEXT(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_DST_ALPHA);
1979 			glBlendEquationSeparateEXT(GL_FUNC_ADD, GL_MAX);
1980 		}
1981 		else
1982 		{
1983 			glBlendFuncSeparateEXT(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_DST_ALPHA);
1984 		}
1985 	}
1986 	else
1987 	{
1988 		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1989 	}
1990 
1991 	// Mirrored Repeat Mode Support
1992 	OGLRef.stateTexMirroredRepeat = isTexMirroredRepeatSupported ? GL_MIRRORED_REPEAT : GL_REPEAT;
1993 
1994 	// Map the vertex list's colors with 4 floats per color. This is being done
1995 	// because OpenGL needs 4-colors per vertex to support translucency. (The DS
1996 	// uses 3-colors per vertex, and adds alpha through the poly, so we can't
1997 	// simply reference the colors+alpha from just the vertices by themselves.)
1998 	OGLRef.color4fBuffer = (this->isShaderSupported) ? NULL : new GLfloat[VERTLIST_SIZE * 4];
1999 
2000 	// If VBOs aren't supported, then we need to create the index buffer on the
2001 	// client side so that we have a buffer to update.
2002 	OGLRef.vertIndexBuffer = (this->isVBOSupported) ? NULL : new GLushort[OGLRENDER_VERT_INDEX_BUFFER_COUNT];
2003 
2004 	return OGLERROR_NOERR;
2005 }
2006 
InitTextures()2007 Render3DError OpenGLRenderer_1_2::InitTextures()
2008 {
2009 	this->ExpandFreeTextures();
2010 
2011 	return OGLERROR_NOERR;
2012 }
2013 
InitTables()2014 Render3DError OpenGLRenderer_1_2::InitTables()
2015 {
2016 	static bool needTableInit = true;
2017 
2018 	if (needTableInit)
2019 	{
2020 		for (size_t i = 0; i < 256; i++)
2021 			material_8bit_to_float[i] = (GLfloat)(i * 4) / 255.0f;
2022 
2023 		needTableInit = false;
2024 	}
2025 
2026 	return OGLERROR_NOERR;
2027 }
2028 
InitPostprocessingPrograms(const std::string & edgeMarkVtxShader,const std::string & edgeMarkFragShader,const std::string & fogVtxShader,const std::string & fogFragShader,const std::string & framebufferOutputVtxShader,const std::string & framebufferOutputRGBA6665FragShader,const std::string & framebufferOutputRGBA8888FragShader)2029 Render3DError OpenGLRenderer_1_2::InitPostprocessingPrograms(const std::string &edgeMarkVtxShader,
2030 															 const std::string &edgeMarkFragShader,
2031 															 const std::string &fogVtxShader,
2032 															 const std::string &fogFragShader,
2033 															 const std::string &framebufferOutputVtxShader,
2034 															 const std::string &framebufferOutputRGBA6665FragShader,
2035 															 const std::string &framebufferOutputRGBA8888FragShader)
2036 {
2037 	return OGLERROR_FEATURE_UNSUPPORTED;
2038 }
2039 
DestroyPostprocessingPrograms()2040 Render3DError OpenGLRenderer_1_2::DestroyPostprocessingPrograms()
2041 {
2042 	return OGLERROR_FEATURE_UNSUPPORTED;
2043 }
2044 
InitEdgeMarkProgramBindings()2045 Render3DError OpenGLRenderer_1_2::InitEdgeMarkProgramBindings()
2046 {
2047 	return OGLERROR_FEATURE_UNSUPPORTED;
2048 }
2049 
InitEdgeMarkProgramShaderLocations()2050 Render3DError OpenGLRenderer_1_2::InitEdgeMarkProgramShaderLocations()
2051 {
2052 	return OGLERROR_FEATURE_UNSUPPORTED;
2053 }
2054 
InitFogProgramBindings()2055 Render3DError OpenGLRenderer_1_2::InitFogProgramBindings()
2056 {
2057 	return OGLERROR_FEATURE_UNSUPPORTED;
2058 }
2059 
InitFogProgramShaderLocations()2060 Render3DError OpenGLRenderer_1_2::InitFogProgramShaderLocations()
2061 {
2062 	return OGLERROR_FEATURE_UNSUPPORTED;
2063 }
2064 
InitFramebufferOutputProgramBindings()2065 Render3DError OpenGLRenderer_1_2::InitFramebufferOutputProgramBindings()
2066 {
2067 	return OGLERROR_FEATURE_UNSUPPORTED;
2068 }
2069 
InitFramebufferOutputShaderLocations()2070 Render3DError OpenGLRenderer_1_2::InitFramebufferOutputShaderLocations()
2071 {
2072 	return OGLERROR_FEATURE_UNSUPPORTED;
2073 }
2074 
CreateToonTable()2075 Render3DError OpenGLRenderer_1_2::CreateToonTable()
2076 {
2077 	OGLRenderRef &OGLRef = *this->ref;
2078 	u16 tempToonTable[32];
2079 	memset(tempToonTable, 0, sizeof(tempToonTable));
2080 
2081 	// The toon table is a special 1D texture where each pixel corresponds
2082 	// to a specific color in the toon table.
2083 	glGenTextures(1, &OGLRef.texToonTableID);
2084 	glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_ToonTable);
2085 	glBindTexture(GL_TEXTURE_1D, OGLRef.texToonTableID);
2086 
2087 	glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2088 	glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2089 	glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
2090 	glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, 32, 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, tempToonTable);
2091 
2092 	glActiveTextureARB(GL_TEXTURE0_ARB);
2093 
2094 	return OGLERROR_NOERR;
2095 }
2096 
DestroyToonTable()2097 Render3DError OpenGLRenderer_1_2::DestroyToonTable()
2098 {
2099 	glDeleteTextures(1, &this->ref->texToonTableID);
2100 
2101 	return OGLERROR_NOERR;
2102 }
2103 
UploadClearImage(const u16 * __restrict colorBuffer,const u32 * __restrict depthBuffer,const u8 * __restrict fogBuffer,const u8 * __restrict polyIDBuffer)2104 Render3DError OpenGLRenderer_1_2::UploadClearImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 *__restrict polyIDBuffer)
2105 {
2106 	OGLRenderRef &OGLRef = *this->ref;
2107 
2108 	if (this->isShaderSupported)
2109 	{
2110 		for (size_t i = 0; i < GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT; i++)
2111 		{
2112 			OGLRef.workingCIDepthStencilBuffer[i] = (depthBuffer[i] << 8) | polyIDBuffer[i];
2113 			OGLRef.workingCIDepthBuffer[i] = depthBuffer[i] | 0xFF000000;
2114 			OGLRef.workingCIFogAttributesBuffer[i] = (fogBuffer[i]) ? 0xFF0000FF : 0xFF000000;
2115 			OGLRef.workingCIPolyIDBuffer[i] = (GLuint)polyIDBuffer[i] | 0xFF000000;
2116 		}
2117 	}
2118 	else
2119 	{
2120 		for (size_t i = 0; i < GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT; i++)
2121 		{
2122 			OGLRef.workingCIDepthStencilBuffer[i] = (depthBuffer[i] << 8) | polyIDBuffer[i];
2123 		}
2124 	}
2125 
2126 	glActiveTextureARB(GL_TEXTURE0_ARB);
2127 
2128 	glBindTexture(GL_TEXTURE_2D, OGLRef.texCIColorID);
2129 	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, colorBuffer);
2130 	glBindTexture(GL_TEXTURE_2D, OGLRef.texCIDepthStencilID);
2131 	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, OGLRef.workingCIDepthStencilBuffer);
2132 
2133 	if (this->isShaderSupported)
2134 	{
2135 		glBindTexture(GL_TEXTURE_2D, OGLRef.texCIDepthID);
2136 		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, OGLRef.workingCIDepthBuffer);
2137 
2138 		glBindTexture(GL_TEXTURE_2D, OGLRef.texCIFogAttrID);
2139 		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, OGLRef.workingCIFogAttributesBuffer);
2140 
2141 		glBindTexture(GL_TEXTURE_2D, OGLRef.texCIPolyID);
2142 		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, OGLRef.workingCIPolyIDBuffer);
2143 	}
2144 
2145 	glBindTexture(GL_TEXTURE_2D, 0);
2146 
2147 	return OGLERROR_NOERR;
2148 }
2149 
GetExtensionSet(std::set<std::string> * oglExtensionSet)2150 void OpenGLRenderer_1_2::GetExtensionSet(std::set<std::string> *oglExtensionSet)
2151 {
2152 	std::string oglExtensionString = std::string((const char *)glGetString(GL_EXTENSIONS));
2153 
2154 	size_t extStringStartLoc = 0;
2155 	size_t delimiterLoc = oglExtensionString.find_first_of(' ', extStringStartLoc);
2156 	while (delimiterLoc != std::string::npos)
2157 	{
2158 		std::string extensionName = oglExtensionString.substr(extStringStartLoc, delimiterLoc - extStringStartLoc);
2159 		oglExtensionSet->insert(extensionName);
2160 
2161 		extStringStartLoc = delimiterLoc + 1;
2162 		delimiterLoc = oglExtensionString.find_first_of(' ', extStringStartLoc);
2163 	}
2164 
2165 	if (extStringStartLoc - oglExtensionString.length() > 0)
2166 	{
2167 		std::string extensionName = oglExtensionString.substr(extStringStartLoc, oglExtensionString.length() - extStringStartLoc);
2168 		oglExtensionSet->insert(extensionName);
2169 	}
2170 }
2171 
ExpandFreeTextures()2172 Render3DError OpenGLRenderer_1_2::ExpandFreeTextures()
2173 {
2174 	static const GLsizei kInitTextures = 128;
2175 	GLuint oglTempTextureID[kInitTextures];
2176 	glGenTextures(kInitTextures, oglTempTextureID);
2177 
2178 	for(GLsizei i = 0; i < kInitTextures; i++)
2179 	{
2180 		this->ref->freeTextureIDs.push(oglTempTextureID[i]);
2181 	}
2182 
2183 	return OGLERROR_NOERR;
2184 }
2185 
EnableVertexAttributes()2186 Render3DError OpenGLRenderer_1_2::EnableVertexAttributes()
2187 {
2188 	OGLRenderRef &OGLRef = *this->ref;
2189 
2190 	if (this->isVAOSupported)
2191 	{
2192 		glBindVertexArray(OGLRef.vaoGeometryStatesID);
2193 	}
2194 	else
2195 	{
2196 		if (this->isShaderSupported)
2197 		{
2198 			glEnableVertexAttribArray(OGLVertexAttributeID_Position);
2199 			glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0);
2200 			glEnableVertexAttribArray(OGLVertexAttributeID_Color);
2201 			glVertexAttribPointer(OGLVertexAttributeID_Position, 4, GL_FLOAT, GL_FALSE, sizeof(VERT), OGLRef.vtxPtrPosition);
2202 			glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(VERT), OGLRef.vtxPtrTexCoord);
2203 			glVertexAttribPointer(OGLVertexAttributeID_Color, 3, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(VERT), OGLRef.vtxPtrColor);
2204 		}
2205 		else
2206 		{
2207 			glEnableClientState(GL_TEXTURE_COORD_ARRAY);
2208 			glEnableClientState(GL_COLOR_ARRAY);
2209 			glEnableClientState(GL_VERTEX_ARRAY);
2210 
2211 			if (this->isVBOSupported)
2212 			{
2213 				glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
2214 				glColorPointer(4, GL_FLOAT, 0, OGLRef.vtxPtrColor);
2215 				glBindBufferARB(GL_ARRAY_BUFFER_ARB, OGLRef.vboGeometryVtxID);
2216 			}
2217 			else
2218 			{
2219 				glColorPointer(4, GL_FLOAT, 0, OGLRef.vtxPtrColor);
2220 			}
2221 
2222 			glVertexPointer(4, GL_FLOAT, sizeof(VERT), OGLRef.vtxPtrPosition);
2223 			glTexCoordPointer(2, GL_FLOAT, sizeof(VERT), OGLRef.vtxPtrTexCoord);
2224 		}
2225 	}
2226 
2227 	glActiveTextureARB(GL_TEXTURE0_ARB);
2228 
2229 	return OGLERROR_NOERR;
2230 }
2231 
DisableVertexAttributes()2232 Render3DError OpenGLRenderer_1_2::DisableVertexAttributes()
2233 {
2234 	if (this->isVAOSupported)
2235 	{
2236 		glBindVertexArray(0);
2237 	}
2238 	else
2239 	{
2240 		if (this->isShaderSupported)
2241 		{
2242 			glDisableVertexAttribArray(OGLVertexAttributeID_Position);
2243 			glDisableVertexAttribArray(OGLVertexAttributeID_TexCoord0);
2244 			glDisableVertexAttribArray(OGLVertexAttributeID_Color);
2245 		}
2246 		else
2247 		{
2248 			glDisableClientState(GL_VERTEX_ARRAY);
2249 			glDisableClientState(GL_COLOR_ARRAY);
2250 			glDisableClientState(GL_TEXTURE_COORD_ARRAY);
2251 		}
2252 	}
2253 
2254 	return OGLERROR_NOERR;
2255 }
2256 
DownsampleFBO()2257 Render3DError OpenGLRenderer_1_2::DownsampleFBO()
2258 {
2259 	OGLRenderRef &OGLRef = *this->ref;
2260 
2261 	if (this->isMultisampledFBOSupported && OGLRef.selectedRenderingFBO == OGLRef.fboMSIntermediateRenderID)
2262 	{
2263 		glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, OGLRef.fboMSIntermediateRenderID);
2264 		glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, OGLRef.fboRenderID);
2265 
2266 		// Blit the color buffer
2267 		glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
2268 		glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
2269 		glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2270 
2271 		// Blit the working depth buffer
2272 		glReadBuffer(GL_COLOR_ATTACHMENT1_EXT);
2273 		glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT);
2274 		glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2275 
2276 		// Blit the polygon ID buffer
2277 		glReadBuffer(GL_COLOR_ATTACHMENT2_EXT);
2278 		glDrawBuffer(GL_COLOR_ATTACHMENT2_EXT);
2279 		glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2280 
2281 		// Blit the fog buffer
2282 		glReadBuffer(GL_COLOR_ATTACHMENT3_EXT);
2283 		glDrawBuffer(GL_COLOR_ATTACHMENT3_EXT);
2284 		glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2285 
2286 		// Reset framebuffer targets
2287 		glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
2288 		glDrawBuffers(4, RenderDrawList);
2289 		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID);
2290 	}
2291 
2292 	return OGLERROR_NOERR;
2293 }
2294 
ReadBackPixels()2295 Render3DError OpenGLRenderer_1_2::ReadBackPixels()
2296 {
2297 	OGLRenderRef &OGLRef = *this->ref;
2298 
2299 	if (!this->isPBOSupported)
2300 	{
2301 		this->_pixelReadNeedsFinish = true;
2302 		return OGLERROR_NOERR;
2303 	}
2304 
2305 	if (this->_mappedFramebuffer != NULL)
2306 	{
2307 		glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
2308 		this->_mappedFramebuffer = NULL;
2309 	}
2310 
2311 	// Flip the framebuffer in Y to match the coordinates of OpenGL and the NDS hardware.
2312 	if (this->willFlipFramebufferOnGPU)
2313 	{
2314 		glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, OGLRef.fboPostprocessID);
2315 		glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT);
2316 		glBlitFramebufferEXT(0, this->_framebufferHeight, this->_framebufferWidth, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2317 		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboPostprocessID);
2318 		glReadBuffer(GL_COLOR_ATTACHMENT1_EXT);
2319 	}
2320 
2321 	if (this->willConvertFramebufferOnGPU)
2322 	{
2323 		// Perform the color space conversion while we're still on the GPU so
2324 		// that we can avoid having to do it on the CPU.
2325 		const GLuint convertProgramID = (this->_outputFormat == NDSColorFormat_BGR666_Rev) ? OGLRef.programFramebufferRGBA6665OutputID : OGLRef.programFramebufferRGBA8888OutputID;
2326 		glDrawBuffer(GL_COLOR_ATTACHMENT2_EXT);
2327 
2328 		glUseProgram(convertProgramID);
2329 		glViewport(0, 0, this->_framebufferWidth, this->_framebufferHeight);
2330 		glDisable(GL_DEPTH_TEST);
2331 		glDisable(GL_STENCIL_TEST);
2332 		glDisable(GL_BLEND);
2333 		glDisable(GL_CULL_FACE);
2334 
2335 		glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID);
2336 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboPostprocessIndexID);
2337 		glBindVertexArray(OGLRef.vaoPostprocessStatesID);
2338 		glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0);
2339 		glBindVertexArray(0);
2340 
2341 		// Read back the pixels.
2342 		glReadBuffer(GL_COLOR_ATTACHMENT2_EXT);
2343 	}
2344 
2345 	// Read back the pixels in BGRA format, since legacy OpenGL devices may experience a performance
2346 	// penalty if the readback is in any other format.
2347 	glReadPixels(0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_BGRA, GL_UNSIGNED_BYTE, 0);
2348 
2349 	// Set the read and draw target buffers back to color attachment 0, which is always the default.
2350 	if (this->willFlipFramebufferOnGPU || this->willConvertFramebufferOnGPU)
2351 	{
2352 		glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
2353 		glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
2354 	}
2355 
2356 	this->_pixelReadNeedsFinish = true;
2357 	return OGLERROR_NOERR;
2358 }
2359 
DeleteTexture(const TexCacheItem * item)2360 Render3DError OpenGLRenderer_1_2::DeleteTexture(const TexCacheItem *item)
2361 {
2362 	this->ref->freeTextureIDs.push((GLuint)item->texid);
2363 	if(this->currTexture == item)
2364 	{
2365 		this->currTexture = NULL;
2366 	}
2367 
2368 	return OGLERROR_NOERR;
2369 }
2370 
BeginRender(const GFX3D & engine)2371 Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D &engine)
2372 {
2373 	OGLRenderRef &OGLRef = *this->ref;
2374 
2375 	if(!BEGINGL())
2376 	{
2377 		return OGLERROR_BEGINGL_FAILED;
2378 	}
2379 
2380 	if (this->isShaderSupported)
2381 	{
2382 		glUseProgram(OGLRef.programGeometryID);
2383 		glUniform1i(OGLRef.uniformStateToonShadingMode, engine.renderState.shading);
2384 		glUniform1i(OGLRef.uniformStateEnableAlphaTest, (engine.renderState.enableAlphaTest) ? GL_TRUE : GL_FALSE);
2385 		glUniform1i(OGLRef.uniformStateEnableAntialiasing, (engine.renderState.enableAntialiasing) ? GL_TRUE : GL_FALSE);
2386 		glUniform1i(OGLRef.uniformStateEnableEdgeMarking, (engine.renderState.enableEdgeMarking) ? GL_TRUE : GL_FALSE);
2387 		glUniform1i(OGLRef.uniformStateUseWDepth, (engine.renderState.wbuffer) ? GL_TRUE : GL_FALSE);
2388 		glUniform1f(OGLRef.uniformStateAlphaTestRef, divide5bitBy31_LUT[engine.renderState.alphaTestRef]);
2389 	}
2390 	else
2391 	{
2392 		if(engine.renderState.enableAlphaTest && (engine.renderState.alphaTestRef > 0))
2393 		{
2394 			glAlphaFunc(GL_GEQUAL, divide5bitBy31_LUT[engine.renderState.alphaTestRef]);
2395 		}
2396 		else
2397 		{
2398 			glAlphaFunc(GL_GREATER, 0);
2399 		}
2400 
2401 		glMatrixMode(GL_PROJECTION);
2402 		glLoadIdentity();
2403 	}
2404 
2405 	GLushort *indexPtr = NULL;
2406 
2407 	if (this->isVBOSupported)
2408 	{
2409 		glBindBufferARB(GL_ARRAY_BUFFER_ARB, OGLRef.vboGeometryVtxID);
2410 		glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, OGLRef.iboGeometryIndexID);
2411 		indexPtr = (GLushort *)glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB);
2412 	}
2413 	else
2414 	{
2415 		// If VBOs aren't supported, we need to use the client-side buffers here.
2416 		OGLRef.vtxPtrPosition = &engine.vertlist->list[0].coord;
2417 		OGLRef.vtxPtrTexCoord = &engine.vertlist->list[0].texcoord;
2418 		OGLRef.vtxPtrColor = (this->isShaderSupported) ? (GLvoid *)&engine.vertlist->list[0].color : OGLRef.color4fBuffer;
2419 		indexPtr = OGLRef.vertIndexBuffer;
2420 	}
2421 
2422 	size_t vertIndexCount = 0;
2423 
2424 	for (size_t i = 0; i < engine.polylist->count; i++)
2425 	{
2426 		const POLY *thePoly = &engine.polylist->list[engine.indexlist.list[i]];
2427 		const size_t polyType = thePoly->type;
2428 
2429 		if (this->isShaderSupported)
2430 		{
2431 			for (size_t j = 0; j < polyType; j++)
2432 			{
2433 				const GLushort vertIndex = thePoly->vertIndexes[j];
2434 
2435 				// While we're looping through our vertices, add each vertex index to
2436 				// a buffer. For GFX3D_QUADS and GFX3D_QUAD_STRIP, we also add additional
2437 				// vertices here to convert them to GL_TRIANGLES, which are much easier
2438 				// to work with and won't be deprecated in future OpenGL versions.
2439 				indexPtr[vertIndexCount++] = vertIndex;
2440 				if (thePoly->vtxFormat == GFX3D_QUADS || thePoly->vtxFormat == GFX3D_QUAD_STRIP)
2441 				{
2442 					if (j == 2)
2443 					{
2444 						indexPtr[vertIndexCount++] = vertIndex;
2445 					}
2446 					else if (j == 3)
2447 					{
2448 						indexPtr[vertIndexCount++] = thePoly->vertIndexes[0];
2449 					}
2450 				}
2451 			}
2452 		}
2453 		else
2454 		{
2455 			const GLfloat thePolyAlpha = (!thePoly->isWireframe() && thePoly->isTranslucent()) ? divide5bitBy31_LUT[thePoly->getAttributeAlpha()] : 1.0f;
2456 
2457 			for (size_t j = 0; j < polyType; j++)
2458 			{
2459 				const GLushort vertIndex = thePoly->vertIndexes[j];
2460 				const size_t colorIndex = vertIndex * 4;
2461 
2462 				// Consolidate the vertex color and the poly alpha to our internal color buffer
2463 				// so that OpenGL can use it.
2464 				const VERT *vert = &engine.vertlist->list[vertIndex];
2465 				OGLRef.color4fBuffer[colorIndex+0] = material_8bit_to_float[vert->color[0]];
2466 				OGLRef.color4fBuffer[colorIndex+1] = material_8bit_to_float[vert->color[1]];
2467 				OGLRef.color4fBuffer[colorIndex+2] = material_8bit_to_float[vert->color[2]];
2468 				OGLRef.color4fBuffer[colorIndex+3] = thePolyAlpha;
2469 
2470 				// While we're looping through our vertices, add each vertex index to a
2471 				// buffer. For GFX3D_QUADS and GFX3D_QUAD_STRIP, we also add additional
2472 				// vertices here to convert them to GL_TRIANGLES, which are much easier
2473 				// to work with and won't be deprecated in future OpenGL versions.
2474 				indexPtr[vertIndexCount++] = vertIndex;
2475 				if (thePoly->vtxFormat == GFX3D_QUADS || thePoly->vtxFormat == GFX3D_QUAD_STRIP)
2476 				{
2477 					if (j == 2)
2478 					{
2479 						indexPtr[vertIndexCount++] = vertIndex;
2480 					}
2481 					else if (j == 3)
2482 					{
2483 						indexPtr[vertIndexCount++] = thePoly->vertIndexes[0];
2484 					}
2485 				}
2486 			}
2487 		}
2488 	}
2489 
2490 	if (this->isVBOSupported)
2491 	{
2492 		glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
2493 		glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(VERT) * engine.vertlist->count, engine.vertlist);
2494 	}
2495 
2496 	return OGLERROR_NOERR;
2497 }
2498 
RenderGeometry(const GFX3D_State & renderState,const POLYLIST * polyList,const INDEXLIST * indexList)2499 Render3DError OpenGLRenderer_1_2::RenderGeometry(const GFX3D_State &renderState, const POLYLIST *polyList, const INDEXLIST *indexList)
2500 {
2501 	OGLRenderRef &OGLRef = *this->ref;
2502 	const size_t polyCount = polyList->count;
2503 
2504 	// Map GFX3D_QUADS and GFX3D_QUAD_STRIP to GL_TRIANGLES since we will convert them.
2505 	//
2506 	// Also map GFX3D_TRIANGLE_STRIP to GL_TRIANGLES. This is okay since this is actually
2507 	// how the POLY struct stores triangle strip vertices, which is in sets of 3 vertices
2508 	// each. This redefinition is necessary since uploading more than 3 indices at a time
2509 	// will cause glDrawElements() to draw the triangle strip incorrectly.
2510 	static const GLenum oglPrimitiveType[]	= {GL_TRIANGLES, GL_TRIANGLES, GL_TRIANGLES, GL_TRIANGLES,
2511 											   GL_LINE_LOOP, GL_LINE_LOOP, GL_LINE_STRIP, GL_LINE_STRIP};
2512 
2513 	static const GLsizei indexIncrementLUT[] = {3, 6, 3, 6, 3, 4, 3, 4};
2514 
2515 	if (polyCount > 0)
2516 	{
2517 		glEnable(GL_DEPTH_TEST);
2518 
2519 		if(renderState.enableAlphaBlending)
2520 		{
2521 			glEnable(GL_BLEND);
2522 		}
2523 		else
2524 		{
2525 			glDisable(GL_BLEND);
2526 		}
2527 
2528 		this->EnableVertexAttributes();
2529 
2530 		this->_shadowPolyID.clear();
2531 		for (size_t i = 0; i < polyCount; i++)
2532 		{
2533 			const POLY &thePoly = polyList->list[i];
2534 
2535 			if (thePoly.getAttributePolygonMode() != POLYGON_MODE_SHADOW)
2536 			{
2537 				continue;
2538 			}
2539 
2540 			const u8 polyID = thePoly.getAttributePolygonID();
2541 
2542 			if ( (polyID == 0) || (std::find(this->_shadowPolyID.begin(), this->_shadowPolyID.end(), polyID) != this->_shadowPolyID.end()) )
2543 			{
2544 				continue;
2545 			}
2546 
2547 			this->_shadowPolyID.push_back(polyID);
2548 		}
2549 
2550 		const POLY &firstPoly = polyList->list[indexList->list[0]];
2551 		u32 lastPolyAttr = firstPoly.polyAttr;
2552 		u32 lastTexParams = firstPoly.texParam;
2553 		u32 lastTexPalette = firstPoly.texPalette;
2554 		u32 lastViewport = firstPoly.viewport;
2555 
2556 		this->SetupPolygon(firstPoly);
2557 		this->SetupTexture(firstPoly, renderState.enableTexturing);
2558 		this->SetupViewport(lastViewport);
2559 
2560 		GLsizei vertIndexCount = 0;
2561 		GLushort *indexBufferPtr = OGLRef.vertIndexBuffer;
2562 
2563 		// Enumerate through all polygons and render
2564 		for (size_t i = 0; i < polyCount; i++)
2565 		{
2566 			const POLY &thePoly = polyList->list[indexList->list[i]];
2567 
2568 			// Set up the polygon if it changed
2569 			if (lastPolyAttr != thePoly.polyAttr)
2570 			{
2571 				lastPolyAttr = thePoly.polyAttr;
2572 				this->SetupPolygon(thePoly);
2573 			}
2574 
2575 			// Set up the texture if it changed
2576 			if (lastTexParams != thePoly.texParam || lastTexPalette != thePoly.texPalette)
2577 			{
2578 				lastTexParams = thePoly.texParam;
2579 				lastTexPalette = thePoly.texPalette;
2580 				this->SetupTexture(thePoly, renderState.enableTexturing);
2581 			}
2582 
2583 			// Set up the viewport if it changed
2584 			if (lastViewport != thePoly.viewport)
2585 			{
2586 				lastViewport = thePoly.viewport;
2587 				this->SetupViewport(thePoly.viewport);
2588 			}
2589 
2590 			// In wireframe mode, redefine all primitives as GL_LINE_LOOP rather than
2591 			// setting the polygon mode to GL_LINE though glPolygonMode(). Not only is
2592 			// drawing more accurate this way, but it also allows GFX3D_QUADS and
2593 			// GFX3D_QUAD_STRIP primitives to properly draw as wireframe without the
2594 			// extra diagonal line.
2595 			const GLenum polyPrimitive = (!thePoly.isWireframe()) ? oglPrimitiveType[thePoly.vtxFormat] : GL_LINE_LOOP;
2596 
2597 			// Increment the vertex count
2598 			vertIndexCount += indexIncrementLUT[thePoly.vtxFormat];
2599 
2600 			// Look ahead to the next polygon to see if we can simply buffer the indices
2601 			// instead of uploading them now. We can buffer if all polygon states remain
2602 			// the same and we're not drawing a line loop or line strip.
2603 			if (i+1 < polyCount)
2604 			{
2605 				const POLY *nextPoly = &polyList->list[indexList->list[i+1]];
2606 
2607 				if (lastPolyAttr == nextPoly->polyAttr &&
2608 					lastTexParams == nextPoly->texParam &&
2609 					lastTexPalette == nextPoly->texPalette &&
2610 					lastViewport == nextPoly->viewport &&
2611 					polyPrimitive == oglPrimitiveType[nextPoly->vtxFormat] &&
2612 					polyPrimitive != GL_LINE_LOOP &&
2613 					polyPrimitive != GL_LINE_STRIP &&
2614 					oglPrimitiveType[nextPoly->vtxFormat] != GL_LINE_LOOP &&
2615 					oglPrimitiveType[nextPoly->vtxFormat] != GL_LINE_STRIP)
2616 				{
2617 					continue;
2618 				}
2619 			}
2620 
2621 			// Render the polygons
2622 			this->SetPolygonIndex(i);
2623 			glDrawElements(polyPrimitive, vertIndexCount, GL_UNSIGNED_SHORT, indexBufferPtr);
2624 			indexBufferPtr += vertIndexCount;
2625 			vertIndexCount = 0;
2626 		}
2627 
2628 		this->DisableVertexAttributes();
2629 	}
2630 
2631 	this->DownsampleFBO();
2632 
2633 	return OGLERROR_NOERR;
2634 }
2635 
EndRender(const u64 frameCount)2636 Render3DError OpenGLRenderer_1_2::EndRender(const u64 frameCount)
2637 {
2638 	//needs to happen before endgl because it could free some textureids for expired cache items
2639 	TexCache_EvictFrame();
2640 
2641 	this->ReadBackPixels();
2642 
2643 	ENDGL();
2644 
2645 	return OGLERROR_NOERR;
2646 }
2647 
UpdateToonTable(const u16 * toonTableBuffer)2648 Render3DError OpenGLRenderer_1_2::UpdateToonTable(const u16 *toonTableBuffer)
2649 {
2650 	glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_ToonTable);
2651 	glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 32, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, toonTableBuffer);
2652 
2653 	return OGLERROR_NOERR;
2654 }
2655 
ClearUsingImage(const u16 * __restrict colorBuffer,const u32 * __restrict depthBuffer,const u8 * __restrict fogBuffer,const u8 * __restrict polyIDBuffer)2656 Render3DError OpenGLRenderer_1_2::ClearUsingImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 *__restrict polyIDBuffer)
2657 {
2658 	if (!this->isFBOSupported)
2659 	{
2660 		return OGLERROR_FEATURE_UNSUPPORTED;
2661 	}
2662 
2663 	OGLRenderRef &OGLRef = *this->ref;
2664 
2665 	this->UploadClearImage(colorBuffer, depthBuffer, fogBuffer, polyIDBuffer);
2666 
2667 	glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, OGLRef.fboClearImageID);
2668 	glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, OGLRef.fboRenderID);
2669 
2670 	// It might seem wasteful to be doing a separate glClear(GL_STENCIL_BUFFER_BIT) instead
2671 	// of simply blitting the stencil buffer with everything else.
2672 	//
2673 	// We do this because glBlitFramebufferEXT() for GL_STENCIL_BUFFER_BIT has been tested
2674 	// to be unsupported on ATI/AMD GPUs running in compatibility mode. So we do the separate
2675 	// glClear() for GL_STENCIL_BUFFER_BIT to keep these GPUs working.
2676 	glClearStencil(polyIDBuffer[0]);
2677 	glClear(GL_STENCIL_BUFFER_BIT);
2678 
2679 	// Blit the working depth buffer
2680 	glReadBuffer(GL_COLOR_ATTACHMENT1_EXT);
2681 	glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT);
2682 	glBlitFramebufferEXT(0, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GPU_FRAMEBUFFER_NATIVE_WIDTH, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2683 
2684 	// Blit the polygon ID buffer
2685 	glReadBuffer(GL_COLOR_ATTACHMENT2_EXT);
2686 	glDrawBuffer(GL_COLOR_ATTACHMENT2_EXT);
2687 	glBlitFramebufferEXT(0, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GPU_FRAMEBUFFER_NATIVE_WIDTH, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2688 
2689 	// Blit the fog buffer
2690 	glReadBuffer(GL_COLOR_ATTACHMENT3_EXT);
2691 	glDrawBuffer(GL_COLOR_ATTACHMENT3_EXT);
2692 	glBlitFramebufferEXT(0, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GPU_FRAMEBUFFER_NATIVE_WIDTH, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2693 
2694 	// Blit the color buffer. Do this last so that color attachment 0 is set to the read FBO.
2695 	glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
2696 	glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
2697 	glBlitFramebufferEXT(0, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GPU_FRAMEBUFFER_NATIVE_WIDTH, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
2698 
2699 	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID);
2700 	glDrawBuffers(4, RenderDrawList);
2701 
2702 	if (this->isMultisampledFBOSupported)
2703 	{
2704 		OGLRef.selectedRenderingFBO = (CommonSettings.GFX3D_Renderer_Multisample) ? OGLRef.fboMSIntermediateRenderID : OGLRef.fboRenderID;
2705 		if (OGLRef.selectedRenderingFBO == OGLRef.fboMSIntermediateRenderID)
2706 		{
2707 			glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, OGLRef.fboRenderID);
2708 			glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, OGLRef.selectedRenderingFBO);
2709 
2710 			glClearStencil(polyIDBuffer[0]);
2711 			glClear(GL_STENCIL_BUFFER_BIT);
2712 
2713 			// Blit the working depth buffer
2714 			glReadBuffer(GL_COLOR_ATTACHMENT1_EXT);
2715 			glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT);
2716 			glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2717 
2718 			// Blit the polygon ID buffer
2719 			glReadBuffer(GL_COLOR_ATTACHMENT2_EXT);
2720 			glDrawBuffer(GL_COLOR_ATTACHMENT2_EXT);
2721 			glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2722 
2723 			// Blit the fog buffer
2724 			glReadBuffer(GL_COLOR_ATTACHMENT3_EXT);
2725 			glDrawBuffer(GL_COLOR_ATTACHMENT3_EXT);
2726 			glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
2727 
2728 			// Blit the color buffer. Do this last so that color attachment 0 is set to the read FBO.
2729 			glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
2730 			glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
2731 			glBlitFramebufferEXT(0, 0, this->_framebufferWidth, this->_framebufferHeight, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
2732 
2733 			glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.selectedRenderingFBO);
2734 			glDrawBuffers(4, RenderDrawList);
2735 		}
2736 	}
2737 
2738 	return OGLERROR_NOERR;
2739 }
2740 
ClearUsingValues(const FragmentColor & clearColor,const FragmentAttributes & clearAttributes) const2741 Render3DError OpenGLRenderer_1_2::ClearUsingValues(const FragmentColor &clearColor, const FragmentAttributes &clearAttributes) const
2742 {
2743 	OGLRenderRef &OGLRef = *this->ref;
2744 
2745 	if (this->isMultisampledFBOSupported)
2746 	{
2747 		OGLRef.selectedRenderingFBO = (CommonSettings.GFX3D_Renderer_Multisample) ? OGLRef.fboMSIntermediateRenderID : OGLRef.fboRenderID;
2748 		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.selectedRenderingFBO);
2749 	}
2750 
2751 	glDepthMask(GL_TRUE);
2752 
2753 	if (this->isShaderSupported && this->isFBOSupported)
2754 	{
2755 		glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); // texGColorID
2756 		glClearColor(divide5bitBy31_LUT[clearColor.r], divide5bitBy31_LUT[clearColor.g], divide5bitBy31_LUT[clearColor.b], divide5bitBy31_LUT[clearColor.a]);
2757 		glClearDepth((GLclampd)clearAttributes.depth / (GLclampd)0x00FFFFFF);
2758 		glClearStencil(0xFF);
2759 		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2760 
2761 		glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); // texGDepthID
2762 		glClearColor((GLfloat)(clearAttributes.depth & 0x000000FF)/255.0f, (GLfloat)((clearAttributes.depth >> 8) & 0x000000FF)/255.0f, (GLfloat)((clearAttributes.depth >> 16) & 0x000000FF)/255.0f, 1.0);
2763 		glClear(GL_COLOR_BUFFER_BIT);
2764 
2765 		glDrawBuffer(GL_COLOR_ATTACHMENT2_EXT); // texGPolyID
2766 		glClearColor((GLfloat)clearAttributes.opaquePolyID/63.0f, 0.0, 0.0, 1.0);
2767 		glClear(GL_COLOR_BUFFER_BIT);
2768 
2769 		glDrawBuffer(GL_COLOR_ATTACHMENT3_EXT); // texGFogAttrID
2770 		glClearColor(clearAttributes.isFogged, 0.0, 0.0, 1.0);
2771 		glClear(GL_COLOR_BUFFER_BIT);
2772 
2773 		glDrawBuffers(4, RenderDrawList);
2774 	}
2775 	else
2776 	{
2777 		glClearColor(divide5bitBy31_LUT[clearColor.r], divide5bitBy31_LUT[clearColor.g], divide5bitBy31_LUT[clearColor.b], divide5bitBy31_LUT[clearColor.a]);
2778 		glClearDepth((GLclampd)clearAttributes.depth / (GLclampd)0x00FFFFFF);
2779 		glClearStencil(clearAttributes.opaquePolyID);
2780 		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
2781 	}
2782 
2783 	return OGLERROR_NOERR;
2784 }
2785 
SetPolygonIndex(const size_t index)2786 void OpenGLRenderer_1_2::SetPolygonIndex(const size_t index)
2787 {
2788 	this->_currentPolyIndex = index;
2789 }
2790 
SetupPolygon(const POLY & thePoly)2791 Render3DError OpenGLRenderer_1_2::SetupPolygon(const POLY &thePoly)
2792 {
2793 	const PolygonAttributes attr = thePoly.getAttributes();
2794 
2795 	// Set up depth test mode
2796 	static const GLenum oglDepthFunc[2] = {GL_LESS, GL_EQUAL};
2797 	glDepthFunc(oglDepthFunc[attr.enableDepthEqualTest]);
2798 
2799 	// Set up culling mode
2800 	static const GLenum oglCullingMode[4] = {GL_FRONT_AND_BACK, GL_FRONT, GL_BACK, 0};
2801 	GLenum cullingMode = oglCullingMode[attr.surfaceCullingMode];
2802 
2803 	if (cullingMode == 0)
2804 	{
2805 		glDisable(GL_CULL_FACE);
2806 	}
2807 	else
2808 	{
2809 		glEnable(GL_CULL_FACE);
2810 		glCullFace(cullingMode);
2811 	}
2812 
2813 	// Set up depth write
2814 	GLboolean enableDepthWrite = GL_TRUE;
2815 
2816 	// Handle shadow polys. Do this after checking for depth write, since shadow polys
2817 	// can change this too.
2818 	if (attr.polygonMode == POLYGON_MODE_SHADOW)
2819 	{
2820 		glEnable(GL_STENCIL_TEST);
2821 
2822 		if (attr.polygonID == 0)
2823 		{
2824 			//when the polyID is zero, we are writing the shadow mask.
2825 			//set stencilbuf = 1 where the shadow volume is obstructed by geometry.
2826 			//do not write color or depth information.
2827 			glStencilFunc(GL_NOTEQUAL, 0x80, 0xFF);
2828 			glStencilOp(GL_KEEP, GL_ZERO, GL_KEEP);
2829 			glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
2830 			enableDepthWrite = GL_FALSE;
2831 		}
2832 		else
2833 		{
2834 			//when the polyid is nonzero, we are drawing the shadow poly.
2835 			//only draw the shadow poly where the stencilbuf==1.
2836 			glStencilFunc(GL_EQUAL, 0, 0xFF);
2837 			glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
2838 			glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2839 			enableDepthWrite = GL_TRUE;
2840 		}
2841 	}
2842 	else if ( attr.isTranslucent || (std::find(this->_shadowPolyID.begin(), this->_shadowPolyID.end(), attr.polygonID) == this->_shadowPolyID.end()) )
2843 	{
2844 		glDisable(GL_STENCIL_TEST);
2845 		glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2846 		enableDepthWrite = (!attr.isTranslucent || ( (attr.polygonMode == POLYGON_MODE_DECAL) && attr.isOpaque ) || attr.enableAlphaDepthWrite) ? GL_TRUE : GL_FALSE;
2847 	}
2848 	else
2849 	{
2850 		glEnable(GL_STENCIL_TEST);
2851 		glStencilFunc(GL_ALWAYS, 0x80, 0xFF);
2852 		glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
2853 		glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
2854 		enableDepthWrite = GL_TRUE;
2855 	}
2856 
2857 	glDepthMask(enableDepthWrite);
2858 
2859 	// Set up polygon attributes
2860 	if (this->isShaderSupported)
2861 	{
2862 		OGLRenderRef &OGLRef = *this->ref;
2863 		glUniform1i(OGLRef.uniformPolyMode, attr.polygonMode);
2864 		glUniform1i(OGLRef.uniformPolyEnableFog, (attr.enableRenderFog) ? GL_TRUE : GL_FALSE);
2865 		glUniform1f(OGLRef.uniformPolyAlpha, (!attr.isWireframe && attr.isTranslucent) ? divide5bitBy31_LUT[attr.alpha] : 1.0f);
2866 		glUniform1i(OGLRef.uniformPolyID, attr.polygonID);
2867 		glUniform1i(OGLRef.uniformPolyEnableDepthWrite, enableDepthWrite);
2868 		glUniform1i(OGLRef.uniformPolySetNewDepthForTranslucent, (attr.enableAlphaDepthWrite) ? GL_TRUE : GL_FALSE);
2869 	}
2870 	else
2871 	{
2872 		// Set the texture blending mode
2873 		static const GLint oglTexBlendMode[4] = {GL_MODULATE, GL_DECAL, GL_MODULATE, GL_MODULATE};
2874 		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, oglTexBlendMode[attr.polygonMode]);
2875 	}
2876 
2877 	return OGLERROR_NOERR;
2878 }
2879 
SetupTexture(const POLY & thePoly,bool enableTexturing)2880 Render3DError OpenGLRenderer_1_2::SetupTexture(const POLY &thePoly, bool enableTexturing)
2881 {
2882 	OGLRenderRef &OGLRef = *this->ref;
2883 	const PolygonTexParams params = thePoly.getTexParams();
2884 
2885 	// Check if we need to use textures
2886 	if (params.texFormat == TEXMODE_NONE || !enableTexturing)
2887 	{
2888 		if (this->isShaderSupported)
2889 		{
2890 			glUniform1i(OGLRef.uniformPolyEnableTexture, GL_FALSE);
2891 		}
2892 		else
2893 		{
2894 			glDisable(GL_TEXTURE_2D);
2895 		}
2896 
2897 		return OGLERROR_NOERR;
2898 	}
2899 
2900 	// Enable textures if they weren't already enabled
2901 	if (this->isShaderSupported)
2902 	{
2903 		glUniform1i(OGLRef.uniformPolyEnableTexture, GL_TRUE);
2904 	}
2905 	else
2906 	{
2907 		glEnable(GL_TEXTURE_2D);
2908 	}
2909 
2910 	TexCacheItem *newTexture = TexCache_SetTexture(TexFormat_32bpp, thePoly.texParam, thePoly.texPalette);
2911 	if(newTexture != this->currTexture)
2912 	{
2913 		this->currTexture = newTexture;
2914 		//has the ogl renderer initialized the texture?
2915 		if(this->currTexture->GetDeleteCallback() == NULL)
2916 		{
2917 			this->currTexture->SetDeleteCallback(&texDeleteCallback, this, NULL);
2918 
2919 			if(OGLRef.freeTextureIDs.empty())
2920 			{
2921 				this->ExpandFreeTextures();
2922 			}
2923 
2924 			this->currTexture->texid = (u64)OGLRef.freeTextureIDs.front();
2925 			OGLRef.freeTextureIDs.pop();
2926 
2927 			glBindTexture(GL_TEXTURE_2D, (GLuint)this->currTexture->texid);
2928 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2929 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2930 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (params.enableRepeatS ? (params.enableMirroredRepeatS ? OGLRef.stateTexMirroredRepeat : GL_REPEAT) : GL_CLAMP_TO_EDGE));
2931 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (params.enableRepeatT ? (params.enableMirroredRepeatT ? OGLRef.stateTexMirroredRepeat : GL_REPEAT) : GL_CLAMP_TO_EDGE));
2932 
2933 			u32 *textureSrc = (u32 *)currTexture->decoded;
2934 			size_t texWidth = currTexture->sizeX;
2935 			size_t texHeight = currTexture->sizeY;
2936 
2937 			if (this->_textureDeposterizeBuffer != NULL)
2938 			{
2939 				this->TextureDeposterize(textureSrc, texWidth, texHeight);
2940 				textureSrc = this->_textureDeposterizeBuffer;
2941 			}
2942 
2943 			switch (this->_textureScalingFactor)
2944 			{
2945 				case 2:
2946 				{
2947 					this->TextureUpscale<2>(textureSrc, texWidth, texHeight);
2948 					textureSrc = this->_textureUpscaleBuffer;
2949 					break;
2950 				}
2951 
2952 				case 4:
2953 				{
2954 					this->TextureUpscale<4>(textureSrc, texWidth, texHeight);
2955 					textureSrc = this->_textureUpscaleBuffer;
2956 					break;
2957 				}
2958 
2959 				default:
2960 					break;
2961 			}
2962 
2963 			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureSrc);
2964 		}
2965 		else
2966 		{
2967 			//otherwise, just bind it
2968 			glBindTexture(GL_TEXTURE_2D, (GLuint)this->currTexture->texid);
2969 		}
2970 
2971 		if (this->isShaderSupported)
2972 		{
2973 			glUniform2f(OGLRef.uniformPolyTexScale, this->currTexture->invSizeX, this->currTexture->invSizeY);
2974 		}
2975 		else
2976 		{
2977 			glMatrixMode(GL_TEXTURE);
2978 			glLoadIdentity();
2979 			glScalef(this->currTexture->invSizeX, this->currTexture->invSizeY, 1.0f);
2980 		}
2981 	}
2982 
2983 	return OGLERROR_NOERR;
2984 }
2985 
SetupViewport(const u32 viewportValue)2986 Render3DError OpenGLRenderer_1_2::SetupViewport(const u32 viewportValue)
2987 {
2988 	const GLfloat wScalar = this->_framebufferWidth / GPU_FRAMEBUFFER_NATIVE_WIDTH;
2989 	const GLfloat hScalar = this->_framebufferHeight / GPU_FRAMEBUFFER_NATIVE_HEIGHT;
2990 
2991 	VIEWPORT viewport;
2992 	viewport.decode(viewportValue);
2993 	glViewport(viewport.x * wScalar, viewport.y * hScalar, viewport.width * wScalar, viewport.height * hScalar);
2994 
2995 	return OGLERROR_NOERR;
2996 }
2997 
Reset()2998 Render3DError OpenGLRenderer_1_2::Reset()
2999 {
3000 	OGLRenderRef &OGLRef = *this->ref;
3001 
3002 	if(!BEGINGL())
3003 	{
3004 		return OGLERROR_BEGINGL_FAILED;
3005 	}
3006 
3007 	glFinish();
3008 
3009 	if (!this->isShaderSupported)
3010 	{
3011 		glEnable(GL_NORMALIZE);
3012 		glEnable(GL_TEXTURE_1D);
3013 		glEnable(GL_TEXTURE_2D);
3014 		glAlphaFunc(GL_GREATER, 0);
3015 		glEnable(GL_ALPHA_TEST);
3016 		glEnable(GL_BLEND);
3017 	}
3018 
3019 	ENDGL();
3020 
3021 	this->_pixelReadNeedsFinish = false;
3022 
3023 	if (OGLRef.color4fBuffer != NULL)
3024 	{
3025 		memset(OGLRef.color4fBuffer, 0, VERTLIST_SIZE * 4 * sizeof(GLfloat));
3026 	}
3027 
3028 	if (OGLRef.vertIndexBuffer != NULL)
3029 	{
3030 		memset(OGLRef.vertIndexBuffer, 0, OGLRENDER_VERT_INDEX_BUFFER_COUNT * sizeof(GLushort));
3031 	}
3032 
3033 	this->currTexture = NULL;
3034 	this->_currentPolyIndex = 0;
3035 
3036 	OGLRef.vtxPtrPosition = (GLvoid *)offsetof(VERT, coord);
3037 	OGLRef.vtxPtrTexCoord = (GLvoid *)offsetof(VERT, texcoord);
3038 	OGLRef.vtxPtrColor = (this->isShaderSupported) ? (GLvoid *)offsetof(VERT, color) : OGLRef.color4fBuffer;
3039 
3040 	memset(this->clearImageColor16Buffer, 0, sizeof(this->clearImageColor16Buffer));
3041 	memset(this->clearImageDepthBuffer, 0, sizeof(this->clearImageDepthBuffer));
3042 	memset(this->clearImagePolyIDBuffer, 0, sizeof(this->clearImagePolyIDBuffer));
3043 	memset(this->clearImageFogBuffer, 0, sizeof(this->clearImageFogBuffer));
3044 
3045 	TexCache_Reset();
3046 
3047 	return OGLERROR_NOERR;
3048 }
3049 
RenderFinish()3050 Render3DError OpenGLRenderer_1_2::RenderFinish()
3051 {
3052 	if (!this->_renderNeedsFinish || !this->_pixelReadNeedsFinish)
3053 	{
3054 		return OGLERROR_NOERR;
3055 	}
3056 
3057 	FragmentColor *framebufferMain = (this->_willFlushFramebufferRGBA6665) ? GPU->GetEngineMain()->Get3DFramebufferRGBA6665() : NULL;
3058 	u16 *framebufferRGBA5551 = (this->_willFlushFramebufferRGBA5551) ? GPU->GetEngineMain()->Get3DFramebufferRGBA5551() : NULL;
3059 
3060 	if ( (framebufferMain != NULL) || (framebufferRGBA5551 != NULL) )
3061 	{
3062 		if(!BEGINGL())
3063 		{
3064 			return OGLERROR_BEGINGL_FAILED;
3065 		}
3066 
3067 		if (this->isPBOSupported)
3068 		{
3069 			this->_mappedFramebuffer = (FragmentColor *__restrict)glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY_ARB);
3070 			this->FlushFramebuffer(this->_mappedFramebuffer, framebufferMain, framebufferRGBA5551);
3071 		}
3072 		else
3073 		{
3074 			glReadPixels(0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_BGRA, GL_UNSIGNED_BYTE, this->_framebufferColor);
3075 			this->FlushFramebuffer(this->_framebufferColor, framebufferMain, framebufferRGBA5551);
3076 		}
3077 
3078 		ENDGL();
3079 	}
3080 
3081 	this->_pixelReadNeedsFinish = false;
3082 
3083 	return OGLERROR_NOERR;
3084 }
3085 
SetFramebufferSize(size_t w,size_t h)3086 Render3DError OpenGLRenderer_1_2::SetFramebufferSize(size_t w, size_t h)
3087 {
3088 	OGLRenderRef &OGLRef = *this->ref;
3089 
3090 	if (w < GPU_FRAMEBUFFER_NATIVE_WIDTH || h < GPU_FRAMEBUFFER_NATIVE_HEIGHT)
3091 	{
3092 		return OGLERROR_NOERR;
3093 	}
3094 
3095 	if (!BEGINGL())
3096 	{
3097 		return OGLERROR_BEGINGL_FAILED;
3098 	}
3099 
3100 	if (this->isPBOSupported)
3101 	{
3102 		if (this->_mappedFramebuffer != NULL)
3103 		{
3104 			glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
3105 			this->_mappedFramebuffer = NULL;
3106 		}
3107 	}
3108 
3109 	if (this->isFBOSupported)
3110 	{
3111 		glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_GColor);
3112 		glBindTexture(GL_TEXTURE_2D, OGLRef.texGDepthStencilID);
3113 		glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8_EXT, w, h, 0, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, NULL);
3114 		glBindTexture(GL_TEXTURE_2D, OGLRef.texGColorID);
3115 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
3116 
3117 		glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_GDepth);
3118 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
3119 
3120 		glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_GPolyID);
3121 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
3122 
3123 		glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_FogAttr);
3124 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
3125 
3126 		glActiveTextureARB(GL_TEXTURE0_ARB);
3127 		glBindTexture(GL_TEXTURE_2D, OGLRef.texPostprocessFogID);
3128 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
3129 	}
3130 
3131 	if (this->isMultisampledFBOSupported)
3132 	{
3133 		GLint maxSamples = 0;
3134 		glGetIntegerv(GL_MAX_SAMPLES_EXT, &maxSamples);
3135 
3136 		glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGColorID);
3137 		glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_RGBA, w, h);
3138 		glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGDepthID);
3139 		glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_RGBA, w, h);
3140 		glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGPolyID);
3141 		glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_RGBA, w, h);
3142 		glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGFogAttrID);
3143 		glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_RGBA, w, h);
3144 		glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGDepthStencilID);
3145 		glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_DEPTH24_STENCIL8_EXT, w, h);
3146 	}
3147 
3148 	if (this->willFlipFramebufferOnGPU)
3149 	{
3150 		glActiveTextureARB(GL_TEXTURE0_ARB + OGLTextureUnitID_FinalColor);
3151 		glBindTexture(GL_TEXTURE_2D, OGLRef.texFinalColorID);
3152 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
3153 	}
3154 
3155 	if (this->willConvertFramebufferOnGPU)
3156 	{
3157 		glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboFramebufferRGBA6665ID);
3158 		glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA, w, h);
3159 	}
3160 
3161 	const size_t newFramebufferColorSizeBytes = w * h * sizeof(FragmentColor);
3162 
3163 	this->_framebufferWidth = w;
3164 	this->_framebufferHeight = h;
3165 	this->_framebufferColorSizeBytes = newFramebufferColorSizeBytes;
3166 
3167 	if (this->isPBOSupported)
3168 	{
3169 		glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, newFramebufferColorSizeBytes, NULL, GL_STREAM_READ_ARB);
3170 		this->_framebufferColor = NULL;
3171 	}
3172 	else
3173 	{
3174 		FragmentColor *oldFramebufferColor = this->_framebufferColor;
3175 		FragmentColor *newFramebufferColor = (FragmentColor *)memalign_alloc_aligned(newFramebufferColorSizeBytes);
3176 		this->_framebufferColor = newFramebufferColor;
3177 		free_aligned(oldFramebufferColor);
3178 	}
3179 
3180 	if (oglrender_framebufferDidResizeCallback != NULL)
3181 	{
3182 		oglrender_framebufferDidResizeCallback(w, h);
3183 	}
3184 
3185 	ENDGL();
3186 
3187 	return OGLERROR_NOERR;
3188 }
3189 
CreateToonTable()3190 Render3DError OpenGLRenderer_1_3::CreateToonTable()
3191 {
3192 	OGLRenderRef &OGLRef = *this->ref;
3193 	u16 tempToonTable[32];
3194 	memset(tempToonTable, 0, sizeof(tempToonTable));
3195 
3196 	// The toon table is a special 1D texture where each pixel corresponds
3197 	// to a specific color in the toon table.
3198 	glGenTextures(1, &OGLRef.texToonTableID);
3199 	glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_ToonTable);
3200 	glBindTexture(GL_TEXTURE_1D, OGLRef.texToonTableID);
3201 
3202 	glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3203 	glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3204 	glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
3205 	glTexImage1D(GL_TEXTURE_1D, 0, GL_RGB, 32, 0, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, tempToonTable);
3206 
3207 	glActiveTexture(GL_TEXTURE0);
3208 
3209 	return OGLERROR_NOERR;
3210 }
3211 
UpdateToonTable(const u16 * toonTableBuffer)3212 Render3DError OpenGLRenderer_1_3::UpdateToonTable(const u16 *toonTableBuffer)
3213 {
3214 	glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_ToonTable);
3215 	glTexSubImage1D(GL_TEXTURE_1D, 0, 0, 32, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, toonTableBuffer);
3216 
3217 	return OGLERROR_NOERR;
3218 }
3219 
UploadClearImage(const u16 * __restrict colorBuffer,const u32 * __restrict depthBuffer,const u8 * __restrict fogBuffer,const u8 * __restrict polyIDBuffer)3220 Render3DError OpenGLRenderer_1_3::UploadClearImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const u8 *__restrict fogBuffer, const u8 *__restrict polyIDBuffer)
3221 {
3222 	OGLRenderRef &OGLRef = *this->ref;
3223 
3224 	if (this->isShaderSupported)
3225 	{
3226 		for (size_t i = 0; i < GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT; i++)
3227 		{
3228 			OGLRef.workingCIDepthStencilBuffer[i] = (depthBuffer[i] << 8) | polyIDBuffer[i];
3229 			OGLRef.workingCIDepthBuffer[i] = depthBuffer[i] | 0xFF000000;
3230 			OGLRef.workingCIFogAttributesBuffer[i] = (fogBuffer[i]) ? 0xFF0000FF : 0xFF000000;
3231 			OGLRef.workingCIPolyIDBuffer[i] = (GLuint)polyIDBuffer[i] | 0xFF000000;
3232 		}
3233 	}
3234 	else
3235 	{
3236 		for (size_t i = 0; i < GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT; i++)
3237 		{
3238 			OGLRef.workingCIDepthStencilBuffer[i] = (depthBuffer[i] << 8) | polyIDBuffer[i];
3239 		}
3240 	}
3241 
3242 	glActiveTexture(GL_TEXTURE0);
3243 
3244 	glBindTexture(GL_TEXTURE_2D, OGLRef.texCIColorID);
3245 	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, colorBuffer);
3246 	glBindTexture(GL_TEXTURE_2D, OGLRef.texCIDepthStencilID);
3247 	glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, OGLRef.workingCIDepthStencilBuffer);
3248 
3249 	if (this->isShaderSupported)
3250 	{
3251 		glBindTexture(GL_TEXTURE_2D, OGLRef.texCIDepthID);
3252 		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, OGLRef.workingCIDepthBuffer);
3253 
3254 		glBindTexture(GL_TEXTURE_2D, OGLRef.texCIFogAttrID);
3255 		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, OGLRef.workingCIFogAttributesBuffer);
3256 
3257 		glBindTexture(GL_TEXTURE_2D, OGLRef.texCIPolyID);
3258 		glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, OGLRef.workingCIPolyIDBuffer);
3259 	}
3260 
3261 	glBindTexture(GL_TEXTURE_2D, 0);
3262 
3263 	return OGLERROR_NOERR;
3264 }
3265 
SetFramebufferSize(size_t w,size_t h)3266 Render3DError OpenGLRenderer_1_3::SetFramebufferSize(size_t w, size_t h)
3267 {
3268 	OGLRenderRef &OGLRef = *this->ref;
3269 
3270 	if (w < GPU_FRAMEBUFFER_NATIVE_WIDTH || h < GPU_FRAMEBUFFER_NATIVE_HEIGHT)
3271 	{
3272 		return OGLERROR_NOERR;
3273 	}
3274 
3275 	if (!BEGINGL())
3276 	{
3277 		return OGLERROR_BEGINGL_FAILED;
3278 	}
3279 
3280 	if (this->isPBOSupported)
3281 	{
3282 		if (this->_mappedFramebuffer != NULL)
3283 		{
3284 			glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
3285 			this->_mappedFramebuffer = NULL;
3286 		}
3287 	}
3288 
3289 	if (this->isFBOSupported)
3290 	{
3291 		glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GColor);
3292 		glBindTexture(GL_TEXTURE_2D, OGLRef.texGDepthStencilID);
3293 		glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8_EXT, w, h, 0, GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, NULL);
3294 		glBindTexture(GL_TEXTURE_2D, OGLRef.texGColorID);
3295 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
3296 
3297 		glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GDepth);
3298 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
3299 
3300 		glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_GPolyID);
3301 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
3302 
3303 		glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_FogAttr);
3304 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
3305 
3306 		glActiveTexture(GL_TEXTURE0);
3307 		glBindTexture(GL_TEXTURE_2D, OGLRef.texPostprocessFogID);
3308 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
3309 	}
3310 
3311 	if (this->isMultisampledFBOSupported)
3312 	{
3313 		GLint maxSamples = 0;
3314 		glGetIntegerv(GL_MAX_SAMPLES_EXT, &maxSamples);
3315 
3316 		glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGColorID);
3317 		glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_RGBA, w, h);
3318 		glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGDepthID);
3319 		glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_RGBA, w, h);
3320 		glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGPolyID);
3321 		glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_RGBA, w, h);
3322 		glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGFogAttrID);
3323 		glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_RGBA, w, h);
3324 		glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboMSGDepthStencilID);
3325 		glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, maxSamples, GL_DEPTH24_STENCIL8_EXT, w, h);
3326 	}
3327 
3328 	if (this->willFlipFramebufferOnGPU)
3329 	{
3330 		glActiveTexture(GL_TEXTURE0 + OGLTextureUnitID_FinalColor);
3331 		glBindTexture(GL_TEXTURE_2D, OGLRef.texFinalColorID);
3332 		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
3333 	}
3334 
3335 	if (this->willConvertFramebufferOnGPU)
3336 	{
3337 		glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, OGLRef.rboFramebufferRGBA6665ID);
3338 		glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA, w, h);
3339 	}
3340 
3341 	const size_t newFramebufferColorSizeBytes = w * h * sizeof(FragmentColor);
3342 
3343 	this->_framebufferWidth = w;
3344 	this->_framebufferHeight = h;
3345 	this->_framebufferColorSizeBytes = newFramebufferColorSizeBytes;
3346 
3347 	if (this->isPBOSupported)
3348 	{
3349 		glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, newFramebufferColorSizeBytes, NULL, GL_STREAM_READ_ARB);
3350 		this->_framebufferColor = NULL;
3351 	}
3352 	else
3353 	{
3354 		FragmentColor *oldFramebufferColor = this->_framebufferColor;
3355 		FragmentColor *newFramebufferColor = (FragmentColor *)memalign_alloc_aligned(newFramebufferColorSizeBytes);
3356 		this->_framebufferColor = newFramebufferColor;
3357 		free_aligned(oldFramebufferColor);
3358 	}
3359 
3360 	if (oglrender_framebufferDidResizeCallback != NULL)
3361 	{
3362 		oglrender_framebufferDidResizeCallback(w, h);
3363 	}
3364 
3365 	ENDGL();
3366 
3367 	return OGLERROR_NOERR;
3368 }
3369 
InitFinalRenderStates(const std::set<std::string> * oglExtensionSet)3370 Render3DError OpenGLRenderer_1_4::InitFinalRenderStates(const std::set<std::string> *oglExtensionSet)
3371 {
3372 	OGLRenderRef &OGLRef = *this->ref;
3373 
3374 	bool isBlendEquationSeparateSupported = this->IsExtensionPresent(oglExtensionSet, "GL_EXT_blend_equation_separate");
3375 
3376 	// Blending Support
3377 	if (isBlendEquationSeparateSupported)
3378 	{
3379 		// we want to use alpha destination blending so we can track the last-rendered alpha value
3380 		// test: new super mario brothers renders the stormclouds at the beginning
3381 		glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_DST_ALPHA);
3382 		glBlendEquationSeparateEXT(GL_FUNC_ADD, GL_MAX);
3383 	}
3384 	else
3385 	{
3386 		glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_DST_ALPHA);
3387 	}
3388 
3389 	// Mirrored Repeat Mode Support
3390 	OGLRef.stateTexMirroredRepeat = GL_MIRRORED_REPEAT;
3391 
3392 	// Map the vertex list's colors with 4 floats per color. This is being done
3393 	// because OpenGL needs 4-colors per vertex to support translucency. (The DS
3394 	// uses 3-colors per vertex, and adds alpha through the poly, so we can't
3395 	// simply reference the colors+alpha from just the vertices by themselves.)
3396 	OGLRef.color4fBuffer = (this->isShaderSupported) ? NULL : new GLfloat[VERTLIST_SIZE * 4];
3397 
3398 	// If VBOs aren't supported, then we need to create the index buffer on the
3399 	// client side so that we have a buffer to update.
3400 	OGLRef.vertIndexBuffer = (this->isVBOSupported) ? NULL : new GLushort[OGLRENDER_VERT_INDEX_BUFFER_COUNT];
3401 
3402 	return OGLERROR_NOERR;
3403 }
3404 
~OpenGLRenderer_1_5()3405 OpenGLRenderer_1_5::~OpenGLRenderer_1_5()
3406 {
3407 	glFinish();
3408 
3409 	DestroyVAOs();
3410 	DestroyVBOs();
3411 	DestroyPBOs();
3412 }
3413 
CreateVBOs()3414 Render3DError OpenGLRenderer_1_5::CreateVBOs()
3415 {
3416 	OGLRenderRef &OGLRef = *this->ref;
3417 
3418 	glGenBuffers(1, &OGLRef.vboGeometryVtxID);
3419 	glGenBuffers(1, &OGLRef.iboGeometryIndexID);
3420 	glGenBuffers(1, &OGLRef.vboPostprocessVtxID);
3421 	glGenBuffers(1, &OGLRef.iboPostprocessIndexID);
3422 
3423 	glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboGeometryVtxID);
3424 	glBufferData(GL_ARRAY_BUFFER, VERTLIST_SIZE * sizeof(VERT), NULL, GL_STREAM_DRAW);
3425 	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboGeometryIndexID);
3426 	glBufferData(GL_ELEMENT_ARRAY_BUFFER, OGLRENDER_VERT_INDEX_BUFFER_COUNT * sizeof(GLushort), NULL, GL_STREAM_DRAW);
3427 
3428 	glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID);
3429 	glBufferData(GL_ARRAY_BUFFER, sizeof(PostprocessVtxBuffer), PostprocessVtxBuffer, GL_STATIC_DRAW);
3430 	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboPostprocessIndexID);
3431 	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(PostprocessElementBuffer), PostprocessElementBuffer, GL_STATIC_DRAW);
3432 
3433 	glBindBuffer(GL_ARRAY_BUFFER, 0);
3434 	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
3435 
3436 	return OGLERROR_NOERR;
3437 }
3438 
DestroyVBOs()3439 void OpenGLRenderer_1_5::DestroyVBOs()
3440 {
3441 	if (!this->isVBOSupported)
3442 	{
3443 		return;
3444 	}
3445 
3446 	OGLRenderRef &OGLRef = *this->ref;
3447 
3448 	glBindBuffer(GL_ARRAY_BUFFER, 0);
3449 	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
3450 
3451 	glDeleteBuffers(1, &OGLRef.vboGeometryVtxID);
3452 	glDeleteBuffers(1, &OGLRef.iboGeometryIndexID);
3453 	glDeleteBuffers(1, &OGLRef.vboPostprocessVtxID);
3454 	glDeleteBuffers(1, &OGLRef.iboPostprocessIndexID);
3455 
3456 	this->isVBOSupported = false;
3457 }
3458 
CreateVAOs()3459 Render3DError OpenGLRenderer_1_5::CreateVAOs()
3460 {
3461 	OGLRenderRef &OGLRef = *this->ref;
3462 
3463 	glGenVertexArrays(1, &OGLRef.vaoGeometryStatesID);
3464 	glGenVertexArrays(1, &OGLRef.vaoPostprocessStatesID);
3465 
3466 	glBindVertexArray(OGLRef.vaoGeometryStatesID);
3467 	glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboGeometryVtxID);
3468 	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboGeometryIndexID);
3469 
3470 	glEnableVertexAttribArray(OGLVertexAttributeID_Position);
3471 	glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0);
3472 	glEnableVertexAttribArray(OGLVertexAttributeID_Color);
3473 	glVertexAttribPointer(OGLVertexAttributeID_Position, 4, GL_FLOAT, GL_FALSE, sizeof(VERT), (const GLvoid *)offsetof(VERT, coord));
3474 	glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(VERT), (const GLvoid *)offsetof(VERT, texcoord));
3475 	glVertexAttribPointer(OGLVertexAttributeID_Color, 3, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(VERT), (const GLvoid *)offsetof(VERT, color));
3476 
3477 	glBindVertexArray(0);
3478 
3479 	glBindVertexArray(OGLRef.vaoPostprocessStatesID);
3480 	glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID);
3481 	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboPostprocessIndexID);
3482 
3483 	glEnableVertexAttribArray(OGLVertexAttributeID_Position);
3484 	glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0);
3485 	glVertexAttribPointer(OGLVertexAttributeID_Position, 2, GL_FLOAT, GL_FALSE, 0, 0);
3486 	glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *)(sizeof(GLfloat) * 8));
3487 
3488 	glBindVertexArray(0);
3489 
3490 	return OGLERROR_NOERR;
3491 }
3492 
EnableVertexAttributes()3493 Render3DError OpenGLRenderer_1_5::EnableVertexAttributes()
3494 {
3495 	OGLRenderRef &OGLRef = *this->ref;
3496 
3497 	if (this->isVAOSupported)
3498 	{
3499 		glBindVertexArray(OGLRef.vaoGeometryStatesID);
3500 	}
3501 	else
3502 	{
3503 		if (this->isShaderSupported)
3504 		{
3505 			glEnableVertexAttribArray(OGLVertexAttributeID_Position);
3506 			glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0);
3507 			glEnableVertexAttribArray(OGLVertexAttributeID_Color);
3508 			glVertexAttribPointer(OGLVertexAttributeID_Position, 4, GL_FLOAT, GL_FALSE, sizeof(VERT), OGLRef.vtxPtrPosition);
3509 			glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(VERT), OGLRef.vtxPtrTexCoord);
3510 			glVertexAttribPointer(OGLVertexAttributeID_Color, 3, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(VERT), OGLRef.vtxPtrColor);
3511 		}
3512 		else
3513 		{
3514 			glEnableClientState(GL_TEXTURE_COORD_ARRAY);
3515 			glEnableClientState(GL_COLOR_ARRAY);
3516 			glEnableClientState(GL_VERTEX_ARRAY);
3517 
3518 			glBindBuffer(GL_ARRAY_BUFFER, 0);
3519 			glColorPointer(4, GL_FLOAT, 0, OGLRef.vtxPtrColor);
3520 
3521 			glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboGeometryVtxID);
3522 			glVertexPointer(4, GL_FLOAT, sizeof(VERT), OGLRef.vtxPtrPosition);
3523 			glTexCoordPointer(2, GL_FLOAT, sizeof(VERT), OGLRef.vtxPtrTexCoord);
3524 		}
3525 	}
3526 
3527 	glActiveTexture(GL_TEXTURE0);
3528 
3529 	return OGLERROR_NOERR;
3530 }
3531 
DisableVertexAttributes()3532 Render3DError OpenGLRenderer_1_5::DisableVertexAttributes()
3533 {
3534 	if (this->isVAOSupported)
3535 	{
3536 		glBindVertexArray(0);
3537 	}
3538 	else
3539 	{
3540 		if (this->isShaderSupported)
3541 		{
3542 			glDisableVertexAttribArray(OGLVertexAttributeID_Position);
3543 			glDisableVertexAttribArray(OGLVertexAttributeID_TexCoord0);
3544 			glDisableVertexAttribArray(OGLVertexAttributeID_Color);
3545 		}
3546 		else
3547 		{
3548 			glDisableClientState(GL_VERTEX_ARRAY);
3549 			glDisableClientState(GL_COLOR_ARRAY);
3550 			glDisableClientState(GL_TEXTURE_COORD_ARRAY);
3551 		}
3552 	}
3553 
3554 	return OGLERROR_NOERR;
3555 }
3556 
BeginRender(const GFX3D & engine)3557 Render3DError OpenGLRenderer_1_5::BeginRender(const GFX3D &engine)
3558 {
3559 	OGLRenderRef &OGLRef = *this->ref;
3560 
3561 	if(!BEGINGL())
3562 	{
3563 		return OGLERROR_BEGINGL_FAILED;
3564 	}
3565 
3566 	if (this->isShaderSupported)
3567 	{
3568 		glUseProgram(OGLRef.programGeometryID);
3569 		glUniform1i(OGLRef.uniformStateToonShadingMode, engine.renderState.shading);
3570 		glUniform1i(OGLRef.uniformStateEnableAlphaTest, (engine.renderState.enableAlphaTest) ? GL_TRUE : GL_FALSE);
3571 		glUniform1i(OGLRef.uniformStateEnableAntialiasing, (engine.renderState.enableAntialiasing) ? GL_TRUE : GL_FALSE);
3572 		glUniform1i(OGLRef.uniformStateEnableEdgeMarking, (engine.renderState.enableEdgeMarking) ? GL_TRUE : GL_FALSE);
3573 		glUniform1i(OGLRef.uniformStateUseWDepth, (engine.renderState.wbuffer) ? GL_TRUE : GL_FALSE);
3574 		glUniform1f(OGLRef.uniformStateAlphaTestRef, divide5bitBy31_LUT[engine.renderState.alphaTestRef]);
3575 	}
3576 	else
3577 	{
3578 		if(engine.renderState.enableAlphaTest && (engine.renderState.alphaTestRef > 0))
3579 		{
3580 			glAlphaFunc(GL_GEQUAL, divide5bitBy31_LUT[engine.renderState.alphaTestRef]);
3581 		}
3582 		else
3583 		{
3584 			glAlphaFunc(GL_GREATER, 0);
3585 		}
3586 
3587 		glMatrixMode(GL_PROJECTION);
3588 		glLoadIdentity();
3589 	}
3590 
3591 	glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboGeometryVtxID);
3592 	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboGeometryIndexID);
3593 
3594 	size_t vertIndexCount = 0;
3595 	GLushort *indexPtr = (GLushort *)glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
3596 
3597 	for (size_t i = 0; i < engine.polylist->count; i++)
3598 	{
3599 		const POLY *thePoly = &engine.polylist->list[engine.indexlist.list[i]];
3600 		const size_t polyType = thePoly->type;
3601 
3602 		for (size_t j = 0; j < polyType; j++)
3603 		{
3604 			const GLushort vertIndex = thePoly->vertIndexes[j];
3605 
3606 			// While we're looping through our vertices, add each vertex index to
3607 			// a buffer. For GFX3D_QUADS and GFX3D_QUAD_STRIP, we also add additional
3608 			// vertices here to convert them to GL_TRIANGLES, which are much easier
3609 			// to work with and won't be deprecated in future OpenGL versions.
3610 			indexPtr[vertIndexCount++] = vertIndex;
3611 			if (thePoly->vtxFormat == GFX3D_QUADS || thePoly->vtxFormat == GFX3D_QUAD_STRIP)
3612 			{
3613 				if (j == 2)
3614 				{
3615 					indexPtr[vertIndexCount++] = vertIndex;
3616 				}
3617 				else if (j == 3)
3618 				{
3619 					indexPtr[vertIndexCount++] = thePoly->vertIndexes[0];
3620 				}
3621 			}
3622 		}
3623 	}
3624 
3625 	glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
3626 	glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(VERT) * engine.vertlist->count, engine.vertlist);
3627 
3628 	return OGLERROR_NOERR;
3629 }
3630 
InitExtensions()3631 Render3DError OpenGLRenderer_2_0::InitExtensions()
3632 {
3633 	Render3DError error = OGLERROR_NOERR;
3634 
3635 	// Get OpenGL extensions
3636 	std::set<std::string> oglExtensionSet;
3637 	this->GetExtensionSet(&oglExtensionSet);
3638 
3639 	// Initialize OpenGL
3640 	this->InitTables();
3641 
3642 	// Load and create shaders. Return on any error, since a v2.0 driver will assume that shaders are available.
3643 	this->isShaderSupported	= true;
3644 
3645 	std::string vertexShaderProgram;
3646 	std::string fragmentShaderProgram;
3647 	error = this->LoadGeometryShaders(vertexShaderProgram, fragmentShaderProgram);
3648 	if (error != OGLERROR_NOERR)
3649 	{
3650 		this->isShaderSupported = false;
3651 		return error;
3652 	}
3653 
3654 	error = this->InitGeometryProgram(vertexShaderProgram, fragmentShaderProgram);
3655 	if (error != OGLERROR_NOERR)
3656 	{
3657 		this->isShaderSupported = false;
3658 		return error;
3659 	}
3660 
3661 	std::string edgeMarkVtxShaderString = std::string(EdgeMarkVtxShader_100);
3662 	std::string edgeMarkFragShaderString = std::string(EdgeMarkFragShader_100);
3663 	std::string fogVtxShaderString = std::string(FogVtxShader_100);
3664 	std::string fogFragShaderString = std::string(FogFragShader_100);
3665 	std::string framebufferOutputVtxShaderString = std::string(FramebufferOutputVtxShader_100);
3666 	std::string framebufferOutputRGBA6665FragShaderString = std::string(FramebufferOutputRGBA6665FragShader_100);
3667 	std::string framebufferOutputRGBA8888FragShaderString = std::string(FramebufferOutputRGBA8888FragShader_100);
3668 	error = this->InitPostprocessingPrograms(edgeMarkVtxShaderString,
3669 											 edgeMarkFragShaderString,
3670 											 fogVtxShaderString,
3671 											 fogFragShaderString,
3672 											 framebufferOutputVtxShaderString,
3673 											 framebufferOutputRGBA6665FragShaderString,
3674 											 framebufferOutputRGBA8888FragShaderString);
3675 	if (error != OGLERROR_NOERR)
3676 	{
3677 		this->DestroyGeometryProgram();
3678 		this->isShaderSupported = false;
3679 	}
3680 
3681 	this->isVBOSupported = true;
3682 	this->CreateVBOs();
3683 
3684 	this->isPBOSupported	= this->IsExtensionPresent(&oglExtensionSet, "GL_ARB_vertex_buffer_object") &&
3685 							 (this->IsExtensionPresent(&oglExtensionSet, "GL_ARB_pixel_buffer_object") ||
3686 							  this->IsExtensionPresent(&oglExtensionSet, "GL_EXT_pixel_buffer_object"));
3687 	if (this->isPBOSupported)
3688 	{
3689 		this->CreatePBOs();
3690 	}
3691 
3692 	this->isVAOSupported	= this->isShaderSupported &&
3693 							  this->isVBOSupported &&
3694 							 (this->IsExtensionPresent(&oglExtensionSet, "GL_ARB_vertex_array_object") ||
3695 							  this->IsExtensionPresent(&oglExtensionSet, "GL_APPLE_vertex_array_object"));
3696 	if (this->isVAOSupported)
3697 	{
3698 		this->CreateVAOs();
3699 	}
3700 
3701 	// Don't use ARB versions since we're using the EXT versions for backwards compatibility.
3702 	this->isFBOSupported	= this->IsExtensionPresent(&oglExtensionSet, "GL_EXT_framebuffer_object") &&
3703 							  this->IsExtensionPresent(&oglExtensionSet, "GL_EXT_framebuffer_blit") &&
3704 							  this->IsExtensionPresent(&oglExtensionSet, "GL_EXT_packed_depth_stencil");
3705 	if (this->isFBOSupported)
3706 	{
3707 		this->willFlipFramebufferOnGPU = true;
3708 		this->willConvertFramebufferOnGPU = (this->isShaderSupported && this->isVAOSupported && this->isPBOSupported && this->isFBOSupported);
3709 
3710 		error = this->CreateFBOs();
3711 		if (error != OGLERROR_NOERR)
3712 		{
3713 			this->isFBOSupported = false;
3714 		}
3715 	}
3716 	else
3717 	{
3718 		INFO("OpenGL: FBOs are unsupported. Some emulation features will be disabled.\n");
3719 	}
3720 
3721 	// Set these again after FBO creation just in case FBO creation fails.
3722 	this->willFlipFramebufferOnGPU = this->isFBOSupported;
3723 	this->willConvertFramebufferOnGPU = (this->isShaderSupported && this->isVAOSupported && this->isPBOSupported && this->isFBOSupported);
3724 
3725 	// Don't use ARB versions since we're using the EXT versions for backwards compatibility.
3726 	this->isMultisampledFBOSupported	= this->isFBOSupported &&
3727 										  this->IsExtensionPresent(&oglExtensionSet, "GL_EXT_framebuffer_multisample");
3728 	if (this->isMultisampledFBOSupported)
3729 	{
3730 		error = this->CreateMultisampledFBO();
3731 		if (error != OGLERROR_NOERR)
3732 		{
3733 			this->isMultisampledFBOSupported = false;
3734 		}
3735 	}
3736 	else
3737 	{
3738 		INFO("OpenGL: Multisampled FBOs are unsupported. Multisample antialiasing will be disabled.\n");
3739 	}
3740 
3741 	this->InitTextures();
3742 	this->InitFinalRenderStates(&oglExtensionSet); // This must be done last
3743 
3744 	return OGLERROR_NOERR;
3745 }
3746 
InitFinalRenderStates(const std::set<std::string> * oglExtensionSet)3747 Render3DError OpenGLRenderer_2_0::InitFinalRenderStates(const std::set<std::string> *oglExtensionSet)
3748 {
3749 	OGLRenderRef &OGLRef = *this->ref;
3750 
3751 	// we want to use alpha destination blending so we can track the last-rendered alpha value
3752 	// test: new super mario brothers renders the stormclouds at the beginning
3753 
3754 	// Blending Support
3755 	glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_DST_ALPHA);
3756 	glBlendEquationSeparate(GL_FUNC_ADD, GL_MAX);
3757 
3758 	// Mirrored Repeat Mode Support
3759 	OGLRef.stateTexMirroredRepeat = GL_MIRRORED_REPEAT;
3760 
3761 	// Ignore our color buffer since we'll transfer the polygon alpha through a uniform.
3762 	OGLRef.color4fBuffer = NULL;
3763 
3764 	// VBOs are supported here, so just use the index buffer on the GPU.
3765 	OGLRef.vertIndexBuffer = NULL;
3766 
3767 	return OGLERROR_NOERR;
3768 }
3769 
InitPostprocessingPrograms(const std::string & edgeMarkVtxShader,const std::string & edgeMarkFragShader,const std::string & fogVtxShader,const std::string & fogFragShader,const std::string & framebufferOutputVtxShader,const std::string & framebufferOutputRGBA6665FragShader,const std::string & framebufferOutputRGBA8888FragShader)3770 Render3DError OpenGLRenderer_2_0::InitPostprocessingPrograms(const std::string &edgeMarkVtxShader,
3771 															 const std::string &edgeMarkFragShader,
3772 															 const std::string &fogVtxShader,
3773 															 const std::string &fogFragShader,
3774 															 const std::string &framebufferOutputVtxShader,
3775 															 const std::string &framebufferOutputRGBA6665FragShader,
3776 															 const std::string &framebufferOutputRGBA8888FragShader)
3777 {
3778 	Render3DError error = OGLERROR_NOERR;
3779 	OGLRenderRef &OGLRef = *this->ref;
3780 
3781 	OGLRef.vertexEdgeMarkShaderID = glCreateShader(GL_VERTEX_SHADER);
3782 	if(!OGLRef.vertexEdgeMarkShaderID)
3783 	{
3784 		INFO("OpenGL: Failed to create the edge mark vertex shader.\n");
3785 		return OGLERROR_SHADER_CREATE_ERROR;
3786 	}
3787 
3788 	const char *edgeMarkVtxShaderCStr = edgeMarkVtxShader.c_str();
3789 	glShaderSource(OGLRef.vertexEdgeMarkShaderID, 1, (const GLchar **)&edgeMarkVtxShaderCStr, NULL);
3790 	glCompileShader(OGLRef.vertexEdgeMarkShaderID);
3791 	if (!this->ValidateShaderCompile(OGLRef.vertexEdgeMarkShaderID))
3792 	{
3793 		glDeleteShader(OGLRef.vertexEdgeMarkShaderID);
3794 		INFO("OpenGL: Failed to compile the edge mark vertex shader.\n");
3795 		return OGLERROR_SHADER_CREATE_ERROR;
3796 	}
3797 
3798 	OGLRef.fragmentEdgeMarkShaderID = glCreateShader(GL_FRAGMENT_SHADER);
3799 	if(!OGLRef.fragmentEdgeMarkShaderID)
3800 	{
3801 		glDeleteShader(OGLRef.vertexEdgeMarkShaderID);
3802 		INFO("OpenGL: Failed to create the edge mark fragment shader.\n");
3803 		return OGLERROR_SHADER_CREATE_ERROR;
3804 	}
3805 
3806 	const char *edgeMarkFragShaderCStr = edgeMarkFragShader.c_str();
3807 	glShaderSource(OGLRef.fragmentEdgeMarkShaderID, 1, (const GLchar **)&edgeMarkFragShaderCStr, NULL);
3808 	glCompileShader(OGLRef.fragmentEdgeMarkShaderID);
3809 	if (!this->ValidateShaderCompile(OGLRef.fragmentEdgeMarkShaderID))
3810 	{
3811 		glDeleteShader(OGLRef.vertexEdgeMarkShaderID);
3812 		glDeleteShader(OGLRef.fragmentEdgeMarkShaderID);
3813 		INFO("OpenGL: Failed to compile the edge mark fragment shader.\n");
3814 		return OGLERROR_SHADER_CREATE_ERROR;
3815 	}
3816 
3817 	OGLRef.programEdgeMarkID = glCreateProgram();
3818 	if(!OGLRef.programEdgeMarkID)
3819 	{
3820 		glDeleteShader(OGLRef.vertexEdgeMarkShaderID);
3821 		glDeleteShader(OGLRef.fragmentEdgeMarkShaderID);
3822 		INFO("OpenGL: Failed to create the edge mark shader program.\n");
3823 		return OGLERROR_SHADER_CREATE_ERROR;
3824 	}
3825 
3826 	glAttachShader(OGLRef.programEdgeMarkID, OGLRef.vertexEdgeMarkShaderID);
3827 	glAttachShader(OGLRef.programEdgeMarkID, OGLRef.fragmentEdgeMarkShaderID);
3828 
3829 	error = this->InitEdgeMarkProgramBindings();
3830 	if (error != OGLERROR_NOERR)
3831 	{
3832 		glDetachShader(OGLRef.programEdgeMarkID, OGLRef.vertexEdgeMarkShaderID);
3833 		glDetachShader(OGLRef.programEdgeMarkID, OGLRef.fragmentEdgeMarkShaderID);
3834 		glDeleteProgram(OGLRef.programEdgeMarkID);
3835 		glDeleteShader(OGLRef.vertexEdgeMarkShaderID);
3836 		glDeleteShader(OGLRef.fragmentEdgeMarkShaderID);
3837 		INFO("OpenGL: Failed to make the edge mark shader bindings.\n");
3838 		return error;
3839 	}
3840 
3841 	glLinkProgram(OGLRef.programEdgeMarkID);
3842 	if (!this->ValidateShaderProgramLink(OGLRef.programEdgeMarkID))
3843 	{
3844 		glDetachShader(OGLRef.programEdgeMarkID, OGLRef.vertexEdgeMarkShaderID);
3845 		glDetachShader(OGLRef.programEdgeMarkID, OGLRef.fragmentEdgeMarkShaderID);
3846 		glDeleteProgram(OGLRef.programEdgeMarkID);
3847 		glDeleteShader(OGLRef.vertexEdgeMarkShaderID);
3848 		glDeleteShader(OGLRef.fragmentEdgeMarkShaderID);
3849 		INFO("OpenGL: Failed to link the edge mark shader program.\n");
3850 		return OGLERROR_SHADER_CREATE_ERROR;
3851 	}
3852 
3853 	glValidateProgram(OGLRef.programEdgeMarkID);
3854 	this->InitEdgeMarkProgramShaderLocations();
3855 
3856 	// ------------------------------------------
3857 
3858 	OGLRef.vertexFogShaderID = glCreateShader(GL_VERTEX_SHADER);
3859 	if(!OGLRef.vertexFogShaderID)
3860 	{
3861 		INFO("OpenGL: Failed to create the fog vertex shader.\n");
3862 		return OGLERROR_SHADER_CREATE_ERROR;
3863 	}
3864 
3865 	const char *fogVtxShaderCStr = fogVtxShader.c_str();
3866 	glShaderSource(OGLRef.vertexFogShaderID, 1, (const GLchar **)&fogVtxShaderCStr, NULL);
3867 	glCompileShader(OGLRef.vertexFogShaderID);
3868 	if (!this->ValidateShaderCompile(OGLRef.vertexFogShaderID))
3869 	{
3870 		glDeleteShader(OGLRef.vertexFogShaderID);
3871 		INFO("OpenGL: Failed to compile the fog vertex shader.\n");
3872 		return OGLERROR_SHADER_CREATE_ERROR;
3873 	}
3874 
3875 	OGLRef.fragmentFogShaderID = glCreateShader(GL_FRAGMENT_SHADER);
3876 	if(!OGLRef.fragmentFogShaderID)
3877 	{
3878 		glDeleteShader(OGLRef.vertexFogShaderID);
3879 		INFO("OpenGL: Failed to create the fog fragment shader.\n");
3880 		return OGLERROR_SHADER_CREATE_ERROR;
3881 	}
3882 
3883 	const char *fogFragShaderCStr = fogFragShader.c_str();
3884 	glShaderSource(OGLRef.fragmentFogShaderID, 1, (const GLchar **)&fogFragShaderCStr, NULL);
3885 	glCompileShader(OGLRef.fragmentFogShaderID);
3886 	if (!this->ValidateShaderCompile(OGLRef.fragmentFogShaderID))
3887 	{
3888 		glDeleteShader(OGLRef.vertexFogShaderID);
3889 		glDeleteShader(OGLRef.fragmentFogShaderID);
3890 		INFO("OpenGL: Failed to compile the fog fragment shader.\n");
3891 		return OGLERROR_SHADER_CREATE_ERROR;
3892 	}
3893 
3894 	OGLRef.programFogID = glCreateProgram();
3895 	if(!OGLRef.programFogID)
3896 	{
3897 		glDeleteShader(OGLRef.vertexFogShaderID);
3898 		glDeleteShader(OGLRef.fragmentFogShaderID);
3899 		INFO("OpenGL: Failed to create the fog shader program.\n");
3900 		return OGLERROR_SHADER_CREATE_ERROR;
3901 	}
3902 
3903 	glAttachShader(OGLRef.programFogID, OGLRef.vertexFogShaderID);
3904 	glAttachShader(OGLRef.programFogID, OGLRef.fragmentFogShaderID);
3905 
3906 	error = this->InitFogProgramBindings();
3907 	if (error != OGLERROR_NOERR)
3908 	{
3909 		glDetachShader(OGLRef.programFogID, OGLRef.vertexFogShaderID);
3910 		glDetachShader(OGLRef.programFogID, OGLRef.fragmentFogShaderID);
3911 		glDeleteProgram(OGLRef.programFogID);
3912 		glDeleteShader(OGLRef.vertexFogShaderID);
3913 		glDeleteShader(OGLRef.fragmentFogShaderID);
3914 		INFO("OpenGL: Failed to make the fog shader bindings.\n");
3915 		return error;
3916 	}
3917 
3918 	glLinkProgram(OGLRef.programFogID);
3919 	if (!this->ValidateShaderProgramLink(OGLRef.programFogID))
3920 	{
3921 		glDetachShader(OGLRef.programFogID, OGLRef.vertexFogShaderID);
3922 		glDetachShader(OGLRef.programFogID, OGLRef.fragmentFogShaderID);
3923 		glDeleteProgram(OGLRef.programFogID);
3924 		glDeleteShader(OGLRef.vertexFogShaderID);
3925 		glDeleteShader(OGLRef.fragmentFogShaderID);
3926 		INFO("OpenGL: Failed to link the fog shader program.\n");
3927 		return OGLERROR_SHADER_CREATE_ERROR;
3928 	}
3929 
3930 	glValidateProgram(OGLRef.programFogID);
3931 	this->InitFogProgramShaderLocations();
3932 
3933 	// ------------------------------------------
3934 
3935 	OGLRef.vertexFramebufferOutputShaderID = glCreateShader(GL_VERTEX_SHADER);
3936 	if(!OGLRef.vertexFramebufferOutputShaderID)
3937 	{
3938 		INFO("OpenGL: Failed to create the framebuffer output vertex shader.\n");
3939 		return OGLERROR_SHADER_CREATE_ERROR;
3940 	}
3941 
3942 	const char *framebufferOutputVtxShaderCStr = framebufferOutputVtxShader.c_str();
3943 	glShaderSource(OGLRef.vertexFramebufferOutputShaderID, 1, (const GLchar **)&framebufferOutputVtxShaderCStr, NULL);
3944 	glCompileShader(OGLRef.vertexFramebufferOutputShaderID);
3945 	if (!this->ValidateShaderCompile(OGLRef.vertexFramebufferOutputShaderID))
3946 	{
3947 		glDeleteShader(OGLRef.vertexFramebufferOutputShaderID);
3948 		INFO("OpenGL: Failed to compile the framebuffer output vertex shader.\n");
3949 		return OGLERROR_SHADER_CREATE_ERROR;
3950 	}
3951 
3952 	OGLRef.fragmentFramebufferRGBA6665OutputShaderID = glCreateShader(GL_FRAGMENT_SHADER);
3953 	if(!OGLRef.fragmentFramebufferRGBA6665OutputShaderID)
3954 	{
3955 		glDeleteShader(OGLRef.vertexFramebufferOutputShaderID);
3956 		INFO("OpenGL: Failed to create the framebuffer output fragment shader.\n");
3957 		return OGLERROR_SHADER_CREATE_ERROR;
3958 	}
3959 
3960 	OGLRef.fragmentFramebufferRGBA8888OutputShaderID = glCreateShader(GL_FRAGMENT_SHADER);
3961 	if(!OGLRef.fragmentFramebufferRGBA8888OutputShaderID)
3962 	{
3963 		glDeleteShader(OGLRef.vertexFramebufferOutputShaderID);
3964 		glDeleteShader(OGLRef.fragmentFramebufferRGBA6665OutputShaderID);
3965 		INFO("OpenGL: Failed to create the framebuffer output fragment shader.\n");
3966 		return OGLERROR_SHADER_CREATE_ERROR;
3967 	}
3968 
3969 	const char *framebufferOutputRGBA6665FragShaderCStr = framebufferOutputRGBA6665FragShader.c_str();
3970 	glShaderSource(OGLRef.fragmentFramebufferRGBA6665OutputShaderID, 1, (const GLchar **)&framebufferOutputRGBA6665FragShaderCStr, NULL);
3971 	glCompileShader(OGLRef.fragmentFramebufferRGBA6665OutputShaderID);
3972 	if (!this->ValidateShaderCompile(OGLRef.fragmentFramebufferRGBA6665OutputShaderID))
3973 	{
3974 		glDeleteShader(OGLRef.vertexFramebufferOutputShaderID);
3975 		glDeleteShader(OGLRef.fragmentFramebufferRGBA6665OutputShaderID);
3976 		glDeleteShader(OGLRef.fragmentFramebufferRGBA8888OutputShaderID);
3977 		INFO("OpenGL: Failed to compile the framebuffer output fragment shader.\n");
3978 		return OGLERROR_SHADER_CREATE_ERROR;
3979 	}
3980 
3981 	const char *framebufferOutputRGBA8888FragShaderCStr = framebufferOutputRGBA8888FragShader.c_str();
3982 	glShaderSource(OGLRef.fragmentFramebufferRGBA8888OutputShaderID, 1, (const GLchar **)&framebufferOutputRGBA8888FragShaderCStr, NULL);
3983 	glCompileShader(OGLRef.fragmentFramebufferRGBA8888OutputShaderID);
3984 	if (!this->ValidateShaderCompile(OGLRef.fragmentFramebufferRGBA8888OutputShaderID))
3985 	{
3986 		glDeleteShader(OGLRef.vertexFramebufferOutputShaderID);
3987 		glDeleteShader(OGLRef.fragmentFramebufferRGBA6665OutputShaderID);
3988 		glDeleteShader(OGLRef.fragmentFramebufferRGBA8888OutputShaderID);
3989 		INFO("OpenGL: Failed to compile the framebuffer output fragment shader.\n");
3990 		return OGLERROR_SHADER_CREATE_ERROR;
3991 	}
3992 
3993 	OGLRef.programFramebufferRGBA6665OutputID = glCreateProgram();
3994 	if(!OGLRef.programFramebufferRGBA6665OutputID)
3995 	{
3996 		glDeleteShader(OGLRef.vertexFramebufferOutputShaderID);
3997 		glDeleteShader(OGLRef.fragmentFramebufferRGBA6665OutputShaderID);
3998 		glDeleteShader(OGLRef.fragmentFramebufferRGBA8888OutputShaderID);
3999 		INFO("OpenGL: Failed to create the framebuffer output shader program.\n");
4000 		return OGLERROR_SHADER_CREATE_ERROR;
4001 	}
4002 
4003 	OGLRef.programFramebufferRGBA8888OutputID = glCreateProgram();
4004 	if(!OGLRef.programFramebufferRGBA8888OutputID)
4005 	{
4006 		glDeleteShader(OGLRef.vertexFramebufferOutputShaderID);
4007 		glDeleteShader(OGLRef.fragmentFramebufferRGBA6665OutputShaderID);
4008 		glDeleteShader(OGLRef.fragmentFramebufferRGBA8888OutputShaderID);
4009 		INFO("OpenGL: Failed to create the framebuffer output shader program.\n");
4010 		return OGLERROR_SHADER_CREATE_ERROR;
4011 	}
4012 
4013 	glAttachShader(OGLRef.programFramebufferRGBA6665OutputID, OGLRef.vertexFramebufferOutputShaderID);
4014 	glAttachShader(OGLRef.programFramebufferRGBA6665OutputID, OGLRef.fragmentFramebufferRGBA6665OutputShaderID);
4015 	glAttachShader(OGLRef.programFramebufferRGBA8888OutputID, OGLRef.vertexFramebufferOutputShaderID);
4016 	glAttachShader(OGLRef.programFramebufferRGBA8888OutputID, OGLRef.fragmentFramebufferRGBA8888OutputShaderID);
4017 
4018 	error = this->InitFramebufferOutputProgramBindings();
4019 	if (error != OGLERROR_NOERR)
4020 	{
4021 		glDetachShader(OGLRef.programFramebufferRGBA6665OutputID, OGLRef.vertexFramebufferOutputShaderID);
4022 		glDetachShader(OGLRef.programFramebufferRGBA6665OutputID, OGLRef.fragmentFramebufferRGBA6665OutputShaderID);
4023 		glDetachShader(OGLRef.programFramebufferRGBA8888OutputID, OGLRef.vertexFramebufferOutputShaderID);
4024 		glDetachShader(OGLRef.programFramebufferRGBA8888OutputID, OGLRef.fragmentFramebufferRGBA8888OutputShaderID);
4025 
4026 		glDeleteProgram(OGLRef.programFramebufferRGBA6665OutputID);
4027 		glDeleteProgram(OGLRef.programFramebufferRGBA8888OutputID);
4028 		glDeleteShader(OGLRef.vertexFramebufferOutputShaderID);
4029 		glDeleteShader(OGLRef.fragmentFramebufferRGBA6665OutputShaderID);
4030 		glDeleteShader(OGLRef.fragmentFramebufferRGBA8888OutputShaderID);
4031 		INFO("OpenGL: Failed to make the framebuffer output shader bindings.\n");
4032 		return error;
4033 	}
4034 
4035 	glLinkProgram(OGLRef.programFramebufferRGBA6665OutputID);
4036 	glLinkProgram(OGLRef.programFramebufferRGBA8888OutputID);
4037 
4038 	if (!this->ValidateShaderProgramLink(OGLRef.programFramebufferRGBA6665OutputID) || !this->ValidateShaderProgramLink(OGLRef.programFramebufferRGBA8888OutputID))
4039 	{
4040 		glDetachShader(OGLRef.programFramebufferRGBA6665OutputID, OGLRef.vertexFramebufferOutputShaderID);
4041 		glDetachShader(OGLRef.programFramebufferRGBA6665OutputID, OGLRef.fragmentFramebufferRGBA6665OutputShaderID);
4042 		glDetachShader(OGLRef.programFramebufferRGBA8888OutputID, OGLRef.vertexFramebufferOutputShaderID);
4043 		glDetachShader(OGLRef.programFramebufferRGBA8888OutputID, OGLRef.fragmentFramebufferRGBA8888OutputShaderID);
4044 
4045 		glDeleteProgram(OGLRef.programFramebufferRGBA6665OutputID);
4046 		glDeleteProgram(OGLRef.programFramebufferRGBA8888OutputID);
4047 		glDeleteShader(OGLRef.vertexFramebufferOutputShaderID);
4048 		glDeleteShader(OGLRef.fragmentFramebufferRGBA6665OutputShaderID);
4049 		glDeleteShader(OGLRef.fragmentFramebufferRGBA8888OutputShaderID);
4050 		INFO("OpenGL: Failed to link the framebuffer output shader program.\n");
4051 		return OGLERROR_SHADER_CREATE_ERROR;
4052 	}
4053 
4054 	glValidateProgram(OGLRef.programFramebufferRGBA6665OutputID);
4055 	glValidateProgram(OGLRef.programFramebufferRGBA8888OutputID);
4056 	this->InitFramebufferOutputShaderLocations();
4057 
4058 	// ------------------------------------------
4059 
4060 	glUseProgram(OGLRef.programGeometryID);
4061 	INFO("OpenGL: Successfully created postprocess shaders.\n");
4062 
4063 	return OGLERROR_NOERR;
4064 }
4065 
DestroyPostprocessingPrograms()4066 Render3DError OpenGLRenderer_2_0::DestroyPostprocessingPrograms()
4067 {
4068 	OGLRenderRef &OGLRef = *this->ref;
4069 
4070 	glUseProgram(0);
4071 	glDetachShader(OGLRef.programEdgeMarkID, OGLRef.vertexEdgeMarkShaderID);
4072 	glDetachShader(OGLRef.programEdgeMarkID, OGLRef.fragmentEdgeMarkShaderID);
4073 	glDetachShader(OGLRef.programFogID, OGLRef.vertexFogShaderID);
4074 	glDetachShader(OGLRef.programFogID, OGLRef.fragmentFogShaderID);
4075 
4076 	glDeleteProgram(OGLRef.programEdgeMarkID);
4077 	glDeleteProgram(OGLRef.programFogID);
4078 
4079 	glDeleteShader(OGLRef.vertexEdgeMarkShaderID);
4080 	glDeleteShader(OGLRef.fragmentEdgeMarkShaderID);
4081 	glDeleteShader(OGLRef.vertexFogShaderID);
4082 	glDeleteShader(OGLRef.fragmentFogShaderID);
4083 
4084 	glDetachShader(OGLRef.programFramebufferRGBA6665OutputID, OGLRef.vertexFramebufferOutputShaderID);
4085 	glDetachShader(OGLRef.programFramebufferRGBA6665OutputID, OGLRef.fragmentFramebufferRGBA6665OutputShaderID);
4086 	glDetachShader(OGLRef.programFramebufferRGBA8888OutputID, OGLRef.vertexFramebufferOutputShaderID);
4087 	glDetachShader(OGLRef.programFramebufferRGBA8888OutputID, OGLRef.fragmentFramebufferRGBA8888OutputShaderID);
4088 
4089 	glDeleteProgram(OGLRef.programFramebufferRGBA6665OutputID);
4090 	glDeleteProgram(OGLRef.programFramebufferRGBA8888OutputID);
4091 	glDeleteShader(OGLRef.vertexFramebufferOutputShaderID);
4092 	glDeleteShader(OGLRef.fragmentFramebufferRGBA6665OutputShaderID);
4093 	glDeleteShader(OGLRef.fragmentFramebufferRGBA8888OutputShaderID);
4094 
4095 	return OGLERROR_NOERR;
4096 }
4097 
InitEdgeMarkProgramBindings()4098 Render3DError OpenGLRenderer_2_0::InitEdgeMarkProgramBindings()
4099 {
4100 	OGLRenderRef &OGLRef = *this->ref;
4101 	glBindAttribLocation(OGLRef.programEdgeMarkID, OGLVertexAttributeID_Position, "inPosition");
4102 	glBindAttribLocation(OGLRef.programEdgeMarkID, OGLVertexAttributeID_TexCoord0, "inTexCoord0");
4103 
4104 	return OGLERROR_NOERR;
4105 }
4106 
InitEdgeMarkProgramShaderLocations()4107 Render3DError OpenGLRenderer_2_0::InitEdgeMarkProgramShaderLocations()
4108 {
4109 	OGLRenderRef &OGLRef = *this->ref;
4110 
4111 	glUseProgram(OGLRef.programEdgeMarkID);
4112 
4113 	const GLint uniformTexGDepth	= glGetUniformLocation(OGLRef.programEdgeMarkID, "texInFragDepth");
4114 	const GLint uniformTexGPolyID	= glGetUniformLocation(OGLRef.programEdgeMarkID, "texInPolyID");
4115 	glUniform1i(uniformTexGDepth, OGLTextureUnitID_GDepth);
4116 	glUniform1i(uniformTexGPolyID, OGLTextureUnitID_GPolyID);
4117 
4118 	OGLRef.uniformFramebufferSize	= glGetUniformLocation(OGLRef.programEdgeMarkID, "framebufferSize");
4119 	OGLRef.uniformStateEdgeColor	= glGetUniformLocation(OGLRef.programEdgeMarkID, "stateEdgeColor");
4120 
4121 	return OGLERROR_NOERR;
4122 }
4123 
InitFogProgramBindings()4124 Render3DError OpenGLRenderer_2_0::InitFogProgramBindings()
4125 {
4126 	OGLRenderRef &OGLRef = *this->ref;
4127 	glBindAttribLocation(OGLRef.programFogID, OGLVertexAttributeID_Position, "inPosition");
4128 	glBindAttribLocation(OGLRef.programFogID, OGLVertexAttributeID_TexCoord0, "inTexCoord0");
4129 
4130 	return OGLERROR_NOERR;
4131 }
4132 
InitFogProgramShaderLocations()4133 Render3DError OpenGLRenderer_2_0::InitFogProgramShaderLocations()
4134 {
4135 	OGLRenderRef &OGLRef = *this->ref;
4136 
4137 	glUseProgram(OGLRef.programFogID);
4138 
4139 	const GLint uniformTexGColor			= glGetUniformLocation(OGLRef.programFogID, "texInFragColor");
4140 	const GLint uniformTexGDepth			= glGetUniformLocation(OGLRef.programFogID, "texInFragDepth");
4141 	const GLint uniformTexGFog				= glGetUniformLocation(OGLRef.programFogID, "texInFogAttributes");
4142 	glUniform1i(uniformTexGColor, OGLTextureUnitID_GColor);
4143 	glUniform1i(uniformTexGDepth, OGLTextureUnitID_GDepth);
4144 	glUniform1i(uniformTexGFog, OGLTextureUnitID_FogAttr);
4145 
4146 	OGLRef.uniformStateEnableFogAlphaOnly	= glGetUniformLocation(OGLRef.programFogID, "stateEnableFogAlphaOnly");
4147 	OGLRef.uniformStateFogColor				= glGetUniformLocation(OGLRef.programFogID, "stateFogColor");
4148 	OGLRef.uniformStateFogDensity			= glGetUniformLocation(OGLRef.programFogID, "stateFogDensity");
4149 	OGLRef.uniformStateFogOffset			= glGetUniformLocation(OGLRef.programFogID, "stateFogOffset");
4150 	OGLRef.uniformStateFogStep				= glGetUniformLocation(OGLRef.programFogID, "stateFogStep");
4151 
4152 	return OGLERROR_NOERR;
4153 }
4154 
InitFramebufferOutputProgramBindings()4155 Render3DError OpenGLRenderer_2_0::InitFramebufferOutputProgramBindings()
4156 {
4157 	OGLRenderRef &OGLRef = *this->ref;
4158 	glBindAttribLocation(OGLRef.programFramebufferRGBA6665OutputID, OGLVertexAttributeID_Position, "inPosition");
4159 	glBindAttribLocation(OGLRef.programFramebufferRGBA6665OutputID, OGLVertexAttributeID_TexCoord0, "inTexCoord0");
4160 	glBindAttribLocation(OGLRef.programFramebufferRGBA8888OutputID, OGLVertexAttributeID_Position, "inPosition");
4161 	glBindAttribLocation(OGLRef.programFramebufferRGBA8888OutputID, OGLVertexAttributeID_TexCoord0, "inTexCoord0");
4162 
4163 	return OGLERROR_NOERR;
4164 }
4165 
InitFramebufferOutputShaderLocations()4166 Render3DError OpenGLRenderer_2_0::InitFramebufferOutputShaderLocations()
4167 {
4168 	OGLRenderRef &OGLRef = *this->ref;
4169 
4170 	glUseProgram(OGLRef.programFramebufferRGBA6665OutputID);
4171 	const GLint uniformTexFinalColorRGBA6665 = glGetUniformLocation(OGLRef.programFramebufferRGBA6665OutputID, "texInFragColor");
4172 	glUniform1i(uniformTexFinalColorRGBA6665, OGLTextureUnitID_FinalColor);
4173 
4174 	glUseProgram(OGLRef.programFramebufferRGBA8888OutputID);
4175 	const GLint uniformTexFinalColorRGBA8888 = glGetUniformLocation(OGLRef.programFramebufferRGBA8888OutputID, "texInFragColor");
4176 	glUniform1i(uniformTexFinalColorRGBA8888, OGLTextureUnitID_FinalColor);
4177 
4178 	return OGLERROR_NOERR;
4179 }
4180 
EnableVertexAttributes()4181 Render3DError OpenGLRenderer_2_0::EnableVertexAttributes()
4182 {
4183 	OGLRenderRef &OGLRef = *this->ref;
4184 
4185 	if (this->isVAOSupported)
4186 	{
4187 		glBindVertexArray(OGLRef.vaoGeometryStatesID);
4188 	}
4189 	else
4190 	{
4191 		glEnableVertexAttribArray(OGLVertexAttributeID_Position);
4192 		glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0);
4193 		glEnableVertexAttribArray(OGLVertexAttributeID_Color);
4194 		glVertexAttribPointer(OGLVertexAttributeID_Position, 4, GL_FLOAT, GL_FALSE, sizeof(VERT), OGLRef.vtxPtrPosition);
4195 		glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(VERT), OGLRef.vtxPtrTexCoord);
4196 		glVertexAttribPointer(OGLVertexAttributeID_Color, 3, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(VERT), OGLRef.vtxPtrColor);
4197 	}
4198 
4199 	glActiveTexture(GL_TEXTURE0);
4200 
4201 	return OGLERROR_NOERR;
4202 }
4203 
DisableVertexAttributes()4204 Render3DError OpenGLRenderer_2_0::DisableVertexAttributes()
4205 {
4206 	if (this->isVAOSupported)
4207 	{
4208 		glBindVertexArray(0);
4209 	}
4210 	else
4211 	{
4212 		glDisableVertexAttribArray(OGLVertexAttributeID_Position);
4213 		glDisableVertexAttribArray(OGLVertexAttributeID_TexCoord0);
4214 		glDisableVertexAttribArray(OGLVertexAttributeID_Color);
4215 	}
4216 
4217 	return OGLERROR_NOERR;
4218 }
4219 
BeginRender(const GFX3D & engine)4220 Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D &engine)
4221 {
4222 	OGLRenderRef &OGLRef = *this->ref;
4223 
4224 	if(!BEGINGL())
4225 	{
4226 		return OGLERROR_BEGINGL_FAILED;
4227 	}
4228 
4229 	// Setup render states
4230 	glUseProgram(OGLRef.programGeometryID);
4231 	glUniform1i(OGLRef.uniformStateToonShadingMode, engine.renderState.shading);
4232 	glUniform1i(OGLRef.uniformStateEnableAlphaTest, (engine.renderState.enableAlphaTest) ? GL_TRUE : GL_FALSE);
4233 	glUniform1i(OGLRef.uniformStateEnableAntialiasing, (engine.renderState.enableAntialiasing) ? GL_TRUE : GL_FALSE);
4234 	glUniform1i(OGLRef.uniformStateEnableEdgeMarking, (engine.renderState.enableEdgeMarking) ? GL_TRUE : GL_FALSE);
4235 	glUniform1i(OGLRef.uniformStateUseWDepth, (engine.renderState.wbuffer) ? GL_TRUE : GL_FALSE);
4236 	glUniform1f(OGLRef.uniformStateAlphaTestRef, divide5bitBy31_LUT[engine.renderState.alphaTestRef]);
4237 
4238 	glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboGeometryVtxID);
4239 	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboGeometryIndexID);
4240 
4241 	size_t vertIndexCount = 0;
4242 	GLushort *indexPtr = (GLushort *)glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY);
4243 
4244 	for (size_t i = 0; i < engine.polylist->count; i++)
4245 	{
4246 		const POLY *thePoly = &engine.polylist->list[engine.indexlist.list[i]];
4247 		const size_t polyType = thePoly->type;
4248 
4249 		for (size_t j = 0; j < polyType; j++)
4250 		{
4251 			const GLushort vertIndex = thePoly->vertIndexes[j];
4252 
4253 			// While we're looping through our vertices, add each vertex index to
4254 			// a buffer. For GFX3D_QUADS and GFX3D_QUAD_STRIP, we also add additional
4255 			// vertices here to convert them to GL_TRIANGLES, which are much easier
4256 			// to work with and won't be deprecated in future OpenGL versions.
4257 			indexPtr[vertIndexCount++] = vertIndex;
4258 			if (thePoly->vtxFormat == GFX3D_QUADS || thePoly->vtxFormat == GFX3D_QUAD_STRIP)
4259 			{
4260 				if (j == 2)
4261 				{
4262 					indexPtr[vertIndexCount++] = vertIndex;
4263 				}
4264 				else if (j == 3)
4265 				{
4266 					indexPtr[vertIndexCount++] = thePoly->vertIndexes[0];
4267 				}
4268 			}
4269 		}
4270 	}
4271 
4272 	glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
4273 	glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(VERT) * engine.vertlist->count, engine.vertlist);
4274 
4275 	return OGLERROR_NOERR;
4276 }
4277 
RenderEdgeMarking(const u16 * colorTable,const bool useAntialias)4278 Render3DError OpenGLRenderer_2_0::RenderEdgeMarking(const u16 *colorTable, const bool useAntialias)
4279 {
4280 	OGLRenderRef &OGLRef = *this->ref;
4281 
4282 	const GLfloat alpha = (useAntialias) ? (16.0f/31.0f) : 1.0f;
4283 	const GLfloat oglColor[4*8]	= {divide5bitBy31_LUT[(colorTable[0]      ) & 0x001F],
4284 								   divide5bitBy31_LUT[(colorTable[0] >>  5) & 0x001F],
4285 								   divide5bitBy31_LUT[(colorTable[0] >> 10) & 0x001F],
4286 								   alpha,
4287 								   divide5bitBy31_LUT[(colorTable[1]      ) & 0x001F],
4288 								   divide5bitBy31_LUT[(colorTable[1] >>  5) & 0x001F],
4289 								   divide5bitBy31_LUT[(colorTable[1] >> 10) & 0x001F],
4290 								   alpha,
4291 								   divide5bitBy31_LUT[(colorTable[2]      ) & 0x001F],
4292 								   divide5bitBy31_LUT[(colorTable[2] >>  5) & 0x001F],
4293 								   divide5bitBy31_LUT[(colorTable[2] >> 10) & 0x001F],
4294 								   alpha,
4295 								   divide5bitBy31_LUT[(colorTable[3]      ) & 0x001F],
4296 								   divide5bitBy31_LUT[(colorTable[3] >>  5) & 0x001F],
4297 								   divide5bitBy31_LUT[(colorTable[3] >> 10) & 0x001F],
4298 								   alpha,
4299 								   divide5bitBy31_LUT[(colorTable[4]      ) & 0x001F],
4300 								   divide5bitBy31_LUT[(colorTable[4] >>  5) & 0x001F],
4301 								   divide5bitBy31_LUT[(colorTable[4] >> 10) & 0x001F],
4302 								   alpha,
4303 								   divide5bitBy31_LUT[(colorTable[5]      ) & 0x001F],
4304 								   divide5bitBy31_LUT[(colorTable[5] >>  5) & 0x001F],
4305 								   divide5bitBy31_LUT[(colorTable[5] >> 10) & 0x001F],
4306 								   alpha,
4307 								   divide5bitBy31_LUT[(colorTable[6]      ) & 0x001F],
4308 								   divide5bitBy31_LUT[(colorTable[6] >>  5) & 0x001F],
4309 								   divide5bitBy31_LUT[(colorTable[6] >> 10) & 0x001F],
4310 								   alpha,
4311 								   divide5bitBy31_LUT[(colorTable[7]      ) & 0x001F],
4312 								   divide5bitBy31_LUT[(colorTable[7] >>  5) & 0x001F],
4313 								   divide5bitBy31_LUT[(colorTable[7] >> 10) & 0x001F],
4314 								   alpha};
4315 
4316 	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboRenderID);
4317 	glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
4318 	glUseProgram(OGLRef.programEdgeMarkID);
4319 	glUniform2f(OGLRef.uniformFramebufferSize, this->_framebufferWidth, this->_framebufferHeight);
4320 	glUniform4fv(OGLRef.uniformStateEdgeColor, 8, oglColor);
4321 
4322 	glViewport(0, 0, this->_framebufferWidth, this->_framebufferHeight);
4323 	glDisable(GL_DEPTH_TEST);
4324 	glDisable(GL_STENCIL_TEST);
4325 	glEnable(GL_BLEND);
4326 	glDisable(GL_CULL_FACE);
4327 
4328 	glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID);
4329 	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboPostprocessIndexID);
4330 
4331 	if (this->isVAOSupported)
4332 	{
4333 		glBindVertexArray(OGLRef.vaoPostprocessStatesID);
4334 	}
4335 	else
4336 	{
4337 		glEnableVertexAttribArray(OGLVertexAttributeID_Position);
4338 		glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0);
4339 		glVertexAttribPointer(OGLVertexAttributeID_Position, 2, GL_FLOAT, GL_FALSE, 0, 0);
4340 		glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *)(sizeof(GLfloat) * 8));
4341 	}
4342 
4343 	glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0);
4344 
4345 	if (this->isVAOSupported)
4346 	{
4347 		glBindVertexArray(0);
4348 	}
4349 	else
4350 	{
4351 		glDisableVertexAttribArray(OGLVertexAttributeID_Position);
4352 		glDisableVertexAttribArray(OGLVertexAttributeID_TexCoord0);
4353 	}
4354 
4355 	return RENDER3DERROR_NOERR;
4356 }
4357 
RenderFog(const u8 * densityTable,const u32 color,const u32 offset,const u8 shift,const bool alphaOnly)4358 Render3DError OpenGLRenderer_2_0::RenderFog(const u8 *densityTable, const u32 color, const u32 offset, const u8 shift, const bool alphaOnly)
4359 {
4360 	OGLRenderRef &OGLRef = *this->ref;
4361 	static GLfloat oglDensityTable[32];
4362 
4363 	if (!this->isFBOSupported)
4364 	{
4365 		return OGLERROR_FEATURE_UNSUPPORTED;
4366 	}
4367 
4368 	for (size_t i = 0; i < 32; i++)
4369 	{
4370 		oglDensityTable[i] = (densityTable[i] == 127) ? 1.0f : (GLfloat)densityTable[i] / 128.0f;
4371 	}
4372 
4373 	const GLfloat oglColor[4]	= {divide5bitBy31_LUT[(color      ) & 0x0000001F],
4374 								   divide5bitBy31_LUT[(color >>  5) & 0x0000001F],
4375 								   divide5bitBy31_LUT[(color >> 10) & 0x0000001F],
4376 								   divide5bitBy31_LUT[(color >> 16) & 0x0000001F]};
4377 
4378 	const GLfloat oglOffset = (GLfloat)offset / 32767.0f;
4379 	const GLfloat oglFogStep = (GLfloat)(0x0400 >> shift) / 32767.0f;
4380 
4381 	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboPostprocessID);
4382 	glUseProgram(OGLRef.programFogID);
4383 	glUniform1i(OGLRef.uniformStateEnableFogAlphaOnly, (alphaOnly) ? GL_TRUE : GL_FALSE);
4384 	glUniform4f(OGLRef.uniformStateFogColor, oglColor[0], oglColor[1], oglColor[2], oglColor[3]);
4385 	glUniform1f(OGLRef.uniformStateFogOffset, oglOffset);
4386 	glUniform1f(OGLRef.uniformStateFogStep, oglFogStep);
4387 	glUniform1fv(OGLRef.uniformStateFogDensity, 32, oglDensityTable);
4388 
4389 	glViewport(0, 0, this->_framebufferWidth, this->_framebufferHeight);
4390 	glDisable(GL_DEPTH_TEST);
4391 	glDisable(GL_STENCIL_TEST);
4392 	glDisable(GL_BLEND);
4393 	glDisable(GL_CULL_FACE);
4394 
4395 	glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID);
4396 	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboPostprocessIndexID);
4397 
4398 	if (this->isVAOSupported)
4399 	{
4400 		glBindVertexArray(OGLRef.vaoPostprocessStatesID);
4401 	}
4402 	else
4403 	{
4404 		glEnableVertexAttribArray(OGLVertexAttributeID_Position);
4405 		glEnableVertexAttribArray(OGLVertexAttributeID_TexCoord0);
4406 		glVertexAttribPointer(OGLVertexAttributeID_Position, 2, GL_FLOAT, GL_FALSE, 0, 0);
4407 		glVertexAttribPointer(OGLVertexAttributeID_TexCoord0, 2, GL_FLOAT, GL_FALSE, 0, (const GLvoid *)(sizeof(GLfloat) * 8));
4408 	}
4409 
4410 	glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0);
4411 
4412 	if (this->isVAOSupported)
4413 	{
4414 		glBindVertexArray(0);
4415 	}
4416 	else
4417 	{
4418 		glDisableVertexAttribArray(OGLVertexAttributeID_Position);
4419 		glDisableVertexAttribArray(OGLVertexAttributeID_TexCoord0);
4420 	}
4421 
4422 	return OGLERROR_NOERR;
4423 }
4424 
SetupPolygon(const POLY & thePoly)4425 Render3DError OpenGLRenderer_2_0::SetupPolygon(const POLY &thePoly)
4426 {
4427 	const PolygonAttributes attr = thePoly.getAttributes();
4428 
4429 	// Set up depth test mode
4430 	static const GLenum oglDepthFunc[2] = {GL_LESS, GL_EQUAL};
4431 	glDepthFunc(oglDepthFunc[attr.enableDepthEqualTest]);
4432 
4433 	// Set up culling mode
4434 	static const GLenum oglCullingMode[4] = {GL_FRONT_AND_BACK, GL_FRONT, GL_BACK, 0};
4435 	GLenum cullingMode = oglCullingMode[attr.surfaceCullingMode];
4436 
4437 	if (cullingMode == 0)
4438 	{
4439 		glDisable(GL_CULL_FACE);
4440 	}
4441 	else
4442 	{
4443 		glEnable(GL_CULL_FACE);
4444 		glCullFace(cullingMode);
4445 	}
4446 
4447 	// Set up depth write
4448 	GLboolean enableDepthWrite = GL_TRUE;
4449 
4450 	// Handle shadow polys. Do this after checking for depth write, since shadow polys
4451 	// can change this too.
4452 	if (attr.polygonMode == POLYGON_MODE_SHADOW)
4453 	{
4454 		glEnable(GL_STENCIL_TEST);
4455 
4456 		if (attr.polygonID == 0)
4457 		{
4458 			//when the polyID is zero, we are writing the shadow mask.
4459 			//set stencilbuf = 1 where the shadow volume is obstructed by geometry.
4460 			//do not write color or depth information.
4461 			glStencilFunc(GL_NOTEQUAL, 0x80, 0xFF);
4462 			glStencilOp(GL_KEEP, GL_ZERO, GL_KEEP);
4463 			glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
4464 			enableDepthWrite = GL_FALSE;
4465 		}
4466 		else
4467 		{
4468 			//when the polyid is nonzero, we are drawing the shadow poly.
4469 			//only draw the shadow poly where the stencilbuf==1.
4470 			glStencilFunc(GL_EQUAL, 0, 0xFF);
4471 			glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
4472 			glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4473 			enableDepthWrite = GL_TRUE;
4474 		}
4475 	}
4476 	else if ( attr.isTranslucent || (std::find(this->_shadowPolyID.begin(), this->_shadowPolyID.end(), attr.polygonID) == this->_shadowPolyID.end()) )
4477 	{
4478 		glDisable(GL_STENCIL_TEST);
4479 		glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4480 		enableDepthWrite = (!attr.isTranslucent || ( (attr.polygonMode == POLYGON_MODE_DECAL) && attr.isOpaque ) || attr.enableAlphaDepthWrite) ? GL_TRUE : GL_FALSE;
4481 	}
4482 	else
4483 	{
4484 		glEnable(GL_STENCIL_TEST);
4485 		glStencilFunc(GL_ALWAYS, 0x80, 0xFF);
4486 		glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
4487 		glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4488 		enableDepthWrite = GL_TRUE;
4489 	}
4490 
4491 	glDepthMask(enableDepthWrite);
4492 
4493 	// Set up polygon attributes
4494 	OGLRenderRef &OGLRef = *this->ref;
4495 	glUniform1i(OGLRef.uniformPolyMode, attr.polygonMode);
4496 	glUniform1i(OGLRef.uniformPolyEnableFog, (attr.enableRenderFog) ? GL_TRUE : GL_FALSE);
4497 	glUniform1f(OGLRef.uniformPolyAlpha, (!attr.isWireframe && attr.isTranslucent) ? divide5bitBy31_LUT[attr.alpha] : 1.0f);
4498 	glUniform1i(OGLRef.uniformPolyID, attr.polygonID);
4499 	glUniform1i(OGLRef.uniformPolyEnableDepthWrite, enableDepthWrite);
4500 	glUniform1i(OGLRef.uniformPolySetNewDepthForTranslucent, (attr.enableAlphaDepthWrite) ? GL_TRUE : GL_FALSE);
4501 
4502 	return OGLERROR_NOERR;
4503 }
4504 
SetupTexture(const POLY & thePoly,bool enableTexturing)4505 Render3DError OpenGLRenderer_2_0::SetupTexture(const POLY &thePoly, bool enableTexturing)
4506 {
4507 	OGLRenderRef &OGLRef = *this->ref;
4508 	const PolygonTexParams params = thePoly.getTexParams();
4509 
4510 	// Check if we need to use textures
4511 	if (params.texFormat == TEXMODE_NONE || !enableTexturing)
4512 	{
4513 		glUniform1i(OGLRef.uniformPolyEnableTexture, GL_FALSE);
4514 		return OGLERROR_NOERR;
4515 	}
4516 
4517 	glUniform1i(OGLRef.uniformPolyEnableTexture, GL_TRUE);
4518 
4519 	TexCacheItem *newTexture = TexCache_SetTexture(TexFormat_32bpp, thePoly.texParam, thePoly.texPalette);
4520 	if(newTexture != this->currTexture)
4521 	{
4522 		this->currTexture = newTexture;
4523 		//has the ogl renderer initialized the texture?
4524 		if(this->currTexture->GetDeleteCallback() == NULL)
4525 		{
4526 			this->currTexture->SetDeleteCallback(&texDeleteCallback, this, NULL);
4527 
4528 			if(OGLRef.freeTextureIDs.empty())
4529 			{
4530 				this->ExpandFreeTextures();
4531 			}
4532 
4533 			this->currTexture->texid = (u64)OGLRef.freeTextureIDs.front();
4534 			OGLRef.freeTextureIDs.pop();
4535 
4536 			glBindTexture(GL_TEXTURE_2D, (GLuint)this->currTexture->texid);
4537 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
4538 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
4539 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, (params.enableRepeatS ? (params.enableMirroredRepeatS ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE));
4540 			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, (params.enableRepeatT ? (params.enableMirroredRepeatT ? GL_MIRRORED_REPEAT : GL_REPEAT) : GL_CLAMP_TO_EDGE));
4541 
4542 			u32 *textureSrc = (u32 *)currTexture->decoded;
4543 			size_t texWidth = currTexture->sizeX;
4544 			size_t texHeight = currTexture->sizeY;
4545 
4546 			if (this->_textureDeposterizeBuffer != NULL)
4547 			{
4548 				this->TextureDeposterize(textureSrc, texWidth, texHeight);
4549 				textureSrc = this->_textureDeposterizeBuffer;
4550 			}
4551 
4552 			switch (this->_textureScalingFactor)
4553 			{
4554 				case 2:
4555 				{
4556 					this->TextureUpscale<2>(textureSrc, texWidth, texHeight);
4557 					textureSrc = this->_textureUpscaleBuffer;
4558 					break;
4559 				}
4560 
4561 				case 4:
4562 				{
4563 					this->TextureUpscale<4>(textureSrc, texWidth, texHeight);
4564 					textureSrc = this->_textureUpscaleBuffer;
4565 					break;
4566 				}
4567 
4568 				default:
4569 					break;
4570 			}
4571 
4572 			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureSrc);
4573 		}
4574 		else
4575 		{
4576 			//otherwise, just bind it
4577 			glBindTexture(GL_TEXTURE_2D, (GLuint)this->currTexture->texid);
4578 		}
4579 
4580 		glUniform2f(OGLRef.uniformPolyTexScale, this->currTexture->invSizeX, this->currTexture->invSizeY);
4581 	}
4582 
4583 	return OGLERROR_NOERR;
4584 }
4585 
ReadBackPixels()4586 Render3DError OpenGLRenderer_2_1::ReadBackPixels()
4587 {
4588 	OGLRenderRef &OGLRef = *this->ref;
4589 
4590 	if (this->_mappedFramebuffer != NULL)
4591 	{
4592 		glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
4593 		this->_mappedFramebuffer = NULL;
4594 	}
4595 
4596 	// Flip the framebuffer in Y to match the coordinates of OpenGL and the NDS hardware.
4597 	if (this->willFlipFramebufferOnGPU)
4598 	{
4599 		glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, OGLRef.fboPostprocessID);
4600 		glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT);
4601 		glBlitFramebufferEXT(0, this->_framebufferHeight, this->_framebufferWidth, 0, 0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
4602 		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, OGLRef.fboPostprocessID);
4603 		glReadBuffer(GL_COLOR_ATTACHMENT1_EXT);
4604 	}
4605 
4606 	if (this->willConvertFramebufferOnGPU)
4607 	{
4608 		// Perform the color space conversion while we're still on the GPU so
4609 		// that we can avoid having to do it on the CPU.
4610 		const GLuint convertProgramID = (this->_outputFormat == NDSColorFormat_BGR666_Rev) ? OGLRef.programFramebufferRGBA6665OutputID : OGLRef.programFramebufferRGBA8888OutputID;
4611 		glDrawBuffer(GL_COLOR_ATTACHMENT2_EXT);
4612 
4613 		glUseProgram(convertProgramID);
4614 		glViewport(0, 0, this->_framebufferWidth, this->_framebufferHeight);
4615 		glDisable(GL_DEPTH_TEST);
4616 		glDisable(GL_STENCIL_TEST);
4617 		glDisable(GL_BLEND);
4618 		glDisable(GL_CULL_FACE);
4619 
4620 		glBindBuffer(GL_ARRAY_BUFFER, OGLRef.vboPostprocessVtxID);
4621 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboPostprocessIndexID);
4622 		glBindVertexArray(OGLRef.vaoPostprocessStatesID);
4623 		glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0);
4624 		glBindVertexArray(0);
4625 
4626 		// Read back the pixels.
4627 		glReadBuffer(GL_COLOR_ATTACHMENT2_EXT);
4628 	}
4629 
4630 	// Read back the pixels in BGRA format, since legacy OpenGL devices may experience a performance
4631 	// penalty if the readback is in any other format.
4632 	glReadPixels(0, 0, this->_framebufferWidth, this->_framebufferHeight, GL_BGRA, GL_UNSIGNED_BYTE, 0);
4633 
4634 	// Set the read and draw target buffers back to color attachment 0, which is always the default.
4635 	if (this->willFlipFramebufferOnGPU || this->willConvertFramebufferOnGPU)
4636 	{
4637 		glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
4638 		glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
4639 	}
4640 
4641 	this->_pixelReadNeedsFinish = true;
4642 	return OGLERROR_NOERR;
4643 }
4644 
RenderFinish()4645 Render3DError OpenGLRenderer_2_1::RenderFinish()
4646 {
4647 	if (!this->_renderNeedsFinish || !this->_pixelReadNeedsFinish)
4648 	{
4649 		return OGLERROR_NOERR;
4650 	}
4651 
4652 	FragmentColor *framebufferMain = (this->_willFlushFramebufferRGBA6665) ? GPU->GetEngineMain()->Get3DFramebufferRGBA6665() : NULL;
4653 	u16 *framebufferRGBA5551 = (this->_willFlushFramebufferRGBA5551) ? GPU->GetEngineMain()->Get3DFramebufferRGBA5551() : NULL;
4654 
4655 	if ( (framebufferMain != NULL) || (framebufferRGBA5551 != NULL) )
4656 	{
4657 		if(!BEGINGL())
4658 		{
4659 			return OGLERROR_BEGINGL_FAILED;
4660 		}
4661 
4662 		this->_mappedFramebuffer = (FragmentColor *__restrict)glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
4663 		this->FlushFramebuffer(this->_mappedFramebuffer, framebufferMain, framebufferRGBA5551);
4664 
4665 		ENDGL();
4666 	}
4667 
4668 	this->_pixelReadNeedsFinish = false;
4669 
4670 	return OGLERROR_NOERR;
4671 }
4672