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