]> git.lizzy.rs Git - irrlicht.git/blob - source/Irrlicht/COGLES2Driver.cpp
Fix `getViewPort` returning incorrect results
[irrlicht.git] / source / Irrlicht / COGLES2Driver.cpp
1 // Copyright (C) 2014 Patryk Nadrowski\r
2 // Copyright (C) 2009-2010 Amundis\r
3 // This file is part of the "Irrlicht Engine".\r
4 // For conditions of distribution and use, see copyright notice in Irrlicht.h\r
5 \r
6 #include "COGLES2Driver.h"\r
7 #include "CNullDriver.h"\r
8 #include "IContextManager.h"\r
9 \r
10 #ifdef _IRR_COMPILE_WITH_OGLES2_\r
11 \r
12 #include "COpenGLCoreTexture.h"\r
13 #include "COpenGLCoreRenderTarget.h"\r
14 #include "COpenGLCoreCacheHandler.h"\r
15 \r
16 #include "COGLES2MaterialRenderer.h"\r
17 #include "COGLES2FixedPipelineRenderer.h"\r
18 #include "COGLES2NormalMapRenderer.h"\r
19 #include "COGLES2ParallaxMapRenderer.h"\r
20 #include "COGLES2Renderer2D.h"\r
21 \r
22 #include "EVertexAttributes.h"\r
23 #include "CImage.h"\r
24 #include "os.h"\r
25 #include "EProfileIDs.h"\r
26 #include "IProfiler.h"\r
27 \r
28 #ifdef _IRR_COMPILE_WITH_ANDROID_DEVICE_\r
29 #include "android_native_app_glue.h"\r
30 #endif\r
31 \r
32 namespace irr\r
33 {\r
34 namespace video\r
35 {\r
36 \r
37 COGLES2Driver::COGLES2Driver(const SIrrlichtCreationParameters& params, io::IFileSystem* io, IContextManager* contextManager) :\r
38         CNullDriver(io, params.WindowSize), COGLES2ExtensionHandler(), CacheHandler(0),\r
39         Params(params), ResetRenderStates(true), LockRenderStateMode(false), AntiAlias(params.AntiAlias),\r
40         MaterialRenderer2DActive(0), MaterialRenderer2DTexture(0), MaterialRenderer2DNoTexture(0),\r
41         CurrentRenderMode(ERM_NONE), Transformation3DChanged(true),\r
42         OGLES2ShaderPath(params.OGLES2ShaderPath),\r
43         ColorFormat(ECF_R8G8B8), ContextManager(contextManager)\r
44 {\r
45 #ifdef _DEBUG\r
46         setDebugName("COGLES2Driver");\r
47 #endif\r
48 \r
49         IRR_PROFILE(\r
50                 static bool initProfile = false;\r
51                 if (!initProfile )\r
52                 {\r
53                         initProfile = true;\r
54                         getProfiler().add(EPID_ES2_END_SCENE, L"endScene", L"ES2");\r
55                         getProfiler().add(EPID_ES2_BEGIN_SCENE, L"beginScene", L"ES2");\r
56                         getProfiler().add(EPID_ES2_UPDATE_VERTEX_HW_BUF, L"upVertBuf", L"ES2");\r
57                         getProfiler().add(EPID_ES2_UPDATE_INDEX_HW_BUF, L"upIdxBuf", L"ES2");\r
58                         getProfiler().add(EPID_ES2_DRAW_PRIMITIVES, L"drawPrim", L"ES2");\r
59                         getProfiler().add(EPID_ES2_DRAW_2DIMAGE, L"draw2dImg", L"ES2");\r
60                         getProfiler().add(EPID_ES2_DRAW_2DIMAGE_BATCH, L"draw2dImgB", L"ES2");\r
61                         getProfiler().add(EPID_ES2_DRAW_2DRECTANGLE, L"draw2dRect", L"ES2");\r
62                         getProfiler().add(EPID_ES2_DRAW_2DLINE, L"draw2dLine", L"ES2");\r
63                         getProfiler().add(EPID_ES2_DRAW_3DLINE, L"draw3dLine", L"ES2");\r
64                         getProfiler().add(EPID_ES2_SET_RENDERSTATE_2D, L"rstate2d", L"ES2");\r
65                         getProfiler().add(EPID_ES2_SET_RENDERSTATE_3D, L"rstate3d", L"ES2");\r
66                         getProfiler().add(EPID_ES2_SET_RENDERSTATE_BASIC, L"rstateBasic", L"ES2");\r
67                         getProfiler().add(EPID_ES2_SET_RENDERSTATE_TEXTURE, L"rstateTex", L"ES2");\r
68                         getProfiler().add(EPID_ES2_DRAW_SHADOW, L"shadows", L"ES2");\r
69                 }\r
70         )\r
71         if (!ContextManager)\r
72                 return;\r
73 \r
74         ContextManager->grab();\r
75         ContextManager->generateSurface();\r
76         ContextManager->generateContext();\r
77         ExposedData = ContextManager->getContext();\r
78         ContextManager->activateContext(ExposedData, false);\r
79 }\r
80 \r
81 COGLES2Driver::~COGLES2Driver()\r
82 {\r
83         RequestedLights.clear();\r
84 \r
85         deleteMaterialRenders();\r
86 \r
87         CacheHandler->getTextureCache().clear();\r
88 \r
89         removeAllRenderTargets();\r
90         deleteAllTextures();\r
91         removeAllOcclusionQueries();\r
92         removeAllHardwareBuffers();\r
93 \r
94         delete MaterialRenderer2DTexture;\r
95         delete MaterialRenderer2DNoTexture;\r
96         delete CacheHandler;\r
97 \r
98         if (ContextManager)\r
99         {\r
100                 ContextManager->destroyContext();\r
101                 ContextManager->destroySurface();\r
102                 ContextManager->terminate();\r
103                 ContextManager->drop();\r
104         }\r
105 }\r
106 \r
107         bool COGLES2Driver::genericDriverInit(const core::dimension2d<u32>& screenSize, bool stencilBuffer)\r
108         {\r
109                 Name = glGetString(GL_VERSION);\r
110                 printVersion();\r
111 \r
112                 // print renderer information\r
113                 VendorName = glGetString(GL_VENDOR);\r
114                 os::Printer::log(VendorName.c_str(), ELL_INFORMATION);\r
115 \r
116                 // load extensions\r
117                 initExtensions();\r
118 \r
119                 // reset cache handler\r
120                 delete CacheHandler;\r
121                 CacheHandler = new COGLES2CacheHandler(this);\r
122 \r
123                 StencilBuffer = stencilBuffer;\r
124 \r
125                 DriverAttributes->setAttribute("MaxTextures", (s32)Feature.MaxTextureUnits);\r
126                 DriverAttributes->setAttribute("MaxSupportedTextures", (s32)Feature.MaxTextureUnits);\r
127 //              DriverAttributes->setAttribute("MaxLights", MaxLights);\r
128                 DriverAttributes->setAttribute("MaxAnisotropy", MaxAnisotropy);\r
129 //              DriverAttributes->setAttribute("MaxUserClipPlanes", MaxUserClipPlanes);\r
130 //              DriverAttributes->setAttribute("MaxAuxBuffers", MaxAuxBuffers);\r
131 //              DriverAttributes->setAttribute("MaxMultipleRenderTargets", MaxMultipleRenderTargets);\r
132                 DriverAttributes->setAttribute("MaxIndices", (s32)MaxIndices);\r
133                 DriverAttributes->setAttribute("MaxTextureSize", (s32)MaxTextureSize);\r
134                 DriverAttributes->setAttribute("MaxTextureLODBias", MaxTextureLODBias);\r
135                 DriverAttributes->setAttribute("Version", Version);\r
136                 DriverAttributes->setAttribute("AntiAlias", AntiAlias);\r
137 \r
138                 glPixelStorei(GL_PACK_ALIGNMENT, 1);\r
139 \r
140                 UserClipPlane.reallocate(0);\r
141 \r
142                 for (s32 i = 0; i < ETS_COUNT; ++i)\r
143                         setTransform(static_cast<E_TRANSFORMATION_STATE>(i), core::IdentityMatrix);\r
144 \r
145                 setAmbientLight(SColorf(0.0f, 0.0f, 0.0f, 0.0f));\r
146                 glClearDepthf(1.0f);\r
147 \r
148                 glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST);\r
149                 glFrontFace(GL_CW);\r
150 \r
151                 // create material renderers\r
152                 createMaterialRenderers();\r
153 \r
154                 // set the renderstates\r
155                 setRenderStates3DMode();\r
156 \r
157                 // set fog mode\r
158                 setFog(FogColor, FogType, FogStart, FogEnd, FogDensity, PixelFog, RangeFog);\r
159 \r
160                 // create matrix for flipping textures\r
161                 TextureFlipMatrix.buildTextureTransform(0.0f, core::vector2df(0, 0), core::vector2df(0, 1.0f), core::vector2df(1.0f, -1.0f));\r
162 \r
163                 // We need to reset once more at the beginning of the first rendering.\r
164                 // This fixes problems with intermediate changes to the material during texture load.\r
165                 ResetRenderStates = true;\r
166 \r
167                 testGLError(__LINE__);\r
168 \r
169                 return true;\r
170         }\r
171 \r
172         void COGLES2Driver::loadShaderData(const io::path& vertexShaderName, const io::path& fragmentShaderName, c8** vertexShaderData, c8** fragmentShaderData)\r
173         {\r
174                 io::path vsPath(OGLES2ShaderPath);\r
175                 vsPath += vertexShaderName;\r
176 \r
177                 io::path fsPath(OGLES2ShaderPath);\r
178                 fsPath += fragmentShaderName;\r
179 \r
180                 *vertexShaderData = 0;\r
181                 *fragmentShaderData = 0;\r
182 \r
183                 io::IReadFile* vsFile = FileSystem->createAndOpenFile(vsPath);\r
184                 if ( !vsFile )\r
185                 {\r
186                         core::stringw warning(L"Warning: Missing shader files needed to simulate fixed function materials:\n");\r
187                         warning += core::stringw(vsPath) + L"\n";\r
188                         warning += L"Shaderpath can be changed in SIrrCreationParamters::OGLES2ShaderPath";\r
189                         os::Printer::log(warning.c_str(), ELL_WARNING);\r
190                         return;\r
191                 }\r
192 \r
193                 io::IReadFile* fsFile = FileSystem->createAndOpenFile(fsPath);\r
194                 if ( !fsFile )\r
195                 {\r
196                         core::stringw warning(L"Warning: Missing shader files needed to simulate fixed function materials:\n");\r
197                         warning += core::stringw(fsPath) + L"\n";\r
198                         warning += L"Shaderpath can be changed in SIrrCreationParamters::OGLES2ShaderPath";\r
199                         os::Printer::log(warning.c_str(), ELL_WARNING);\r
200                         return;\r
201                 }\r
202 \r
203                 long size = vsFile->getSize();\r
204                 if (size)\r
205                 {\r
206                         *vertexShaderData = new c8[size+1];\r
207                         vsFile->read(*vertexShaderData, size);\r
208                         (*vertexShaderData)[size] = 0;\r
209                 }\r
210 \r
211                 size = fsFile->getSize();\r
212                 if (size)\r
213                 {\r
214                         // if both handles are the same we must reset the file\r
215                         if (fsFile == vsFile)\r
216                                 fsFile->seek(0);\r
217 \r
218                         *fragmentShaderData = new c8[size+1];\r
219                         fsFile->read(*fragmentShaderData, size);\r
220                         (*fragmentShaderData)[size] = 0;\r
221                 }\r
222 \r
223                 vsFile->drop();\r
224                 fsFile->drop();\r
225         }\r
226 \r
227         void COGLES2Driver::createMaterialRenderers()\r
228         {\r
229                 // Create callbacks.\r
230 \r
231                 COGLES2MaterialSolidCB* SolidCB = new COGLES2MaterialSolidCB();\r
232                 COGLES2MaterialSolid2CB* Solid2LayerCB = new COGLES2MaterialSolid2CB();\r
233                 COGLES2MaterialLightmapCB* LightmapCB = new COGLES2MaterialLightmapCB(1.f);\r
234                 COGLES2MaterialLightmapCB* LightmapAddCB = new COGLES2MaterialLightmapCB(1.f);\r
235                 COGLES2MaterialLightmapCB* LightmapM2CB = new COGLES2MaterialLightmapCB(2.f);\r
236                 COGLES2MaterialLightmapCB* LightmapM4CB = new COGLES2MaterialLightmapCB(4.f);\r
237                 COGLES2MaterialLightmapCB* LightmapLightingCB = new COGLES2MaterialLightmapCB(1.f);\r
238                 COGLES2MaterialLightmapCB* LightmapLightingM2CB = new COGLES2MaterialLightmapCB(2.f);\r
239                 COGLES2MaterialLightmapCB* LightmapLightingM4CB = new COGLES2MaterialLightmapCB(4.f);\r
240                 COGLES2MaterialSolid2CB* DetailMapCB = new COGLES2MaterialSolid2CB();\r
241                 COGLES2MaterialReflectionCB* SphereMapCB = new COGLES2MaterialReflectionCB();\r
242                 COGLES2MaterialReflectionCB* Reflection2LayerCB = new COGLES2MaterialReflectionCB();\r
243                 COGLES2MaterialSolidCB* TransparentAddColorCB = new COGLES2MaterialSolidCB();\r
244                 COGLES2MaterialSolidCB* TransparentAlphaChannelCB = new COGLES2MaterialSolidCB();\r
245                 COGLES2MaterialSolidCB* TransparentAlphaChannelRefCB = new COGLES2MaterialSolidCB();\r
246                 COGLES2MaterialSolidCB* TransparentVertexAlphaCB = new COGLES2MaterialSolidCB();\r
247                 COGLES2MaterialReflectionCB* TransparentReflection2LayerCB = new COGLES2MaterialReflectionCB();\r
248                 COGLES2MaterialNormalMapCB* NormalMapCB = new COGLES2MaterialNormalMapCB();\r
249                 COGLES2MaterialNormalMapCB* NormalMapAddColorCB = new COGLES2MaterialNormalMapCB();\r
250                 COGLES2MaterialNormalMapCB* NormalMapVertexAlphaCB = new COGLES2MaterialNormalMapCB();\r
251                 COGLES2MaterialParallaxMapCB* ParallaxMapCB = new COGLES2MaterialParallaxMapCB();\r
252                 COGLES2MaterialParallaxMapCB* ParallaxMapAddColorCB = new COGLES2MaterialParallaxMapCB();\r
253                 COGLES2MaterialParallaxMapCB* ParallaxMapVertexAlphaCB = new COGLES2MaterialParallaxMapCB();\r
254                 COGLES2MaterialOneTextureBlendCB* OneTextureBlendCB = new COGLES2MaterialOneTextureBlendCB();\r
255 \r
256                 // Create built-in materials.\r
257 \r
258                 core::stringc VertexShader = OGLES2ShaderPath + "COGLES2Solid.vsh";\r
259                 core::stringc FragmentShader = OGLES2ShaderPath + "COGLES2Solid.fsh";\r
260 \r
261                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
262                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, SolidCB, EMT_SOLID, 0);\r
263 \r
264                 VertexShader = OGLES2ShaderPath + "COGLES2Solid2.vsh";\r
265                 FragmentShader = OGLES2ShaderPath + "COGLES2Solid2Layer.fsh";\r
266 \r
267                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
268                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, Solid2LayerCB, EMT_SOLID, 0);\r
269 \r
270                 VertexShader = OGLES2ShaderPath + "COGLES2Solid2.vsh";\r
271                 FragmentShader = OGLES2ShaderPath + "COGLES2LightmapModulate.fsh";\r
272 \r
273                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
274                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, LightmapCB, EMT_SOLID, 0);\r
275 \r
276                 FragmentShader = OGLES2ShaderPath + "COGLES2LightmapAdd.fsh";\r
277 \r
278                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
279                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, LightmapAddCB, EMT_SOLID, 0);\r
280 \r
281                 FragmentShader = OGLES2ShaderPath + "COGLES2LightmapModulate.fsh";\r
282 \r
283                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
284                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, LightmapM2CB, EMT_SOLID, 0);\r
285 \r
286                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
287                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, LightmapM4CB, EMT_SOLID, 0);\r
288 \r
289                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
290                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, LightmapLightingCB, EMT_SOLID, 0);\r
291 \r
292                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
293                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, LightmapLightingM2CB, EMT_SOLID, 0);\r
294 \r
295                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
296                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, LightmapLightingM4CB, EMT_SOLID, 0);\r
297 \r
298                 VertexShader = OGLES2ShaderPath + "COGLES2Solid2.vsh";\r
299                 FragmentShader = OGLES2ShaderPath + "COGLES2DetailMap.fsh";\r
300 \r
301                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
302                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, DetailMapCB, EMT_SOLID, 0);\r
303 \r
304                 VertexShader = OGLES2ShaderPath + "COGLES2SphereMap.vsh";\r
305                 FragmentShader = OGLES2ShaderPath + "COGLES2SphereMap.fsh";\r
306 \r
307                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
308                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, SphereMapCB, EMT_SOLID, 0);\r
309 \r
310                 VertexShader = OGLES2ShaderPath + "COGLES2Reflection2Layer.vsh";\r
311                 FragmentShader = OGLES2ShaderPath + "COGLES2Reflection2Layer.fsh";\r
312 \r
313                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
314                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, Reflection2LayerCB, EMT_SOLID, 0);\r
315 \r
316                 VertexShader = OGLES2ShaderPath + "COGLES2Solid.vsh";\r
317                 FragmentShader = OGLES2ShaderPath + "COGLES2Solid.fsh";\r
318 \r
319                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
320                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, TransparentAddColorCB, EMT_TRANSPARENT_ADD_COLOR, 0);\r
321 \r
322                 FragmentShader = OGLES2ShaderPath + "COGLES2TransparentAlphaChannel.fsh";\r
323                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
324                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, TransparentAlphaChannelCB, EMT_TRANSPARENT_ALPHA_CHANNEL, 0);\r
325 \r
326                 FragmentShader = OGLES2ShaderPath + "COGLES2TransparentAlphaChannelRef.fsh";\r
327 \r
328                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
329                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, TransparentAlphaChannelRefCB, EMT_SOLID, 0);\r
330 \r
331                 FragmentShader = OGLES2ShaderPath + "COGLES2TransparentVertexAlpha.fsh";\r
332 \r
333                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
334                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, TransparentVertexAlphaCB, EMT_TRANSPARENT_ALPHA_CHANNEL, 0);\r
335 \r
336                 VertexShader = OGLES2ShaderPath + "COGLES2Reflection2Layer.vsh";\r
337                 FragmentShader = OGLES2ShaderPath + "COGLES2Reflection2Layer.fsh";\r
338 \r
339                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
340                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, TransparentReflection2LayerCB, EMT_TRANSPARENT_ALPHA_CHANNEL, 0);\r
341 \r
342                 VertexShader = OGLES2ShaderPath + "COGLES2NormalMap.vsh";\r
343                 FragmentShader = OGLES2ShaderPath + "COGLES2NormalMap.fsh";\r
344 \r
345                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
346                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, NormalMapCB, EMT_SOLID, 0);\r
347 \r
348                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
349                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, NormalMapAddColorCB, EMT_TRANSPARENT_ADD_COLOR, 0);\r
350 \r
351                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
352                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, NormalMapVertexAlphaCB, EMT_TRANSPARENT_ALPHA_CHANNEL, 0);\r
353 \r
354                 VertexShader = OGLES2ShaderPath + "COGLES2ParallaxMap.vsh";\r
355                 FragmentShader = OGLES2ShaderPath + "COGLES2ParallaxMap.fsh";\r
356 \r
357                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
358                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, ParallaxMapCB, EMT_SOLID, 0);\r
359 \r
360                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
361                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, ParallaxMapAddColorCB, EMT_TRANSPARENT_ADD_COLOR, 0);\r
362 \r
363                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
364                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, ParallaxMapVertexAlphaCB, EMT_TRANSPARENT_ALPHA_CHANNEL, 0);\r
365 \r
366                 VertexShader = OGLES2ShaderPath + "COGLES2Solid.vsh";\r
367                 FragmentShader = OGLES2ShaderPath + "COGLES2OneTextureBlend.fsh";\r
368 \r
369                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
370                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, OneTextureBlendCB, EMT_ONETEXTURE_BLEND, 0);\r
371 \r
372                 // Drop callbacks.\r
373 \r
374                 SolidCB->drop();\r
375                 Solid2LayerCB->drop();\r
376                 LightmapCB->drop();\r
377                 LightmapAddCB->drop();\r
378                 LightmapM2CB->drop();\r
379                 LightmapM4CB->drop();\r
380                 LightmapLightingCB->drop();\r
381                 LightmapLightingM2CB->drop();\r
382                 LightmapLightingM4CB->drop();\r
383                 DetailMapCB->drop();\r
384                 SphereMapCB->drop();\r
385                 Reflection2LayerCB->drop();\r
386                 TransparentAddColorCB->drop();\r
387                 TransparentAlphaChannelCB->drop();\r
388                 TransparentAlphaChannelRefCB->drop();\r
389                 TransparentVertexAlphaCB->drop();\r
390                 TransparentReflection2LayerCB->drop();\r
391                 NormalMapCB->drop();\r
392                 NormalMapAddColorCB->drop();\r
393                 NormalMapVertexAlphaCB->drop();\r
394                 ParallaxMapCB->drop();\r
395                 ParallaxMapAddColorCB->drop();\r
396                 ParallaxMapVertexAlphaCB->drop();\r
397                 OneTextureBlendCB->drop();\r
398 \r
399                 // Create 2D material renderers\r
400 \r
401                 c8* vs2DData = 0;\r
402                 c8* fs2DData = 0;\r
403                 loadShaderData(io::path("COGLES2Renderer2D.vsh"), io::path("COGLES2Renderer2D.fsh"), &vs2DData, &fs2DData);\r
404                 MaterialRenderer2DTexture = new COGLES2Renderer2D(vs2DData, fs2DData, this, true);\r
405                 delete[] vs2DData;\r
406                 delete[] fs2DData;\r
407                 vs2DData = 0;\r
408                 fs2DData = 0;\r
409 \r
410                 loadShaderData(io::path("COGLES2Renderer2D.vsh"), io::path("COGLES2Renderer2D_noTex.fsh"), &vs2DData, &fs2DData);\r
411                 MaterialRenderer2DNoTexture = new COGLES2Renderer2D(vs2DData, fs2DData, this, false);\r
412                 delete[] vs2DData;\r
413                 delete[] fs2DData;\r
414         }\r
415 \r
416         bool COGLES2Driver::setMaterialTexture(irr::u32 layerIdx, const irr::video::ITexture* texture)\r
417         {\r
418                 Material.TextureLayer[layerIdx].Texture = const_cast<ITexture*>(texture); // function uses const-pointer for texture because all draw functions use const-pointers already\r
419                 return CacheHandler->getTextureCache().set(0, texture);\r
420         }\r
421 \r
422         bool COGLES2Driver::beginScene(u16 clearFlag, SColor clearColor, f32 clearDepth, u8 clearStencil, const SExposedVideoData& videoData, core::rect<s32>* sourceRect)\r
423         {\r
424                 IRR_PROFILE(CProfileScope p1(EPID_ES2_BEGIN_SCENE);)\r
425 \r
426                 CNullDriver::beginScene(clearFlag, clearColor, clearDepth, clearStencil, videoData, sourceRect);\r
427 \r
428                 if (ContextManager)\r
429                         ContextManager->activateContext(videoData, true);\r
430 \r
431                 clearBuffers(clearFlag, clearColor, clearDepth, clearStencil);\r
432 \r
433                 return true;\r
434         }\r
435 \r
436         bool COGLES2Driver::endScene()\r
437         {\r
438                 IRR_PROFILE(CProfileScope p1(EPID_ES2_END_SCENE);)\r
439 \r
440                 CNullDriver::endScene();\r
441 \r
442                 glFlush();\r
443 \r
444                 if (ContextManager)\r
445                         return ContextManager->swapBuffers();\r
446 \r
447                 return false;\r
448         }\r
449 \r
450 \r
451         //! Returns the transformation set by setTransform\r
452         const core::matrix4& COGLES2Driver::getTransform(E_TRANSFORMATION_STATE state) const\r
453         {\r
454                 return Matrices[state];\r
455         }\r
456 \r
457 \r
458         //! sets transformation\r
459         void COGLES2Driver::setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat)\r
460         {\r
461                 Matrices[state] = mat;\r
462                 Transformation3DChanged = true;\r
463         }\r
464 \r
465 \r
466         bool COGLES2Driver::updateVertexHardwareBuffer(SHWBufferLink_opengl *HWBuffer)\r
467         {\r
468                 if (!HWBuffer)\r
469                         return false;\r
470 \r
471                 IRR_PROFILE(CProfileScope p1(EPID_ES2_UPDATE_VERTEX_HW_BUF);)\r
472 \r
473                 const scene::IMeshBuffer* mb = HWBuffer->MeshBuffer;\r
474                 const void* vertices = mb->getVertices();\r
475                 const u32 vertexCount = mb->getVertexCount();\r
476                 const E_VERTEX_TYPE vType = mb->getVertexType();\r
477                 const u32 vertexSize = getVertexPitchFromType(vType);\r
478 \r
479                 //buffer vertex data, and convert colours...\r
480                 core::array<c8> buffer(vertexSize * vertexCount);\r
481                 memcpy(buffer.pointer(), vertices, vertexSize * vertexCount);\r
482 \r
483                 //get or create buffer\r
484                 bool newBuffer = false;\r
485                 if (!HWBuffer->vbo_verticesID)\r
486                 {\r
487                         glGenBuffers(1, &HWBuffer->vbo_verticesID);\r
488                         if (!HWBuffer->vbo_verticesID) return false;\r
489                         newBuffer = true;\r
490                 }\r
491                 else if (HWBuffer->vbo_verticesSize < vertexCount*vertexSize)\r
492                 {\r
493                         newBuffer = true;\r
494                 }\r
495 \r
496                 glBindBuffer(GL_ARRAY_BUFFER, HWBuffer->vbo_verticesID);\r
497 \r
498                 // copy data to graphics card\r
499                 if (!newBuffer)\r
500                         glBufferSubData(GL_ARRAY_BUFFER, 0, vertexCount * vertexSize, buffer.const_pointer());\r
501                 else\r
502                 {\r
503                         HWBuffer->vbo_verticesSize = vertexCount * vertexSize;\r
504 \r
505                         if (HWBuffer->Mapped_Vertex == scene::EHM_STATIC)\r
506                                 glBufferData(GL_ARRAY_BUFFER, vertexCount * vertexSize, buffer.const_pointer(), GL_STATIC_DRAW);\r
507                         else\r
508                                 glBufferData(GL_ARRAY_BUFFER, vertexCount * vertexSize, buffer.const_pointer(), GL_DYNAMIC_DRAW);\r
509                 }\r
510 \r
511                 glBindBuffer(GL_ARRAY_BUFFER, 0);\r
512 \r
513                 return (!testGLError(__LINE__));\r
514         }\r
515 \r
516 \r
517         bool COGLES2Driver::updateIndexHardwareBuffer(SHWBufferLink_opengl *HWBuffer)\r
518         {\r
519                 if (!HWBuffer)\r
520                         return false;\r
521 \r
522                 IRR_PROFILE(CProfileScope p1(EPID_ES2_UPDATE_INDEX_HW_BUF);)\r
523 \r
524                 const scene::IMeshBuffer* mb = HWBuffer->MeshBuffer;\r
525 \r
526                 const void* indices = mb->getIndices();\r
527                 u32 indexCount = mb->getIndexCount();\r
528 \r
529                 GLenum indexSize;\r
530                 switch (mb->getIndexType())\r
531                 {\r
532                         case(EIT_16BIT):\r
533                         {\r
534                                 indexSize = sizeof(u16);\r
535                                 break;\r
536                         }\r
537                         case(EIT_32BIT):\r
538                         {\r
539                                 indexSize = sizeof(u32);\r
540                                 break;\r
541                         }\r
542                         default:\r
543                         {\r
544                                 return false;\r
545                         }\r
546                 }\r
547 \r
548                 //get or create buffer\r
549                 bool newBuffer = false;\r
550                 if (!HWBuffer->vbo_indicesID)\r
551                 {\r
552                         glGenBuffers(1, &HWBuffer->vbo_indicesID);\r
553                         if (!HWBuffer->vbo_indicesID) return false;\r
554                         newBuffer = true;\r
555                 }\r
556                 else if (HWBuffer->vbo_indicesSize < indexCount*indexSize)\r
557                 {\r
558                         newBuffer = true;\r
559                 }\r
560 \r
561                 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, HWBuffer->vbo_indicesID);\r
562 \r
563                 // copy data to graphics card\r
564                 if (!newBuffer)\r
565                         glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, indexCount * indexSize, indices);\r
566                 else\r
567                 {\r
568                         HWBuffer->vbo_indicesSize = indexCount * indexSize;\r
569 \r
570                         if (HWBuffer->Mapped_Index == scene::EHM_STATIC)\r
571                                 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * indexSize, indices, GL_STATIC_DRAW);\r
572                         else\r
573                                 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * indexSize, indices, GL_DYNAMIC_DRAW);\r
574                 }\r
575 \r
576                 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);\r
577 \r
578                 return (!testGLError(__LINE__));\r
579         }\r
580 \r
581 \r
582         //! updates hardware buffer if needed\r
583         bool COGLES2Driver::updateHardwareBuffer(SHWBufferLink *HWBuffer)\r
584         {\r
585                 if (!HWBuffer)\r
586                         return false;\r
587 \r
588                 if (HWBuffer->Mapped_Vertex != scene::EHM_NEVER)\r
589                 {\r
590                         if (HWBuffer->ChangedID_Vertex != HWBuffer->MeshBuffer->getChangedID_Vertex()\r
591                                 || !static_cast<SHWBufferLink_opengl*>(HWBuffer)->vbo_verticesID)\r
592                         {\r
593 \r
594                                 HWBuffer->ChangedID_Vertex = HWBuffer->MeshBuffer->getChangedID_Vertex();\r
595 \r
596                                 if (!updateVertexHardwareBuffer(static_cast<SHWBufferLink_opengl*>(HWBuffer)))\r
597                                         return false;\r
598                         }\r
599                 }\r
600 \r
601                 if (HWBuffer->Mapped_Index != scene::EHM_NEVER)\r
602                 {\r
603                         if (HWBuffer->ChangedID_Index != HWBuffer->MeshBuffer->getChangedID_Index()\r
604                                 || !static_cast<SHWBufferLink_opengl*>(HWBuffer)->vbo_indicesID)\r
605                         {\r
606 \r
607                                 HWBuffer->ChangedID_Index = HWBuffer->MeshBuffer->getChangedID_Index();\r
608 \r
609                                 if (!updateIndexHardwareBuffer((SHWBufferLink_opengl*)HWBuffer))\r
610                                         return false;\r
611                         }\r
612                 }\r
613 \r
614                 return true;\r
615         }\r
616 \r
617 \r
618         //! Create hardware buffer from meshbuffer\r
619         COGLES2Driver::SHWBufferLink *COGLES2Driver::createHardwareBuffer(const scene::IMeshBuffer* mb)\r
620         {\r
621                 if (!mb || (mb->getHardwareMappingHint_Index() == scene::EHM_NEVER && mb->getHardwareMappingHint_Vertex() == scene::EHM_NEVER))\r
622                         return 0;\r
623 \r
624                 SHWBufferLink_opengl *HWBuffer = new SHWBufferLink_opengl(mb);\r
625 \r
626                 //add to map\r
627                 HWBufferMap.insert(HWBuffer->MeshBuffer, HWBuffer);\r
628 \r
629                 HWBuffer->ChangedID_Vertex = HWBuffer->MeshBuffer->getChangedID_Vertex();\r
630                 HWBuffer->ChangedID_Index = HWBuffer->MeshBuffer->getChangedID_Index();\r
631                 HWBuffer->Mapped_Vertex = mb->getHardwareMappingHint_Vertex();\r
632                 HWBuffer->Mapped_Index = mb->getHardwareMappingHint_Index();\r
633                 HWBuffer->LastUsed = 0;\r
634                 HWBuffer->vbo_verticesID = 0;\r
635                 HWBuffer->vbo_indicesID = 0;\r
636                 HWBuffer->vbo_verticesSize = 0;\r
637                 HWBuffer->vbo_indicesSize = 0;\r
638 \r
639                 if (!updateHardwareBuffer(HWBuffer))\r
640                 {\r
641                         deleteHardwareBuffer(HWBuffer);\r
642                         return 0;\r
643                 }\r
644 \r
645                 return HWBuffer;\r
646         }\r
647 \r
648 \r
649         void COGLES2Driver::deleteHardwareBuffer(SHWBufferLink *_HWBuffer)\r
650         {\r
651                 if (!_HWBuffer)\r
652                         return;\r
653 \r
654                 SHWBufferLink_opengl *HWBuffer = static_cast<SHWBufferLink_opengl*>(_HWBuffer);\r
655                 if (HWBuffer->vbo_verticesID)\r
656                 {\r
657                         glDeleteBuffers(1, &HWBuffer->vbo_verticesID);\r
658                         HWBuffer->vbo_verticesID = 0;\r
659                 }\r
660                 if (HWBuffer->vbo_indicesID)\r
661                 {\r
662                         glDeleteBuffers(1, &HWBuffer->vbo_indicesID);\r
663                         HWBuffer->vbo_indicesID = 0;\r
664                 }\r
665 \r
666                 CNullDriver::deleteHardwareBuffer(_HWBuffer);\r
667         }\r
668 \r
669 \r
670         //! Draw hardware buffer\r
671         void COGLES2Driver::drawHardwareBuffer(SHWBufferLink *_HWBuffer)\r
672         {\r
673                 if (!_HWBuffer)\r
674                         return;\r
675 \r
676                 SHWBufferLink_opengl *HWBuffer = static_cast<SHWBufferLink_opengl*>(_HWBuffer);\r
677 \r
678                 updateHardwareBuffer(HWBuffer); //check if update is needed\r
679 \r
680                 HWBuffer->LastUsed = 0;//reset count\r
681 \r
682                 const scene::IMeshBuffer* mb = HWBuffer->MeshBuffer;\r
683                 const void *vertices = mb->getVertices();\r
684                 const void *indexList = mb->getIndices();\r
685 \r
686                 if (HWBuffer->Mapped_Vertex != scene::EHM_NEVER)\r
687                 {\r
688                         glBindBuffer(GL_ARRAY_BUFFER, HWBuffer->vbo_verticesID);\r
689                         vertices = 0;\r
690                 }\r
691 \r
692                 if (HWBuffer->Mapped_Index != scene::EHM_NEVER)\r
693                 {\r
694                         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, HWBuffer->vbo_indicesID);\r
695                         indexList = 0;\r
696                 }\r
697 \r
698 \r
699                 drawVertexPrimitiveList(vertices, mb->getVertexCount(),\r
700                                 indexList, mb->getPrimitiveCount(),\r
701                                 mb->getVertexType(), mb->getPrimitiveType(),\r
702                                 mb->getIndexType());\r
703 \r
704                 if (HWBuffer->Mapped_Vertex != scene::EHM_NEVER)\r
705                         glBindBuffer(GL_ARRAY_BUFFER, 0);\r
706 \r
707                 if (HWBuffer->Mapped_Index != scene::EHM_NEVER)\r
708                         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);\r
709         }\r
710 \r
711 \r
712         IRenderTarget* COGLES2Driver::addRenderTarget()\r
713         {\r
714                 COGLES2RenderTarget* renderTarget = new COGLES2RenderTarget(this);\r
715                 RenderTargets.push_back(renderTarget);\r
716 \r
717                 return renderTarget;\r
718         }\r
719 \r
720 \r
721         // small helper function to create vertex buffer object adress offsets\r
722         static inline u8* buffer_offset(const long offset)\r
723         {\r
724                 return ((u8*)0 + offset);\r
725         }\r
726 \r
727 \r
728         //! draws a vertex primitive list\r
729         void COGLES2Driver::drawVertexPrimitiveList(const void* vertices, u32 vertexCount,\r
730                         const void* indexList, u32 primitiveCount,\r
731                         E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType)\r
732         {\r
733                 if (!primitiveCount || !vertexCount)\r
734                         return;\r
735 \r
736                 if (!checkPrimitiveCount(primitiveCount))\r
737                         return;\r
738 \r
739                 IRR_PROFILE(CProfileScope p1(EPID_ES2_DRAW_PRIMITIVES);)\r
740 \r
741                 CNullDriver::drawVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, vType, pType, iType);\r
742 \r
743                 setRenderStates3DMode();\r
744 \r
745                 glEnableVertexAttribArray(EVA_POSITION);\r
746                 glEnableVertexAttribArray(EVA_COLOR);\r
747                 glEnableVertexAttribArray(EVA_NORMAL);\r
748                 glEnableVertexAttribArray(EVA_TCOORD0);\r
749 \r
750                 switch (vType)\r
751                 {\r
752                 case EVT_STANDARD:\r
753                         if (vertices)\r
754                         {\r
755                                 glVertexAttribPointer(EVA_POSITION, 3, GL_FLOAT, false, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Pos);\r
756                                 glVertexAttribPointer(EVA_NORMAL, 3, GL_FLOAT, false, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Normal);\r
757                                 glVertexAttribPointer(EVA_COLOR, 4, GL_UNSIGNED_BYTE, true, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Color);\r
758                                 glVertexAttribPointer(EVA_TCOORD0, 2, GL_FLOAT, false, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].TCoords);\r
759                         }\r
760                         else\r
761                         {\r
762                                 glVertexAttribPointer(EVA_POSITION, 3, GL_FLOAT, false, sizeof(S3DVertex), 0);\r
763                                 glVertexAttribPointer(EVA_NORMAL, 3, GL_FLOAT, false, sizeof(S3DVertex), buffer_offset(12));\r
764                                 glVertexAttribPointer(EVA_COLOR, 4, GL_UNSIGNED_BYTE, true, sizeof(S3DVertex), buffer_offset(24));\r
765                                 glVertexAttribPointer(EVA_TCOORD0, 2, GL_FLOAT, false, sizeof(S3DVertex), buffer_offset(28));\r
766                         }\r
767 \r
768                         break;\r
769                 case EVT_2TCOORDS:\r
770                         glEnableVertexAttribArray(EVA_TCOORD1);\r
771 \r
772                         if (vertices)\r
773                         {\r
774                                 glVertexAttribPointer(EVA_POSITION, 3, GL_FLOAT, false, sizeof(S3DVertex2TCoords), &(static_cast<const S3DVertex2TCoords*>(vertices))[0].Pos);\r
775                                 glVertexAttribPointer(EVA_NORMAL, 3, GL_FLOAT, false, sizeof(S3DVertex2TCoords), &(static_cast<const S3DVertex2TCoords*>(vertices))[0].Normal);\r
776                                 glVertexAttribPointer(EVA_COLOR, 4, GL_UNSIGNED_BYTE, true, sizeof(S3DVertex2TCoords), &(static_cast<const S3DVertex2TCoords*>(vertices))[0].Color);\r
777                                 glVertexAttribPointer(EVA_TCOORD0, 2, GL_FLOAT, false, sizeof(S3DVertex2TCoords), &(static_cast<const S3DVertex2TCoords*>(vertices))[0].TCoords);\r
778                                 glVertexAttribPointer(EVA_TCOORD1, 2, GL_FLOAT, false, sizeof(S3DVertex2TCoords), &(static_cast<const S3DVertex2TCoords*>(vertices))[0].TCoords2);\r
779                         }\r
780                         else\r
781                         {\r
782                                 glVertexAttribPointer(EVA_POSITION, 3, GL_FLOAT, false, sizeof(S3DVertex2TCoords), buffer_offset(0));\r
783                                 glVertexAttribPointer(EVA_NORMAL, 3, GL_FLOAT, false, sizeof(S3DVertex2TCoords), buffer_offset(12));\r
784                                 glVertexAttribPointer(EVA_COLOR, 4, GL_UNSIGNED_BYTE, true, sizeof(S3DVertex2TCoords), buffer_offset(24));\r
785                                 glVertexAttribPointer(EVA_TCOORD0, 2, GL_FLOAT, false, sizeof(S3DVertex2TCoords), buffer_offset(28));\r
786                                 glVertexAttribPointer(EVA_TCOORD1, 2, GL_FLOAT, false, sizeof(S3DVertex2TCoords), buffer_offset(36));\r
787                         }\r
788                         break;\r
789                 case EVT_TANGENTS:\r
790                         glEnableVertexAttribArray(EVA_TANGENT);\r
791                         glEnableVertexAttribArray(EVA_BINORMAL);\r
792 \r
793                         if (vertices)\r
794                         {\r
795                                 glVertexAttribPointer(EVA_POSITION, 3, GL_FLOAT, false, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].Pos);\r
796                                 glVertexAttribPointer(EVA_NORMAL, 3, GL_FLOAT, false, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].Normal);\r
797                                 glVertexAttribPointer(EVA_COLOR, 4, GL_UNSIGNED_BYTE, true, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].Color);\r
798                                 glVertexAttribPointer(EVA_TCOORD0, 2, GL_FLOAT, false, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].TCoords);\r
799                                 glVertexAttribPointer(EVA_TANGENT, 3, GL_FLOAT, false, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].Tangent);\r
800                                 glVertexAttribPointer(EVA_BINORMAL, 3, GL_FLOAT, false, sizeof(S3DVertexTangents), &(static_cast<const S3DVertexTangents*>(vertices))[0].Binormal);\r
801                         }\r
802                         else\r
803                         {\r
804                                 glVertexAttribPointer(EVA_POSITION, 3, GL_FLOAT, false, sizeof(S3DVertexTangents), buffer_offset(0));\r
805                                 glVertexAttribPointer(EVA_NORMAL, 3, GL_FLOAT, false, sizeof(S3DVertexTangents), buffer_offset(12));\r
806                                 glVertexAttribPointer(EVA_COLOR, 4, GL_UNSIGNED_BYTE, true, sizeof(S3DVertexTangents), buffer_offset(24));\r
807                                 glVertexAttribPointer(EVA_TCOORD0, 2, GL_FLOAT, false, sizeof(S3DVertexTangents), buffer_offset(28));\r
808                                 glVertexAttribPointer(EVA_TANGENT, 3, GL_FLOAT, false, sizeof(S3DVertexTangents), buffer_offset(36));\r
809                                 glVertexAttribPointer(EVA_BINORMAL, 3, GL_FLOAT, false, sizeof(S3DVertexTangents), buffer_offset(48));\r
810                         }\r
811                         break;\r
812                 }\r
813 \r
814                 GLenum indexSize = 0;\r
815 \r
816                 switch (iType)\r
817                 {\r
818                         case(EIT_16BIT):\r
819                         {\r
820                                 indexSize = GL_UNSIGNED_SHORT;\r
821                                 break;\r
822                         }\r
823                         case(EIT_32BIT):\r
824                         {\r
825 #ifdef GL_OES_element_index_uint\r
826 #ifndef GL_UNSIGNED_INT\r
827 #define GL_UNSIGNED_INT 0x1405\r
828 #endif\r
829                                 if (FeatureAvailable[COGLESCoreExtensionHandler::IRR_GL_OES_element_index_uint])\r
830                                         indexSize = GL_UNSIGNED_INT;\r
831                                 else\r
832 #endif\r
833                                         indexSize = GL_UNSIGNED_SHORT;\r
834                                 break;\r
835                         }\r
836                 }\r
837 \r
838                 switch (pType)\r
839                 {\r
840                         case scene::EPT_POINTS:\r
841                         case scene::EPT_POINT_SPRITES:\r
842                                 glDrawArrays(GL_POINTS, 0, primitiveCount);\r
843                                 break;\r
844                         case scene::EPT_LINE_STRIP:\r
845                                 glDrawElements(GL_LINE_STRIP, primitiveCount + 1, indexSize, indexList);\r
846                                 break;\r
847                         case scene::EPT_LINE_LOOP:\r
848                                 glDrawElements(GL_LINE_LOOP, primitiveCount, indexSize, indexList);\r
849                                 break;\r
850                         case scene::EPT_LINES:\r
851                                 glDrawElements(GL_LINES, primitiveCount*2, indexSize, indexList);\r
852                                 break;\r
853                         case scene::EPT_TRIANGLE_STRIP:\r
854                                 glDrawElements(GL_TRIANGLE_STRIP, primitiveCount + 2, indexSize, indexList);\r
855                                 break;\r
856                         case scene::EPT_TRIANGLE_FAN:\r
857                                 glDrawElements(GL_TRIANGLE_FAN, primitiveCount + 2, indexSize, indexList);\r
858                                 break;\r
859                         case scene::EPT_TRIANGLES:\r
860                                 glDrawElements((LastMaterial.Wireframe) ? GL_LINES : (LastMaterial.PointCloud) ? GL_POINTS : GL_TRIANGLES, primitiveCount*3, indexSize, indexList);\r
861                                 break;\r
862                         default:\r
863                                 break;\r
864                 }\r
865 \r
866                 switch (vType)\r
867                 {\r
868                 case EVT_2TCOORDS:\r
869                         glDisableVertexAttribArray(EVA_TCOORD1);\r
870                         break;\r
871                 case EVT_TANGENTS:\r
872                         glDisableVertexAttribArray(EVA_TANGENT);\r
873                         glDisableVertexAttribArray(EVA_BINORMAL);\r
874                         break;\r
875                 default:\r
876                         break;\r
877                 }\r
878 \r
879                 glDisableVertexAttribArray(EVA_POSITION);\r
880                 glDisableVertexAttribArray(EVA_NORMAL);\r
881                 glDisableVertexAttribArray(EVA_COLOR);\r
882                 glDisableVertexAttribArray(EVA_TCOORD0);\r
883         }\r
884 \r
885 \r
886         void COGLES2Driver::draw2DImage(const video::ITexture* texture, const core::position2d<s32>& destPos,\r
887                 const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect, SColor color,\r
888                 bool useAlphaChannelOfTexture)\r
889         {\r
890                 if (!texture)\r
891                         return;\r
892 \r
893                 if (!sourceRect.isValid())\r
894                         return;\r
895 \r
896                 IRR_PROFILE(CProfileScope p1(EPID_ES2_DRAW_2DIMAGE);)\r
897 \r
898                 core::position2d<s32> targetPos(destPos);\r
899                 core::position2d<s32> sourcePos(sourceRect.UpperLeftCorner);\r
900                 core::dimension2d<s32> sourceSize(sourceRect.getSize());\r
901                 if (clipRect)\r
902                 {\r
903                         if (targetPos.X < clipRect->UpperLeftCorner.X)\r
904                         {\r
905                                 sourceSize.Width += targetPos.X - clipRect->UpperLeftCorner.X;\r
906                                 if (sourceSize.Width <= 0)\r
907                                         return;\r
908 \r
909                                 sourcePos.X -= targetPos.X - clipRect->UpperLeftCorner.X;\r
910                                 targetPos.X = clipRect->UpperLeftCorner.X;\r
911                         }\r
912 \r
913                         if (targetPos.X + sourceSize.Width > clipRect->LowerRightCorner.X)\r
914                         {\r
915                                 sourceSize.Width -= (targetPos.X + sourceSize.Width) - clipRect->LowerRightCorner.X;\r
916                                 if (sourceSize.Width <= 0)\r
917                                         return;\r
918                         }\r
919 \r
920                         if (targetPos.Y < clipRect->UpperLeftCorner.Y)\r
921                         {\r
922                                 sourceSize.Height += targetPos.Y - clipRect->UpperLeftCorner.Y;\r
923                                 if (sourceSize.Height <= 0)\r
924                                         return;\r
925 \r
926                                 sourcePos.Y -= targetPos.Y - clipRect->UpperLeftCorner.Y;\r
927                                 targetPos.Y = clipRect->UpperLeftCorner.Y;\r
928                         }\r
929 \r
930                         if (targetPos.Y + sourceSize.Height > clipRect->LowerRightCorner.Y)\r
931                         {\r
932                                 sourceSize.Height -= (targetPos.Y + sourceSize.Height) - clipRect->LowerRightCorner.Y;\r
933                                 if (sourceSize.Height <= 0)\r
934                                         return;\r
935                         }\r
936                 }\r
937 \r
938                 // clip these coordinates\r
939 \r
940                 if (targetPos.X < 0)\r
941                 {\r
942                         sourceSize.Width += targetPos.X;\r
943                         if (sourceSize.Width <= 0)\r
944                                 return;\r
945 \r
946                         sourcePos.X -= targetPos.X;\r
947                         targetPos.X = 0;\r
948                 }\r
949 \r
950                 const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();\r
951 \r
952                 if (targetPos.X + sourceSize.Width > (s32)renderTargetSize.Width)\r
953                 {\r
954                         sourceSize.Width -= (targetPos.X + sourceSize.Width) - renderTargetSize.Width;\r
955                         if (sourceSize.Width <= 0)\r
956                                 return;\r
957                 }\r
958 \r
959                 if (targetPos.Y < 0)\r
960                 {\r
961                         sourceSize.Height += targetPos.Y;\r
962                         if (sourceSize.Height <= 0)\r
963                                 return;\r
964 \r
965                         sourcePos.Y -= targetPos.Y;\r
966                         targetPos.Y = 0;\r
967                 }\r
968 \r
969                 if (targetPos.Y + sourceSize.Height > (s32)renderTargetSize.Height)\r
970                 {\r
971                         sourceSize.Height -= (targetPos.Y + sourceSize.Height) - renderTargetSize.Height;\r
972                         if (sourceSize.Height <= 0)\r
973                                 return;\r
974                 }\r
975 \r
976                 // ok, we've clipped everything.\r
977                 // now draw it.\r
978 \r
979                 // texcoords need to be flipped horizontally for RTTs\r
980                 const bool isRTT = texture->isRenderTarget();\r
981                 const core::dimension2d<u32>& ss = texture->getOriginalSize();\r
982                 const f32 invW = 1.f / static_cast<f32>(ss.Width);\r
983                 const f32 invH = 1.f / static_cast<f32>(ss.Height);\r
984                 const core::rect<f32> tcoords(\r
985                         sourcePos.X * invW,\r
986                         (isRTT ? (sourcePos.Y + sourceSize.Height) : sourcePos.Y) * invH,\r
987                         (sourcePos.X + sourceSize.Width) * invW,\r
988                         (isRTT ? sourcePos.Y : (sourcePos.Y + sourceSize.Height)) * invH);\r
989 \r
990                 const core::rect<s32> poss(targetPos, sourceSize);\r
991 \r
992                 chooseMaterial2D();\r
993                 if (!setMaterialTexture(0, texture ))\r
994                         return;\r
995 \r
996                 setRenderStates2DMode(color.getAlpha() < 255, true, useAlphaChannelOfTexture);\r
997 \r
998                 f32 left = (f32)poss.UpperLeftCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;\r
999                 f32 right = (f32)poss.LowerRightCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;\r
1000                 f32 down = 2.f - (f32)poss.LowerRightCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
1001                 f32 top = 2.f - (f32)poss.UpperLeftCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
1002 \r
1003                 u16 indices[] = {0, 1, 2, 3};\r
1004                 S3DVertex vertices[4];\r
1005                 vertices[0] = S3DVertex(left, top, 0, 0, 0, 1, color, tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y);\r
1006                 vertices[1] = S3DVertex(right, top, 0, 0, 0, 1, color, tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y);\r
1007                 vertices[2] = S3DVertex(right, down, 0, 0, 0, 1, color, tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y);\r
1008                 vertices[3] = S3DVertex(left, down, 0, 0, 0, 1, color, tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y);\r
1009 \r
1010                 glEnableVertexAttribArray(EVA_POSITION);\r
1011                 glEnableVertexAttribArray(EVA_COLOR);\r
1012                 glEnableVertexAttribArray(EVA_TCOORD0);\r
1013                 glVertexAttribPointer(EVA_POSITION, 3, GL_FLOAT, false, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Pos);\r
1014                 glVertexAttribPointer(EVA_COLOR, 4, GL_UNSIGNED_BYTE, true, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Color);\r
1015                 glVertexAttribPointer(EVA_TCOORD0, 2, GL_FLOAT, false, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].TCoords);\r
1016                 glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, indices);\r
1017                 glDisableVertexAttribArray(EVA_TCOORD0);\r
1018                 glDisableVertexAttribArray(EVA_COLOR);\r
1019                 glDisableVertexAttribArray(EVA_POSITION);\r
1020         }\r
1021 \r
1022 \r
1023         void COGLES2Driver::draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect,\r
1024                 const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,\r
1025                 const video::SColor* const colors, bool useAlphaChannelOfTexture)\r
1026         {\r
1027                 if (!texture)\r
1028                         return;\r
1029 \r
1030                 IRR_PROFILE(CProfileScope p1(EPID_ES2_DRAW_2DIMAGE);)\r
1031 \r
1032                         // texcoords need to be flipped horizontally for RTTs\r
1033                         const bool isRTT = texture->isRenderTarget();\r
1034                 const core::dimension2du& ss = texture->getOriginalSize();\r
1035                 const f32 invW = 1.f / static_cast<f32>(ss.Width);\r
1036                 const f32 invH = 1.f / static_cast<f32>(ss.Height);\r
1037                 const core::rect<f32> tcoords(\r
1038                         sourceRect.UpperLeftCorner.X * invW,\r
1039                         (isRTT ? sourceRect.LowerRightCorner.Y : sourceRect.UpperLeftCorner.Y) * invH,\r
1040                         sourceRect.LowerRightCorner.X * invW,\r
1041                         (isRTT ? sourceRect.UpperLeftCorner.Y : sourceRect.LowerRightCorner.Y) *invH);\r
1042 \r
1043                 const video::SColor temp[4] =\r
1044                 {\r
1045                         0xFFFFFFFF,\r
1046                         0xFFFFFFFF,\r
1047                         0xFFFFFFFF,\r
1048                         0xFFFFFFFF\r
1049                 };\r
1050 \r
1051                 const video::SColor* const useColor = colors ? colors : temp;\r
1052 \r
1053                 chooseMaterial2D();\r
1054                 if (!setMaterialTexture(0, texture ))\r
1055                         return;\r
1056 \r
1057                 setRenderStates2DMode(useColor[0].getAlpha() < 255 || useColor[1].getAlpha() < 255 ||\r
1058                         useColor[2].getAlpha() < 255 || useColor[3].getAlpha() < 255,\r
1059                         true, useAlphaChannelOfTexture);\r
1060 \r
1061                 const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();\r
1062 \r
1063                 if (clipRect)\r
1064                 {\r
1065                         if (!clipRect->isValid())\r
1066                                 return;\r
1067 \r
1068                         glEnable(GL_SCISSOR_TEST);\r
1069                         glScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height - clipRect->LowerRightCorner.Y,\r
1070                                 clipRect->getWidth(), clipRect->getHeight());\r
1071                 }\r
1072 \r
1073                 f32 left = (f32)destRect.UpperLeftCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;\r
1074                 f32 right = (f32)destRect.LowerRightCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;\r
1075                 f32 down = 2.f - (f32)destRect.LowerRightCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
1076                 f32 top = 2.f - (f32)destRect.UpperLeftCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
1077 \r
1078                 u16 indices[] = { 0, 1, 2, 3 };\r
1079                 S3DVertex vertices[4];\r
1080                 vertices[0] = S3DVertex(left, top, 0, 0, 0, 1, useColor[0], tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y);\r
1081                 vertices[1] = S3DVertex(right, top, 0, 0, 0, 1, useColor[3], tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y);\r
1082                 vertices[2] = S3DVertex(right, down, 0, 0, 0, 1, useColor[2], tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y);\r
1083                 vertices[3] = S3DVertex(left, down, 0, 0, 0, 1, useColor[1], tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y);\r
1084 \r
1085                 glEnableVertexAttribArray(EVA_POSITION);\r
1086                 glEnableVertexAttribArray(EVA_COLOR);\r
1087                 glEnableVertexAttribArray(EVA_TCOORD0);\r
1088                 glVertexAttribPointer(EVA_POSITION, 3, GL_FLOAT, false, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Pos);\r
1089                 glVertexAttribPointer(EVA_COLOR, 4, GL_UNSIGNED_BYTE, true, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Color);\r
1090                 glVertexAttribPointer(EVA_TCOORD0, 2, GL_FLOAT, false, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].TCoords);\r
1091                 glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, indices);\r
1092                 glDisableVertexAttribArray(EVA_TCOORD0);\r
1093                 glDisableVertexAttribArray(EVA_COLOR);\r
1094                 glDisableVertexAttribArray(EVA_POSITION);\r
1095 \r
1096                 if (clipRect)\r
1097                         glDisable(GL_SCISSOR_TEST);\r
1098 \r
1099                 testGLError(__LINE__);\r
1100         }\r
1101 \r
1102         void COGLES2Driver::draw2DImage(const video::ITexture* texture, u32 layer, bool flip)\r
1103         {\r
1104                 if (!texture)\r
1105                         return;\r
1106 \r
1107                 chooseMaterial2D();\r
1108                 if (!setMaterialTexture(0, texture ))\r
1109                         return;\r
1110 \r
1111                 setRenderStates2DMode(false, true, true);\r
1112 \r
1113                 u16 quad2DIndices[] = { 0, 1, 2, 3 };\r
1114                 S3DVertex quad2DVertices[4];\r
1115 \r
1116                 quad2DVertices[0].Pos = core::vector3df(-1.f, 1.f, 0.f);\r
1117                 quad2DVertices[1].Pos = core::vector3df(1.f, 1.f, 0.f);\r
1118                 quad2DVertices[2].Pos = core::vector3df(1.f, -1.f, 0.f);\r
1119                 quad2DVertices[3].Pos = core::vector3df(-1.f, -1.f, 0.f);\r
1120 \r
1121                 f32 modificator = (flip) ? 1.f : 0.f;\r
1122 \r
1123                 quad2DVertices[0].TCoords = core::vector2df(0.f, 0.f + modificator);\r
1124                 quad2DVertices[1].TCoords = core::vector2df(1.f, 0.f + modificator);\r
1125                 quad2DVertices[2].TCoords = core::vector2df(1.f, 1.f - modificator);\r
1126                 quad2DVertices[3].TCoords = core::vector2df(0.f, 1.f - modificator);\r
1127 \r
1128                 quad2DVertices[0].Color = SColor(0xFFFFFFFF);\r
1129                 quad2DVertices[1].Color = SColor(0xFFFFFFFF);\r
1130                 quad2DVertices[2].Color = SColor(0xFFFFFFFF);\r
1131                 quad2DVertices[3].Color = SColor(0xFFFFFFFF);\r
1132 \r
1133                 glEnableVertexAttribArray(EVA_POSITION);\r
1134                 glEnableVertexAttribArray(EVA_COLOR);\r
1135                 glEnableVertexAttribArray(EVA_TCOORD0);\r
1136                 glVertexAttribPointer(EVA_POSITION, 3, GL_FLOAT, false, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(quad2DVertices))[0].Pos);\r
1137                 glVertexAttribPointer(EVA_COLOR, 4, GL_UNSIGNED_BYTE, true, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(quad2DVertices))[0].Color);\r
1138                 glVertexAttribPointer(EVA_TCOORD0, 2, GL_FLOAT, false, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(quad2DVertices))[0].TCoords);\r
1139                 glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, quad2DIndices);\r
1140                 glDisableVertexAttribArray(EVA_TCOORD0);\r
1141                 glDisableVertexAttribArray(EVA_COLOR);\r
1142                 glDisableVertexAttribArray(EVA_POSITION);\r
1143         }\r
1144 \r
1145 \r
1146         void COGLES2Driver::draw2DImageBatch(const video::ITexture* texture,\r
1147                         const core::array<core::position2d<s32> >& positions,\r
1148                         const core::array<core::rect<s32> >& sourceRects,\r
1149                         const core::rect<s32>* clipRect,\r
1150                         SColor color, bool useAlphaChannelOfTexture)\r
1151         {\r
1152                 if (!texture)\r
1153                         return;\r
1154 \r
1155                 IRR_PROFILE(CProfileScope p1(EPID_ES2_DRAW_2DIMAGE_BATCH);)\r
1156 \r
1157                 const irr::u32 drawCount = core::min_<u32>(positions.size(), sourceRects.size());\r
1158 \r
1159                 core::array<S3DVertex> vtx(drawCount * 4);\r
1160                 core::array<u16> indices(drawCount * 6);\r
1161 \r
1162                 for (u32 i = 0; i < drawCount; i++)\r
1163                 {\r
1164                         core::position2d<s32> targetPos = positions[i];\r
1165                         core::position2d<s32> sourcePos = sourceRects[i].UpperLeftCorner;\r
1166                         // This needs to be signed as it may go negative.\r
1167                         core::dimension2d<s32> sourceSize(sourceRects[i].getSize());\r
1168 \r
1169                         if (clipRect)\r
1170                         {\r
1171                                 if (targetPos.X < clipRect->UpperLeftCorner.X)\r
1172                                 {\r
1173                                         sourceSize.Width += targetPos.X - clipRect->UpperLeftCorner.X;\r
1174                                         if (sourceSize.Width <= 0)\r
1175                                                 continue;\r
1176 \r
1177                                         sourcePos.X -= targetPos.X - clipRect->UpperLeftCorner.X;\r
1178                                         targetPos.X = clipRect->UpperLeftCorner.X;\r
1179                                 }\r
1180 \r
1181                                 if (targetPos.X + (s32)sourceSize.Width > clipRect->LowerRightCorner.X)\r
1182                                 {\r
1183                                         sourceSize.Width -= (targetPos.X + sourceSize.Width) - clipRect->LowerRightCorner.X;\r
1184                                         if (sourceSize.Width <= 0)\r
1185                                                 continue;\r
1186                                 }\r
1187 \r
1188                                 if (targetPos.Y < clipRect->UpperLeftCorner.Y)\r
1189                                 {\r
1190                                         sourceSize.Height += targetPos.Y - clipRect->UpperLeftCorner.Y;\r
1191                                         if (sourceSize.Height <= 0)\r
1192                                                 continue;\r
1193 \r
1194                                         sourcePos.Y -= targetPos.Y - clipRect->UpperLeftCorner.Y;\r
1195                                         targetPos.Y = clipRect->UpperLeftCorner.Y;\r
1196                                 }\r
1197 \r
1198                                 if (targetPos.Y + (s32)sourceSize.Height > clipRect->LowerRightCorner.Y)\r
1199                                 {\r
1200                                         sourceSize.Height -= (targetPos.Y + sourceSize.Height) - clipRect->LowerRightCorner.Y;\r
1201                                         if (sourceSize.Height <= 0)\r
1202                                                 continue;\r
1203                                 }\r
1204                         }\r
1205 \r
1206                         // clip these coordinates\r
1207 \r
1208                         if (targetPos.X < 0)\r
1209                         {\r
1210                                 sourceSize.Width += targetPos.X;\r
1211                                 if (sourceSize.Width <= 0)\r
1212                                         continue;\r
1213 \r
1214                                 sourcePos.X -= targetPos.X;\r
1215                                 targetPos.X = 0;\r
1216                         }\r
1217 \r
1218                         const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();\r
1219 \r
1220                         if (targetPos.X + sourceSize.Width > (s32)renderTargetSize.Width)\r
1221                         {\r
1222                                 sourceSize.Width -= (targetPos.X + sourceSize.Width) - renderTargetSize.Width;\r
1223                                 if (sourceSize.Width <= 0)\r
1224                                         continue;\r
1225                         }\r
1226 \r
1227                         if (targetPos.Y < 0)\r
1228                         {\r
1229                                 sourceSize.Height += targetPos.Y;\r
1230                                 if (sourceSize.Height <= 0)\r
1231                                         continue;\r
1232 \r
1233                                 sourcePos.Y -= targetPos.Y;\r
1234                                 targetPos.Y = 0;\r
1235                         }\r
1236 \r
1237                         if (targetPos.Y + sourceSize.Height > (s32)renderTargetSize.Height)\r
1238                         {\r
1239                                 sourceSize.Height -= (targetPos.Y + sourceSize.Height) - renderTargetSize.Height;\r
1240                                 if (sourceSize.Height <= 0)\r
1241                                         continue;\r
1242                         }\r
1243 \r
1244                         // ok, we've clipped everything.\r
1245                         // now draw it.\r
1246 \r
1247                         core::rect<f32> tcoords;\r
1248                         tcoords.UpperLeftCorner.X = (((f32)sourcePos.X)) / texture->getOriginalSize().Width ;\r
1249                         tcoords.UpperLeftCorner.Y = (((f32)sourcePos.Y)) / texture->getOriginalSize().Height;\r
1250                         tcoords.LowerRightCorner.X = tcoords.UpperLeftCorner.X + ((f32)(sourceSize.Width) / texture->getOriginalSize().Width);\r
1251                         tcoords.LowerRightCorner.Y = tcoords.UpperLeftCorner.Y + ((f32)(sourceSize.Height) / texture->getOriginalSize().Height);\r
1252 \r
1253                         const core::rect<s32> poss(targetPos, sourceSize);\r
1254 \r
1255                         chooseMaterial2D();\r
1256                         if (!setMaterialTexture(0, texture))\r
1257                                 return;\r
1258 \r
1259                         setRenderStates2DMode(color.getAlpha() < 255, true, useAlphaChannelOfTexture);\r
1260 \r
1261                         f32 left = (f32)poss.UpperLeftCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;\r
1262                         f32 right = (f32)poss.LowerRightCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;\r
1263                         f32 down = 2.f - (f32)poss.LowerRightCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
1264                         f32 top = 2.f - (f32)poss.UpperLeftCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
1265 \r
1266                         vtx.push_back(S3DVertex(left, top, 0.0f,\r
1267                                         0.0f, 0.0f, 0.0f, color,\r
1268                                         tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y));\r
1269                         vtx.push_back(S3DVertex(right, top, 0.0f,\r
1270                                         0.0f, 0.0f, 0.0f, color,\r
1271                                         tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y));\r
1272                         vtx.push_back(S3DVertex(right, down, 0.0f,\r
1273                                         0.0f, 0.0f, 0.0f, color,\r
1274                                         tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y));\r
1275                         vtx.push_back(S3DVertex(left, down, 0.0f,\r
1276                                         0.0f, 0.0f, 0.0f, color,\r
1277                                         tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y));\r
1278 \r
1279                         const u32 curPos = vtx.size() - 4;\r
1280                         indices.push_back(0 + curPos);\r
1281                         indices.push_back(1 + curPos);\r
1282                         indices.push_back(2 + curPos);\r
1283 \r
1284                         indices.push_back(0 + curPos);\r
1285                         indices.push_back(2 + curPos);\r
1286                         indices.push_back(3 + curPos);\r
1287                 }\r
1288 \r
1289                 if (vtx.size())\r
1290                 {\r
1291                         glEnableVertexAttribArray(EVA_POSITION);\r
1292                         glEnableVertexAttribArray(EVA_COLOR);\r
1293                         glEnableVertexAttribArray(EVA_TCOORD0);\r
1294                         glVertexAttribPointer(EVA_POSITION, 3, GL_FLOAT, false, sizeof(S3DVertex), &vtx[0].Pos);\r
1295                         glVertexAttribPointer(EVA_COLOR, 4, GL_UNSIGNED_BYTE, true, sizeof(S3DVertex), &vtx[0].Color);\r
1296                         glVertexAttribPointer(EVA_TCOORD0, 2, GL_FLOAT, false, sizeof(S3DVertex), &vtx[0].TCoords);\r
1297                         glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_SHORT, indices.pointer());\r
1298                         glDisableVertexAttribArray(EVA_TCOORD0);\r
1299                         glDisableVertexAttribArray(EVA_COLOR);\r
1300                         glDisableVertexAttribArray(EVA_POSITION);\r
1301                 }\r
1302         }\r
1303 \r
1304 \r
1305         //! draws a set of 2d images, using a color and the alpha channel\r
1306         void COGLES2Driver::draw2DImageBatch(const video::ITexture* texture,\r
1307                         const core::position2d<s32>& pos,\r
1308                         const core::array<core::rect<s32> >& sourceRects,\r
1309                         const core::array<s32>& indices, s32 kerningWidth,\r
1310                         const core::rect<s32>* clipRect, SColor color,\r
1311                         bool useAlphaChannelOfTexture)\r
1312         {\r
1313                 if (!texture)\r
1314                         return;\r
1315 \r
1316                 IRR_PROFILE(CProfileScope p1(EPID_ES2_DRAW_2DIMAGE_BATCH);)\r
1317 \r
1318                 chooseMaterial2D();\r
1319                 if (!setMaterialTexture(0, texture))\r
1320                         return;\r
1321 \r
1322                 setRenderStates2DMode(color.getAlpha() < 255, true, useAlphaChannelOfTexture);\r
1323 \r
1324                 const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();\r
1325 \r
1326                 if (clipRect)\r
1327                 {\r
1328                         if (!clipRect->isValid())\r
1329                                 return;\r
1330 \r
1331                         glEnable(GL_SCISSOR_TEST);\r
1332                         glScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height - clipRect->LowerRightCorner.Y,\r
1333                                         clipRect->getWidth(), clipRect->getHeight());\r
1334                 }\r
1335 \r
1336                 const core::dimension2du& ss = texture->getOriginalSize();\r
1337                 core::position2d<s32> targetPos(pos);\r
1338                 // texcoords need to be flipped horizontally for RTTs\r
1339                 const bool isRTT = texture->isRenderTarget();\r
1340                 const f32 invW = 1.f / static_cast<f32>(ss.Width);\r
1341                 const f32 invH = 1.f / static_cast<f32>(ss.Height);\r
1342 \r
1343                 core::array<S3DVertex> vertices;\r
1344                 core::array<u16> quadIndices;\r
1345                 vertices.reallocate(indices.size()*4);\r
1346                 quadIndices.reallocate(indices.size()*3);\r
1347 \r
1348                 for (u32 i = 0; i < indices.size(); ++i)\r
1349                 {\r
1350                         const s32 currentIndex = indices[i];\r
1351                         if (!sourceRects[currentIndex].isValid())\r
1352                                 break;\r
1353 \r
1354                         const core::rect<f32> tcoords(\r
1355                                 sourceRects[currentIndex].UpperLeftCorner.X * invW,\r
1356                                 (isRTT ? sourceRects[currentIndex].LowerRightCorner.Y : sourceRects[currentIndex].UpperLeftCorner.Y) * invH,\r
1357                                 sourceRects[currentIndex].LowerRightCorner.X * invW,\r
1358                                 (isRTT ? sourceRects[currentIndex].UpperLeftCorner.Y : sourceRects[currentIndex].LowerRightCorner.Y) * invH);\r
1359 \r
1360                         const core::rect<s32> poss(targetPos, sourceRects[currentIndex].getSize());\r
1361 \r
1362                         f32 left = (f32)poss.UpperLeftCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;\r
1363                         f32 right = (f32)poss.LowerRightCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;\r
1364                         f32 down = 2.f - (f32)poss.LowerRightCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
1365                         f32 top = 2.f - (f32)poss.UpperLeftCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
1366 \r
1367                         const u32 vstart = vertices.size();\r
1368                         vertices.push_back(S3DVertex(left, top, 0, 0, 0, 1, color, tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y));\r
1369                         vertices.push_back(S3DVertex(right, top, 0, 0, 0, 1, color, tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y));\r
1370                         vertices.push_back(S3DVertex(right, down, 0, 0, 0, 1, color, tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y));\r
1371                         vertices.push_back(S3DVertex(left, down, 0, 0, 0, 1, color, tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y));\r
1372                         quadIndices.push_back(vstart);\r
1373                         quadIndices.push_back(vstart+1);\r
1374                         quadIndices.push_back(vstart+2);\r
1375                         quadIndices.push_back(vstart);\r
1376                         quadIndices.push_back(vstart+2);\r
1377                         quadIndices.push_back(vstart+3);\r
1378 \r
1379                         targetPos.X += sourceRects[currentIndex].getWidth();\r
1380                 }\r
1381 \r
1382                 if (vertices.size())\r
1383                 {\r
1384                         glEnableVertexAttribArray(EVA_POSITION);\r
1385                         glEnableVertexAttribArray(EVA_COLOR);\r
1386                         glEnableVertexAttribArray(EVA_TCOORD0);\r
1387                         glVertexAttribPointer(EVA_POSITION, 3, GL_FLOAT, false, sizeof(S3DVertex), &vertices[0].Pos);\r
1388                         glVertexAttribPointer(EVA_COLOR, 4, GL_UNSIGNED_BYTE, true, sizeof(S3DVertex), &vertices[0].Color);\r
1389                         glVertexAttribPointer(EVA_TCOORD0, 2, GL_FLOAT, false, sizeof(S3DVertex), &vertices[0].TCoords);\r
1390                         glDrawElements(GL_TRIANGLES, quadIndices.size(), GL_UNSIGNED_SHORT, quadIndices.pointer());\r
1391                         glDisableVertexAttribArray(EVA_TCOORD0);\r
1392                         glDisableVertexAttribArray(EVA_COLOR);\r
1393                         glDisableVertexAttribArray(EVA_POSITION);\r
1394                 }\r
1395 \r
1396                 if (clipRect)\r
1397                         glDisable(GL_SCISSOR_TEST);\r
1398 \r
1399                 testGLError(__LINE__);\r
1400         }\r
1401 \r
1402 \r
1403         //! draw a 2d rectangle\r
1404         void COGLES2Driver::draw2DRectangle(SColor color,\r
1405                         const core::rect<s32>& position,\r
1406                         const core::rect<s32>* clip)\r
1407         {\r
1408                 IRR_PROFILE(CProfileScope p1(EPID_ES2_DRAW_2DRECTANGLE);)\r
1409 \r
1410                 chooseMaterial2D();\r
1411                 setMaterialTexture(0, 0);\r
1412 \r
1413                 setRenderStates2DMode(color.getAlpha() < 255, false, false);\r
1414 \r
1415                 core::rect<s32> pos = position;\r
1416 \r
1417                 if (clip)\r
1418                         pos.clipAgainst(*clip);\r
1419 \r
1420                 if (!pos.isValid())\r
1421                         return;\r
1422 \r
1423                 const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();\r
1424 \r
1425                 f32 left = (f32)pos.UpperLeftCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;\r
1426                 f32 right = (f32)pos.LowerRightCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;\r
1427                 f32 down = 2.f - (f32)pos.LowerRightCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
1428                 f32 top = 2.f - (f32)pos.UpperLeftCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
1429 \r
1430                 u16 indices[] = {0, 1, 2, 3};\r
1431                 S3DVertex vertices[4];\r
1432                 vertices[0] = S3DVertex(left, top, 0, 0, 0, 1, color, 0, 0);\r
1433                 vertices[1] = S3DVertex(right, top, 0, 0, 0, 1, color, 0, 0);\r
1434                 vertices[2] = S3DVertex(right, down, 0, 0, 0, 1, color, 0, 0);\r
1435                 vertices[3] = S3DVertex(left, down, 0, 0, 0, 1, color, 0, 0);\r
1436 \r
1437                 glEnableVertexAttribArray(EVA_POSITION);\r
1438                 glEnableVertexAttribArray(EVA_COLOR);\r
1439                 glVertexAttribPointer(EVA_POSITION, 3, GL_FLOAT, false, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Pos);\r
1440                 glVertexAttribPointer(EVA_COLOR, 4, GL_UNSIGNED_BYTE, true, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Color);\r
1441                 glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, indices);\r
1442                 glDisableVertexAttribArray(EVA_COLOR);\r
1443                 glDisableVertexAttribArray(EVA_POSITION);\r
1444         }\r
1445 \r
1446 \r
1447         //! draw an 2d rectangle\r
1448         void COGLES2Driver::draw2DRectangle(const core::rect<s32>& position,\r
1449                         SColor colorLeftUp, SColor colorRightUp,\r
1450                         SColor colorLeftDown, SColor colorRightDown,\r
1451                         const core::rect<s32>* clip)\r
1452         {\r
1453                 IRR_PROFILE(CProfileScope p1(EPID_ES2_DRAW_2DRECTANGLE);)\r
1454 \r
1455                 core::rect<s32> pos = position;\r
1456 \r
1457                 if (clip)\r
1458                         pos.clipAgainst(*clip);\r
1459 \r
1460                 if (!pos.isValid())\r
1461                         return;\r
1462 \r
1463                 chooseMaterial2D();\r
1464                 setMaterialTexture(0, 0);\r
1465 \r
1466                 setRenderStates2DMode(colorLeftUp.getAlpha() < 255 ||\r
1467                                 colorRightUp.getAlpha() < 255 ||\r
1468                                 colorLeftDown.getAlpha() < 255 ||\r
1469                                 colorRightDown.getAlpha() < 255, false, false);\r
1470 \r
1471                 const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();\r
1472 \r
1473                 f32 left = (f32)pos.UpperLeftCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;\r
1474                 f32 right = (f32)pos.LowerRightCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;\r
1475                 f32 down = 2.f - (f32)pos.LowerRightCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
1476                 f32 top = 2.f - (f32)pos.UpperLeftCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
1477 \r
1478                 u16 indices[] = {0, 1, 2, 3};\r
1479                 S3DVertex vertices[4];\r
1480                 vertices[0] = S3DVertex(left, top, 0, 0, 0, 1, colorLeftUp, 0, 0);\r
1481                 vertices[1] = S3DVertex(right, top, 0, 0, 0, 1, colorRightUp, 0, 0);\r
1482                 vertices[2] = S3DVertex(right, down, 0, 0, 0, 1, colorRightDown, 0, 0);\r
1483                 vertices[3] = S3DVertex(left, down, 0, 0, 0, 1, colorLeftDown, 0, 0);\r
1484 \r
1485                 glEnableVertexAttribArray(EVA_POSITION);\r
1486                 glEnableVertexAttribArray(EVA_COLOR);\r
1487                 glVertexAttribPointer(EVA_POSITION, 3, GL_FLOAT, false, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Pos);\r
1488                 glVertexAttribPointer(EVA_COLOR, 4, GL_UNSIGNED_BYTE, true, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Color);\r
1489                 glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, indices);\r
1490                 glDisableVertexAttribArray(EVA_COLOR);\r
1491                 glDisableVertexAttribArray(EVA_POSITION);\r
1492         }\r
1493 \r
1494 \r
1495         //! Draws a 2d line.\r
1496         void COGLES2Driver::draw2DLine(const core::position2d<s32>& start,\r
1497                         const core::position2d<s32>& end, SColor color)\r
1498         {\r
1499                 IRR_PROFILE(CProfileScope p1(EPID_ES2_DRAW_2DLINE);)\r
1500 \r
1501                 if (start==end)\r
1502                         drawPixel(start.X, start.Y, color);\r
1503                 else\r
1504                 {\r
1505                         chooseMaterial2D();\r
1506                         setMaterialTexture(0, 0);\r
1507 \r
1508                         setRenderStates2DMode(color.getAlpha() < 255, false, false);\r
1509 \r
1510                         const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();\r
1511 \r
1512                         f32 startX = (f32)start.X / (f32)renderTargetSize.Width * 2.f - 1.f;\r
1513                         f32 endX = (f32)end.X / (f32)renderTargetSize.Width * 2.f - 1.f;\r
1514                         f32 startY = 2.f - (f32)start.Y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
1515                         f32 endY = 2.f - (f32)end.Y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
1516 \r
1517                         u16 indices[] = {0, 1};\r
1518                         S3DVertex vertices[2];\r
1519                         vertices[0] = S3DVertex(startX, startY, 0, 0, 0, 1, color, 0, 0);\r
1520                         vertices[1] = S3DVertex(endX, endY, 0, 0, 0, 1, color, 1, 1);\r
1521 \r
1522                         glEnableVertexAttribArray(EVA_POSITION);\r
1523                         glEnableVertexAttribArray(EVA_COLOR);\r
1524                         glVertexAttribPointer(EVA_POSITION, 3, GL_FLOAT, false, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Pos);\r
1525                         glVertexAttribPointer(EVA_COLOR, 4, GL_UNSIGNED_BYTE, true, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Color);\r
1526                         glDrawElements(GL_LINES, 2, GL_UNSIGNED_SHORT, indices);\r
1527                         glDisableVertexAttribArray(EVA_COLOR);\r
1528                         glDisableVertexAttribArray(EVA_POSITION);\r
1529                 }\r
1530         }\r
1531 \r
1532 \r
1533         //! Draws a pixel\r
1534         void COGLES2Driver::drawPixel(u32 x, u32 y, const SColor &color)\r
1535         {\r
1536                 const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();\r
1537                 if (x > (u32)renderTargetSize.Width || y > (u32)renderTargetSize.Height)\r
1538                         return;\r
1539 \r
1540                 chooseMaterial2D();\r
1541                 setMaterialTexture(0, 0);\r
1542 \r
1543                 setRenderStates2DMode(color.getAlpha() < 255, false, false);\r
1544 \r
1545                 f32 X = (f32)x / (f32)renderTargetSize.Width * 2.f - 1.f;\r
1546                 f32 Y = 2.f - (f32)y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
1547 \r
1548                 S3DVertex vertices[1];\r
1549                 vertices[0] = S3DVertex(X, Y, 0, 0, 0, 1, color, 0, 0);\r
1550 \r
1551                 glEnableVertexAttribArray(EVA_POSITION);\r
1552                 glEnableVertexAttribArray(EVA_COLOR);\r
1553                 glVertexAttribPointer(EVA_POSITION, 3, GL_FLOAT, false, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Pos);\r
1554                 glVertexAttribPointer(EVA_COLOR, 4, GL_UNSIGNED_BYTE, true, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Color);\r
1555                 glDrawArrays(GL_POINTS, 0, 1);\r
1556                 glDisableVertexAttribArray(EVA_COLOR);\r
1557                 glDisableVertexAttribArray(EVA_POSITION);\r
1558         }\r
1559 \r
1560         ITexture* COGLES2Driver::createDeviceDependentTexture(const io::path& name, IImage* image)\r
1561         {\r
1562                 core::array<IImage*> imageArray(1);\r
1563                 imageArray.push_back(image);\r
1564 \r
1565                 COGLES2Texture* texture = new COGLES2Texture(name, imageArray, ETT_2D, this);\r
1566 \r
1567                 return texture;\r
1568         }\r
1569 \r
1570         ITexture* COGLES2Driver::createDeviceDependentTextureCubemap(const io::path& name, const core::array<IImage*>& image)\r
1571         {\r
1572                 COGLES2Texture* texture = new COGLES2Texture(name, image, ETT_CUBEMAP, this);\r
1573 \r
1574                 return texture;\r
1575         }\r
1576 \r
1577         //! Sets a material.\r
1578         void COGLES2Driver::setMaterial(const SMaterial& material)\r
1579         {\r
1580                 Material = material;\r
1581                 OverrideMaterial.apply(Material);\r
1582 \r
1583                 for (u32 i = 0; i < Feature.MaxTextureUnits; ++i)\r
1584                 {\r
1585                         CacheHandler->getTextureCache().set(i, material.getTexture(i));\r
1586                         setTransform((E_TRANSFORMATION_STATE)(ETS_TEXTURE_0 + i), material.getTextureMatrix(i));\r
1587                 }\r
1588         }\r
1589 \r
1590         //! prints error if an error happened.\r
1591         bool COGLES2Driver::testGLError(int code)\r
1592         {\r
1593 #ifdef _DEBUG\r
1594                 GLenum g = glGetError();\r
1595                 switch (g)\r
1596                 {\r
1597                         case GL_NO_ERROR:\r
1598                                 return false;\r
1599                         case GL_INVALID_ENUM:\r
1600                                 os::Printer::log("GL_INVALID_ENUM", core::stringc(code).c_str(), ELL_ERROR);\r
1601                                 break;\r
1602                         case GL_INVALID_VALUE:\r
1603                                 os::Printer::log("GL_INVALID_VALUE", core::stringc(code).c_str(), ELL_ERROR);\r
1604                                 break;\r
1605                         case GL_INVALID_OPERATION:\r
1606                                 os::Printer::log("GL_INVALID_OPERATION", core::stringc(code).c_str(), ELL_ERROR);\r
1607                                 break;\r
1608                         case GL_OUT_OF_MEMORY:\r
1609                                 os::Printer::log("GL_OUT_OF_MEMORY", core::stringc(code).c_str(), ELL_ERROR);\r
1610                                 break;\r
1611                 };\r
1612                 return true;\r
1613 #else\r
1614                 return false;\r
1615 #endif\r
1616         }\r
1617 \r
1618         //! prints error if an error happened.\r
1619         bool COGLES2Driver::testEGLError()\r
1620         {\r
1621 #if defined(EGL_VERSION_1_0) && defined(_DEBUG)\r
1622                 EGLint g = eglGetError();\r
1623                 switch (g)\r
1624                 {\r
1625                         case EGL_SUCCESS:\r
1626                                 return false;\r
1627                         case EGL_NOT_INITIALIZED :\r
1628                                 os::Printer::log("Not Initialized", ELL_ERROR);\r
1629                                 break;\r
1630                         case EGL_BAD_ACCESS:\r
1631                                 os::Printer::log("Bad Access", ELL_ERROR);\r
1632                                 break;\r
1633                         case EGL_BAD_ALLOC:\r
1634                                 os::Printer::log("Bad Alloc", ELL_ERROR);\r
1635                                 break;\r
1636                         case EGL_BAD_ATTRIBUTE:\r
1637                                 os::Printer::log("Bad Attribute", ELL_ERROR);\r
1638                                 break;\r
1639                         case EGL_BAD_CONTEXT:\r
1640                                 os::Printer::log("Bad Context", ELL_ERROR);\r
1641                                 break;\r
1642                         case EGL_BAD_CONFIG:\r
1643                                 os::Printer::log("Bad Config", ELL_ERROR);\r
1644                                 break;\r
1645                         case EGL_BAD_CURRENT_SURFACE:\r
1646                                 os::Printer::log("Bad Current Surface", ELL_ERROR);\r
1647                                 break;\r
1648                         case EGL_BAD_DISPLAY:\r
1649                                 os::Printer::log("Bad Display", ELL_ERROR);\r
1650                                 break;\r
1651                         case EGL_BAD_SURFACE:\r
1652                                 os::Printer::log("Bad Surface", ELL_ERROR);\r
1653                                 break;\r
1654                         case EGL_BAD_MATCH:\r
1655                                 os::Printer::log("Bad Match", ELL_ERROR);\r
1656                                 break;\r
1657                         case EGL_BAD_PARAMETER:\r
1658                                 os::Printer::log("Bad Parameter", ELL_ERROR);\r
1659                                 break;\r
1660                         case EGL_BAD_NATIVE_PIXMAP:\r
1661                                 os::Printer::log("Bad Native Pixmap", ELL_ERROR);\r
1662                                 break;\r
1663                         case EGL_BAD_NATIVE_WINDOW:\r
1664                                 os::Printer::log("Bad Native Window", ELL_ERROR);\r
1665                                 break;\r
1666                         case EGL_CONTEXT_LOST:\r
1667                                 os::Printer::log("Context Lost", ELL_ERROR);\r
1668                                 break;\r
1669                 };\r
1670                 return true;\r
1671 #else\r
1672                 return false;\r
1673 #endif\r
1674         }\r
1675 \r
1676 \r
1677         void COGLES2Driver::setRenderStates3DMode()\r
1678         {\r
1679                 IRR_PROFILE(CProfileScope p1(EPID_ES2_SET_RENDERSTATE_3D);)\r
1680 \r
1681                 if ( LockRenderStateMode )\r
1682                         return;\r
1683 \r
1684                 if (CurrentRenderMode != ERM_3D)\r
1685                 {\r
1686                         // Reset Texture Stages\r
1687                         CacheHandler->setBlend(false);\r
1688                         CacheHandler->setBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\r
1689 \r
1690                         ResetRenderStates = true;\r
1691                 }\r
1692 \r
1693                 if (ResetRenderStates || LastMaterial != Material)\r
1694                 {\r
1695                         // unset old material\r
1696 \r
1697                         // unset last 3d material\r
1698                         if (CurrentRenderMode == ERM_2D && MaterialRenderer2DActive)\r
1699                         {\r
1700                                 MaterialRenderer2DActive->OnUnsetMaterial();\r
1701                                 MaterialRenderer2DActive = 0;\r
1702                         }\r
1703                         else if (LastMaterial.MaterialType != Material.MaterialType &&\r
1704                                         static_cast<u32>(LastMaterial.MaterialType) < MaterialRenderers.size())\r
1705                                 MaterialRenderers[LastMaterial.MaterialType].Renderer->OnUnsetMaterial();\r
1706 \r
1707                         // set new material.\r
1708                         if (static_cast<u32>(Material.MaterialType) < MaterialRenderers.size())\r
1709                                 MaterialRenderers[Material.MaterialType].Renderer->OnSetMaterial(\r
1710                                         Material, LastMaterial, ResetRenderStates, this);\r
1711 \r
1712                         LastMaterial = Material;\r
1713                         CacheHandler->correctCacheMaterial(LastMaterial);\r
1714                         ResetRenderStates = false;\r
1715                 }\r
1716 \r
1717                 if (static_cast<u32>(Material.MaterialType) < MaterialRenderers.size())\r
1718                         MaterialRenderers[Material.MaterialType].Renderer->OnRender(this, video::EVT_STANDARD);\r
1719 \r
1720                 CurrentRenderMode = ERM_3D;\r
1721         }\r
1722 \r
1723         //! Can be called by an IMaterialRenderer to make its work easier.\r
1724         void COGLES2Driver::setBasicRenderStates(const SMaterial& material, const SMaterial& lastmaterial, bool resetAllRenderStates)\r
1725         {\r
1726                 IRR_PROFILE(CProfileScope p1(EPID_ES2_SET_RENDERSTATE_BASIC);)\r
1727 \r
1728                 // ZBuffer\r
1729                 switch (material.ZBuffer)\r
1730                 {\r
1731                         case ECFN_DISABLED:\r
1732                                 CacheHandler->setDepthTest(false);\r
1733                                 break;\r
1734                         case ECFN_LESSEQUAL:\r
1735                                 CacheHandler->setDepthTest(true);\r
1736                                 CacheHandler->setDepthFunc(GL_LEQUAL);\r
1737                                 break;\r
1738                         case ECFN_EQUAL:\r
1739                                 CacheHandler->setDepthTest(true);\r
1740                                 CacheHandler->setDepthFunc(GL_EQUAL);\r
1741                                 break;\r
1742                         case ECFN_LESS:\r
1743                                 CacheHandler->setDepthTest(true);\r
1744                                 CacheHandler->setDepthFunc(GL_LESS);\r
1745                                 break;\r
1746                         case ECFN_NOTEQUAL:\r
1747                                 CacheHandler->setDepthTest(true);\r
1748                                 CacheHandler->setDepthFunc(GL_NOTEQUAL);\r
1749                                 break;\r
1750                         case ECFN_GREATEREQUAL:\r
1751                                 CacheHandler->setDepthTest(true);\r
1752                                 CacheHandler->setDepthFunc(GL_GEQUAL);\r
1753                                 break;\r
1754                         case ECFN_GREATER:\r
1755                                 CacheHandler->setDepthTest(true);\r
1756                                 CacheHandler->setDepthFunc(GL_GREATER);\r
1757                                 break;\r
1758                         case ECFN_ALWAYS:\r
1759                                 CacheHandler->setDepthTest(true);\r
1760                                 CacheHandler->setDepthFunc(GL_ALWAYS);\r
1761                                 break;\r
1762                         case ECFN_NEVER:\r
1763                                 CacheHandler->setDepthTest(true);\r
1764                                 CacheHandler->setDepthFunc(GL_NEVER);\r
1765                                 break;\r
1766                         default:\r
1767                                 break;\r
1768                 }\r
1769 \r
1770                 // ZWrite\r
1771                 if (getWriteZBuffer(material))\r
1772                 {\r
1773                         CacheHandler->setDepthMask(true);\r
1774                 }\r
1775                 else\r
1776                 {\r
1777                         CacheHandler->setDepthMask(false);\r
1778                 }\r
1779 \r
1780                 // Back face culling\r
1781                 if ((material.FrontfaceCulling) && (material.BackfaceCulling))\r
1782                 {\r
1783                         CacheHandler->setCullFaceFunc(GL_FRONT_AND_BACK);\r
1784                         CacheHandler->setCullFace(true);\r
1785                 }\r
1786                 else if (material.BackfaceCulling)\r
1787                 {\r
1788                         CacheHandler->setCullFaceFunc(GL_BACK);\r
1789                         CacheHandler->setCullFace(true);\r
1790                 }\r
1791                 else if (material.FrontfaceCulling)\r
1792                 {\r
1793                         CacheHandler->setCullFaceFunc(GL_FRONT);\r
1794                         CacheHandler->setCullFace(true);\r
1795                 }\r
1796                 else\r
1797                 {\r
1798                         CacheHandler->setCullFace(false);\r
1799                 }\r
1800 \r
1801                 // Color Mask\r
1802                 CacheHandler->setColorMask(material.ColorMask);\r
1803 \r
1804                 // Blend Equation\r
1805                 if (material.BlendOperation == EBO_NONE)\r
1806                         CacheHandler->setBlend(false);\r
1807                 else\r
1808                 {\r
1809                         CacheHandler->setBlend(true);\r
1810 \r
1811                         switch (material.BlendOperation)\r
1812                         {\r
1813                         case EBO_ADD:\r
1814                                 CacheHandler->setBlendEquation(GL_FUNC_ADD);\r
1815                                 break;\r
1816                         case EBO_SUBTRACT:\r
1817                                 CacheHandler->setBlendEquation(GL_FUNC_SUBTRACT);\r
1818                                 break;\r
1819                         case EBO_REVSUBTRACT:\r
1820                                 CacheHandler->setBlendEquation(GL_FUNC_REVERSE_SUBTRACT);\r
1821                                 break;\r
1822                         default:\r
1823                                 break;\r
1824                         }\r
1825                 }\r
1826 \r
1827                 // Blend Factor\r
1828                 if (IR(material.BlendFactor) & 0xFFFFFFFF       // TODO: why the & 0xFFFFFFFF?\r
1829                         && material.MaterialType != EMT_ONETEXTURE_BLEND\r
1830                 )\r
1831                 {\r
1832                     E_BLEND_FACTOR srcRGBFact = EBF_ZERO;\r
1833                     E_BLEND_FACTOR dstRGBFact = EBF_ZERO;\r
1834                     E_BLEND_FACTOR srcAlphaFact = EBF_ZERO;\r
1835                     E_BLEND_FACTOR dstAlphaFact = EBF_ZERO;\r
1836                     E_MODULATE_FUNC modulo = EMFN_MODULATE_1X;\r
1837                     u32 alphaSource = 0;\r
1838 \r
1839                     unpack_textureBlendFuncSeparate(srcRGBFact, dstRGBFact, srcAlphaFact, dstAlphaFact, modulo, alphaSource, material.BlendFactor);\r
1840 \r
1841                         CacheHandler->setBlendFuncSeparate(getGLBlend(srcRGBFact), getGLBlend(dstRGBFact),\r
1842                                 getGLBlend(srcAlphaFact), getGLBlend(dstAlphaFact));\r
1843                 }\r
1844 \r
1845                 // TODO: Polygon Offset. Not sure if it was left out deliberately or if it won't work with this driver.\r
1846 \r
1847                 if (resetAllRenderStates || lastmaterial.Thickness != material.Thickness)\r
1848                         glLineWidth(core::clamp(static_cast<GLfloat>(material.Thickness), DimAliasedLine[0], DimAliasedLine[1]));\r
1849 \r
1850                 // Anti aliasing\r
1851                 if (resetAllRenderStates || lastmaterial.AntiAliasing != material.AntiAliasing)\r
1852                 {\r
1853                         if (material.AntiAliasing & EAAM_ALPHA_TO_COVERAGE)\r
1854                                 glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);\r
1855                         else if (lastmaterial.AntiAliasing & EAAM_ALPHA_TO_COVERAGE)\r
1856                                 glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);\r
1857                 }\r
1858 \r
1859                 // Texture parameters\r
1860                 setTextureRenderStates(material, resetAllRenderStates);\r
1861         }\r
1862 \r
1863         //! Compare in SMaterial doesn't check texture parameters, so we should call this on each OnRender call.\r
1864         void COGLES2Driver::setTextureRenderStates(const SMaterial& material, bool resetAllRenderstates)\r
1865         {\r
1866                 IRR_PROFILE(CProfileScope p1(EPID_ES2_SET_RENDERSTATE_TEXTURE);)\r
1867 \r
1868                 // Set textures to TU/TIU and apply filters to them\r
1869 \r
1870                 for (s32 i = Feature.MaxTextureUnits - 1; i >= 0; --i)\r
1871                 {\r
1872                         const COGLES2Texture* tmpTexture = CacheHandler->getTextureCache()[i];\r
1873 \r
1874                         if (!tmpTexture)\r
1875                                 continue;\r
1876 \r
1877                         GLenum tmpTextureType = tmpTexture->getOpenGLTextureType();\r
1878 \r
1879                         CacheHandler->setActiveTexture(GL_TEXTURE0 + i);\r
1880 \r
1881                         if (resetAllRenderstates)\r
1882                                 tmpTexture->getStatesCache().IsCached = false;\r
1883 \r
1884                         if (!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].BilinearFilter != tmpTexture->getStatesCache().BilinearFilter ||\r
1885                                 material.TextureLayer[i].TrilinearFilter != tmpTexture->getStatesCache().TrilinearFilter)\r
1886                         {\r
1887                                 glTexParameteri(tmpTextureType, GL_TEXTURE_MAG_FILTER,\r
1888                                         (material.TextureLayer[i].BilinearFilter || material.TextureLayer[i].TrilinearFilter) ? GL_LINEAR : GL_NEAREST);\r
1889 \r
1890                                 tmpTexture->getStatesCache().BilinearFilter = material.TextureLayer[i].BilinearFilter;\r
1891                                 tmpTexture->getStatesCache().TrilinearFilter = material.TextureLayer[i].TrilinearFilter;\r
1892                         }\r
1893 \r
1894                         if (material.UseMipMaps && tmpTexture->hasMipMaps())\r
1895                         {\r
1896                                 if (!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].BilinearFilter != tmpTexture->getStatesCache().BilinearFilter ||\r
1897                                         material.TextureLayer[i].TrilinearFilter != tmpTexture->getStatesCache().TrilinearFilter || !tmpTexture->getStatesCache().MipMapStatus)\r
1898                                 {\r
1899                                         glTexParameteri(tmpTextureType, GL_TEXTURE_MIN_FILTER,\r
1900                                                 material.TextureLayer[i].TrilinearFilter ? GL_LINEAR_MIPMAP_LINEAR :\r
1901                                                 material.TextureLayer[i].BilinearFilter ? GL_LINEAR_MIPMAP_NEAREST :\r
1902                                                 GL_NEAREST_MIPMAP_NEAREST);\r
1903 \r
1904                                         tmpTexture->getStatesCache().BilinearFilter = material.TextureLayer[i].BilinearFilter;\r
1905                                         tmpTexture->getStatesCache().TrilinearFilter = material.TextureLayer[i].TrilinearFilter;\r
1906                                         tmpTexture->getStatesCache().MipMapStatus = true;\r
1907                                 }\r
1908                         }\r
1909                         else\r
1910                         {\r
1911                                 if (!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].BilinearFilter != tmpTexture->getStatesCache().BilinearFilter ||\r
1912                                         material.TextureLayer[i].TrilinearFilter != tmpTexture->getStatesCache().TrilinearFilter || tmpTexture->getStatesCache().MipMapStatus)\r
1913                                 {\r
1914                                         glTexParameteri(tmpTextureType, GL_TEXTURE_MIN_FILTER,\r
1915                                                 (material.TextureLayer[i].BilinearFilter || material.TextureLayer[i].TrilinearFilter) ? GL_LINEAR : GL_NEAREST);\r
1916 \r
1917                                         tmpTexture->getStatesCache().BilinearFilter = material.TextureLayer[i].BilinearFilter;\r
1918                                         tmpTexture->getStatesCache().TrilinearFilter = material.TextureLayer[i].TrilinearFilter;\r
1919                                         tmpTexture->getStatesCache().MipMapStatus = false;\r
1920                                 }\r
1921                         }\r
1922 \r
1923         #ifdef GL_EXT_texture_filter_anisotropic\r
1924                         if (FeatureAvailable[COGLESCoreExtensionHandler::IRR_GL_EXT_texture_filter_anisotropic] &&\r
1925                                 (!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].AnisotropicFilter != tmpTexture->getStatesCache().AnisotropicFilter))\r
1926                         {\r
1927                                 glTexParameteri(tmpTextureType, GL_TEXTURE_MAX_ANISOTROPY_EXT,\r
1928                                         material.TextureLayer[i].AnisotropicFilter>1 ? core::min_(MaxAnisotropy, material.TextureLayer[i].AnisotropicFilter) : 1);\r
1929 \r
1930                                 tmpTexture->getStatesCache().AnisotropicFilter = material.TextureLayer[i].AnisotropicFilter;\r
1931                         }\r
1932         #endif\r
1933 \r
1934                         if (!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].TextureWrapU != tmpTexture->getStatesCache().WrapU)\r
1935                         {\r
1936                                 glTexParameteri(tmpTextureType, GL_TEXTURE_WRAP_S, getTextureWrapMode(material.TextureLayer[i].TextureWrapU));\r
1937                                 tmpTexture->getStatesCache().WrapU = material.TextureLayer[i].TextureWrapU;\r
1938                         }\r
1939 \r
1940                         if (!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].TextureWrapV != tmpTexture->getStatesCache().WrapV)\r
1941                         {\r
1942                                 glTexParameteri(tmpTextureType, GL_TEXTURE_WRAP_T, getTextureWrapMode(material.TextureLayer[i].TextureWrapV));\r
1943                                 tmpTexture->getStatesCache().WrapV = material.TextureLayer[i].TextureWrapV;\r
1944                         }\r
1945 \r
1946                         tmpTexture->getStatesCache().IsCached = true;\r
1947                 }\r
1948         }\r
1949 \r
1950 \r
1951         // Get OpenGL ES2.0 texture wrap mode from Irrlicht wrap mode.\r
1952         GLint COGLES2Driver::getTextureWrapMode(u8 clamp) const\r
1953         {\r
1954                 switch (clamp)\r
1955                 {\r
1956                         case ETC_CLAMP:\r
1957                         case ETC_CLAMP_TO_EDGE:\r
1958                         case ETC_CLAMP_TO_BORDER:\r
1959                                 return GL_CLAMP_TO_EDGE;\r
1960                         case ETC_MIRROR:\r
1961                                 return GL_REPEAT;\r
1962                         default:\r
1963                                 return GL_REPEAT;\r
1964                 }\r
1965         }\r
1966 \r
1967 \r
1968         //! sets the needed renderstates\r
1969         void COGLES2Driver::setRenderStates2DMode(bool alpha, bool texture, bool alphaChannel)\r
1970         {\r
1971                 IRR_PROFILE(CProfileScope p1(EPID_ES2_SET_RENDERSTATE_2D);)\r
1972 \r
1973                 if ( LockRenderStateMode )\r
1974                         return;\r
1975 \r
1976                 COGLES2Renderer2D* nextActiveRenderer = texture ? MaterialRenderer2DTexture : MaterialRenderer2DNoTexture;\r
1977 \r
1978                 if (CurrentRenderMode != ERM_2D)\r
1979                 {\r
1980                         // unset last 3d material\r
1981                         if (CurrentRenderMode == ERM_3D)\r
1982                         {\r
1983                                 if (static_cast<u32>(LastMaterial.MaterialType) < MaterialRenderers.size())\r
1984                                         MaterialRenderers[LastMaterial.MaterialType].Renderer->OnUnsetMaterial();\r
1985                         }\r
1986 \r
1987                         CurrentRenderMode = ERM_2D;\r
1988                 }\r
1989                 else if ( MaterialRenderer2DActive && MaterialRenderer2DActive != nextActiveRenderer)\r
1990                 {\r
1991                         MaterialRenderer2DActive->OnUnsetMaterial();\r
1992                 }\r
1993 \r
1994                 MaterialRenderer2DActive = nextActiveRenderer;\r
1995 \r
1996                 MaterialRenderer2DActive->OnSetMaterial(Material, LastMaterial, true, 0);\r
1997                 LastMaterial = Material;\r
1998                 CacheHandler->correctCacheMaterial(LastMaterial);\r
1999 \r
2000                 // no alphaChannel without texture\r
2001                 alphaChannel &= texture;\r
2002 \r
2003                 if (alphaChannel || alpha)\r
2004                 {\r
2005                         CacheHandler->setBlend(true);\r
2006                         CacheHandler->setBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\r
2007                 }\r
2008                 else\r
2009                         CacheHandler->setBlend(false);\r
2010 \r
2011                 Material.setTexture(0, const_cast<COGLES2Texture*>(CacheHandler->getTextureCache().get(0)));\r
2012                 setTransform(ETS_TEXTURE_0, core::IdentityMatrix);\r
2013 \r
2014                 if (texture)\r
2015                 {\r
2016                         if (OverrideMaterial2DEnabled)\r
2017                                 setTextureRenderStates(OverrideMaterial2D, false);\r
2018                         else\r
2019                                 setTextureRenderStates(InitMaterial2D, false);\r
2020                 }\r
2021 \r
2022                 MaterialRenderer2DActive->OnRender(this, video::EVT_STANDARD);\r
2023         }\r
2024 \r
2025 \r
2026         void COGLES2Driver::chooseMaterial2D()\r
2027         {\r
2028                 if (!OverrideMaterial2DEnabled)\r
2029                         Material = InitMaterial2D;\r
2030 \r
2031                 if (OverrideMaterial2DEnabled)\r
2032                 {\r
2033                         OverrideMaterial2D.Lighting=false;\r
2034                         OverrideMaterial2D.ZWriteEnable=EZW_OFF;\r
2035                         OverrideMaterial2D.ZBuffer=ECFN_DISABLED; // it will be ECFN_DISABLED after merge\r
2036                         OverrideMaterial2D.Lighting=false;\r
2037 \r
2038                         Material = OverrideMaterial2D;\r
2039                 }\r
2040         }\r
2041 \r
2042 \r
2043         //! \return Returns the name of the video driver.\r
2044         const wchar_t* COGLES2Driver::getName() const\r
2045         {\r
2046                 return Name.c_str();\r
2047         }\r
2048 \r
2049 \r
2050         //! deletes all dynamic lights there are\r
2051         void COGLES2Driver::deleteAllDynamicLights()\r
2052         {\r
2053                 RequestedLights.clear();\r
2054                 CNullDriver::deleteAllDynamicLights();\r
2055         }\r
2056 \r
2057 \r
2058         //! adds a dynamic light\r
2059         s32 COGLES2Driver::addDynamicLight(const SLight& light)\r
2060         {\r
2061                 CNullDriver::addDynamicLight(light);\r
2062 \r
2063                 RequestedLights.push_back(RequestedLight(light));\r
2064 \r
2065                 u32 newLightIndex = RequestedLights.size() - 1;\r
2066 \r
2067                 return (s32)newLightIndex;\r
2068         }\r
2069 \r
2070         //! Turns a dynamic light on or off\r
2071         //! \param lightIndex: the index returned by addDynamicLight\r
2072         //! \param turnOn: true to turn the light on, false to turn it off\r
2073         void COGLES2Driver::turnLightOn(s32 lightIndex, bool turnOn)\r
2074         {\r
2075                 if (lightIndex < 0 || lightIndex >= (s32)RequestedLights.size())\r
2076                         return;\r
2077 \r
2078                 RequestedLight & requestedLight = RequestedLights[lightIndex];\r
2079                 requestedLight.DesireToBeOn = turnOn;\r
2080         }\r
2081 \r
2082 \r
2083         //! returns the maximal amount of dynamic lights the device can handle\r
2084         u32 COGLES2Driver::getMaximalDynamicLightAmount() const\r
2085         {\r
2086                 return 8;\r
2087         }\r
2088 \r
2089         void COGLES2Driver::setViewPort(const core::rect<s32>& area)\r
2090         {\r
2091                 core::rect<s32> vp = area;\r
2092                 core::rect<s32> rendert(0, 0, getCurrentRenderTargetSize().Width, getCurrentRenderTargetSize().Height);\r
2093                 vp.clipAgainst(rendert);\r
2094 \r
2095                 if (vp.getHeight() > 0 && vp.getWidth() > 0)\r
2096                         CacheHandler->setViewport(vp.UpperLeftCorner.X, getCurrentRenderTargetSize().Height - vp.UpperLeftCorner.Y - vp.getHeight(), vp.getWidth(), vp.getHeight());\r
2097 \r
2098                 ViewPort = vp;\r
2099         }\r
2100 \r
2101 \r
2102         void COGLES2Driver::setViewPortRaw(u32 width, u32 height)\r
2103         {\r
2104                 CacheHandler->setViewport(0, 0, width, height);\r
2105                 ViewPort = core::recti(0, 0, width, height);\r
2106         }\r
2107 \r
2108 \r
2109         //! Draws a shadow volume into the stencil buffer.\r
2110         void COGLES2Driver::drawStencilShadowVolume(const core::array<core::vector3df>& triangles, bool zfail, u32 debugDataVisible)\r
2111         {\r
2112                 IRR_PROFILE(CProfileScope p1(EPID_ES2_DRAW_SHADOW);)\r
2113 \r
2114                 const u32 count=triangles.size();\r
2115                 if (!StencilBuffer || !count)\r
2116                         return;\r
2117 \r
2118                 bool fog = Material.FogEnable;\r
2119                 bool lighting = Material.Lighting;\r
2120                 E_MATERIAL_TYPE materialType = Material.MaterialType;\r
2121 \r
2122                 Material.FogEnable = false;\r
2123                 Material.Lighting = false;\r
2124                 Material.MaterialType = EMT_SOLID; // Dedicated material in future.\r
2125 \r
2126                 setRenderStates3DMode();\r
2127 \r
2128                 CacheHandler->setDepthTest(true);\r
2129                 CacheHandler->setDepthFunc(GL_LESS);\r
2130                 CacheHandler->setDepthMask(false);\r
2131 \r
2132                 if (!(debugDataVisible & (scene::EDS_SKELETON|scene::EDS_MESH_WIRE_OVERLAY)))\r
2133                 {\r
2134                         CacheHandler->setColorMask(ECP_NONE);\r
2135                         glEnable(GL_STENCIL_TEST);\r
2136                 }\r
2137 \r
2138                 glEnableVertexAttribArray(EVA_POSITION);\r
2139                 glVertexAttribPointer(EVA_POSITION, 3, GL_FLOAT, false, sizeof(core::vector3df), triangles.const_pointer());\r
2140 \r
2141                 glStencilMask(~0);\r
2142                 glStencilFunc(GL_ALWAYS, 0, ~0);\r
2143 \r
2144                 GLenum decr = GL_DECR;\r
2145                 GLenum incr = GL_INCR;\r
2146 \r
2147 #if defined(GL_OES_stencil_wrap)\r
2148                 if (FeatureAvailable[IRR_OES_stencil_wrap])\r
2149                 {\r
2150                         decr = GL_DECR_WRAP_OES;\r
2151                         incr = GL_INCR_WRAP_OES;\r
2152                 }\r
2153 #endif\r
2154 \r
2155                 CacheHandler->setCullFace(true);\r
2156 \r
2157                 if (zfail)\r
2158                 {\r
2159                         CacheHandler->setCullFaceFunc(GL_FRONT);\r
2160                         glStencilOp(GL_KEEP, incr, GL_KEEP);\r
2161                         glDrawArrays(GL_TRIANGLES, 0, count);\r
2162 \r
2163                         CacheHandler->setCullFaceFunc(GL_BACK);\r
2164                         glStencilOp(GL_KEEP, decr, GL_KEEP);\r
2165                         glDrawArrays(GL_TRIANGLES, 0, count);\r
2166                 }\r
2167                 else // zpass\r
2168                 {\r
2169                         CacheHandler->setCullFaceFunc(GL_BACK);\r
2170                         glStencilOp(GL_KEEP, GL_KEEP, incr);\r
2171                         glDrawArrays(GL_TRIANGLES, 0, count);\r
2172 \r
2173                         CacheHandler->setCullFaceFunc(GL_FRONT);\r
2174                         glStencilOp(GL_KEEP, GL_KEEP, decr);\r
2175                         glDrawArrays(GL_TRIANGLES, 0, count);\r
2176                 }\r
2177 \r
2178                 glDisableVertexAttribArray(EVA_POSITION);\r
2179 \r
2180                 glDisable(GL_STENCIL_TEST);\r
2181 \r
2182                 Material.FogEnable = fog;\r
2183                 Material.Lighting = lighting;\r
2184                 Material.MaterialType = materialType;\r
2185         }\r
2186 \r
2187 \r
2188         void COGLES2Driver::drawStencilShadow(bool clearStencilBuffer,\r
2189                         video::SColor leftUpEdge, video::SColor rightUpEdge,\r
2190                         video::SColor leftDownEdge, video::SColor rightDownEdge)\r
2191         {\r
2192                 IRR_PROFILE(CProfileScope p1(EPID_ES2_DRAW_SHADOW);)\r
2193 \r
2194                 if (!StencilBuffer)\r
2195                         return;\r
2196 \r
2197                 chooseMaterial2D();\r
2198                 setMaterialTexture(0, 0);\r
2199 \r
2200                 setRenderStates2DMode(true, false, false);\r
2201 \r
2202                 CacheHandler->setDepthMask(false);\r
2203                 CacheHandler->setColorMask(ECP_ALL);\r
2204 \r
2205                 CacheHandler->setBlend(true);\r
2206                 CacheHandler->setBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\r
2207 \r
2208                 glEnable(GL_STENCIL_TEST);\r
2209                 glStencilFunc(GL_NOTEQUAL, 0, ~0);\r
2210                 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);\r
2211 \r
2212                 u16 indices[] = {0, 1, 2, 3};\r
2213                 S3DVertex vertices[4];\r
2214                 vertices[0] = S3DVertex(-1.f, 1.f, 0.9f, 0, 0, 1, leftDownEdge, 0, 0);\r
2215                 vertices[1] = S3DVertex(1.f, 1.f, 0.9f, 0, 0, 1, leftUpEdge, 0, 0);\r
2216                 vertices[2] = S3DVertex(1.f, -1.f, 0.9f, 0, 0, 1, rightUpEdge, 0, 0);\r
2217                 vertices[3] = S3DVertex(-1.f, -1.f, 0.9f, 0, 0, 1, rightDownEdge, 0, 0);\r
2218 \r
2219                 glEnableVertexAttribArray(EVA_POSITION);\r
2220                 glEnableVertexAttribArray(EVA_COLOR);\r
2221                 glVertexAttribPointer(EVA_POSITION, 3, GL_FLOAT, false, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Pos);\r
2222                 glVertexAttribPointer(EVA_COLOR, 4, GL_UNSIGNED_BYTE, true, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Color);\r
2223                 glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, indices);\r
2224                 glDisableVertexAttribArray(EVA_COLOR);\r
2225                 glDisableVertexAttribArray(EVA_POSITION);\r
2226 \r
2227                 if (clearStencilBuffer)\r
2228                         glClear(GL_STENCIL_BUFFER_BIT);\r
2229 \r
2230                 glDisable(GL_STENCIL_TEST);\r
2231         }\r
2232 \r
2233 \r
2234         //! Draws a 3d line.\r
2235         void COGLES2Driver::draw3DLine(const core::vector3df& start,\r
2236                         const core::vector3df& end, SColor color)\r
2237         {\r
2238                 IRR_PROFILE(CProfileScope p1(EPID_ES2_DRAW_3DLINE);)\r
2239 \r
2240                 setRenderStates3DMode();\r
2241 \r
2242                 u16 indices[] = {0, 1};\r
2243                 S3DVertex vertices[2];\r
2244                 vertices[0] = S3DVertex(start.X, start.Y, start.Z, 0, 0, 1, color, 0, 0);\r
2245                 vertices[1] = S3DVertex(end.X, end.Y, end.Z, 0, 0, 1, color, 0, 0);\r
2246 \r
2247                 glEnableVertexAttribArray(EVA_POSITION);\r
2248                 glEnableVertexAttribArray(EVA_COLOR);\r
2249                 glVertexAttribPointer(EVA_POSITION, 3, GL_FLOAT, false, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Pos);\r
2250                 glVertexAttribPointer(EVA_COLOR, 4, GL_UNSIGNED_BYTE, true, sizeof(S3DVertex), &(static_cast<const S3DVertex*>(vertices))[0].Color);\r
2251                 glDrawElements(GL_LINES, 2, GL_UNSIGNED_SHORT, indices);\r
2252                 glDisableVertexAttribArray(EVA_COLOR);\r
2253                 glDisableVertexAttribArray(EVA_POSITION);\r
2254         }\r
2255 \r
2256 \r
2257         //! Only used by the internal engine. Used to notify the driver that\r
2258         //! the window was resized.\r
2259         void COGLES2Driver::OnResize(const core::dimension2d<u32>& size)\r
2260         {\r
2261                 CNullDriver::OnResize(size);\r
2262                 CacheHandler->setViewport(0, 0, size.Width, size.Height);\r
2263                 Transformation3DChanged = true;\r
2264         }\r
2265 \r
2266 \r
2267         //! Returns type of video driver\r
2268         E_DRIVER_TYPE COGLES2Driver::getDriverType() const\r
2269         {\r
2270                 return EDT_OGLES2;\r
2271         }\r
2272 \r
2273 \r
2274         //! returns color format\r
2275         ECOLOR_FORMAT COGLES2Driver::getColorFormat() const\r
2276         {\r
2277                 return ColorFormat;\r
2278         }\r
2279 \r
2280 \r
2281         //! Get a vertex shader constant index.\r
2282         s32 COGLES2Driver::getVertexShaderConstantID(const c8* name)\r
2283         {\r
2284                 return getPixelShaderConstantID(name);\r
2285         }\r
2286 \r
2287         //! Get a pixel shader constant index.\r
2288         s32 COGLES2Driver::getPixelShaderConstantID(const c8* name)\r
2289         {\r
2290                 os::Printer::log("Error: Please call services->getPixelShaderConstantID(), not VideoDriver->getPixelShaderConstantID().");\r
2291                 return -1;\r
2292         }\r
2293 \r
2294         //! Sets a vertex shader constant.\r
2295         void COGLES2Driver::setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount)\r
2296         {\r
2297                 os::Printer::log("Error: Please call services->setVertexShaderConstant(), not VideoDriver->setPixelShaderConstant().");\r
2298         }\r
2299 \r
2300         //! Sets a pixel shader constant.\r
2301         void COGLES2Driver::setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount)\r
2302         {\r
2303                 os::Printer::log("Error: Please call services->setPixelShaderConstant(), not VideoDriver->setPixelShaderConstant().");\r
2304         }\r
2305 \r
2306         //! Sets a constant for the vertex shader based on an index.\r
2307         bool COGLES2Driver::setVertexShaderConstant(s32 index, const f32* floats, int count)\r
2308         {\r
2309                 os::Printer::log("Error: Please call services->setVertexShaderConstant(), not VideoDriver->setVertexShaderConstant().");\r
2310                 return false;\r
2311         }\r
2312 \r
2313         //! Int interface for the above.\r
2314         bool COGLES2Driver::setVertexShaderConstant(s32 index, const s32* ints, int count)\r
2315         {\r
2316                 os::Printer::log("Error: Please call services->setVertexShaderConstant(), not VideoDriver->setVertexShaderConstant().");\r
2317                 return false;\r
2318         }\r
2319 \r
2320         bool COGLES2Driver::setVertexShaderConstant(s32 index, const u32* ints, int count)\r
2321         {\r
2322                 os::Printer::log("Error: Please call services->setVertexShaderConstant(), not VideoDriver->setVertexShaderConstant().");\r
2323                 return false;\r
2324         }\r
2325 \r
2326         //! Sets a constant for the pixel shader based on an index.\r
2327         bool COGLES2Driver::setPixelShaderConstant(s32 index, const f32* floats, int count)\r
2328         {\r
2329                 os::Printer::log("Error: Please call services->setPixelShaderConstant(), not VideoDriver->setPixelShaderConstant().");\r
2330                 return false;\r
2331         }\r
2332 \r
2333         //! Int interface for the above.\r
2334         bool COGLES2Driver::setPixelShaderConstant(s32 index, const s32* ints, int count)\r
2335         {\r
2336                 os::Printer::log("Error: Please call services->setPixelShaderConstant(), not VideoDriver->setPixelShaderConstant().");\r
2337                 return false;\r
2338         }\r
2339 \r
2340         bool COGLES2Driver::setPixelShaderConstant(s32 index, const u32* ints, int count)\r
2341         {\r
2342                 os::Printer::log("Error: Please call services->setPixelShaderConstant(), not VideoDriver->setPixelShaderConstant().");\r
2343                 return false;\r
2344         }\r
2345 \r
2346         //! Adds a new material renderer to the VideoDriver, using pixel and/or\r
2347         //! vertex shaders to render geometry.\r
2348         s32 COGLES2Driver::addShaderMaterial(const c8* vertexShaderProgram,\r
2349                         const c8* pixelShaderProgram,\r
2350                         IShaderConstantSetCallBack* callback,\r
2351                         E_MATERIAL_TYPE baseMaterial, s32 userData)\r
2352         {\r
2353                 os::Printer::log("No shader support.");\r
2354                 return -1;\r
2355         }\r
2356 \r
2357 \r
2358         //! Adds a new material renderer to the VideoDriver, using GLSL to render geometry.\r
2359         s32 COGLES2Driver::addHighLevelShaderMaterial(\r
2360                         const c8* vertexShaderProgram,\r
2361                         const c8* vertexShaderEntryPointName,\r
2362                         E_VERTEX_SHADER_TYPE vsCompileTarget,\r
2363                         const c8* pixelShaderProgram,\r
2364                         const c8* pixelShaderEntryPointName,\r
2365                         E_PIXEL_SHADER_TYPE psCompileTarget,\r
2366                         const c8* geometryShaderProgram,\r
2367                         const c8* geometryShaderEntryPointName,\r
2368                         E_GEOMETRY_SHADER_TYPE gsCompileTarget,\r
2369                         scene::E_PRIMITIVE_TYPE inType,\r
2370                         scene::E_PRIMITIVE_TYPE outType,\r
2371                         u32 verticesOut,\r
2372                         IShaderConstantSetCallBack* callback,\r
2373                         E_MATERIAL_TYPE baseMaterial,\r
2374                         s32 userData)\r
2375         {\r
2376                 s32 nr = -1;\r
2377                 COGLES2MaterialRenderer* r = new COGLES2MaterialRenderer(\r
2378                         this, nr, vertexShaderProgram,\r
2379                         pixelShaderProgram,\r
2380                         callback, baseMaterial, userData);\r
2381 \r
2382                 r->drop();\r
2383                 return nr;\r
2384         }\r
2385 \r
2386         //! Returns a pointer to the IVideoDriver interface. (Implementation for\r
2387         //! IMaterialRendererServices)\r
2388         IVideoDriver* COGLES2Driver::getVideoDriver()\r
2389         {\r
2390                 return this;\r
2391         }\r
2392 \r
2393 \r
2394         //! Returns pointer to the IGPUProgrammingServices interface.\r
2395         IGPUProgrammingServices* COGLES2Driver::getGPUProgrammingServices()\r
2396         {\r
2397                 return this;\r
2398         }\r
2399 \r
2400         ITexture* COGLES2Driver::addRenderTargetTexture(const core::dimension2d<u32>& size,\r
2401                 const io::path& name, const ECOLOR_FORMAT format)\r
2402         {\r
2403                 //disable mip-mapping\r
2404                 bool generateMipLevels = getTextureCreationFlag(ETCF_CREATE_MIP_MAPS);\r
2405                 setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, false);\r
2406 \r
2407                 COGLES2Texture* renderTargetTexture = new COGLES2Texture(name, size, ETT_2D, format, this);\r
2408                 addTexture(renderTargetTexture);\r
2409                 renderTargetTexture->drop();\r
2410 \r
2411                 //restore mip-mapping\r
2412                 setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, generateMipLevels);\r
2413 \r
2414                 return renderTargetTexture;\r
2415         }\r
2416 \r
2417         ITexture* COGLES2Driver::addRenderTargetTextureCubemap(const irr::u32 sideLen, const io::path& name, const ECOLOR_FORMAT format)\r
2418         {\r
2419                 //disable mip-mapping\r
2420                 bool generateMipLevels = getTextureCreationFlag(ETCF_CREATE_MIP_MAPS);\r
2421                 setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, false);\r
2422 \r
2423                 bool supportForFBO = (Feature.ColorAttachment > 0);\r
2424 \r
2425                 const core::dimension2d<u32> size(sideLen, sideLen);\r
2426                 core::dimension2du destSize(size);\r
2427 \r
2428                 if (!supportForFBO)\r
2429                 {\r
2430                         destSize = core::dimension2d<u32>(core::min_(size.Width, ScreenSize.Width), core::min_(size.Height, ScreenSize.Height));\r
2431                         destSize = destSize.getOptimalSize((size == size.getOptimalSize()), false, false);\r
2432                 }\r
2433 \r
2434                 COGLES2Texture* renderTargetTexture = new COGLES2Texture(name, destSize, ETT_CUBEMAP, format, this);\r
2435                 addTexture(renderTargetTexture);\r
2436                 renderTargetTexture->drop();\r
2437 \r
2438                 //restore mip-mapping\r
2439                 setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, generateMipLevels);\r
2440 \r
2441                 return renderTargetTexture;\r
2442         }\r
2443 \r
2444 \r
2445         //! Returns the maximum amount of primitives\r
2446         u32 COGLES2Driver::getMaximalPrimitiveCount() const\r
2447         {\r
2448                 return 65535;\r
2449         }\r
2450 \r
2451         bool COGLES2Driver::setRenderTargetEx(IRenderTarget* target, u16 clearFlag, SColor clearColor, f32 clearDepth, u8 clearStencil)\r
2452         {\r
2453                 if (target && target->getDriverType() != EDT_OGLES2  && target->getDriverType() != EDT_WEBGL1)\r
2454                 {\r
2455                         os::Printer::log("Fatal Error: Tried to set a render target not owned by OGLES2 driver.", ELL_ERROR);\r
2456                         return false;\r
2457                 }\r
2458 \r
2459                 core::dimension2d<u32> destRenderTargetSize(0, 0);\r
2460 \r
2461                 if (target)\r
2462                 {\r
2463                         COGLES2RenderTarget* renderTarget = static_cast<COGLES2RenderTarget*>(target);\r
2464 \r
2465                         CacheHandler->setFBO(renderTarget->getBufferID());\r
2466                         renderTarget->update();\r
2467 \r
2468                         destRenderTargetSize = renderTarget->getSize();\r
2469 \r
2470                         setViewPortRaw(destRenderTargetSize.Width, destRenderTargetSize.Height);\r
2471                 }\r
2472                 else\r
2473                 {\r
2474                         CacheHandler->setFBO(0);\r
2475 \r
2476                         destRenderTargetSize = core::dimension2d<u32>(0, 0);\r
2477 \r
2478                         setViewPortRaw(ScreenSize.Width, ScreenSize.Height);\r
2479                 }\r
2480 \r
2481                 if (CurrentRenderTargetSize != destRenderTargetSize)\r
2482                 {\r
2483                         CurrentRenderTargetSize = destRenderTargetSize;\r
2484 \r
2485                         Transformation3DChanged = true;\r
2486                 }\r
2487 \r
2488                 CurrentRenderTarget = target;\r
2489 \r
2490                 clearBuffers(clearFlag, clearColor, clearDepth, clearStencil);\r
2491 \r
2492                 return true;\r
2493         }\r
2494 \r
2495         void COGLES2Driver::clearBuffers(u16 flag, SColor color, f32 depth, u8 stencil)\r
2496         {\r
2497                 GLbitfield mask = 0;\r
2498                 u8 colorMask = 0;\r
2499                 bool depthMask = false;\r
2500 \r
2501                 CacheHandler->getColorMask(colorMask);\r
2502                 CacheHandler->getDepthMask(depthMask);\r
2503 \r
2504                 if (flag & ECBF_COLOR)\r
2505                 {\r
2506                         CacheHandler->setColorMask(ECP_ALL);\r
2507 \r
2508                         const f32 inv = 1.0f / 255.0f;\r
2509                         glClearColor(color.getRed() * inv, color.getGreen() * inv,\r
2510                                 color.getBlue() * inv, color.getAlpha() * inv);\r
2511 \r
2512                         mask |= GL_COLOR_BUFFER_BIT;\r
2513                 }\r
2514 \r
2515                 if (flag & ECBF_DEPTH)\r
2516                 {\r
2517                         CacheHandler->setDepthMask(true);\r
2518                         glClearDepthf(depth);\r
2519                         mask |= GL_DEPTH_BUFFER_BIT;\r
2520                 }\r
2521 \r
2522                 if (flag & ECBF_STENCIL)\r
2523                 {\r
2524                         glClearStencil(stencil);\r
2525                         mask |= GL_STENCIL_BUFFER_BIT;\r
2526                 }\r
2527 \r
2528                 if (mask)\r
2529                         glClear(mask);\r
2530 \r
2531                 CacheHandler->setColorMask(colorMask);\r
2532                 CacheHandler->setDepthMask(depthMask);\r
2533         }\r
2534 \r
2535 \r
2536         //! Returns an image created from the last rendered frame.\r
2537         // We want to read the front buffer to get the latest render finished.\r
2538         // This is not possible under ogl-es, though, so one has to call this method\r
2539         // outside of the render loop only.\r
2540         IImage* COGLES2Driver::createScreenShot(video::ECOLOR_FORMAT format, video::E_RENDER_TARGET target)\r
2541         {\r
2542                 if (target==video::ERT_MULTI_RENDER_TEXTURES || target==video::ERT_RENDER_TEXTURE || target==video::ERT_STEREO_BOTH_BUFFERS)\r
2543                         return 0;\r
2544 \r
2545                 GLint internalformat = GL_RGBA;\r
2546                 GLint type = GL_UNSIGNED_BYTE;\r
2547                 {\r
2548 //                      glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &internalformat);\r
2549 //                      glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &type);\r
2550                         // there's a format we don't support ATM\r
2551                         if (GL_UNSIGNED_SHORT_4_4_4_4 == type)\r
2552                         {\r
2553                                 internalformat = GL_RGBA;\r
2554                                 type = GL_UNSIGNED_BYTE;\r
2555                         }\r
2556                 }\r
2557 \r
2558                 IImage* newImage = 0;\r
2559                 if (GL_RGBA == internalformat)\r
2560                 {\r
2561                         if (GL_UNSIGNED_BYTE == type)\r
2562                                 newImage = new CImage(ECF_A8R8G8B8, ScreenSize);\r
2563                         else\r
2564                                 newImage = new CImage(ECF_A1R5G5B5, ScreenSize);\r
2565                 }\r
2566                 else\r
2567                 {\r
2568                         if (GL_UNSIGNED_BYTE == type)\r
2569                                 newImage = new CImage(ECF_R8G8B8, ScreenSize);\r
2570                         else\r
2571                                 newImage = new CImage(ECF_R5G6B5, ScreenSize);\r
2572                 }\r
2573 \r
2574                 if (!newImage)\r
2575                         return 0;\r
2576 \r
2577                 u8* pixels = static_cast<u8*>(newImage->getData());\r
2578                 if (!pixels)\r
2579                 {\r
2580                         newImage->drop();\r
2581                         return 0;\r
2582                 }\r
2583 \r
2584                 glReadPixels(0, 0, ScreenSize.Width, ScreenSize.Height, internalformat, type, pixels);\r
2585                 testGLError(__LINE__);\r
2586 \r
2587                 // opengl images are horizontally flipped, so we have to fix that here.\r
2588                 const s32 pitch = newImage->getPitch();\r
2589                 u8* p2 = pixels + (ScreenSize.Height - 1) * pitch;\r
2590                 u8* tmpBuffer = new u8[pitch];\r
2591                 for (u32 i = 0; i < ScreenSize.Height; i += 2)\r
2592                 {\r
2593                         memcpy(tmpBuffer, pixels, pitch);\r
2594                         memcpy(pixels, p2, pitch);\r
2595                         memcpy(p2, tmpBuffer, pitch);\r
2596                         pixels += pitch;\r
2597                         p2 -= pitch;\r
2598                 }\r
2599                 delete [] tmpBuffer;\r
2600 \r
2601                 // also GL_RGBA doesn't match the internal encoding of the image (which is BGRA)\r
2602                 if (GL_RGBA == internalformat && GL_UNSIGNED_BYTE == type)\r
2603                 {\r
2604                         pixels = static_cast<u8*>(newImage->getData());\r
2605                         for (u32 i = 0; i < ScreenSize.Height; i++)\r
2606                         {\r
2607                                 for (u32 j = 0; j < ScreenSize.Width; j++)\r
2608                                 {\r
2609                                         u32 c = *(u32*) (pixels + 4 * j);\r
2610                                         *(u32*) (pixels + 4 * j) = (c & 0xFF00FF00) |\r
2611                                                 ((c & 0x00FF0000) >> 16) | ((c & 0x000000FF) << 16);\r
2612                                 }\r
2613                                 pixels += pitch;\r
2614                         }\r
2615                 }\r
2616 \r
2617                 if (testGLError(__LINE__))\r
2618                 {\r
2619                         newImage->drop();\r
2620                         return 0;\r
2621                 }\r
2622                 testGLError(__LINE__);\r
2623                 return newImage;\r
2624         }\r
2625 \r
2626         void COGLES2Driver::removeTexture(ITexture* texture)\r
2627         {\r
2628                 CacheHandler->getTextureCache().remove(texture);\r
2629                 CNullDriver::removeTexture(texture);\r
2630         }\r
2631 \r
2632         //! Set/unset a clipping plane.\r
2633         bool COGLES2Driver::setClipPlane(u32 index, const core::plane3df& plane, bool enable)\r
2634         {\r
2635                 if (index >= UserClipPlane.size())\r
2636                         UserClipPlane.push_back(SUserClipPlane());\r
2637 \r
2638                 UserClipPlane[index].Plane = plane;\r
2639                 UserClipPlane[index].Enabled = enable;\r
2640                 return true;\r
2641         }\r
2642 \r
2643         //! Enable/disable a clipping plane.\r
2644         void COGLES2Driver::enableClipPlane(u32 index, bool enable)\r
2645         {\r
2646                 UserClipPlane[index].Enabled = enable;\r
2647         }\r
2648 \r
2649         //! Get the ClipPlane Count\r
2650         u32 COGLES2Driver::getClipPlaneCount() const\r
2651         {\r
2652                 return UserClipPlane.size();\r
2653         }\r
2654 \r
2655         const core::plane3df& COGLES2Driver::getClipPlane(irr::u32 index) const\r
2656         {\r
2657                 if (index < UserClipPlane.size())\r
2658                         return UserClipPlane[index].Plane;\r
2659                 else\r
2660                 {\r
2661                         _IRR_DEBUG_BREAK_IF(true)       // invalid index\r
2662                         static const core::plane3df dummy;\r
2663                         return dummy;\r
2664                 }\r
2665         }\r
2666 \r
2667         core::dimension2du COGLES2Driver::getMaxTextureSize() const\r
2668         {\r
2669                 return core::dimension2du(MaxTextureSize, MaxTextureSize);\r
2670         }\r
2671 \r
2672         GLenum COGLES2Driver::getGLBlend(E_BLEND_FACTOR factor) const\r
2673         {\r
2674                 static GLenum const blendTable[] =\r
2675                 {\r
2676                         GL_ZERO,\r
2677                         GL_ONE,\r
2678                         GL_DST_COLOR,\r
2679                         GL_ONE_MINUS_DST_COLOR,\r
2680                         GL_SRC_COLOR,\r
2681                         GL_ONE_MINUS_SRC_COLOR,\r
2682                         GL_SRC_ALPHA,\r
2683                         GL_ONE_MINUS_SRC_ALPHA,\r
2684                         GL_DST_ALPHA,\r
2685                         GL_ONE_MINUS_DST_ALPHA,\r
2686                         GL_SRC_ALPHA_SATURATE\r
2687                 };\r
2688 \r
2689                 return blendTable[factor];\r
2690         }\r
2691 \r
2692         GLenum COGLES2Driver::getZBufferBits() const\r
2693         {\r
2694                 // TODO: never used, so not sure what this was really about (zbuffer used by device? Or for RTT's?)\r
2695 \r
2696                 GLenum bits = 0;\r
2697 \r
2698                 switch (Params.ZBufferBits)\r
2699                 {\r
2700                 case 24:\r
2701 #if defined(GL_OES_depth24)\r
2702                         if (queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_OES_depth24))\r
2703                                 bits = GL_DEPTH_COMPONENT24_OES;\r
2704                         else\r
2705 #endif\r
2706                                 bits = GL_DEPTH_COMPONENT16;\r
2707                         break;\r
2708                 case 32:\r
2709 #if defined(GL_OES_depth32)\r
2710                         if (queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_OES_depth32))\r
2711                                 bits = GL_DEPTH_COMPONENT32_OES;\r
2712                         else\r
2713 #endif\r
2714                                 bits = GL_DEPTH_COMPONENT16;\r
2715                         break;\r
2716                 default:\r
2717                         bits = GL_DEPTH_COMPONENT16;\r
2718                         break;\r
2719                 }\r
2720 \r
2721                 return bits;\r
2722         }\r
2723 \r
2724         bool COGLES2Driver::getColorFormatParameters(ECOLOR_FORMAT format, GLint& internalFormat, GLenum& pixelFormat,\r
2725                 GLenum& pixelType, void(**converter)(const void*, s32, void*)) const\r
2726         {\r
2727                 bool supported = false;\r
2728                 pixelFormat = GL_RGBA;\r
2729                 pixelType = GL_UNSIGNED_BYTE;\r
2730                 *converter = 0;\r
2731 \r
2732                 switch (format)\r
2733                 {\r
2734                 case ECF_A1R5G5B5:\r
2735                         supported = true;\r
2736                         pixelFormat = GL_RGBA;\r
2737                         pixelType = GL_UNSIGNED_SHORT_5_5_5_1;\r
2738                         *converter = CColorConverter::convert_A1R5G5B5toR5G5B5A1;\r
2739                         break;\r
2740                 case ECF_R5G6B5:\r
2741                         supported = true;\r
2742                         pixelFormat = GL_RGB;\r
2743                         pixelType = GL_UNSIGNED_SHORT_5_6_5;\r
2744                         break;\r
2745                 case ECF_R8G8B8:\r
2746                         supported = true;\r
2747                         pixelFormat = GL_RGB;\r
2748                         pixelType = GL_UNSIGNED_BYTE;\r
2749                         break;\r
2750                 case ECF_A8R8G8B8:\r
2751                         supported = true;\r
2752                         if (queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_IMG_texture_format_BGRA8888) ||\r
2753                                 queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_EXT_texture_format_BGRA8888) ||\r
2754                                 queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_APPLE_texture_format_BGRA8888))\r
2755                         {\r
2756                                 pixelFormat = GL_BGRA;\r
2757                         }\r
2758                         else\r
2759                         {\r
2760                                 pixelFormat = GL_RGBA;\r
2761                                 *converter = CColorConverter::convert_A8R8G8B8toA8B8G8R8;\r
2762                         }\r
2763                         pixelType = GL_UNSIGNED_BYTE;\r
2764                         break;\r
2765 #ifdef GL_EXT_texture_compression_s3tc\r
2766                 case ECF_DXT1:\r
2767                         supported = true;\r
2768                         pixelFormat = GL_RGBA;\r
2769                         pixelType = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;\r
2770                         break;\r
2771 #endif\r
2772 #ifdef GL_EXT_texture_compression_s3tc\r
2773                 case ECF_DXT2:\r
2774                 case ECF_DXT3:\r
2775                         supported = true;\r
2776                         pixelFormat = GL_RGBA;\r
2777                         pixelType = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;\r
2778                         break;\r
2779 #endif\r
2780 #ifdef GL_EXT_texture_compression_s3tc\r
2781                 case ECF_DXT4:\r
2782                 case ECF_DXT5:\r
2783                         supported = true;\r
2784                         pixelFormat = GL_RGBA;\r
2785                         pixelType = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;\r
2786                         break;\r
2787 #endif\r
2788 #ifdef GL_IMG_texture_compression_pvrtc\r
2789                 case ECF_PVRTC_RGB2:\r
2790                         supported = true;\r
2791                         pixelFormat = GL_RGB;\r
2792                         pixelType = GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;\r
2793                         break;\r
2794 #endif\r
2795 #ifdef GL_IMG_texture_compression_pvrtc\r
2796                 case ECF_PVRTC_ARGB2:\r
2797                         supported = true;\r
2798                         pixelFormat = GL_RGBA;\r
2799                         pixelType = GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;\r
2800                         break;\r
2801 #endif\r
2802 #ifdef GL_IMG_texture_compression_pvrtc\r
2803                 case ECF_PVRTC_RGB4:\r
2804                         supported = true;\r
2805                         pixelFormat = GL_RGB;\r
2806                         pixelType = GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;\r
2807                         break;\r
2808 #endif\r
2809 #ifdef GL_IMG_texture_compression_pvrtc\r
2810                 case ECF_PVRTC_ARGB4:\r
2811                         supported = true;\r
2812                         pixelFormat = GL_RGBA;\r
2813                         pixelType = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;\r
2814                         break;\r
2815 #endif\r
2816 #ifdef GL_IMG_texture_compression_pvrtc2\r
2817                 case ECF_PVRTC2_ARGB2:\r
2818                         supported = true;\r
2819                         pixelFormat = GL_RGBA;\r
2820                         pixelType = GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG;\r
2821                         break;\r
2822 #endif\r
2823 #ifdef GL_IMG_texture_compression_pvrtc2\r
2824                 case ECF_PVRTC2_ARGB4:\r
2825                         supported = true;\r
2826                         pixelFormat = GL_RGBA;\r
2827                         pixelType = GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG;\r
2828                         break;\r
2829 #endif\r
2830 #ifdef GL_OES_compressed_ETC1_RGB8_texture\r
2831                 case ECF_ETC1:\r
2832                         supported = true;\r
2833                         pixelFormat = GL_RGB;\r
2834                         pixelType = GL_ETC1_RGB8_OES;\r
2835                         break;\r
2836 #endif\r
2837 #ifdef GL_ES_VERSION_3_0 // TO-DO - fix when extension name will be available\r
2838                 case ECF_ETC2_RGB:\r
2839                         supported = true;\r
2840                         pixelFormat = GL_RGB;\r
2841                         pixelType = GL_COMPRESSED_RGB8_ETC2;\r
2842                         break;\r
2843 #endif\r
2844 #ifdef GL_ES_VERSION_3_0 // TO-DO - fix when extension name will be available\r
2845                 case ECF_ETC2_ARGB:\r
2846                         supported = true;\r
2847                         pixelFormat = GL_RGBA;\r
2848                         pixelType = GL_COMPRESSED_RGBA8_ETC2_EAC;\r
2849                         break;\r
2850 #endif\r
2851                 case ECF_D16:\r
2852                         supported = true;\r
2853                         pixelFormat = GL_DEPTH_COMPONENT;\r
2854                         pixelType = GL_UNSIGNED_SHORT;\r
2855                         break;\r
2856                 case ECF_D32:\r
2857 #if defined(GL_OES_depth32)\r
2858                         if (queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_OES_depth32))\r
2859                         {\r
2860                                 supported = true;\r
2861                                 pixelFormat = GL_DEPTH_COMPONENT;\r
2862                                 pixelType = GL_UNSIGNED_INT;\r
2863                         }\r
2864 #endif\r
2865                         break;\r
2866                 case ECF_D24S8:\r
2867 #ifdef GL_OES_packed_depth_stencil\r
2868                         if (queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_OES_packed_depth_stencil))\r
2869                         {\r
2870                                 supported = true;\r
2871                                 pixelFormat = GL_DEPTH_STENCIL_OES;\r
2872                                 pixelType = GL_UNSIGNED_INT_24_8_OES;\r
2873                         }\r
2874 #endif\r
2875                         break;\r
2876                 case ECF_R8:\r
2877 #if defined(GL_EXT_texture_rg)\r
2878                         if (queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_EXT_texture_rg))\r
2879                         {\r
2880                                 supported = true;\r
2881                                 pixelFormat = GL_RED_EXT;\r
2882                                 pixelType = GL_UNSIGNED_BYTE;\r
2883                         }\r
2884 #endif\r
2885                         break;\r
2886                 case ECF_R8G8:\r
2887 #if defined(GL_EXT_texture_rg)\r
2888                         if (queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_EXT_texture_rg))\r
2889                         {\r
2890                                 supported = true;\r
2891                                 pixelFormat = GL_RG_EXT;\r
2892                                 pixelType = GL_UNSIGNED_BYTE;\r
2893                         }\r
2894 #endif\r
2895                         break;\r
2896                 case ECF_R16:\r
2897                         break;\r
2898                 case ECF_R16G16:\r
2899                         break;\r
2900                 case ECF_R16F:\r
2901 #if defined(GL_OES_texture_half_float) && defined(GL_EXT_texture_rg)\r
2902                         if (queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_EXT_texture_rg)\r
2903                                 && queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_OES_texture_half_float)\r
2904                                 )\r
2905                         {\r
2906                                 supported = true;\r
2907                                 pixelFormat = GL_RED_EXT;\r
2908                                 pixelType = GL_HALF_FLOAT_OES ;\r
2909                         }\r
2910 #endif\r
2911                         break;\r
2912                 case ECF_G16R16F:\r
2913 #if defined(GL_OES_texture_half_float) && defined(GL_EXT_texture_rg)\r
2914                         if (queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_EXT_texture_rg)\r
2915                                 && queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_OES_texture_half_float)\r
2916                                 )\r
2917                         {\r
2918                                 supported = true;\r
2919                                 pixelFormat = GL_RG_EXT;\r
2920                                 pixelType = GL_HALF_FLOAT_OES ;\r
2921                         }\r
2922 #endif\r
2923                         break;\r
2924                 case ECF_A16B16G16R16F:\r
2925 #if defined(GL_OES_texture_half_float)\r
2926                         if (queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_OES_texture_half_float))\r
2927                         {\r
2928                                 supported = true;\r
2929                                 pixelFormat = GL_RGBA;\r
2930                                 pixelType = GL_HALF_FLOAT_OES ;\r
2931                         }\r
2932 #endif\r
2933                         break;\r
2934                 case ECF_R32F:\r
2935 #if defined(GL_OES_texture_float) && defined(GL_EXT_texture_rg)\r
2936                         if (queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_EXT_texture_rg)\r
2937                                 && queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_OES_texture_float)\r
2938                                 )\r
2939                         {\r
2940                                 supported = true;\r
2941                                 pixelFormat = GL_RED_EXT;\r
2942                                 pixelType = GL_FLOAT;\r
2943                         }\r
2944 #endif\r
2945                         break;\r
2946                 case ECF_G32R32F:\r
2947 #if defined(GL_OES_texture_float) && defined(GL_EXT_texture_rg)\r
2948                         if (queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_EXT_texture_rg)\r
2949                                 && queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_OES_texture_float)\r
2950                                 )\r
2951                         {\r
2952                                 supported = true;\r
2953                                 pixelFormat = GL_RG_EXT;\r
2954                                 pixelType = GL_FLOAT;\r
2955                         }\r
2956 #endif\r
2957                         break;\r
2958                 case ECF_A32B32G32R32F:\r
2959 #if defined(GL_OES_texture_float)\r
2960                         if (queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_OES_texture_half_float))\r
2961                         {\r
2962                                 supported = true;\r
2963                                 pixelFormat = GL_RGBA;\r
2964                                 pixelType = GL_FLOAT ;\r
2965                         }\r
2966 #endif\r
2967                         break;\r
2968                 default:\r
2969                         break;\r
2970                 }\r
2971 \r
2972                 // ES 2.0 says internalFormat must match pixelFormat (chapter 3.7.1 in Spec).\r
2973                 // Doesn't mention if "match" means "equal" or some other way of matching, but\r
2974                 // some bug on Emscripten and browsing discussions by others lead me to believe\r
2975                 // it means they have to be equal. Note that this was different in OpenGL.\r
2976                 internalFormat = pixelFormat;\r
2977 \r
2978 #ifdef _IRR_IOS_PLATFORM_\r
2979                 if (internalFormat == GL_BGRA)\r
2980                         internalFormat = GL_RGBA;\r
2981 #endif\r
2982 \r
2983                 return supported;\r
2984         }\r
2985 \r
2986         bool COGLES2Driver::queryTextureFormat(ECOLOR_FORMAT format) const\r
2987         {\r
2988                 GLint dummyInternalFormat;\r
2989                 GLenum dummyPixelFormat;\r
2990                 GLenum dummyPixelType;\r
2991                 void (*dummyConverter)(const void*, s32, void*);\r
2992                 return getColorFormatParameters(format, dummyInternalFormat, dummyPixelFormat, dummyPixelType, &dummyConverter);\r
2993         }\r
2994 \r
2995         bool COGLES2Driver::needsTransparentRenderPass(const irr::video::SMaterial& material) const\r
2996         {\r
2997                 return CNullDriver::needsTransparentRenderPass(material) || material.isAlphaBlendOperation();\r
2998         }\r
2999 \r
3000         const SMaterial& COGLES2Driver::getCurrentMaterial() const\r
3001         {\r
3002                 return Material;\r
3003         }\r
3004 \r
3005         COGLES2CacheHandler* COGLES2Driver::getCacheHandler() const\r
3006         {\r
3007                 return CacheHandler;\r
3008         }\r
3009 \r
3010 \r
3011 } // end namespace\r
3012 } // end namespace\r
3013 \r
3014 #endif // _IRR_COMPILE_WITH_OGLES2_\r
3015 \r
3016 namespace irr\r
3017 {\r
3018 namespace video\r
3019 {\r
3020 \r
3021 #ifndef _IRR_COMPILE_WITH_OGLES2_\r
3022 class IVideoDriver;\r
3023 class IContextManager;\r
3024 #endif\r
3025 \r
3026 IVideoDriver* createOGLES2Driver(const SIrrlichtCreationParameters& params, io::IFileSystem* io, IContextManager* contextManager)\r
3027 {\r
3028 #ifdef _IRR_COMPILE_WITH_OGLES2_\r
3029         COGLES2Driver* driver = new COGLES2Driver(params, io, contextManager);\r
3030         driver->genericDriverInit(params.WindowSize, params.Stencilbuffer);     // don't call in constructor, it uses virtual function calls of driver\r
3031         return driver;\r
3032 #else\r
3033         return 0;\r
3034 #endif //  _IRR_COMPILE_WITH_OGLES2_\r
3035 }\r
3036 \r
3037 } // end namespace\r
3038 } // end namespace\r