]> git.lizzy.rs Git - irrlicht.git/blob - source/Irrlicht/OpenGL/Driver.cpp
Split new GL3/GLES2 drivers
[irrlicht.git] / source / Irrlicht / OpenGL / Driver.cpp
1 // Copyright (C) 2023 Vitaliy Lobachevskiy\r
2 // Copyright (C) 2014 Patryk Nadrowski\r
3 // Copyright (C) 2009-2010 Amundis\r
4 // This file is part of the "Irrlicht Engine".\r
5 // For conditions of distribution and use, see copyright notice in Irrlicht.h\r
6 \r
7 #include "Driver.h"\r
8 #include "CNullDriver.h"\r
9 #include "IContextManager.h"\r
10 \r
11 #include "COpenGLCoreTexture.h"\r
12 #include "COpenGLCoreRenderTarget.h"\r
13 #include "COpenGLCoreCacheHandler.h"\r
14 \r
15 #include "MaterialRenderer.h"\r
16 #include "FixedPipelineRenderer.h"\r
17 #include "Renderer2D.h"\r
18 \r
19 #include "EVertexAttributes.h"\r
20 #include "CImage.h"\r
21 #include "os.h"\r
22 \r
23 #ifdef _IRR_COMPILE_WITH_ANDROID_DEVICE_\r
24 #include "android_native_app_glue.h"\r
25 #endif\r
26 \r
27 #include "mt_opengl.h"\r
28 \r
29 namespace irr\r
30 {\r
31 namespace video\r
32 {\r
33         struct VertexAttribute {\r
34                 enum class Mode {\r
35                         Regular,\r
36                         Normalized,\r
37                         Integral,\r
38                 };\r
39                 int Index;\r
40                 int ComponentCount;\r
41                 GLenum ComponentType;\r
42                 Mode mode;\r
43                 int Offset;\r
44         };\r
45 \r
46         struct VertexType {\r
47                 int VertexSize;\r
48                 int AttributeCount;\r
49                 VertexAttribute Attributes[];\r
50 \r
51                 VertexType(const VertexType &) = delete;\r
52                 VertexType &operator= (const VertexType &) = delete;\r
53         };\r
54 \r
55         static const VertexAttribute *begin(const VertexType &type)\r
56         {\r
57                 return type.Attributes;\r
58         }\r
59 \r
60         static const VertexAttribute *end(const VertexType &type)\r
61         {\r
62                 return type.Attributes + type.AttributeCount;\r
63         }\r
64 \r
65         static constexpr VertexType vtStandard = {\r
66                 sizeof(S3DVertex), 4, {\r
67                         {EVA_POSITION, 3, GL_FLOAT, VertexAttribute::Mode::Regular, offsetof(S3DVertex, Pos)},\r
68                         {EVA_NORMAL, 3, GL_FLOAT, VertexAttribute::Mode::Regular, offsetof(S3DVertex, Normal)},\r
69                         {EVA_COLOR, 4, GL_UNSIGNED_BYTE, VertexAttribute::Mode::Normalized, offsetof(S3DVertex, Color)},\r
70                         {EVA_TCOORD0, 2, GL_FLOAT, VertexAttribute::Mode::Regular, offsetof(S3DVertex, TCoords)},\r
71                 },\r
72         };\r
73 \r
74 #pragma GCC diagnostic push\r
75 #pragma GCC diagnostic ignored "-Winvalid-offsetof"\r
76 \r
77         static constexpr VertexType vt2TCoords = {\r
78                 sizeof(S3DVertex2TCoords), 5, {\r
79                         {EVA_POSITION, 3, GL_FLOAT, VertexAttribute::Mode::Regular, offsetof(S3DVertex2TCoords, Pos)},\r
80                         {EVA_NORMAL, 3, GL_FLOAT, VertexAttribute::Mode::Regular, offsetof(S3DVertex2TCoords, Normal)},\r
81                         {EVA_COLOR, 4, GL_UNSIGNED_BYTE, VertexAttribute::Mode::Normalized, offsetof(S3DVertex2TCoords, Color)},\r
82                         {EVA_TCOORD0, 2, GL_FLOAT, VertexAttribute::Mode::Regular, offsetof(S3DVertex2TCoords, TCoords)},\r
83                         {EVA_TCOORD1, 2, GL_FLOAT, VertexAttribute::Mode::Regular, offsetof(S3DVertex2TCoords, TCoords2)},\r
84                 },\r
85         };\r
86 \r
87         static constexpr VertexType vtTangents = {\r
88                 sizeof(S3DVertexTangents), 6, {\r
89                         {EVA_POSITION, 3, GL_FLOAT, VertexAttribute::Mode::Regular, offsetof(S3DVertexTangents, Pos)},\r
90                         {EVA_NORMAL, 3, GL_FLOAT, VertexAttribute::Mode::Regular, offsetof(S3DVertexTangents, Normal)},\r
91                         {EVA_COLOR, 4, GL_UNSIGNED_BYTE, VertexAttribute::Mode::Normalized, offsetof(S3DVertexTangents, Color)},\r
92                         {EVA_TCOORD0, 2, GL_FLOAT, VertexAttribute::Mode::Regular, offsetof(S3DVertexTangents, TCoords)},\r
93                         {EVA_TANGENT, 3, GL_FLOAT, VertexAttribute::Mode::Regular, offsetof(S3DVertexTangents, Tangent)},\r
94                         {EVA_BINORMAL, 3, GL_FLOAT, VertexAttribute::Mode::Regular, offsetof(S3DVertexTangents, Binormal)},\r
95                 },\r
96         };\r
97 \r
98 #pragma GCC diagnostic pop\r
99 \r
100         static const VertexType &getVertexTypeDescription(E_VERTEX_TYPE type)\r
101         {\r
102                 switch (type) {\r
103                         case EVT_STANDARD: return vtStandard;\r
104                         case EVT_2TCOORDS: return vt2TCoords;\r
105                         case EVT_TANGENTS: return vtTangents;\r
106                         default: assert(false);\r
107                 }\r
108         }\r
109 \r
110         static constexpr VertexType vt2DImage = {\r
111                 sizeof(S3DVertex), 3, {\r
112                         {EVA_POSITION, 3, GL_FLOAT, VertexAttribute::Mode::Regular, offsetof(S3DVertex, Pos)},\r
113                         {EVA_COLOR, 4, GL_UNSIGNED_BYTE, VertexAttribute::Mode::Normalized, offsetof(S3DVertex, Color)},\r
114                         {EVA_TCOORD0, 2, GL_FLOAT, VertexAttribute::Mode::Regular, offsetof(S3DVertex, TCoords)},\r
115                 },\r
116         };\r
117 \r
118         static constexpr VertexType vtPrimitive = {\r
119                 sizeof(S3DVertex), 2, {\r
120                         {EVA_POSITION, 3, GL_FLOAT, VertexAttribute::Mode::Regular, offsetof(S3DVertex, Pos)},\r
121                         {EVA_COLOR, 4, GL_UNSIGNED_BYTE, VertexAttribute::Mode::Normalized, offsetof(S3DVertex, Color)},\r
122                 },\r
123         };\r
124 \r
125 \r
126 void APIENTRY COpenGL3DriverBase::debugCb(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *userParam)\r
127 {\r
128         ((COpenGL3DriverBase *)userParam)->debugCb(source, type, id, severity, length, message);\r
129 }\r
130 \r
131 void COpenGL3DriverBase::debugCb(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message)\r
132 {\r
133         printf("%04x %04x %x %x %.*s\n", source, type, id, severity, length, message);\r
134 }\r
135 \r
136 COpenGL3DriverBase::COpenGL3DriverBase(const SIrrlichtCreationParameters& params, io::IFileSystem* io, IContextManager* contextManager) :\r
137         CNullDriver(io, params.WindowSize), COpenGL3ExtensionHandler(), CacheHandler(0),\r
138         Params(params), ResetRenderStates(true), LockRenderStateMode(false), AntiAlias(params.AntiAlias),\r
139         MaterialRenderer2DActive(0), MaterialRenderer2DTexture(0), MaterialRenderer2DNoTexture(0),\r
140         CurrentRenderMode(ERM_NONE), Transformation3DChanged(true),\r
141         OGLES2ShaderPath(params.OGLES2ShaderPath),\r
142         ColorFormat(ECF_R8G8B8), ContextManager(contextManager)\r
143 {\r
144 #ifdef _DEBUG\r
145         setDebugName("Driver");\r
146 #endif\r
147 \r
148         if (!ContextManager)\r
149                 return;\r
150 \r
151         ContextManager->grab();\r
152         ContextManager->generateSurface();\r
153         ContextManager->generateContext();\r
154         ExposedData = ContextManager->getContext();\r
155         ContextManager->activateContext(ExposedData, false);\r
156         GL.LoadAllProcedures(ContextManager);\r
157         GL.DebugMessageCallback(debugCb, this);\r
158         initQuadsIndices();\r
159 }\r
160 \r
161 COpenGL3DriverBase::~COpenGL3DriverBase()\r
162 {\r
163         deleteMaterialRenders();\r
164 \r
165         CacheHandler->getTextureCache().clear();\r
166 \r
167         removeAllRenderTargets();\r
168         deleteAllTextures();\r
169         removeAllOcclusionQueries();\r
170         removeAllHardwareBuffers();\r
171 \r
172         delete MaterialRenderer2DTexture;\r
173         delete MaterialRenderer2DNoTexture;\r
174         delete CacheHandler;\r
175 \r
176         if (ContextManager)\r
177         {\r
178                 ContextManager->destroyContext();\r
179                 ContextManager->destroySurface();\r
180                 ContextManager->terminate();\r
181                 ContextManager->drop();\r
182         }\r
183 }\r
184 \r
185         void COpenGL3DriverBase::initQuadsIndices(int max_vertex_count)\r
186         {\r
187                 int max_quad_count = max_vertex_count / 4;\r
188                 QuadsIndices.reserve(6 * max_quad_count);\r
189                 for (int k = 0; k < max_quad_count; k++) {\r
190                         QuadsIndices.push_back(4 * k + 0);\r
191                         QuadsIndices.push_back(4 * k + 1);\r
192                         QuadsIndices.push_back(4 * k + 2);\r
193                         QuadsIndices.push_back(4 * k + 0);\r
194                         QuadsIndices.push_back(4 * k + 2);\r
195                         QuadsIndices.push_back(4 * k + 3);\r
196                 }\r
197         }\r
198 \r
199         bool COpenGL3DriverBase::genericDriverInit(const core::dimension2d<u32>& screenSize, bool stencilBuffer)\r
200         {\r
201                 Name = glGetString(GL_VERSION);\r
202                 printVersion();\r
203 \r
204                 // print renderer information\r
205                 VendorName = glGetString(GL_VENDOR);\r
206                 os::Printer::log(VendorName.c_str(), ELL_INFORMATION);\r
207 \r
208                 // load extensions\r
209                 initExtensions();\r
210 \r
211                 // reset cache handler\r
212                 delete CacheHandler;\r
213                 CacheHandler = new COpenGL3CacheHandler(this);\r
214 \r
215                 StencilBuffer = stencilBuffer;\r
216 \r
217                 DriverAttributes->setAttribute("MaxTextures", (s32)Feature.MaxTextureUnits);\r
218                 DriverAttributes->setAttribute("MaxSupportedTextures", (s32)Feature.MaxTextureUnits);\r
219 //              DriverAttributes->setAttribute("MaxLights", MaxLights);\r
220                 DriverAttributes->setAttribute("MaxAnisotropy", MaxAnisotropy);\r
221 //              DriverAttributes->setAttribute("MaxUserClipPlanes", MaxUserClipPlanes);\r
222 //              DriverAttributes->setAttribute("MaxAuxBuffers", MaxAuxBuffers);\r
223 //              DriverAttributes->setAttribute("MaxMultipleRenderTargets", MaxMultipleRenderTargets);\r
224                 DriverAttributes->setAttribute("MaxIndices", (s32)MaxIndices);\r
225                 DriverAttributes->setAttribute("MaxTextureSize", (s32)MaxTextureSize);\r
226                 DriverAttributes->setAttribute("MaxTextureLODBias", MaxTextureLODBias);\r
227                 DriverAttributes->setAttribute("Version", Version);\r
228                 DriverAttributes->setAttribute("AntiAlias", AntiAlias);\r
229 \r
230                 glPixelStorei(GL_PACK_ALIGNMENT, 1);\r
231 \r
232                 UserClipPlane.reallocate(0);\r
233 \r
234                 for (s32 i = 0; i < ETS_COUNT; ++i)\r
235                         setTransform(static_cast<E_TRANSFORMATION_STATE>(i), core::IdentityMatrix);\r
236 \r
237                 setAmbientLight(SColorf(0.0f, 0.0f, 0.0f, 0.0f));\r
238                 glClearDepthf(1.0f);\r
239 \r
240                 glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST);\r
241                 glFrontFace(GL_CW);\r
242 \r
243                 // create material renderers\r
244                 createMaterialRenderers();\r
245 \r
246                 // set the renderstates\r
247                 setRenderStates3DMode();\r
248 \r
249                 // set fog mode\r
250                 setFog(FogColor, FogType, FogStart, FogEnd, FogDensity, PixelFog, RangeFog);\r
251 \r
252                 // create matrix for flipping textures\r
253                 TextureFlipMatrix.buildTextureTransform(0.0f, core::vector2df(0, 0), core::vector2df(0, 1.0f), core::vector2df(1.0f, -1.0f));\r
254 \r
255                 // We need to reset once more at the beginning of the first rendering.\r
256                 // This fixes problems with intermediate changes to the material during texture load.\r
257                 ResetRenderStates = true;\r
258 \r
259                 testGLError(__LINE__);\r
260 \r
261                 return true;\r
262         }\r
263 \r
264         void COpenGL3DriverBase::loadShaderData(const io::path& vertexShaderName, const io::path& fragmentShaderName, c8** vertexShaderData, c8** fragmentShaderData)\r
265         {\r
266                 io::path vsPath(OGLES2ShaderPath);\r
267                 vsPath += vertexShaderName;\r
268 \r
269                 io::path fsPath(OGLES2ShaderPath);\r
270                 fsPath += fragmentShaderName;\r
271 \r
272                 *vertexShaderData = 0;\r
273                 *fragmentShaderData = 0;\r
274 \r
275                 io::IReadFile* vsFile = FileSystem->createAndOpenFile(vsPath);\r
276                 if ( !vsFile )\r
277                 {\r
278                         core::stringw warning(L"Warning: Missing shader files needed to simulate fixed function materials:\n");\r
279                         warning += core::stringw(vsPath) + L"\n";\r
280                         warning += L"Shaderpath can be changed in SIrrCreationParamters::OGLES2ShaderPath";\r
281                         os::Printer::log(warning.c_str(), ELL_WARNING);\r
282                         return;\r
283                 }\r
284 \r
285                 io::IReadFile* fsFile = FileSystem->createAndOpenFile(fsPath);\r
286                 if ( !fsFile )\r
287                 {\r
288                         core::stringw warning(L"Warning: Missing shader files needed to simulate fixed function materials:\n");\r
289                         warning += core::stringw(fsPath) + L"\n";\r
290                         warning += L"Shaderpath can be changed in SIrrCreationParamters::OGLES2ShaderPath";\r
291                         os::Printer::log(warning.c_str(), ELL_WARNING);\r
292                         return;\r
293                 }\r
294 \r
295                 long size = vsFile->getSize();\r
296                 if (size)\r
297                 {\r
298                         *vertexShaderData = new c8[size+1];\r
299                         vsFile->read(*vertexShaderData, size);\r
300                         (*vertexShaderData)[size] = 0;\r
301                 }\r
302 \r
303                 size = fsFile->getSize();\r
304                 if (size)\r
305                 {\r
306                         // if both handles are the same we must reset the file\r
307                         if (fsFile == vsFile)\r
308                                 fsFile->seek(0);\r
309 \r
310                         *fragmentShaderData = new c8[size+1];\r
311                         fsFile->read(*fragmentShaderData, size);\r
312                         (*fragmentShaderData)[size] = 0;\r
313                 }\r
314 \r
315                 vsFile->drop();\r
316                 fsFile->drop();\r
317         }\r
318 \r
319         void COpenGL3DriverBase::createMaterialRenderers()\r
320         {\r
321                 // Create callbacks.\r
322 \r
323                 COpenGL3MaterialSolidCB* SolidCB = new COpenGL3MaterialSolidCB();\r
324                 COpenGL3MaterialSolid2CB* Solid2LayerCB = new COpenGL3MaterialSolid2CB();\r
325                 COpenGL3MaterialLightmapCB* LightmapCB = new COpenGL3MaterialLightmapCB(1.f);\r
326                 COpenGL3MaterialLightmapCB* LightmapAddCB = new COpenGL3MaterialLightmapCB(1.f);\r
327                 COpenGL3MaterialLightmapCB* LightmapM2CB = new COpenGL3MaterialLightmapCB(2.f);\r
328                 COpenGL3MaterialLightmapCB* LightmapM4CB = new COpenGL3MaterialLightmapCB(4.f);\r
329                 COpenGL3MaterialLightmapCB* LightmapLightingCB = new COpenGL3MaterialLightmapCB(1.f);\r
330                 COpenGL3MaterialLightmapCB* LightmapLightingM2CB = new COpenGL3MaterialLightmapCB(2.f);\r
331                 COpenGL3MaterialLightmapCB* LightmapLightingM4CB = new COpenGL3MaterialLightmapCB(4.f);\r
332                 COpenGL3MaterialSolid2CB* DetailMapCB = new COpenGL3MaterialSolid2CB();\r
333                 COpenGL3MaterialReflectionCB* SphereMapCB = new COpenGL3MaterialReflectionCB();\r
334                 COpenGL3MaterialReflectionCB* Reflection2LayerCB = new COpenGL3MaterialReflectionCB();\r
335                 COpenGL3MaterialSolidCB* TransparentAddColorCB = new COpenGL3MaterialSolidCB();\r
336                 COpenGL3MaterialSolidCB* TransparentAlphaChannelCB = new COpenGL3MaterialSolidCB();\r
337                 COpenGL3MaterialSolidCB* TransparentAlphaChannelRefCB = new COpenGL3MaterialSolidCB();\r
338                 COpenGL3MaterialSolidCB* TransparentVertexAlphaCB = new COpenGL3MaterialSolidCB();\r
339                 COpenGL3MaterialReflectionCB* TransparentReflection2LayerCB = new COpenGL3MaterialReflectionCB();\r
340                 COpenGL3MaterialOneTextureBlendCB* OneTextureBlendCB = new COpenGL3MaterialOneTextureBlendCB();\r
341 \r
342                 // Create built-in materials.\r
343 \r
344                 core::stringc VertexShader = OGLES2ShaderPath + "Solid.vsh";\r
345                 core::stringc FragmentShader = OGLES2ShaderPath + "Solid.fsh";\r
346 \r
347                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
348                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, SolidCB, EMT_SOLID, 0);\r
349 \r
350                 VertexShader = OGLES2ShaderPath + "Solid2.vsh";\r
351                 FragmentShader = OGLES2ShaderPath + "Solid2Layer.fsh";\r
352 \r
353                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
354                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, Solid2LayerCB, EMT_SOLID, 0);\r
355 \r
356                 VertexShader = OGLES2ShaderPath + "Solid2.vsh";\r
357                 FragmentShader = OGLES2ShaderPath + "LightmapModulate.fsh";\r
358 \r
359                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
360                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, LightmapCB, EMT_SOLID, 0);\r
361 \r
362                 FragmentShader = OGLES2ShaderPath + "LightmapAdd.fsh";\r
363 \r
364                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
365                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, LightmapAddCB, EMT_SOLID, 0);\r
366 \r
367                 FragmentShader = OGLES2ShaderPath + "LightmapModulate.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, LightmapM2CB, EMT_SOLID, 0);\r
371 \r
372                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
373                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, LightmapM4CB, EMT_SOLID, 0);\r
374 \r
375                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
376                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, LightmapLightingCB, EMT_SOLID, 0);\r
377 \r
378                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
379                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, LightmapLightingM2CB, EMT_SOLID, 0);\r
380 \r
381                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
382                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, LightmapLightingM4CB, EMT_SOLID, 0);\r
383 \r
384                 VertexShader = OGLES2ShaderPath + "Solid2.vsh";\r
385                 FragmentShader = OGLES2ShaderPath + "DetailMap.fsh";\r
386 \r
387                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
388                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, DetailMapCB, EMT_SOLID, 0);\r
389 \r
390                 VertexShader = OGLES2ShaderPath + "SphereMap.vsh";\r
391                 FragmentShader = OGLES2ShaderPath + "SphereMap.fsh";\r
392 \r
393                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
394                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, SphereMapCB, EMT_SOLID, 0);\r
395 \r
396                 VertexShader = OGLES2ShaderPath + "Reflection2Layer.vsh";\r
397                 FragmentShader = OGLES2ShaderPath + "Reflection2Layer.fsh";\r
398 \r
399                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
400                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, Reflection2LayerCB, EMT_SOLID, 0);\r
401 \r
402                 VertexShader = OGLES2ShaderPath + "Solid.vsh";\r
403                 FragmentShader = OGLES2ShaderPath + "Solid.fsh";\r
404 \r
405                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
406                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, TransparentAddColorCB, EMT_TRANSPARENT_ADD_COLOR, 0);\r
407 \r
408                 FragmentShader = OGLES2ShaderPath + "TransparentAlphaChannel.fsh";\r
409                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
410                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, TransparentAlphaChannelCB, EMT_TRANSPARENT_ALPHA_CHANNEL, 0);\r
411 \r
412                 FragmentShader = OGLES2ShaderPath + "TransparentAlphaChannelRef.fsh";\r
413 \r
414                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
415                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, TransparentAlphaChannelRefCB, EMT_SOLID, 0);\r
416 \r
417                 FragmentShader = OGLES2ShaderPath + "TransparentVertexAlpha.fsh";\r
418 \r
419                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
420                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, TransparentVertexAlphaCB, EMT_TRANSPARENT_ALPHA_CHANNEL, 0);\r
421 \r
422                 VertexShader = OGLES2ShaderPath + "Reflection2Layer.vsh";\r
423                 FragmentShader = OGLES2ShaderPath + "Reflection2Layer.fsh";\r
424 \r
425                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
426                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, TransparentReflection2LayerCB, EMT_TRANSPARENT_ALPHA_CHANNEL, 0);\r
427 \r
428                 VertexShader = OGLES2ShaderPath + "Solid.vsh";\r
429                 FragmentShader = OGLES2ShaderPath + "OneTextureBlend.fsh";\r
430 \r
431                 addHighLevelShaderMaterialFromFiles(VertexShader, "main", EVST_VS_2_0, FragmentShader, "main", EPST_PS_2_0, "", "main",\r
432                         EGST_GS_4_0, scene::EPT_TRIANGLES, scene::EPT_TRIANGLE_STRIP, 0, OneTextureBlendCB, EMT_ONETEXTURE_BLEND, 0);\r
433 \r
434                 // Drop callbacks.\r
435 \r
436                 SolidCB->drop();\r
437                 Solid2LayerCB->drop();\r
438                 LightmapCB->drop();\r
439                 LightmapAddCB->drop();\r
440                 LightmapM2CB->drop();\r
441                 LightmapM4CB->drop();\r
442                 LightmapLightingCB->drop();\r
443                 LightmapLightingM2CB->drop();\r
444                 LightmapLightingM4CB->drop();\r
445                 DetailMapCB->drop();\r
446                 SphereMapCB->drop();\r
447                 Reflection2LayerCB->drop();\r
448                 TransparentAddColorCB->drop();\r
449                 TransparentAlphaChannelCB->drop();\r
450                 TransparentAlphaChannelRefCB->drop();\r
451                 TransparentVertexAlphaCB->drop();\r
452                 TransparentReflection2LayerCB->drop();\r
453                 OneTextureBlendCB->drop();\r
454 \r
455                 // Create 2D material renderers\r
456 \r
457                 c8* vs2DData = 0;\r
458                 c8* fs2DData = 0;\r
459                 loadShaderData(io::path("Renderer2D.vsh"), io::path("Renderer2D.fsh"), &vs2DData, &fs2DData);\r
460                 MaterialRenderer2DTexture = new COpenGL3Renderer2D(vs2DData, fs2DData, this, true);\r
461                 delete[] vs2DData;\r
462                 delete[] fs2DData;\r
463                 vs2DData = 0;\r
464                 fs2DData = 0;\r
465 \r
466                 loadShaderData(io::path("Renderer2D.vsh"), io::path("Renderer2D_noTex.fsh"), &vs2DData, &fs2DData);\r
467                 MaterialRenderer2DNoTexture = new COpenGL3Renderer2D(vs2DData, fs2DData, this, false);\r
468                 delete[] vs2DData;\r
469                 delete[] fs2DData;\r
470         }\r
471 \r
472         bool COpenGL3DriverBase::setMaterialTexture(irr::u32 layerIdx, const irr::video::ITexture* texture)\r
473         {\r
474                 Material.TextureLayer[layerIdx].Texture = const_cast<ITexture*>(texture); // function uses const-pointer for texture because all draw functions use const-pointers already\r
475                 return CacheHandler->getTextureCache().set(0, texture);\r
476         }\r
477 \r
478         bool COpenGL3DriverBase::beginScene(u16 clearFlag, SColor clearColor, f32 clearDepth, u8 clearStencil, const SExposedVideoData& videoData, core::rect<s32>* sourceRect)\r
479         {\r
480                 CNullDriver::beginScene(clearFlag, clearColor, clearDepth, clearStencil, videoData, sourceRect);\r
481 \r
482                 if (ContextManager)\r
483                         ContextManager->activateContext(videoData, true);\r
484 \r
485                 clearBuffers(clearFlag, clearColor, clearDepth, clearStencil);\r
486 \r
487                 return true;\r
488         }\r
489 \r
490         bool COpenGL3DriverBase::endScene()\r
491         {\r
492                 CNullDriver::endScene();\r
493 \r
494                 glFlush();\r
495 \r
496                 if (ContextManager)\r
497                         return ContextManager->swapBuffers();\r
498 \r
499                 return false;\r
500         }\r
501 \r
502 \r
503         //! Returns the transformation set by setTransform\r
504         const core::matrix4& COpenGL3DriverBase::getTransform(E_TRANSFORMATION_STATE state) const\r
505         {\r
506                 return Matrices[state];\r
507         }\r
508 \r
509 \r
510         //! sets transformation\r
511         void COpenGL3DriverBase::setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat)\r
512         {\r
513                 Matrices[state] = mat;\r
514                 Transformation3DChanged = true;\r
515         }\r
516 \r
517 \r
518         bool COpenGL3DriverBase::updateVertexHardwareBuffer(SHWBufferLink_opengl *HWBuffer)\r
519         {\r
520                 if (!HWBuffer)\r
521                         return false;\r
522 \r
523                 const scene::IMeshBuffer* mb = HWBuffer->MeshBuffer;\r
524                 const void* vertices = mb->getVertices();\r
525                 const u32 vertexCount = mb->getVertexCount();\r
526                 const E_VERTEX_TYPE vType = mb->getVertexType();\r
527                 const u32 vertexSize = getVertexPitchFromType(vType);\r
528 \r
529                 const void *buffer = vertices;\r
530                 size_t bufferSize = vertexSize * vertexCount;\r
531 \r
532                 //get or create buffer\r
533                 bool newBuffer = false;\r
534                 if (!HWBuffer->vbo_verticesID)\r
535                 {\r
536                         glGenBuffers(1, &HWBuffer->vbo_verticesID);\r
537                         if (!HWBuffer->vbo_verticesID) return false;\r
538                         newBuffer = true;\r
539                 }\r
540                 else if (HWBuffer->vbo_verticesSize < bufferSize)\r
541                 {\r
542                         newBuffer = true;\r
543                 }\r
544 \r
545                 glBindBuffer(GL_ARRAY_BUFFER, HWBuffer->vbo_verticesID);\r
546 \r
547                 // copy data to graphics card\r
548                 if (!newBuffer)\r
549                         glBufferSubData(GL_ARRAY_BUFFER, 0, bufferSize, buffer);\r
550                 else\r
551                 {\r
552                         HWBuffer->vbo_verticesSize = bufferSize;\r
553 \r
554                         if (HWBuffer->Mapped_Vertex == scene::EHM_STATIC)\r
555                                 glBufferData(GL_ARRAY_BUFFER, bufferSize, buffer, GL_STATIC_DRAW);\r
556                         else\r
557                                 glBufferData(GL_ARRAY_BUFFER, bufferSize, buffer, GL_DYNAMIC_DRAW);\r
558                 }\r
559 \r
560                 glBindBuffer(GL_ARRAY_BUFFER, 0);\r
561 \r
562                 return (!testGLError(__LINE__));\r
563         }\r
564 \r
565 \r
566         bool COpenGL3DriverBase::updateIndexHardwareBuffer(SHWBufferLink_opengl *HWBuffer)\r
567         {\r
568                 if (!HWBuffer)\r
569                         return false;\r
570 \r
571                 const scene::IMeshBuffer* mb = HWBuffer->MeshBuffer;\r
572 \r
573                 const void* indices = mb->getIndices();\r
574                 u32 indexCount = mb->getIndexCount();\r
575 \r
576                 GLenum indexSize;\r
577                 switch (mb->getIndexType())\r
578                 {\r
579                         case(EIT_16BIT):\r
580                         {\r
581                                 indexSize = sizeof(u16);\r
582                                 break;\r
583                         }\r
584                         case(EIT_32BIT):\r
585                         {\r
586                                 indexSize = sizeof(u32);\r
587                                 break;\r
588                         }\r
589                         default:\r
590                         {\r
591                                 return false;\r
592                         }\r
593                 }\r
594 \r
595                 //get or create buffer\r
596                 bool newBuffer = false;\r
597                 if (!HWBuffer->vbo_indicesID)\r
598                 {\r
599                         glGenBuffers(1, &HWBuffer->vbo_indicesID);\r
600                         if (!HWBuffer->vbo_indicesID) return false;\r
601                         newBuffer = true;\r
602                 }\r
603                 else if (HWBuffer->vbo_indicesSize < indexCount*indexSize)\r
604                 {\r
605                         newBuffer = true;\r
606                 }\r
607 \r
608                 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, HWBuffer->vbo_indicesID);\r
609 \r
610                 // copy data to graphics card\r
611                 if (!newBuffer)\r
612                         glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, indexCount * indexSize, indices);\r
613                 else\r
614                 {\r
615                         HWBuffer->vbo_indicesSize = indexCount * indexSize;\r
616 \r
617                         if (HWBuffer->Mapped_Index == scene::EHM_STATIC)\r
618                                 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * indexSize, indices, GL_STATIC_DRAW);\r
619                         else\r
620                                 glBufferData(GL_ELEMENT_ARRAY_BUFFER, indexCount * indexSize, indices, GL_DYNAMIC_DRAW);\r
621                 }\r
622 \r
623                 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);\r
624 \r
625                 return (!testGLError(__LINE__));\r
626         }\r
627 \r
628 \r
629         //! updates hardware buffer if needed\r
630         bool COpenGL3DriverBase::updateHardwareBuffer(SHWBufferLink *HWBuffer)\r
631         {\r
632                 if (!HWBuffer)\r
633                         return false;\r
634 \r
635                 if (HWBuffer->Mapped_Vertex != scene::EHM_NEVER)\r
636                 {\r
637                         if (HWBuffer->ChangedID_Vertex != HWBuffer->MeshBuffer->getChangedID_Vertex()\r
638                                 || !static_cast<SHWBufferLink_opengl*>(HWBuffer)->vbo_verticesID)\r
639                         {\r
640 \r
641                                 HWBuffer->ChangedID_Vertex = HWBuffer->MeshBuffer->getChangedID_Vertex();\r
642 \r
643                                 if (!updateVertexHardwareBuffer(static_cast<SHWBufferLink_opengl*>(HWBuffer)))\r
644                                         return false;\r
645                         }\r
646                 }\r
647 \r
648                 if (HWBuffer->Mapped_Index != scene::EHM_NEVER)\r
649                 {\r
650                         if (HWBuffer->ChangedID_Index != HWBuffer->MeshBuffer->getChangedID_Index()\r
651                                 || !static_cast<SHWBufferLink_opengl*>(HWBuffer)->vbo_indicesID)\r
652                         {\r
653 \r
654                                 HWBuffer->ChangedID_Index = HWBuffer->MeshBuffer->getChangedID_Index();\r
655 \r
656                                 if (!updateIndexHardwareBuffer((SHWBufferLink_opengl*)HWBuffer))\r
657                                         return false;\r
658                         }\r
659                 }\r
660 \r
661                 return true;\r
662         }\r
663 \r
664 \r
665         //! Create hardware buffer from meshbuffer\r
666         COpenGL3DriverBase::SHWBufferLink *COpenGL3DriverBase::createHardwareBuffer(const scene::IMeshBuffer* mb)\r
667         {\r
668                 if (!mb || (mb->getHardwareMappingHint_Index() == scene::EHM_NEVER && mb->getHardwareMappingHint_Vertex() == scene::EHM_NEVER))\r
669                         return 0;\r
670 \r
671                 SHWBufferLink_opengl *HWBuffer = new SHWBufferLink_opengl(mb);\r
672 \r
673                 //add to map\r
674                 HWBuffer->listPosition = HWBufferList.insert(HWBufferList.end(), HWBuffer);\r
675 \r
676                 HWBuffer->ChangedID_Vertex = HWBuffer->MeshBuffer->getChangedID_Vertex();\r
677                 HWBuffer->ChangedID_Index = HWBuffer->MeshBuffer->getChangedID_Index();\r
678                 HWBuffer->Mapped_Vertex = mb->getHardwareMappingHint_Vertex();\r
679                 HWBuffer->Mapped_Index = mb->getHardwareMappingHint_Index();\r
680                 HWBuffer->vbo_verticesID = 0;\r
681                 HWBuffer->vbo_indicesID = 0;\r
682                 HWBuffer->vbo_verticesSize = 0;\r
683                 HWBuffer->vbo_indicesSize = 0;\r
684 \r
685                 if (!updateHardwareBuffer(HWBuffer))\r
686                 {\r
687                         deleteHardwareBuffer(HWBuffer);\r
688                         return 0;\r
689                 }\r
690 \r
691                 return HWBuffer;\r
692         }\r
693 \r
694 \r
695         void COpenGL3DriverBase::deleteHardwareBuffer(SHWBufferLink *_HWBuffer)\r
696         {\r
697                 if (!_HWBuffer)\r
698                         return;\r
699 \r
700                 SHWBufferLink_opengl *HWBuffer = static_cast<SHWBufferLink_opengl*>(_HWBuffer);\r
701                 if (HWBuffer->vbo_verticesID)\r
702                 {\r
703                         glDeleteBuffers(1, &HWBuffer->vbo_verticesID);\r
704                         HWBuffer->vbo_verticesID = 0;\r
705                 }\r
706                 if (HWBuffer->vbo_indicesID)\r
707                 {\r
708                         glDeleteBuffers(1, &HWBuffer->vbo_indicesID);\r
709                         HWBuffer->vbo_indicesID = 0;\r
710                 }\r
711 \r
712                 CNullDriver::deleteHardwareBuffer(_HWBuffer);\r
713         }\r
714 \r
715 \r
716         //! Draw hardware buffer\r
717         void COpenGL3DriverBase::drawHardwareBuffer(SHWBufferLink *_HWBuffer)\r
718         {\r
719                 if (!_HWBuffer)\r
720                         return;\r
721 \r
722                 SHWBufferLink_opengl *HWBuffer = static_cast<SHWBufferLink_opengl*>(_HWBuffer);\r
723 \r
724                 updateHardwareBuffer(HWBuffer); //check if update is needed\r
725 \r
726                 const scene::IMeshBuffer* mb = HWBuffer->MeshBuffer;\r
727                 const void *vertices = mb->getVertices();\r
728                 const void *indexList = mb->getIndices();\r
729 \r
730                 if (HWBuffer->Mapped_Vertex != scene::EHM_NEVER)\r
731                 {\r
732                         glBindBuffer(GL_ARRAY_BUFFER, HWBuffer->vbo_verticesID);\r
733                         vertices = 0;\r
734                 }\r
735 \r
736                 if (HWBuffer->Mapped_Index != scene::EHM_NEVER)\r
737                 {\r
738                         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, HWBuffer->vbo_indicesID);\r
739                         indexList = 0;\r
740                 }\r
741 \r
742 \r
743                 drawVertexPrimitiveList(vertices, mb->getVertexCount(),\r
744                                 indexList, mb->getPrimitiveCount(),\r
745                                 mb->getVertexType(), mb->getPrimitiveType(),\r
746                                 mb->getIndexType());\r
747 \r
748                 if (HWBuffer->Mapped_Vertex != scene::EHM_NEVER)\r
749                         glBindBuffer(GL_ARRAY_BUFFER, 0);\r
750 \r
751                 if (HWBuffer->Mapped_Index != scene::EHM_NEVER)\r
752                         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);\r
753         }\r
754 \r
755 \r
756         IRenderTarget* COpenGL3DriverBase::addRenderTarget()\r
757         {\r
758                 COpenGL3RenderTarget* renderTarget = new COpenGL3RenderTarget(this);\r
759                 RenderTargets.push_back(renderTarget);\r
760 \r
761                 return renderTarget;\r
762         }\r
763 \r
764 \r
765         // small helper function to create vertex buffer object adress offsets\r
766         static inline u8* buffer_offset(const long offset)\r
767         {\r
768                 return ((u8*)0 + offset);\r
769         }\r
770 \r
771 \r
772         //! draws a vertex primitive list\r
773         void COpenGL3DriverBase::drawVertexPrimitiveList(const void* vertices, u32 vertexCount,\r
774                         const void* indexList, u32 primitiveCount,\r
775                         E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType)\r
776         {\r
777                 if (!primitiveCount || !vertexCount)\r
778                         return;\r
779 \r
780                 if (!checkPrimitiveCount(primitiveCount))\r
781                         return;\r
782 \r
783                 CNullDriver::drawVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, vType, pType, iType);\r
784 \r
785                 setRenderStates3DMode();\r
786 \r
787                 auto &vTypeDesc = getVertexTypeDescription(vType);\r
788                 beginDraw(vTypeDesc, reinterpret_cast<uintptr_t>(vertices));\r
789                 GLenum indexSize = 0;\r
790 \r
791                 switch (iType)\r
792                 {\r
793                         case(EIT_16BIT):\r
794                         {\r
795                                 indexSize = GL_UNSIGNED_SHORT;\r
796                                 break;\r
797                         }\r
798                         case(EIT_32BIT):\r
799                         {\r
800 #ifdef GL_OES_element_index_uint\r
801 #ifndef GL_UNSIGNED_INT\r
802 #define GL_UNSIGNED_INT 0x1405\r
803 #endif\r
804                                 if (FeatureAvailable[COGLESCoreExtensionHandler::IRR_GL_OES_element_index_uint])\r
805                                         indexSize = GL_UNSIGNED_INT;\r
806                                 else\r
807 #endif\r
808                                         indexSize = GL_UNSIGNED_SHORT;\r
809                                 break;\r
810                         }\r
811                 }\r
812 \r
813                 switch (pType)\r
814                 {\r
815                         case scene::EPT_POINTS:\r
816                         case scene::EPT_POINT_SPRITES:\r
817                                 glDrawArrays(GL_POINTS, 0, primitiveCount);\r
818                                 break;\r
819                         case scene::EPT_LINE_STRIP:\r
820                                 glDrawElements(GL_LINE_STRIP, primitiveCount + 1, indexSize, indexList);\r
821                                 break;\r
822                         case scene::EPT_LINE_LOOP:\r
823                                 glDrawElements(GL_LINE_LOOP, primitiveCount, indexSize, indexList);\r
824                                 break;\r
825                         case scene::EPT_LINES:\r
826                                 glDrawElements(GL_LINES, primitiveCount*2, indexSize, indexList);\r
827                                 break;\r
828                         case scene::EPT_TRIANGLE_STRIP:\r
829                                 glDrawElements(GL_TRIANGLE_STRIP, primitiveCount + 2, indexSize, indexList);\r
830                                 break;\r
831                         case scene::EPT_TRIANGLE_FAN:\r
832                                 glDrawElements(GL_TRIANGLE_FAN, primitiveCount + 2, indexSize, indexList);\r
833                                 break;\r
834                         case scene::EPT_TRIANGLES:\r
835                                 glDrawElements((LastMaterial.Wireframe) ? GL_LINES : (LastMaterial.PointCloud) ? GL_POINTS : GL_TRIANGLES, primitiveCount*3, indexSize, indexList);\r
836                                 break;\r
837                         default:\r
838                                 break;\r
839                 }\r
840 \r
841                 endDraw(vTypeDesc);\r
842         }\r
843 \r
844 \r
845         void COpenGL3DriverBase::draw2DImage(const video::ITexture* texture, const core::position2d<s32>& destPos,\r
846                 const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect, SColor color,\r
847                 bool useAlphaChannelOfTexture)\r
848         {\r
849                 if (!texture)\r
850                         return;\r
851 \r
852                 if (!sourceRect.isValid())\r
853                         return;\r
854 \r
855                 SColor colors[4] = {color, color, color, color};\r
856                 draw2DImage(texture, {destPos, sourceRect.getSize()}, sourceRect, clipRect, colors, useAlphaChannelOfTexture);\r
857         }\r
858 \r
859 \r
860         void COpenGL3DriverBase::draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect,\r
861                 const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,\r
862                 const video::SColor* const colors, bool useAlphaChannelOfTexture)\r
863         {\r
864                 if (!texture)\r
865                         return;\r
866 \r
867                 // texcoords need to be flipped horizontally for RTTs\r
868                 const bool isRTT = texture->isRenderTarget();\r
869                 const core::dimension2du& ss = texture->getOriginalSize();\r
870                 const f32 invW = 1.f / static_cast<f32>(ss.Width);\r
871                 const f32 invH = 1.f / static_cast<f32>(ss.Height);\r
872                 const core::rect<f32> tcoords(\r
873                         sourceRect.UpperLeftCorner.X * invW,\r
874                         (isRTT ? sourceRect.LowerRightCorner.Y : sourceRect.UpperLeftCorner.Y) * invH,\r
875                         sourceRect.LowerRightCorner.X * invW,\r
876                         (isRTT ? sourceRect.UpperLeftCorner.Y : sourceRect.LowerRightCorner.Y) *invH);\r
877 \r
878                 const video::SColor temp[4] =\r
879                 {\r
880                         0xFFFFFFFF,\r
881                         0xFFFFFFFF,\r
882                         0xFFFFFFFF,\r
883                         0xFFFFFFFF\r
884                 };\r
885 \r
886                 const video::SColor* const useColor = colors ? colors : temp;\r
887 \r
888                 chooseMaterial2D();\r
889                 if (!setMaterialTexture(0, texture ))\r
890                         return;\r
891 \r
892                 setRenderStates2DMode(useColor[0].getAlpha() < 255 || useColor[1].getAlpha() < 255 ||\r
893                         useColor[2].getAlpha() < 255 || useColor[3].getAlpha() < 255,\r
894                         true, useAlphaChannelOfTexture);\r
895 \r
896                 const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();\r
897 \r
898                 if (clipRect)\r
899                 {\r
900                         if (!clipRect->isValid())\r
901                                 return;\r
902 \r
903                         glEnable(GL_SCISSOR_TEST);\r
904                         glScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height - clipRect->LowerRightCorner.Y,\r
905                                 clipRect->getWidth(), clipRect->getHeight());\r
906                 }\r
907 \r
908                 f32 left = (f32)destRect.UpperLeftCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;\r
909                 f32 right = (f32)destRect.LowerRightCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;\r
910                 f32 down = 2.f - (f32)destRect.LowerRightCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
911                 f32 top = 2.f - (f32)destRect.UpperLeftCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
912 \r
913                 S3DVertex vertices[4];\r
914                 vertices[0] = S3DVertex(left, top, 0, 0, 0, 1, useColor[0], tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y);\r
915                 vertices[1] = S3DVertex(right, top, 0, 0, 0, 1, useColor[3], tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y);\r
916                 vertices[2] = S3DVertex(right, down, 0, 0, 0, 1, useColor[2], tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y);\r
917                 vertices[3] = S3DVertex(left, down, 0, 0, 0, 1, useColor[1], tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y);\r
918 \r
919                 drawQuad(vt2DImage, vertices);\r
920 \r
921                 if (clipRect)\r
922                         glDisable(GL_SCISSOR_TEST);\r
923 \r
924                 testGLError(__LINE__);\r
925         }\r
926 \r
927         void COpenGL3DriverBase::draw2DImage(const video::ITexture* texture, u32 layer, bool flip)\r
928         {\r
929                 if (!texture)\r
930                         return;\r
931 \r
932                 chooseMaterial2D();\r
933                 if (!setMaterialTexture(0, texture ))\r
934                         return;\r
935 \r
936                 setRenderStates2DMode(false, true, true);\r
937 \r
938                 S3DVertex quad2DVertices[4];\r
939 \r
940                 quad2DVertices[0].Pos = core::vector3df(-1.f, 1.f, 0.f);\r
941                 quad2DVertices[1].Pos = core::vector3df(1.f, 1.f, 0.f);\r
942                 quad2DVertices[2].Pos = core::vector3df(1.f, -1.f, 0.f);\r
943                 quad2DVertices[3].Pos = core::vector3df(-1.f, -1.f, 0.f);\r
944 \r
945                 f32 modificator = (flip) ? 1.f : 0.f;\r
946 \r
947                 quad2DVertices[0].TCoords = core::vector2df(0.f, 0.f + modificator);\r
948                 quad2DVertices[1].TCoords = core::vector2df(1.f, 0.f + modificator);\r
949                 quad2DVertices[2].TCoords = core::vector2df(1.f, 1.f - modificator);\r
950                 quad2DVertices[3].TCoords = core::vector2df(0.f, 1.f - modificator);\r
951 \r
952                 quad2DVertices[0].Color = SColor(0xFFFFFFFF);\r
953                 quad2DVertices[1].Color = SColor(0xFFFFFFFF);\r
954                 quad2DVertices[2].Color = SColor(0xFFFFFFFF);\r
955                 quad2DVertices[3].Color = SColor(0xFFFFFFFF);\r
956 \r
957                 drawQuad(vt2DImage, quad2DVertices);\r
958         }\r
959 \r
960         void COpenGL3DriverBase::draw2DImageBatch(const video::ITexture* texture,\r
961                         const core::array<core::position2d<s32> >& positions,\r
962                         const core::array<core::rect<s32> >& sourceRects,\r
963                         const core::rect<s32>* clipRect,\r
964                         SColor color, bool useAlphaChannelOfTexture)\r
965         {\r
966                 if (!texture)\r
967                         return;\r
968 \r
969                 chooseMaterial2D();\r
970                 if (!setMaterialTexture(0, texture))\r
971                         return;\r
972 \r
973                 setRenderStates2DMode(color.getAlpha() < 255, true, useAlphaChannelOfTexture);\r
974 \r
975                 const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();\r
976 \r
977                 if (clipRect)\r
978                 {\r
979                         if (!clipRect->isValid())\r
980                                 return;\r
981 \r
982                         glEnable(GL_SCISSOR_TEST);\r
983                         glScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height - clipRect->LowerRightCorner.Y,\r
984                                         clipRect->getWidth(), clipRect->getHeight());\r
985                 }\r
986 \r
987                 const irr::u32 drawCount = core::min_<u32>(positions.size(), sourceRects.size());\r
988                 assert(6 * std::size_t(drawCount) <= QuadsIndices.size());\r
989 \r
990                 core::array<S3DVertex> vtx(drawCount * 4);\r
991 \r
992                 for (u32 i = 0; i < drawCount; i++)\r
993                 {\r
994                         core::position2d<s32> targetPos = positions[i];\r
995                         core::position2d<s32> sourcePos = sourceRects[i].UpperLeftCorner;\r
996                         // This needs to be signed as it may go negative.\r
997                         core::dimension2d<s32> sourceSize(sourceRects[i].getSize());\r
998 \r
999                         // now draw it.\r
1000 \r
1001                         core::rect<f32> tcoords;\r
1002                         tcoords.UpperLeftCorner.X = (((f32)sourcePos.X)) / texture->getOriginalSize().Width ;\r
1003                         tcoords.UpperLeftCorner.Y = (((f32)sourcePos.Y)) / texture->getOriginalSize().Height;\r
1004                         tcoords.LowerRightCorner.X = tcoords.UpperLeftCorner.X + ((f32)(sourceSize.Width) / texture->getOriginalSize().Width);\r
1005                         tcoords.LowerRightCorner.Y = tcoords.UpperLeftCorner.Y + ((f32)(sourceSize.Height) / texture->getOriginalSize().Height);\r
1006 \r
1007                         const core::rect<s32> poss(targetPos, sourceSize);\r
1008 \r
1009                         f32 left = (f32)poss.UpperLeftCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;\r
1010                         f32 right = (f32)poss.LowerRightCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;\r
1011                         f32 down = 2.f - (f32)poss.LowerRightCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
1012                         f32 top = 2.f - (f32)poss.UpperLeftCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
1013 \r
1014                         vtx.push_back(S3DVertex(left, top, 0.0f,\r
1015                                         0.0f, 0.0f, 0.0f, color,\r
1016                                         tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y));\r
1017                         vtx.push_back(S3DVertex(right, top, 0.0f,\r
1018                                         0.0f, 0.0f, 0.0f, color,\r
1019                                         tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y));\r
1020                         vtx.push_back(S3DVertex(right, down, 0.0f,\r
1021                                         0.0f, 0.0f, 0.0f, color,\r
1022                                         tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y));\r
1023                         vtx.push_back(S3DVertex(left, down, 0.0f,\r
1024                                         0.0f, 0.0f, 0.0f, color,\r
1025                                         tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y));\r
1026                 }\r
1027 \r
1028                 drawElements(GL_TRIANGLES, vt2DImage, vtx.const_pointer(), QuadsIndices.data(), 6 * drawCount);\r
1029 \r
1030                 if (clipRect)\r
1031                         glDisable(GL_SCISSOR_TEST);\r
1032         }\r
1033 \r
1034 \r
1035         //! draw a 2d rectangle\r
1036         void COpenGL3DriverBase::draw2DRectangle(SColor color,\r
1037                         const core::rect<s32>& position,\r
1038                         const core::rect<s32>* clip)\r
1039         {\r
1040                 chooseMaterial2D();\r
1041                 setMaterialTexture(0, 0);\r
1042 \r
1043                 setRenderStates2DMode(color.getAlpha() < 255, false, false);\r
1044 \r
1045                 core::rect<s32> pos = position;\r
1046 \r
1047                 if (clip)\r
1048                         pos.clipAgainst(*clip);\r
1049 \r
1050                 if (!pos.isValid())\r
1051                         return;\r
1052 \r
1053                 const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();\r
1054 \r
1055                 f32 left = (f32)pos.UpperLeftCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;\r
1056                 f32 right = (f32)pos.LowerRightCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;\r
1057                 f32 down = 2.f - (f32)pos.LowerRightCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
1058                 f32 top = 2.f - (f32)pos.UpperLeftCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
1059 \r
1060                 S3DVertex vertices[4];\r
1061                 vertices[0] = S3DVertex(left, top, 0, 0, 0, 1, color, 0, 0);\r
1062                 vertices[1] = S3DVertex(right, top, 0, 0, 0, 1, color, 0, 0);\r
1063                 vertices[2] = S3DVertex(right, down, 0, 0, 0, 1, color, 0, 0);\r
1064                 vertices[3] = S3DVertex(left, down, 0, 0, 0, 1, color, 0, 0);\r
1065 \r
1066                 drawQuad(vtPrimitive, vertices);\r
1067         }\r
1068 \r
1069 \r
1070         //! draw an 2d rectangle\r
1071         void COpenGL3DriverBase::draw2DRectangle(const core::rect<s32>& position,\r
1072                         SColor colorLeftUp, SColor colorRightUp,\r
1073                         SColor colorLeftDown, SColor colorRightDown,\r
1074                         const core::rect<s32>* clip)\r
1075         {\r
1076                 core::rect<s32> pos = position;\r
1077 \r
1078                 if (clip)\r
1079                         pos.clipAgainst(*clip);\r
1080 \r
1081                 if (!pos.isValid())\r
1082                         return;\r
1083 \r
1084                 chooseMaterial2D();\r
1085                 setMaterialTexture(0, 0);\r
1086 \r
1087                 setRenderStates2DMode(colorLeftUp.getAlpha() < 255 ||\r
1088                                 colorRightUp.getAlpha() < 255 ||\r
1089                                 colorLeftDown.getAlpha() < 255 ||\r
1090                                 colorRightDown.getAlpha() < 255, false, false);\r
1091 \r
1092                 const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();\r
1093 \r
1094                 f32 left = (f32)pos.UpperLeftCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;\r
1095                 f32 right = (f32)pos.LowerRightCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;\r
1096                 f32 down = 2.f - (f32)pos.LowerRightCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
1097                 f32 top = 2.f - (f32)pos.UpperLeftCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
1098 \r
1099                 S3DVertex vertices[4];\r
1100                 vertices[0] = S3DVertex(left, top, 0, 0, 0, 1, colorLeftUp, 0, 0);\r
1101                 vertices[1] = S3DVertex(right, top, 0, 0, 0, 1, colorRightUp, 0, 0);\r
1102                 vertices[2] = S3DVertex(right, down, 0, 0, 0, 1, colorRightDown, 0, 0);\r
1103                 vertices[3] = S3DVertex(left, down, 0, 0, 0, 1, colorLeftDown, 0, 0);\r
1104 \r
1105                 drawQuad(vtPrimitive, vertices);\r
1106         }\r
1107 \r
1108 \r
1109         //! Draws a 2d line.\r
1110         void COpenGL3DriverBase::draw2DLine(const core::position2d<s32>& start,\r
1111                         const core::position2d<s32>& end, SColor color)\r
1112         {\r
1113                 if (start==end)\r
1114                         drawPixel(start.X, start.Y, color);\r
1115                 else\r
1116                 {\r
1117                         chooseMaterial2D();\r
1118                         setMaterialTexture(0, 0);\r
1119 \r
1120                         setRenderStates2DMode(color.getAlpha() < 255, false, false);\r
1121 \r
1122                         const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();\r
1123 \r
1124                         f32 startX = (f32)start.X / (f32)renderTargetSize.Width * 2.f - 1.f;\r
1125                         f32 endX = (f32)end.X / (f32)renderTargetSize.Width * 2.f - 1.f;\r
1126                         f32 startY = 2.f - (f32)start.Y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
1127                         f32 endY = 2.f - (f32)end.Y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
1128 \r
1129                         S3DVertex vertices[2];\r
1130                         vertices[0] = S3DVertex(startX, startY, 0, 0, 0, 1, color, 0, 0);\r
1131                         vertices[1] = S3DVertex(endX, endY, 0, 0, 0, 1, color, 1, 1);\r
1132 \r
1133                         drawArrays(GL_LINES, vtPrimitive, vertices, 2);\r
1134                 }\r
1135         }\r
1136 \r
1137 \r
1138         //! Draws a pixel\r
1139         void COpenGL3DriverBase::drawPixel(u32 x, u32 y, const SColor &color)\r
1140         {\r
1141                 const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();\r
1142                 if (x > (u32)renderTargetSize.Width || y > (u32)renderTargetSize.Height)\r
1143                         return;\r
1144 \r
1145                 chooseMaterial2D();\r
1146                 setMaterialTexture(0, 0);\r
1147 \r
1148                 setRenderStates2DMode(color.getAlpha() < 255, false, false);\r
1149 \r
1150                 f32 X = (f32)x / (f32)renderTargetSize.Width * 2.f - 1.f;\r
1151                 f32 Y = 2.f - (f32)y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
1152 \r
1153                 S3DVertex vertices[1];\r
1154                 vertices[0] = S3DVertex(X, Y, 0, 0, 0, 1, color, 0, 0);\r
1155 \r
1156                 drawArrays(GL_POINTS, vtPrimitive, vertices, 1);\r
1157         }\r
1158 \r
1159         void COpenGL3DriverBase::drawQuad(const VertexType &vertexType, const S3DVertex (&vertices)[4])\r
1160         {\r
1161                 drawArrays(GL_TRIANGLE_FAN, vertexType, vertices, 4);\r
1162         }\r
1163 \r
1164         void COpenGL3DriverBase::drawArrays(GLenum primitiveType, const VertexType &vertexType, const void *vertices, int vertexCount)\r
1165         {\r
1166                 beginDraw(vertexType, reinterpret_cast<uintptr_t>(vertices));\r
1167                 glDrawArrays(primitiveType, 0, vertexCount);\r
1168                 endDraw(vertexType);\r
1169         }\r
1170 \r
1171         void COpenGL3DriverBase::drawElements(GLenum primitiveType, const VertexType &vertexType, const void *vertices, const u16 *indices, int indexCount)\r
1172         {\r
1173                 beginDraw(vertexType, reinterpret_cast<uintptr_t>(vertices));\r
1174                 glDrawElements(primitiveType, indexCount, GL_UNSIGNED_SHORT, indices);\r
1175                 endDraw(vertexType);\r
1176         }\r
1177 \r
1178         void COpenGL3DriverBase::beginDraw(const VertexType &vertexType, uintptr_t verticesBase)\r
1179         {\r
1180                 for (auto attr: vertexType) {\r
1181                         glEnableVertexAttribArray(attr.Index);\r
1182                         switch (attr.mode) {\r
1183                         case VertexAttribute::Mode::Regular: glVertexAttribPointer(attr.Index, attr.ComponentCount, attr.ComponentType, GL_FALSE, vertexType.VertexSize, reinterpret_cast<void *>(verticesBase + attr.Offset)); break;\r
1184                         case VertexAttribute::Mode::Normalized: glVertexAttribPointer(attr.Index, attr.ComponentCount, attr.ComponentType, GL_TRUE, vertexType.VertexSize, reinterpret_cast<void *>(verticesBase + attr.Offset)); break;\r
1185                         case VertexAttribute::Mode::Integral: glVertexAttribIPointer(attr.Index, attr.ComponentCount, attr.ComponentType, vertexType.VertexSize, reinterpret_cast<void *>(verticesBase + attr.Offset)); break;\r
1186                         }\r
1187                 }\r
1188         }\r
1189 \r
1190         void COpenGL3DriverBase::endDraw(const VertexType &vertexType)\r
1191         {\r
1192                 for (auto attr: vertexType)\r
1193                         glDisableVertexAttribArray(attr.Index);\r
1194         }\r
1195 \r
1196         ITexture* COpenGL3DriverBase::createDeviceDependentTexture(const io::path& name, IImage* image)\r
1197         {\r
1198                 core::array<IImage*> imageArray(1);\r
1199                 imageArray.push_back(image);\r
1200 \r
1201                 COpenGL3Texture* texture = new COpenGL3Texture(name, imageArray, ETT_2D, this);\r
1202 \r
1203                 return texture;\r
1204         }\r
1205 \r
1206         ITexture* COpenGL3DriverBase::createDeviceDependentTextureCubemap(const io::path& name, const core::array<IImage*>& image)\r
1207         {\r
1208                 COpenGL3Texture* texture = new COpenGL3Texture(name, image, ETT_CUBEMAP, this);\r
1209 \r
1210                 return texture;\r
1211         }\r
1212 \r
1213         //! Sets a material.\r
1214         void COpenGL3DriverBase::setMaterial(const SMaterial& material)\r
1215         {\r
1216                 Material = material;\r
1217                 OverrideMaterial.apply(Material);\r
1218 \r
1219                 for (u32 i = 0; i < Feature.MaxTextureUnits; ++i)\r
1220                 {\r
1221                         CacheHandler->getTextureCache().set(i, material.getTexture(i));\r
1222                         setTransform((E_TRANSFORMATION_STATE)(ETS_TEXTURE_0 + i), material.getTextureMatrix(i));\r
1223                 }\r
1224         }\r
1225 \r
1226         //! prints error if an error happened.\r
1227         bool COpenGL3DriverBase::testGLError(int code)\r
1228         {\r
1229 #ifdef _DEBUG\r
1230                 GLenum g = glGetError();\r
1231                 switch (g)\r
1232                 {\r
1233                         case GL_NO_ERROR:\r
1234                                 return false;\r
1235                         case GL_INVALID_ENUM:\r
1236                                 os::Printer::log("GL_INVALID_ENUM", core::stringc(code).c_str(), ELL_ERROR);\r
1237                                 break;\r
1238                         case GL_INVALID_VALUE:\r
1239                                 os::Printer::log("GL_INVALID_VALUE", core::stringc(code).c_str(), ELL_ERROR);\r
1240                                 break;\r
1241                         case GL_INVALID_OPERATION:\r
1242                                 os::Printer::log("GL_INVALID_OPERATION", core::stringc(code).c_str(), ELL_ERROR);\r
1243                                 break;\r
1244                         case GL_OUT_OF_MEMORY:\r
1245                                 os::Printer::log("GL_OUT_OF_MEMORY", core::stringc(code).c_str(), ELL_ERROR);\r
1246                                 break;\r
1247                 };\r
1248                 return true;\r
1249 #else\r
1250                 return false;\r
1251 #endif\r
1252         }\r
1253 \r
1254         //! prints error if an error happened.\r
1255         bool COpenGL3DriverBase::testEGLError()\r
1256         {\r
1257 #if defined(EGL_VERSION_1_0) && defined(_DEBUG)\r
1258                 EGLint g = eglGetError();\r
1259                 switch (g)\r
1260                 {\r
1261                         case EGL_SUCCESS:\r
1262                                 return false;\r
1263                         case EGL_NOT_INITIALIZED :\r
1264                                 os::Printer::log("Not Initialized", ELL_ERROR);\r
1265                                 break;\r
1266                         case EGL_BAD_ACCESS:\r
1267                                 os::Printer::log("Bad Access", ELL_ERROR);\r
1268                                 break;\r
1269                         case EGL_BAD_ALLOC:\r
1270                                 os::Printer::log("Bad Alloc", ELL_ERROR);\r
1271                                 break;\r
1272                         case EGL_BAD_ATTRIBUTE:\r
1273                                 os::Printer::log("Bad Attribute", ELL_ERROR);\r
1274                                 break;\r
1275                         case EGL_BAD_CONTEXT:\r
1276                                 os::Printer::log("Bad Context", ELL_ERROR);\r
1277                                 break;\r
1278                         case EGL_BAD_CONFIG:\r
1279                                 os::Printer::log("Bad Config", ELL_ERROR);\r
1280                                 break;\r
1281                         case EGL_BAD_CURRENT_SURFACE:\r
1282                                 os::Printer::log("Bad Current Surface", ELL_ERROR);\r
1283                                 break;\r
1284                         case EGL_BAD_DISPLAY:\r
1285                                 os::Printer::log("Bad Display", ELL_ERROR);\r
1286                                 break;\r
1287                         case EGL_BAD_SURFACE:\r
1288                                 os::Printer::log("Bad Surface", ELL_ERROR);\r
1289                                 break;\r
1290                         case EGL_BAD_MATCH:\r
1291                                 os::Printer::log("Bad Match", ELL_ERROR);\r
1292                                 break;\r
1293                         case EGL_BAD_PARAMETER:\r
1294                                 os::Printer::log("Bad Parameter", ELL_ERROR);\r
1295                                 break;\r
1296                         case EGL_BAD_NATIVE_PIXMAP:\r
1297                                 os::Printer::log("Bad Native Pixmap", ELL_ERROR);\r
1298                                 break;\r
1299                         case EGL_BAD_NATIVE_WINDOW:\r
1300                                 os::Printer::log("Bad Native Window", ELL_ERROR);\r
1301                                 break;\r
1302                         case EGL_CONTEXT_LOST:\r
1303                                 os::Printer::log("Context Lost", ELL_ERROR);\r
1304                                 break;\r
1305                 };\r
1306                 return true;\r
1307 #else\r
1308                 return false;\r
1309 #endif\r
1310         }\r
1311 \r
1312 \r
1313         void COpenGL3DriverBase::setRenderStates3DMode()\r
1314         {\r
1315                 if ( LockRenderStateMode )\r
1316                         return;\r
1317 \r
1318                 if (CurrentRenderMode != ERM_3D)\r
1319                 {\r
1320                         // Reset Texture Stages\r
1321                         CacheHandler->setBlend(false);\r
1322                         CacheHandler->setBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\r
1323 \r
1324                         ResetRenderStates = true;\r
1325                 }\r
1326 \r
1327                 if (ResetRenderStates || LastMaterial != Material)\r
1328                 {\r
1329                         // unset old material\r
1330 \r
1331                         // unset last 3d material\r
1332                         if (CurrentRenderMode == ERM_2D && MaterialRenderer2DActive)\r
1333                         {\r
1334                                 MaterialRenderer2DActive->OnUnsetMaterial();\r
1335                                 MaterialRenderer2DActive = 0;\r
1336                         }\r
1337                         else if (LastMaterial.MaterialType != Material.MaterialType &&\r
1338                                         static_cast<u32>(LastMaterial.MaterialType) < MaterialRenderers.size())\r
1339                                 MaterialRenderers[LastMaterial.MaterialType].Renderer->OnUnsetMaterial();\r
1340 \r
1341                         // set new material.\r
1342                         if (static_cast<u32>(Material.MaterialType) < MaterialRenderers.size())\r
1343                                 MaterialRenderers[Material.MaterialType].Renderer->OnSetMaterial(\r
1344                                         Material, LastMaterial, ResetRenderStates, this);\r
1345 \r
1346                         LastMaterial = Material;\r
1347                         CacheHandler->correctCacheMaterial(LastMaterial);\r
1348                         ResetRenderStates = false;\r
1349                 }\r
1350 \r
1351                 if (static_cast<u32>(Material.MaterialType) < MaterialRenderers.size())\r
1352                         MaterialRenderers[Material.MaterialType].Renderer->OnRender(this, video::EVT_STANDARD);\r
1353 \r
1354                 CurrentRenderMode = ERM_3D;\r
1355         }\r
1356 \r
1357         //! Can be called by an IMaterialRenderer to make its work easier.\r
1358         void COpenGL3DriverBase::setBasicRenderStates(const SMaterial& material, const SMaterial& lastmaterial, bool resetAllRenderStates)\r
1359         {\r
1360                 // ZBuffer\r
1361                 switch (material.ZBuffer)\r
1362                 {\r
1363                         case ECFN_DISABLED:\r
1364                                 CacheHandler->setDepthTest(false);\r
1365                                 break;\r
1366                         case ECFN_LESSEQUAL:\r
1367                                 CacheHandler->setDepthTest(true);\r
1368                                 CacheHandler->setDepthFunc(GL_LEQUAL);\r
1369                                 break;\r
1370                         case ECFN_EQUAL:\r
1371                                 CacheHandler->setDepthTest(true);\r
1372                                 CacheHandler->setDepthFunc(GL_EQUAL);\r
1373                                 break;\r
1374                         case ECFN_LESS:\r
1375                                 CacheHandler->setDepthTest(true);\r
1376                                 CacheHandler->setDepthFunc(GL_LESS);\r
1377                                 break;\r
1378                         case ECFN_NOTEQUAL:\r
1379                                 CacheHandler->setDepthTest(true);\r
1380                                 CacheHandler->setDepthFunc(GL_NOTEQUAL);\r
1381                                 break;\r
1382                         case ECFN_GREATEREQUAL:\r
1383                                 CacheHandler->setDepthTest(true);\r
1384                                 CacheHandler->setDepthFunc(GL_GEQUAL);\r
1385                                 break;\r
1386                         case ECFN_GREATER:\r
1387                                 CacheHandler->setDepthTest(true);\r
1388                                 CacheHandler->setDepthFunc(GL_GREATER);\r
1389                                 break;\r
1390                         case ECFN_ALWAYS:\r
1391                                 CacheHandler->setDepthTest(true);\r
1392                                 CacheHandler->setDepthFunc(GL_ALWAYS);\r
1393                                 break;\r
1394                         case ECFN_NEVER:\r
1395                                 CacheHandler->setDepthTest(true);\r
1396                                 CacheHandler->setDepthFunc(GL_NEVER);\r
1397                                 break;\r
1398                         default:\r
1399                                 break;\r
1400                 }\r
1401 \r
1402                 // ZWrite\r
1403                 if (getWriteZBuffer(material))\r
1404                 {\r
1405                         CacheHandler->setDepthMask(true);\r
1406                 }\r
1407                 else\r
1408                 {\r
1409                         CacheHandler->setDepthMask(false);\r
1410                 }\r
1411 \r
1412                 // Back face culling\r
1413                 if ((material.FrontfaceCulling) && (material.BackfaceCulling))\r
1414                 {\r
1415                         CacheHandler->setCullFaceFunc(GL_FRONT_AND_BACK);\r
1416                         CacheHandler->setCullFace(true);\r
1417                 }\r
1418                 else if (material.BackfaceCulling)\r
1419                 {\r
1420                         CacheHandler->setCullFaceFunc(GL_BACK);\r
1421                         CacheHandler->setCullFace(true);\r
1422                 }\r
1423                 else if (material.FrontfaceCulling)\r
1424                 {\r
1425                         CacheHandler->setCullFaceFunc(GL_FRONT);\r
1426                         CacheHandler->setCullFace(true);\r
1427                 }\r
1428                 else\r
1429                 {\r
1430                         CacheHandler->setCullFace(false);\r
1431                 }\r
1432 \r
1433                 // Color Mask\r
1434                 CacheHandler->setColorMask(material.ColorMask);\r
1435 \r
1436                 // Blend Equation\r
1437                 if (material.BlendOperation == EBO_NONE)\r
1438                         CacheHandler->setBlend(false);\r
1439                 else\r
1440                 {\r
1441                         CacheHandler->setBlend(true);\r
1442 \r
1443                         switch (material.BlendOperation)\r
1444                         {\r
1445                         case EBO_ADD:\r
1446                                 CacheHandler->setBlendEquation(GL_FUNC_ADD);\r
1447                                 break;\r
1448                         case EBO_SUBTRACT:\r
1449                                 CacheHandler->setBlendEquation(GL_FUNC_SUBTRACT);\r
1450                                 break;\r
1451                         case EBO_REVSUBTRACT:\r
1452                                 CacheHandler->setBlendEquation(GL_FUNC_REVERSE_SUBTRACT);\r
1453                                 break;\r
1454                         default:\r
1455                                 break;\r
1456                         }\r
1457                 }\r
1458 \r
1459                 // Blend Factor\r
1460                 if (IR(material.BlendFactor) & 0xFFFFFFFF       // TODO: why the & 0xFFFFFFFF?\r
1461                         && material.MaterialType != EMT_ONETEXTURE_BLEND\r
1462                 )\r
1463                 {\r
1464                     E_BLEND_FACTOR srcRGBFact = EBF_ZERO;\r
1465                     E_BLEND_FACTOR dstRGBFact = EBF_ZERO;\r
1466                     E_BLEND_FACTOR srcAlphaFact = EBF_ZERO;\r
1467                     E_BLEND_FACTOR dstAlphaFact = EBF_ZERO;\r
1468                     E_MODULATE_FUNC modulo = EMFN_MODULATE_1X;\r
1469                     u32 alphaSource = 0;\r
1470 \r
1471                     unpack_textureBlendFuncSeparate(srcRGBFact, dstRGBFact, srcAlphaFact, dstAlphaFact, modulo, alphaSource, material.BlendFactor);\r
1472 \r
1473                         CacheHandler->setBlendFuncSeparate(getGLBlend(srcRGBFact), getGLBlend(dstRGBFact),\r
1474                                 getGLBlend(srcAlphaFact), getGLBlend(dstAlphaFact));\r
1475                 }\r
1476 \r
1477                 // TODO: Polygon Offset. Not sure if it was left out deliberately or if it won't work with this driver.\r
1478 \r
1479                 if (resetAllRenderStates || lastmaterial.Thickness != material.Thickness)\r
1480                         glLineWidth(core::clamp(static_cast<GLfloat>(material.Thickness), DimAliasedLine[0], DimAliasedLine[1]));\r
1481 \r
1482                 // Anti aliasing\r
1483                 if (resetAllRenderStates || lastmaterial.AntiAliasing != material.AntiAliasing)\r
1484                 {\r
1485                         if (material.AntiAliasing & EAAM_ALPHA_TO_COVERAGE)\r
1486                                 glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);\r
1487                         else if (lastmaterial.AntiAliasing & EAAM_ALPHA_TO_COVERAGE)\r
1488                                 glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);\r
1489                 }\r
1490 \r
1491                 // Texture parameters\r
1492                 setTextureRenderStates(material, resetAllRenderStates);\r
1493         }\r
1494 \r
1495         //! Compare in SMaterial doesn't check texture parameters, so we should call this on each OnRender call.\r
1496         void COpenGL3DriverBase::setTextureRenderStates(const SMaterial& material, bool resetAllRenderstates)\r
1497         {\r
1498                 // Set textures to TU/TIU and apply filters to them\r
1499 \r
1500                 for (s32 i = Feature.MaxTextureUnits - 1; i >= 0; --i)\r
1501                 {\r
1502                         const COpenGL3Texture* tmpTexture = CacheHandler->getTextureCache()[i];\r
1503 \r
1504                         if (!tmpTexture)\r
1505                                 continue;\r
1506 \r
1507                         GLenum tmpTextureType = tmpTexture->getOpenGLTextureType();\r
1508 \r
1509                         CacheHandler->setActiveTexture(GL_TEXTURE0 + i);\r
1510 \r
1511                         if (resetAllRenderstates)\r
1512                                 tmpTexture->getStatesCache().IsCached = false;\r
1513 \r
1514                         if (!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].BilinearFilter != tmpTexture->getStatesCache().BilinearFilter ||\r
1515                                 material.TextureLayer[i].TrilinearFilter != tmpTexture->getStatesCache().TrilinearFilter)\r
1516                         {\r
1517                                 glTexParameteri(tmpTextureType, GL_TEXTURE_MAG_FILTER,\r
1518                                         (material.TextureLayer[i].BilinearFilter || material.TextureLayer[i].TrilinearFilter) ? GL_LINEAR : GL_NEAREST);\r
1519 \r
1520                                 tmpTexture->getStatesCache().BilinearFilter = material.TextureLayer[i].BilinearFilter;\r
1521                                 tmpTexture->getStatesCache().TrilinearFilter = material.TextureLayer[i].TrilinearFilter;\r
1522                         }\r
1523 \r
1524                         if (material.UseMipMaps && tmpTexture->hasMipMaps())\r
1525                         {\r
1526                                 if (!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].BilinearFilter != tmpTexture->getStatesCache().BilinearFilter ||\r
1527                                         material.TextureLayer[i].TrilinearFilter != tmpTexture->getStatesCache().TrilinearFilter || !tmpTexture->getStatesCache().MipMapStatus)\r
1528                                 {\r
1529                                         glTexParameteri(tmpTextureType, GL_TEXTURE_MIN_FILTER,\r
1530                                                 material.TextureLayer[i].TrilinearFilter ? GL_LINEAR_MIPMAP_LINEAR :\r
1531                                                 material.TextureLayer[i].BilinearFilter ? GL_LINEAR_MIPMAP_NEAREST :\r
1532                                                 GL_NEAREST_MIPMAP_NEAREST);\r
1533 \r
1534                                         tmpTexture->getStatesCache().BilinearFilter = material.TextureLayer[i].BilinearFilter;\r
1535                                         tmpTexture->getStatesCache().TrilinearFilter = material.TextureLayer[i].TrilinearFilter;\r
1536                                         tmpTexture->getStatesCache().MipMapStatus = true;\r
1537                                 }\r
1538                         }\r
1539                         else\r
1540                         {\r
1541                                 if (!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].BilinearFilter != tmpTexture->getStatesCache().BilinearFilter ||\r
1542                                         material.TextureLayer[i].TrilinearFilter != tmpTexture->getStatesCache().TrilinearFilter || tmpTexture->getStatesCache().MipMapStatus)\r
1543                                 {\r
1544                                         glTexParameteri(tmpTextureType, GL_TEXTURE_MIN_FILTER,\r
1545                                                 (material.TextureLayer[i].BilinearFilter || material.TextureLayer[i].TrilinearFilter) ? GL_LINEAR : GL_NEAREST);\r
1546 \r
1547                                         tmpTexture->getStatesCache().BilinearFilter = material.TextureLayer[i].BilinearFilter;\r
1548                                         tmpTexture->getStatesCache().TrilinearFilter = material.TextureLayer[i].TrilinearFilter;\r
1549                                         tmpTexture->getStatesCache().MipMapStatus = false;\r
1550                                 }\r
1551                         }\r
1552 \r
1553         #ifdef GL_EXT_texture_filter_anisotropic\r
1554                         if (FeatureAvailable[COGLESCoreExtensionHandler::IRR_GL_EXT_texture_filter_anisotropic] &&\r
1555                                 (!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].AnisotropicFilter != tmpTexture->getStatesCache().AnisotropicFilter))\r
1556                         {\r
1557                                 glTexParameteri(tmpTextureType, GL_TEXTURE_MAX_ANISOTROPY_EXT,\r
1558                                         material.TextureLayer[i].AnisotropicFilter>1 ? core::min_(MaxAnisotropy, material.TextureLayer[i].AnisotropicFilter) : 1);\r
1559 \r
1560                                 tmpTexture->getStatesCache().AnisotropicFilter = material.TextureLayer[i].AnisotropicFilter;\r
1561                         }\r
1562         #endif\r
1563 \r
1564                         if (!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].TextureWrapU != tmpTexture->getStatesCache().WrapU)\r
1565                         {\r
1566                                 glTexParameteri(tmpTextureType, GL_TEXTURE_WRAP_S, getTextureWrapMode(material.TextureLayer[i].TextureWrapU));\r
1567                                 tmpTexture->getStatesCache().WrapU = material.TextureLayer[i].TextureWrapU;\r
1568                         }\r
1569 \r
1570                         if (!tmpTexture->getStatesCache().IsCached || material.TextureLayer[i].TextureWrapV != tmpTexture->getStatesCache().WrapV)\r
1571                         {\r
1572                                 glTexParameteri(tmpTextureType, GL_TEXTURE_WRAP_T, getTextureWrapMode(material.TextureLayer[i].TextureWrapV));\r
1573                                 tmpTexture->getStatesCache().WrapV = material.TextureLayer[i].TextureWrapV;\r
1574                         }\r
1575 \r
1576                         tmpTexture->getStatesCache().IsCached = true;\r
1577                 }\r
1578         }\r
1579 \r
1580 \r
1581         // Get OpenGL ES2.0 texture wrap mode from Irrlicht wrap mode.\r
1582         GLint COpenGL3DriverBase::getTextureWrapMode(u8 clamp) const\r
1583         {\r
1584                 switch (clamp)\r
1585                 {\r
1586                         case ETC_CLAMP:\r
1587                         case ETC_CLAMP_TO_EDGE:\r
1588                         case ETC_CLAMP_TO_BORDER:\r
1589                                 return GL_CLAMP_TO_EDGE;\r
1590                         case ETC_MIRROR:\r
1591                                 return GL_REPEAT;\r
1592                         default:\r
1593                                 return GL_REPEAT;\r
1594                 }\r
1595         }\r
1596 \r
1597 \r
1598         //! sets the needed renderstates\r
1599         void COpenGL3DriverBase::setRenderStates2DMode(bool alpha, bool texture, bool alphaChannel)\r
1600         {\r
1601                 if ( LockRenderStateMode )\r
1602                         return;\r
1603 \r
1604                 COpenGL3Renderer2D* nextActiveRenderer = texture ? MaterialRenderer2DTexture : MaterialRenderer2DNoTexture;\r
1605 \r
1606                 if (CurrentRenderMode != ERM_2D)\r
1607                 {\r
1608                         // unset last 3d material\r
1609                         if (CurrentRenderMode == ERM_3D)\r
1610                         {\r
1611                                 if (static_cast<u32>(LastMaterial.MaterialType) < MaterialRenderers.size())\r
1612                                         MaterialRenderers[LastMaterial.MaterialType].Renderer->OnUnsetMaterial();\r
1613                         }\r
1614 \r
1615                         CurrentRenderMode = ERM_2D;\r
1616                 }\r
1617                 else if ( MaterialRenderer2DActive && MaterialRenderer2DActive != nextActiveRenderer)\r
1618                 {\r
1619                         MaterialRenderer2DActive->OnUnsetMaterial();\r
1620                 }\r
1621 \r
1622                 MaterialRenderer2DActive = nextActiveRenderer;\r
1623 \r
1624                 MaterialRenderer2DActive->OnSetMaterial(Material, LastMaterial, true, 0);\r
1625                 LastMaterial = Material;\r
1626                 CacheHandler->correctCacheMaterial(LastMaterial);\r
1627 \r
1628                 // no alphaChannel without texture\r
1629                 alphaChannel &= texture;\r
1630 \r
1631                 if (alphaChannel || alpha)\r
1632                 {\r
1633                         CacheHandler->setBlend(true);\r
1634                         CacheHandler->setBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\r
1635                         CacheHandler->setBlendEquation(GL_FUNC_ADD);\r
1636                 }\r
1637                 else\r
1638                         CacheHandler->setBlend(false);\r
1639 \r
1640                 Material.setTexture(0, const_cast<COpenGL3Texture*>(CacheHandler->getTextureCache().get(0)));\r
1641                 setTransform(ETS_TEXTURE_0, core::IdentityMatrix);\r
1642 \r
1643                 if (texture)\r
1644                 {\r
1645                         if (OverrideMaterial2DEnabled)\r
1646                                 setTextureRenderStates(OverrideMaterial2D, false);\r
1647                         else\r
1648                                 setTextureRenderStates(InitMaterial2D, false);\r
1649                 }\r
1650 \r
1651                 MaterialRenderer2DActive->OnRender(this, video::EVT_STANDARD);\r
1652         }\r
1653 \r
1654 \r
1655         void COpenGL3DriverBase::chooseMaterial2D()\r
1656         {\r
1657                 if (!OverrideMaterial2DEnabled)\r
1658                         Material = InitMaterial2D;\r
1659 \r
1660                 if (OverrideMaterial2DEnabled)\r
1661                 {\r
1662                         OverrideMaterial2D.Lighting=false;\r
1663                         OverrideMaterial2D.ZWriteEnable=EZW_OFF;\r
1664                         OverrideMaterial2D.ZBuffer=ECFN_DISABLED; // it will be ECFN_DISABLED after merge\r
1665                         OverrideMaterial2D.Lighting=false;\r
1666 \r
1667                         Material = OverrideMaterial2D;\r
1668                 }\r
1669         }\r
1670 \r
1671 \r
1672         //! \return Returns the name of the video driver.\r
1673         const wchar_t* COpenGL3DriverBase::getName() const\r
1674         {\r
1675                 return Name.c_str();\r
1676         }\r
1677 \r
1678         void COpenGL3DriverBase::setViewPort(const core::rect<s32>& area)\r
1679         {\r
1680                 core::rect<s32> vp = area;\r
1681                 core::rect<s32> rendert(0, 0, getCurrentRenderTargetSize().Width, getCurrentRenderTargetSize().Height);\r
1682                 vp.clipAgainst(rendert);\r
1683 \r
1684                 if (vp.getHeight() > 0 && vp.getWidth() > 0)\r
1685                         CacheHandler->setViewport(vp.UpperLeftCorner.X, getCurrentRenderTargetSize().Height - vp.UpperLeftCorner.Y - vp.getHeight(), vp.getWidth(), vp.getHeight());\r
1686 \r
1687                 ViewPort = vp;\r
1688         }\r
1689 \r
1690 \r
1691         void COpenGL3DriverBase::setViewPortRaw(u32 width, u32 height)\r
1692         {\r
1693                 CacheHandler->setViewport(0, 0, width, height);\r
1694                 ViewPort = core::recti(0, 0, width, height);\r
1695         }\r
1696 \r
1697 \r
1698         //! Draws a 3d line.\r
1699         void COpenGL3DriverBase::draw3DLine(const core::vector3df& start,\r
1700                         const core::vector3df& end, SColor color)\r
1701         {\r
1702                 setRenderStates3DMode();\r
1703 \r
1704                 S3DVertex vertices[2];\r
1705                 vertices[0] = S3DVertex(start.X, start.Y, start.Z, 0, 0, 1, color, 0, 0);\r
1706                 vertices[1] = S3DVertex(end.X, end.Y, end.Z, 0, 0, 1, color, 0, 0);\r
1707 \r
1708                 drawArrays(GL_LINES, vtPrimitive, vertices, 2);\r
1709         }\r
1710 \r
1711 \r
1712         //! Only used by the internal engine. Used to notify the driver that\r
1713         //! the window was resized.\r
1714         void COpenGL3DriverBase::OnResize(const core::dimension2d<u32>& size)\r
1715         {\r
1716                 CNullDriver::OnResize(size);\r
1717                 CacheHandler->setViewport(0, 0, size.Width, size.Height);\r
1718                 Transformation3DChanged = true;\r
1719         }\r
1720 \r
1721 \r
1722         //! Returns type of video driver\r
1723         E_DRIVER_TYPE COpenGL3DriverBase::getDriverType() const\r
1724         {\r
1725                 return EDT_OPENGL3;\r
1726         }\r
1727 \r
1728 \r
1729         //! returns color format\r
1730         ECOLOR_FORMAT COpenGL3DriverBase::getColorFormat() const\r
1731         {\r
1732                 return ColorFormat;\r
1733         }\r
1734 \r
1735 \r
1736         //! Get a vertex shader constant index.\r
1737         s32 COpenGL3DriverBase::getVertexShaderConstantID(const c8* name)\r
1738         {\r
1739                 return getPixelShaderConstantID(name);\r
1740         }\r
1741 \r
1742         //! Get a pixel shader constant index.\r
1743         s32 COpenGL3DriverBase::getPixelShaderConstantID(const c8* name)\r
1744         {\r
1745                 os::Printer::log("Error: Please call services->getPixelShaderConstantID(), not VideoDriver->getPixelShaderConstantID().");\r
1746                 return -1;\r
1747         }\r
1748 \r
1749         //! Sets a vertex shader constant.\r
1750         void COpenGL3DriverBase::setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount)\r
1751         {\r
1752                 os::Printer::log("Error: Please call services->setVertexShaderConstant(), not VideoDriver->setPixelShaderConstant().");\r
1753         }\r
1754 \r
1755         //! Sets a pixel shader constant.\r
1756         void COpenGL3DriverBase::setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount)\r
1757         {\r
1758                 os::Printer::log("Error: Please call services->setPixelShaderConstant(), not VideoDriver->setPixelShaderConstant().");\r
1759         }\r
1760 \r
1761         //! Sets a constant for the vertex shader based on an index.\r
1762         bool COpenGL3DriverBase::setVertexShaderConstant(s32 index, const f32* floats, int count)\r
1763         {\r
1764                 os::Printer::log("Error: Please call services->setVertexShaderConstant(), not VideoDriver->setVertexShaderConstant().");\r
1765                 return false;\r
1766         }\r
1767 \r
1768         //! Int interface for the above.\r
1769         bool COpenGL3DriverBase::setVertexShaderConstant(s32 index, const s32* ints, int count)\r
1770         {\r
1771                 os::Printer::log("Error: Please call services->setVertexShaderConstant(), not VideoDriver->setVertexShaderConstant().");\r
1772                 return false;\r
1773         }\r
1774 \r
1775         bool COpenGL3DriverBase::setVertexShaderConstant(s32 index, const u32* ints, int count)\r
1776         {\r
1777                 os::Printer::log("Error: Please call services->setVertexShaderConstant(), not VideoDriver->setVertexShaderConstant().");\r
1778                 return false;\r
1779         }\r
1780 \r
1781         //! Sets a constant for the pixel shader based on an index.\r
1782         bool COpenGL3DriverBase::setPixelShaderConstant(s32 index, const f32* floats, int count)\r
1783         {\r
1784                 os::Printer::log("Error: Please call services->setPixelShaderConstant(), not VideoDriver->setPixelShaderConstant().");\r
1785                 return false;\r
1786         }\r
1787 \r
1788         //! Int interface for the above.\r
1789         bool COpenGL3DriverBase::setPixelShaderConstant(s32 index, const s32* ints, int count)\r
1790         {\r
1791                 os::Printer::log("Error: Please call services->setPixelShaderConstant(), not VideoDriver->setPixelShaderConstant().");\r
1792                 return false;\r
1793         }\r
1794 \r
1795         bool COpenGL3DriverBase::setPixelShaderConstant(s32 index, const u32* ints, int count)\r
1796         {\r
1797                 os::Printer::log("Error: Please call services->setPixelShaderConstant(), not VideoDriver->setPixelShaderConstant().");\r
1798                 return false;\r
1799         }\r
1800 \r
1801         //! Adds a new material renderer to the VideoDriver, using pixel and/or\r
1802         //! vertex shaders to render geometry.\r
1803         s32 COpenGL3DriverBase::addShaderMaterial(const c8* vertexShaderProgram,\r
1804                         const c8* pixelShaderProgram,\r
1805                         IShaderConstantSetCallBack* callback,\r
1806                         E_MATERIAL_TYPE baseMaterial, s32 userData)\r
1807         {\r
1808                 os::Printer::log("No shader support.");\r
1809                 return -1;\r
1810         }\r
1811 \r
1812 \r
1813         //! Adds a new material renderer to the VideoDriver, using GLSL to render geometry.\r
1814         s32 COpenGL3DriverBase::addHighLevelShaderMaterial(\r
1815                         const c8* vertexShaderProgram,\r
1816                         const c8* vertexShaderEntryPointName,\r
1817                         E_VERTEX_SHADER_TYPE vsCompileTarget,\r
1818                         const c8* pixelShaderProgram,\r
1819                         const c8* pixelShaderEntryPointName,\r
1820                         E_PIXEL_SHADER_TYPE psCompileTarget,\r
1821                         const c8* geometryShaderProgram,\r
1822                         const c8* geometryShaderEntryPointName,\r
1823                         E_GEOMETRY_SHADER_TYPE gsCompileTarget,\r
1824                         scene::E_PRIMITIVE_TYPE inType,\r
1825                         scene::E_PRIMITIVE_TYPE outType,\r
1826                         u32 verticesOut,\r
1827                         IShaderConstantSetCallBack* callback,\r
1828                         E_MATERIAL_TYPE baseMaterial,\r
1829                         s32 userData)\r
1830         {\r
1831                 s32 nr = -1;\r
1832                 COpenGL3MaterialRenderer* r = new COpenGL3MaterialRenderer(\r
1833                         this, nr, vertexShaderProgram,\r
1834                         pixelShaderProgram,\r
1835                         callback, baseMaterial, userData);\r
1836 \r
1837                 r->drop();\r
1838                 return nr;\r
1839         }\r
1840 \r
1841         //! Returns a pointer to the IVideoDriver interface. (Implementation for\r
1842         //! IMaterialRendererServices)\r
1843         IVideoDriver* COpenGL3DriverBase::getVideoDriver()\r
1844         {\r
1845                 return this;\r
1846         }\r
1847 \r
1848 \r
1849         //! Returns pointer to the IGPUProgrammingServices interface.\r
1850         IGPUProgrammingServices* COpenGL3DriverBase::getGPUProgrammingServices()\r
1851         {\r
1852                 return this;\r
1853         }\r
1854 \r
1855         ITexture* COpenGL3DriverBase::addRenderTargetTexture(const core::dimension2d<u32>& size,\r
1856                 const io::path& name, const ECOLOR_FORMAT format)\r
1857         {\r
1858                 //disable mip-mapping\r
1859                 bool generateMipLevels = getTextureCreationFlag(ETCF_CREATE_MIP_MAPS);\r
1860                 setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, false);\r
1861 \r
1862                 COpenGL3Texture* renderTargetTexture = new COpenGL3Texture(name, size, ETT_2D, format, this);\r
1863                 addTexture(renderTargetTexture);\r
1864                 renderTargetTexture->drop();\r
1865 \r
1866                 //restore mip-mapping\r
1867                 setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, generateMipLevels);\r
1868 \r
1869                 return renderTargetTexture;\r
1870         }\r
1871 \r
1872         ITexture* COpenGL3DriverBase::addRenderTargetTextureCubemap(const irr::u32 sideLen, const io::path& name, const ECOLOR_FORMAT format)\r
1873         {\r
1874                 //disable mip-mapping\r
1875                 bool generateMipLevels = getTextureCreationFlag(ETCF_CREATE_MIP_MAPS);\r
1876                 setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, false);\r
1877 \r
1878                 bool supportForFBO = (Feature.ColorAttachment > 0);\r
1879 \r
1880                 const core::dimension2d<u32> size(sideLen, sideLen);\r
1881                 core::dimension2du destSize(size);\r
1882 \r
1883                 if (!supportForFBO)\r
1884                 {\r
1885                         destSize = core::dimension2d<u32>(core::min_(size.Width, ScreenSize.Width), core::min_(size.Height, ScreenSize.Height));\r
1886                         destSize = destSize.getOptimalSize((size == size.getOptimalSize()), false, false);\r
1887                 }\r
1888 \r
1889                 COpenGL3Texture* renderTargetTexture = new COpenGL3Texture(name, destSize, ETT_CUBEMAP, format, this);\r
1890                 addTexture(renderTargetTexture);\r
1891                 renderTargetTexture->drop();\r
1892 \r
1893                 //restore mip-mapping\r
1894                 setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, generateMipLevels);\r
1895 \r
1896                 return renderTargetTexture;\r
1897         }\r
1898 \r
1899 \r
1900         //! Returns the maximum amount of primitives\r
1901         u32 COpenGL3DriverBase::getMaximalPrimitiveCount() const\r
1902         {\r
1903                 return 65535;\r
1904         }\r
1905 \r
1906         bool COpenGL3DriverBase::setRenderTargetEx(IRenderTarget* target, u16 clearFlag, SColor clearColor, f32 clearDepth, u8 clearStencil)\r
1907         {\r
1908                 if (target && target->getDriverType() != getDriverType())\r
1909                 {\r
1910                         os::Printer::log("Fatal Error: Tried to set a render target not owned by OpenGL 3 driver.", ELL_ERROR);\r
1911                         return false;\r
1912                 }\r
1913 \r
1914                 core::dimension2d<u32> destRenderTargetSize(0, 0);\r
1915 \r
1916                 if (target)\r
1917                 {\r
1918                         COpenGL3RenderTarget* renderTarget = static_cast<COpenGL3RenderTarget*>(target);\r
1919 \r
1920                         CacheHandler->setFBO(renderTarget->getBufferID());\r
1921                         renderTarget->update();\r
1922 \r
1923                         destRenderTargetSize = renderTarget->getSize();\r
1924 \r
1925                         setViewPortRaw(destRenderTargetSize.Width, destRenderTargetSize.Height);\r
1926                 }\r
1927                 else\r
1928                 {\r
1929                         CacheHandler->setFBO(0);\r
1930 \r
1931                         destRenderTargetSize = core::dimension2d<u32>(0, 0);\r
1932 \r
1933                         setViewPortRaw(ScreenSize.Width, ScreenSize.Height);\r
1934                 }\r
1935 \r
1936                 if (CurrentRenderTargetSize != destRenderTargetSize)\r
1937                 {\r
1938                         CurrentRenderTargetSize = destRenderTargetSize;\r
1939 \r
1940                         Transformation3DChanged = true;\r
1941                 }\r
1942 \r
1943                 CurrentRenderTarget = target;\r
1944 \r
1945                 clearBuffers(clearFlag, clearColor, clearDepth, clearStencil);\r
1946 \r
1947                 return true;\r
1948         }\r
1949 \r
1950         void COpenGL3DriverBase::clearBuffers(u16 flag, SColor color, f32 depth, u8 stencil)\r
1951         {\r
1952                 GLbitfield mask = 0;\r
1953                 u8 colorMask = 0;\r
1954                 bool depthMask = false;\r
1955 \r
1956                 CacheHandler->getColorMask(colorMask);\r
1957                 CacheHandler->getDepthMask(depthMask);\r
1958 \r
1959                 if (flag & ECBF_COLOR)\r
1960                 {\r
1961                         CacheHandler->setColorMask(ECP_ALL);\r
1962 \r
1963                         const f32 inv = 1.0f / 255.0f;\r
1964                         glClearColor(color.getRed() * inv, color.getGreen() * inv,\r
1965                                 color.getBlue() * inv, color.getAlpha() * inv);\r
1966 \r
1967                         mask |= GL_COLOR_BUFFER_BIT;\r
1968                 }\r
1969 \r
1970                 if (flag & ECBF_DEPTH)\r
1971                 {\r
1972                         CacheHandler->setDepthMask(true);\r
1973                         glClearDepthf(depth);\r
1974                         mask |= GL_DEPTH_BUFFER_BIT;\r
1975                 }\r
1976 \r
1977                 if (flag & ECBF_STENCIL)\r
1978                 {\r
1979                         glClearStencil(stencil);\r
1980                         mask |= GL_STENCIL_BUFFER_BIT;\r
1981                 }\r
1982 \r
1983                 if (mask)\r
1984                         glClear(mask);\r
1985 \r
1986                 CacheHandler->setColorMask(colorMask);\r
1987                 CacheHandler->setDepthMask(depthMask);\r
1988         }\r
1989 \r
1990 \r
1991         //! Returns an image created from the last rendered frame.\r
1992         // We want to read the front buffer to get the latest render finished.\r
1993         // This is not possible under ogl-es, though, so one has to call this method\r
1994         // outside of the render loop only.\r
1995         IImage* COpenGL3DriverBase::createScreenShot(video::ECOLOR_FORMAT format, video::E_RENDER_TARGET target)\r
1996         {\r
1997                 if (target==video::ERT_MULTI_RENDER_TEXTURES || target==video::ERT_RENDER_TEXTURE || target==video::ERT_STEREO_BOTH_BUFFERS)\r
1998                         return 0;\r
1999 \r
2000                 GLint internalformat = GL_RGBA;\r
2001                 GLint type = GL_UNSIGNED_BYTE;\r
2002                 {\r
2003 //                      glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &internalformat);\r
2004 //                      glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &type);\r
2005                         // there's a format we don't support ATM\r
2006                         if (GL_UNSIGNED_SHORT_4_4_4_4 == type)\r
2007                         {\r
2008                                 internalformat = GL_RGBA;\r
2009                                 type = GL_UNSIGNED_BYTE;\r
2010                         }\r
2011                 }\r
2012 \r
2013                 IImage* newImage = 0;\r
2014                 if (GL_RGBA == internalformat)\r
2015                 {\r
2016                         if (GL_UNSIGNED_BYTE == type)\r
2017                                 newImage = new CImage(ECF_A8R8G8B8, ScreenSize);\r
2018                         else\r
2019                                 newImage = new CImage(ECF_A1R5G5B5, ScreenSize);\r
2020                 }\r
2021                 else\r
2022                 {\r
2023                         if (GL_UNSIGNED_BYTE == type)\r
2024                                 newImage = new CImage(ECF_R8G8B8, ScreenSize);\r
2025                         else\r
2026                                 newImage = new CImage(ECF_R5G6B5, ScreenSize);\r
2027                 }\r
2028 \r
2029                 if (!newImage)\r
2030                         return 0;\r
2031 \r
2032                 u8* pixels = static_cast<u8*>(newImage->getData());\r
2033                 if (!pixels)\r
2034                 {\r
2035                         newImage->drop();\r
2036                         return 0;\r
2037                 }\r
2038 \r
2039                 glReadPixels(0, 0, ScreenSize.Width, ScreenSize.Height, internalformat, type, pixels);\r
2040                 testGLError(__LINE__);\r
2041 \r
2042                 // opengl images are horizontally flipped, so we have to fix that here.\r
2043                 const s32 pitch = newImage->getPitch();\r
2044                 u8* p2 = pixels + (ScreenSize.Height - 1) * pitch;\r
2045                 u8* tmpBuffer = new u8[pitch];\r
2046                 for (u32 i = 0; i < ScreenSize.Height; i += 2)\r
2047                 {\r
2048                         memcpy(tmpBuffer, pixels, pitch);\r
2049                         memcpy(pixels, p2, pitch);\r
2050                         memcpy(p2, tmpBuffer, pitch);\r
2051                         pixels += pitch;\r
2052                         p2 -= pitch;\r
2053                 }\r
2054                 delete [] tmpBuffer;\r
2055 \r
2056                 // also GL_RGBA doesn't match the internal encoding of the image (which is BGRA)\r
2057                 if (GL_RGBA == internalformat && GL_UNSIGNED_BYTE == type)\r
2058                 {\r
2059                         pixels = static_cast<u8*>(newImage->getData());\r
2060                         for (u32 i = 0; i < ScreenSize.Height; i++)\r
2061                         {\r
2062                                 for (u32 j = 0; j < ScreenSize.Width; j++)\r
2063                                 {\r
2064                                         u32 c = *(u32*) (pixels + 4 * j);\r
2065                                         *(u32*) (pixels + 4 * j) = (c & 0xFF00FF00) |\r
2066                                                 ((c & 0x00FF0000) >> 16) | ((c & 0x000000FF) << 16);\r
2067                                 }\r
2068                                 pixels += pitch;\r
2069                         }\r
2070                 }\r
2071 \r
2072                 if (testGLError(__LINE__))\r
2073                 {\r
2074                         newImage->drop();\r
2075                         return 0;\r
2076                 }\r
2077                 testGLError(__LINE__);\r
2078                 return newImage;\r
2079         }\r
2080 \r
2081         void COpenGL3DriverBase::removeTexture(ITexture* texture)\r
2082         {\r
2083                 CacheHandler->getTextureCache().remove(texture);\r
2084                 CNullDriver::removeTexture(texture);\r
2085         }\r
2086 \r
2087         //! Set/unset a clipping plane.\r
2088         bool COpenGL3DriverBase::setClipPlane(u32 index, const core::plane3df& plane, bool enable)\r
2089         {\r
2090                 if (index >= UserClipPlane.size())\r
2091                         UserClipPlane.push_back(SUserClipPlane());\r
2092 \r
2093                 UserClipPlane[index].Plane = plane;\r
2094                 UserClipPlane[index].Enabled = enable;\r
2095                 return true;\r
2096         }\r
2097 \r
2098         //! Enable/disable a clipping plane.\r
2099         void COpenGL3DriverBase::enableClipPlane(u32 index, bool enable)\r
2100         {\r
2101                 UserClipPlane[index].Enabled = enable;\r
2102         }\r
2103 \r
2104         //! Get the ClipPlane Count\r
2105         u32 COpenGL3DriverBase::getClipPlaneCount() const\r
2106         {\r
2107                 return UserClipPlane.size();\r
2108         }\r
2109 \r
2110         const core::plane3df& COpenGL3DriverBase::getClipPlane(irr::u32 index) const\r
2111         {\r
2112                 if (index < UserClipPlane.size())\r
2113                         return UserClipPlane[index].Plane;\r
2114                 else\r
2115                 {\r
2116                         _IRR_DEBUG_BREAK_IF(true)       // invalid index\r
2117                         static const core::plane3df dummy;\r
2118                         return dummy;\r
2119                 }\r
2120         }\r
2121 \r
2122         core::dimension2du COpenGL3DriverBase::getMaxTextureSize() const\r
2123         {\r
2124                 return core::dimension2du(MaxTextureSize, MaxTextureSize);\r
2125         }\r
2126 \r
2127         GLenum COpenGL3DriverBase::getGLBlend(E_BLEND_FACTOR factor) const\r
2128         {\r
2129                 static GLenum const blendTable[] =\r
2130                 {\r
2131                         GL_ZERO,\r
2132                         GL_ONE,\r
2133                         GL_DST_COLOR,\r
2134                         GL_ONE_MINUS_DST_COLOR,\r
2135                         GL_SRC_COLOR,\r
2136                         GL_ONE_MINUS_SRC_COLOR,\r
2137                         GL_SRC_ALPHA,\r
2138                         GL_ONE_MINUS_SRC_ALPHA,\r
2139                         GL_DST_ALPHA,\r
2140                         GL_ONE_MINUS_DST_ALPHA,\r
2141                         GL_SRC_ALPHA_SATURATE\r
2142                 };\r
2143 \r
2144                 return blendTable[factor];\r
2145         }\r
2146 \r
2147         bool COpenGL3DriverBase::getColorFormatParameters(ECOLOR_FORMAT format, GLint& internalFormat, GLenum& pixelFormat,\r
2148                 GLenum& pixelType, void(**converter)(const void*, s32, void*)) const\r
2149         {\r
2150                 bool supported = false;\r
2151                 pixelFormat = GL_RGBA;\r
2152                 pixelType = GL_UNSIGNED_BYTE;\r
2153                 *converter = 0;\r
2154 \r
2155                 switch (format)\r
2156                 {\r
2157                 case ECF_A1R5G5B5:\r
2158                         supported = true;\r
2159                         pixelFormat = GL_RGBA;\r
2160                         pixelType = GL_UNSIGNED_SHORT_5_5_5_1;\r
2161                         *converter = CColorConverter::convert_A1R5G5B5toR5G5B5A1;\r
2162                         break;\r
2163                 case ECF_R5G6B5:\r
2164                         supported = true;\r
2165                         pixelFormat = GL_RGB;\r
2166                         pixelType = GL_UNSIGNED_SHORT_5_6_5;\r
2167                         break;\r
2168                 case ECF_R8G8B8:\r
2169                         supported = true;\r
2170                         pixelFormat = GL_RGB;\r
2171                         pixelType = GL_UNSIGNED_BYTE;\r
2172                         break;\r
2173                 case ECF_A8R8G8B8:\r
2174                         supported = true;\r
2175                         if (queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_IMG_texture_format_BGRA8888) ||\r
2176                                 queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_EXT_texture_format_BGRA8888) ||\r
2177                                 queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_APPLE_texture_format_BGRA8888))\r
2178                         {\r
2179                                 pixelFormat = GL_BGRA;\r
2180                         }\r
2181                         else\r
2182                         {\r
2183                                 pixelFormat = GL_RGBA;\r
2184                                 *converter = CColorConverter::convert_A8R8G8B8toA8B8G8R8;\r
2185                         }\r
2186                         pixelType = GL_UNSIGNED_BYTE;\r
2187                         break;\r
2188 #ifdef GL_EXT_texture_compression_s3tc\r
2189                 case ECF_DXT1:\r
2190                         supported = true;\r
2191                         pixelFormat = GL_RGBA;\r
2192                         pixelType = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;\r
2193                         break;\r
2194                 case ECF_DXT2:\r
2195                 case ECF_DXT3:\r
2196                         supported = true;\r
2197                         pixelFormat = GL_RGBA;\r
2198                         pixelType = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;\r
2199                         break;\r
2200                 case ECF_DXT4:\r
2201                 case ECF_DXT5:\r
2202                         supported = true;\r
2203                         pixelFormat = GL_RGBA;\r
2204                         pixelType = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;\r
2205                         break;\r
2206 #endif\r
2207 #ifdef GL_OES_compressed_ETC1_RGB8_texture\r
2208                 case ECF_ETC1:\r
2209                         supported = true;\r
2210                         pixelFormat = GL_RGB;\r
2211                         pixelType = GL_ETC1_RGB8_OES;\r
2212                         break;\r
2213 #endif\r
2214 #ifdef GL_ES_VERSION_3_0 // TO-DO - fix when extension name will be available\r
2215                 case ECF_ETC2_RGB:\r
2216                         supported = true;\r
2217                         pixelFormat = GL_RGB;\r
2218                         pixelType = GL_COMPRESSED_RGB8_ETC2;\r
2219                         break;\r
2220 #endif\r
2221 #ifdef GL_ES_VERSION_3_0 // TO-DO - fix when extension name will be available\r
2222                 case ECF_ETC2_ARGB:\r
2223                         supported = true;\r
2224                         pixelFormat = GL_RGBA;\r
2225                         pixelType = GL_COMPRESSED_RGBA8_ETC2_EAC;\r
2226                         break;\r
2227 #endif\r
2228                 case ECF_D16:\r
2229                         supported = true;\r
2230                         pixelFormat = GL_DEPTH_COMPONENT;\r
2231                         pixelType = GL_UNSIGNED_SHORT;\r
2232                         break;\r
2233                 case ECF_D32:\r
2234 #if defined(GL_OES_depth32)\r
2235                         if (queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_OES_depth32))\r
2236                         {\r
2237                                 supported = true;\r
2238                                 pixelFormat = GL_DEPTH_COMPONENT;\r
2239                                 pixelType = GL_UNSIGNED_INT;\r
2240                         }\r
2241 #endif\r
2242                         break;\r
2243                 case ECF_D24S8:\r
2244 #ifdef GL_OES_packed_depth_stencil\r
2245                         if (queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_OES_packed_depth_stencil))\r
2246                         {\r
2247                                 supported = true;\r
2248                                 pixelFormat = GL_DEPTH_STENCIL_OES;\r
2249                                 pixelType = GL_UNSIGNED_INT_24_8_OES;\r
2250                         }\r
2251 #endif\r
2252                         break;\r
2253                 case ECF_R8:\r
2254 #if defined(GL_EXT_texture_rg)\r
2255                         if (queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_EXT_texture_rg))\r
2256                         {\r
2257                                 supported = true;\r
2258                                 pixelFormat = GL_RED_EXT;\r
2259                                 pixelType = GL_UNSIGNED_BYTE;\r
2260                         }\r
2261 #endif\r
2262                         break;\r
2263                 case ECF_R8G8:\r
2264 #if defined(GL_EXT_texture_rg)\r
2265                         if (queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_EXT_texture_rg))\r
2266                         {\r
2267                                 supported = true;\r
2268                                 pixelFormat = GL_RG_EXT;\r
2269                                 pixelType = GL_UNSIGNED_BYTE;\r
2270                         }\r
2271 #endif\r
2272                         break;\r
2273                 case ECF_R16:\r
2274                         break;\r
2275                 case ECF_R16G16:\r
2276                         break;\r
2277                 case ECF_R16F:\r
2278 #if defined(GL_OES_texture_half_float) && defined(GL_EXT_texture_rg)\r
2279                         if (queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_EXT_texture_rg)\r
2280                                 && queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_OES_texture_half_float)\r
2281                                 )\r
2282                         {\r
2283                                 supported = true;\r
2284                                 pixelFormat = GL_RED_EXT;\r
2285                                 pixelType = GL_HALF_FLOAT_OES ;\r
2286                         }\r
2287 #endif\r
2288                         break;\r
2289                 case ECF_G16R16F:\r
2290 #if defined(GL_OES_texture_half_float) && defined(GL_EXT_texture_rg)\r
2291                         if (queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_EXT_texture_rg)\r
2292                                 && queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_OES_texture_half_float)\r
2293                                 )\r
2294                         {\r
2295                                 supported = true;\r
2296                                 pixelFormat = GL_RG_EXT;\r
2297                                 pixelType = GL_HALF_FLOAT_OES ;\r
2298                         }\r
2299 #endif\r
2300                         break;\r
2301                 case ECF_A16B16G16R16F:\r
2302 #if defined(GL_OES_texture_half_float)\r
2303                         if (queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_OES_texture_half_float))\r
2304                         {\r
2305                                 supported = true;\r
2306                                 pixelFormat = GL_RGBA;\r
2307                                 pixelType = GL_HALF_FLOAT_OES ;\r
2308                         }\r
2309 #endif\r
2310                         break;\r
2311                 case ECF_R32F:\r
2312 #if defined(GL_OES_texture_float) && defined(GL_EXT_texture_rg)\r
2313                         if (queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_EXT_texture_rg)\r
2314                                 && queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_OES_texture_float)\r
2315                                 )\r
2316                         {\r
2317                                 supported = true;\r
2318                                 pixelFormat = GL_RED_EXT;\r
2319                                 pixelType = GL_FLOAT;\r
2320                         }\r
2321 #endif\r
2322                         break;\r
2323                 case ECF_G32R32F:\r
2324 #if defined(GL_OES_texture_float) && defined(GL_EXT_texture_rg)\r
2325                         if (queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_EXT_texture_rg)\r
2326                                 && queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_OES_texture_float)\r
2327                                 )\r
2328                         {\r
2329                                 supported = true;\r
2330                                 pixelFormat = GL_RG_EXT;\r
2331                                 pixelType = GL_FLOAT;\r
2332                         }\r
2333 #endif\r
2334                         break;\r
2335                 case ECF_A32B32G32R32F:\r
2336 #if defined(GL_OES_texture_float)\r
2337                         if (queryGLESFeature(COGLESCoreExtensionHandler::IRR_GL_OES_texture_half_float))\r
2338                         {\r
2339                                 supported = true;\r
2340                                 pixelFormat = GL_RGBA;\r
2341                                 pixelType = GL_FLOAT ;\r
2342                         }\r
2343 #endif\r
2344                         break;\r
2345                 default:\r
2346                         break;\r
2347                 }\r
2348 \r
2349                 // ES 2.0 says internalFormat must match pixelFormat (chapter 3.7.1 in Spec).\r
2350                 // Doesn't mention if "match" means "equal" or some other way of matching, but\r
2351                 // some bug on Emscripten and browsing discussions by others lead me to believe\r
2352                 // it means they have to be equal. Note that this was different in OpenGL.\r
2353                 internalFormat = pixelFormat;\r
2354 \r
2355 #ifdef _IRR_IOS_PLATFORM_\r
2356                 if (internalFormat == GL_BGRA)\r
2357                         internalFormat = GL_RGBA;\r
2358 #endif\r
2359 \r
2360                 return supported;\r
2361         }\r
2362 \r
2363         bool COpenGL3DriverBase::queryTextureFormat(ECOLOR_FORMAT format) const\r
2364         {\r
2365                 GLint dummyInternalFormat;\r
2366                 GLenum dummyPixelFormat;\r
2367                 GLenum dummyPixelType;\r
2368                 void (*dummyConverter)(const void*, s32, void*);\r
2369                 return getColorFormatParameters(format, dummyInternalFormat, dummyPixelFormat, dummyPixelType, &dummyConverter);\r
2370         }\r
2371 \r
2372         bool COpenGL3DriverBase::needsTransparentRenderPass(const irr::video::SMaterial& material) const\r
2373         {\r
2374                 return CNullDriver::needsTransparentRenderPass(material) || material.isAlphaBlendOperation();\r
2375         }\r
2376 \r
2377         const SMaterial& COpenGL3DriverBase::getCurrentMaterial() const\r
2378         {\r
2379                 return Material;\r
2380         }\r
2381 \r
2382         COpenGL3CacheHandler* COpenGL3DriverBase::getCacheHandler() const\r
2383         {\r
2384                 return CacheHandler;\r
2385         }\r
2386 \r
2387 } // end namespace\r
2388 } // end namespace\r