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