]> git.lizzy.rs Git - irrlicht.git/blob - source/Irrlicht/CWebGL1Driver.cpp
Use swap_control from MESA and EXT before SGI (#151)
[irrlicht.git] / source / Irrlicht / CWebGL1Driver.cpp
1 // Copyright (C) 2017 Michael Zeilfelder\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 "CWebGL1Driver.h"\r
6 \r
7 #ifdef _IRR_COMPILE_WITH_WEBGL1_\r
8 \r
9 #include "COpenGLCoreTexture.h"\r
10 #include "COpenGLCoreRenderTarget.h"\r
11 #include "COpenGLCoreCacheHandler.h"\r
12 #include "EVertexAttributes.h"\r
13 \r
14 namespace irr\r
15 {\r
16 namespace video\r
17 {\r
18 \r
19 CWebGL1Driver::CWebGL1Driver(const SIrrlichtCreationParameters& params, io::IFileSystem* io, IContextManager* contextManager) :\r
20         COGLES2Driver(params, io, contextManager)\r
21         , MBTriangleFanSize4(0), MBLinesSize2(0), MBPointsSize1(0)\r
22 {\r
23 #ifdef _DEBUG\r
24         setDebugName("CWebGL1Driver");\r
25 #endif\r
26 \r
27         // NPOT are not allowed for WebGL in most cases.\r
28         // One can use them when:\r
29         // - The TEXTURE_MIN_FILTER is linear or nearest\r
30         // - no mipmapping is used\r
31         // - no texture wrapping is used (so all texture_wraps have to be CLAMP_TO_EDGE)\r
32         // So users could still enable them for specific cases (usually GUI), but in general better to have it off.\r
33         disableFeature(EVDF_TEXTURE_NPOT);\r
34 \r
35         MBLinesSize2 = createSimpleMeshBuffer(2, scene::EPT_LINES);\r
36         MBTriangleFanSize4 = createSimpleMeshBuffer(4, scene::EPT_TRIANGLE_FAN);\r
37         MBPointsSize1 = createSimpleMeshBuffer(1, scene::EPT_POINTS);\r
38 }\r
39 \r
40 CWebGL1Driver::~CWebGL1Driver()\r
41 {\r
42         if ( MBTriangleFanSize4 )\r
43                 MBTriangleFanSize4->drop();\r
44         if ( MBLinesSize2 )\r
45                 MBLinesSize2->drop();\r
46         if ( MBPointsSize1 )\r
47                 MBPointsSize1->drop();\r
48 }\r
49 \r
50 //! Returns type of video driver\r
51 E_DRIVER_TYPE CWebGL1Driver::getDriverType() const\r
52 {\r
53         return EDT_WEBGL1;\r
54 }\r
55 \r
56 //! draws a vertex primitive list\r
57 void CWebGL1Driver::drawVertexPrimitiveList(const void* vertices, u32 vertexCount,\r
58                              const void* indexList, u32 primitiveCount,\r
59                              E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, E_INDEX_TYPE iType)\r
60 {\r
61         if ( !vertices )\r
62         {\r
63                 COGLES2Driver::drawVertexPrimitiveList(vertices, vertexCount, indexList, primitiveCount, vType, pType, iType);\r
64         }\r
65         else\r
66         {\r
67                 static bool first = true;\r
68                 if ( first )\r
69                 {\r
70                         first = false;\r
71                         os::Printer::log("WebGL driver does not support drawVertexPrimitiveList calls without a VBO", ELL_WARNING);\r
72                         os::Printer::log(__FILE__, irr::core::stringc(__LINE__).c_str(), ELL_WARNING);\r
73                 }\r
74         }\r
75 }\r
76 \r
77 //! Draws a mesh buffer\r
78 void CWebGL1Driver::drawMeshBuffer(const scene::IMeshBuffer* mb)\r
79 {\r
80         if ( mb )\r
81         {\r
82                 // OK - this is bad and I hope I can find a better solution.\r
83                 // Basically casting away a const which shouldn't be cast away.\r
84                 // Not a nice surprise for users to see their mesh changes I guess :-(\r
85                 scene::IMeshBuffer* mbUglyHack = const_cast<scene::IMeshBuffer*>(mb);\r
86 \r
87                 // We can't allow any buffers which are not bound to some VBO.\r
88                 if ( mb->getHardwareMappingHint_Vertex() == scene::EHM_NEVER)\r
89                         mbUglyHack->setHardwareMappingHint(scene::EHM_STREAM, scene::EBT_VERTEX);\r
90                 if ( mb->getHardwareMappingHint_Index() == scene::EHM_NEVER)\r
91                         mbUglyHack->setHardwareMappingHint(scene::EHM_STREAM, scene::EBT_INDEX);\r
92 \r
93                 COGLES2Driver::drawMeshBuffer(mb);\r
94         }\r
95 }\r
96 \r
97 void CWebGL1Driver::draw2DImage(const video::ITexture* texture,\r
98                 const core::position2d<s32>& destPos,const core::rect<s32>& sourceRect,\r
99                 const core::rect<s32>* clipRect, SColor color, bool useAlphaChannelOfTexture)\r
100 {\r
101         if (!texture)\r
102                 return;\r
103 \r
104         if (!sourceRect.isValid())\r
105                 return;\r
106 \r
107         core::position2d<s32> targetPos(destPos);\r
108         core::position2d<s32> sourcePos(sourceRect.UpperLeftCorner);\r
109         core::dimension2d<s32> sourceSize(sourceRect.getSize());\r
110         if (clipRect)\r
111         {\r
112                 if (targetPos.X < clipRect->UpperLeftCorner.X)\r
113                 {\r
114                         sourceSize.Width += targetPos.X - clipRect->UpperLeftCorner.X;\r
115                         if (sourceSize.Width <= 0)\r
116                                 return;\r
117 \r
118                         sourcePos.X -= targetPos.X - clipRect->UpperLeftCorner.X;\r
119                         targetPos.X = clipRect->UpperLeftCorner.X;\r
120                 }\r
121 \r
122                 if (targetPos.X + sourceSize.Width > clipRect->LowerRightCorner.X)\r
123                 {\r
124                         sourceSize.Width -= (targetPos.X + sourceSize.Width) - clipRect->LowerRightCorner.X;\r
125                         if (sourceSize.Width <= 0)\r
126                                 return;\r
127                 }\r
128 \r
129                 if (targetPos.Y < clipRect->UpperLeftCorner.Y)\r
130                 {\r
131                         sourceSize.Height += targetPos.Y - clipRect->UpperLeftCorner.Y;\r
132                         if (sourceSize.Height <= 0)\r
133                                 return;\r
134 \r
135                         sourcePos.Y -= targetPos.Y - clipRect->UpperLeftCorner.Y;\r
136                         targetPos.Y = clipRect->UpperLeftCorner.Y;\r
137                 }\r
138 \r
139                 if (targetPos.Y + sourceSize.Height > clipRect->LowerRightCorner.Y)\r
140                 {\r
141                         sourceSize.Height -= (targetPos.Y + sourceSize.Height) - clipRect->LowerRightCorner.Y;\r
142                         if (sourceSize.Height <= 0)\r
143                                 return;\r
144                 }\r
145         }\r
146 \r
147         // clip these coordinates\r
148 \r
149         if (targetPos.X < 0)\r
150         {\r
151                 sourceSize.Width += targetPos.X;\r
152                 if (sourceSize.Width <= 0)\r
153                         return;\r
154 \r
155                 sourcePos.X -= targetPos.X;\r
156                 targetPos.X = 0;\r
157         }\r
158 \r
159         const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();\r
160 \r
161         if (targetPos.X + sourceSize.Width > (s32)renderTargetSize.Width)\r
162         {\r
163                 sourceSize.Width -= (targetPos.X + sourceSize.Width) - renderTargetSize.Width;\r
164                 if (sourceSize.Width <= 0)\r
165                         return;\r
166         }\r
167 \r
168         if (targetPos.Y < 0)\r
169         {\r
170                 sourceSize.Height += targetPos.Y;\r
171                 if (sourceSize.Height <= 0)\r
172                         return;\r
173 \r
174                 sourcePos.Y -= targetPos.Y;\r
175                 targetPos.Y = 0;\r
176         }\r
177 \r
178         if (targetPos.Y + sourceSize.Height > (s32)renderTargetSize.Height)\r
179         {\r
180                 sourceSize.Height -= (targetPos.Y + sourceSize.Height) - renderTargetSize.Height;\r
181                 if (sourceSize.Height <= 0)\r
182                         return;\r
183         }\r
184 \r
185         // ok, we've clipped everything.\r
186         // now draw it.\r
187 \r
188         // texcoords need to be flipped horizontally for RTTs\r
189         const bool isRTT = texture->isRenderTarget();\r
190         const core::dimension2d<u32>& ss = texture->getOriginalSize();\r
191         const f32 invW = 1.f / static_cast<f32>(ss.Width);\r
192         const f32 invH = 1.f / static_cast<f32>(ss.Height);\r
193         const core::rect<f32> tcoords(\r
194                 sourcePos.X * invW,\r
195                 (isRTT ? (sourcePos.Y + sourceSize.Height) : sourcePos.Y) * invH,\r
196                 (sourcePos.X + sourceSize.Width) * invW,\r
197                 (isRTT ? sourcePos.Y : (sourcePos.Y + sourceSize.Height)) * invH);\r
198 \r
199         const core::rect<s32> poss(targetPos, sourceSize);\r
200 \r
201         chooseMaterial2D();\r
202         if ( !setMaterialTexture(0, texture) )\r
203                 return;\r
204 \r
205         setRenderStates2DMode(color.getAlpha() < 255, true, useAlphaChannelOfTexture);\r
206         lockRenderStateMode();\r
207 \r
208         f32 left = (f32)poss.UpperLeftCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;\r
209         f32 right = (f32)poss.LowerRightCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;\r
210         f32 down = 2.f - (f32)poss.LowerRightCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
211         f32 top = 2.f - (f32)poss.UpperLeftCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
212 \r
213         MBTriangleFanSize4->Vertices[0] = S3DVertex(left, top, 0, 0, 0, 1, color, tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y);\r
214         MBTriangleFanSize4->Vertices[1] = S3DVertex(right, top, 0, 0, 0, 1, color, tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y);\r
215         MBTriangleFanSize4->Vertices[2] = S3DVertex(right, down, 0, 0, 0, 1, color, tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y);\r
216         MBTriangleFanSize4->Vertices[3] = S3DVertex(left, down, 0, 0, 0, 1, color, tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y);\r
217         MBTriangleFanSize4->setDirty(scene::EBT_VERTEX);\r
218 \r
219         drawMeshBuffer(MBTriangleFanSize4);\r
220 \r
221         unlockRenderStateMode();\r
222 }\r
223 \r
224 void CWebGL1Driver::draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect,\r
225         const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect,\r
226         const video::SColor* const colors, bool useAlphaChannelOfTexture)\r
227 {\r
228         if (!texture)\r
229                 return;\r
230 \r
231         // texcoords need to be flipped horizontally for RTTs\r
232         const bool isRTT = texture->isRenderTarget();\r
233         const core::dimension2du& ss = texture->getOriginalSize();\r
234         const f32 invW = 1.f / static_cast<f32>(ss.Width);\r
235         const f32 invH = 1.f / static_cast<f32>(ss.Height);\r
236         const core::rect<f32> tcoords(\r
237                 sourceRect.UpperLeftCorner.X * invW,\r
238                 (isRTT ? sourceRect.LowerRightCorner.Y : sourceRect.UpperLeftCorner.Y) * invH,\r
239                 sourceRect.LowerRightCorner.X * invW,\r
240                 (isRTT ? sourceRect.UpperLeftCorner.Y : sourceRect.LowerRightCorner.Y) *invH);\r
241 \r
242         const video::SColor temp[4] =\r
243         {\r
244                 0xFFFFFFFF,\r
245                 0xFFFFFFFF,\r
246                 0xFFFFFFFF,\r
247                 0xFFFFFFFF\r
248         };\r
249 \r
250         const video::SColor* const useColor = colors ? colors : temp;\r
251 \r
252         chooseMaterial2D();\r
253         if ( !setMaterialTexture(0, texture) )\r
254                 return;\r
255 \r
256         setRenderStates2DMode(useColor[0].getAlpha() < 255 || useColor[1].getAlpha() < 255 ||\r
257                 useColor[2].getAlpha() < 255 || useColor[3].getAlpha() < 255,\r
258                 true, useAlphaChannelOfTexture);\r
259         lockRenderStateMode();\r
260 \r
261         const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();\r
262 \r
263         bool useScissorTest = false;\r
264         if (clipRect && clipRect->isValid())\r
265         {\r
266                 useScissorTest = true;\r
267                 glEnable(GL_SCISSOR_TEST);\r
268                 glScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height - clipRect->LowerRightCorner.Y,\r
269                         clipRect->getWidth(), clipRect->getHeight());\r
270         }\r
271 \r
272         f32 left = (f32)destRect.UpperLeftCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;\r
273         f32 right = (f32)destRect.LowerRightCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;\r
274         f32 down = 2.f - (f32)destRect.LowerRightCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
275         f32 top = 2.f - (f32)destRect.UpperLeftCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
276 \r
277         MBTriangleFanSize4->Vertices[0] = S3DVertex(left, top, 0, 0, 0, 1, useColor[0], tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y);\r
278         MBTriangleFanSize4->Vertices[1] = S3DVertex(right, top, 0, 0, 0, 1, useColor[3], tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y);\r
279         MBTriangleFanSize4->Vertices[2] = S3DVertex(right, down, 0, 0, 0, 1, useColor[2], tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y);\r
280         MBTriangleFanSize4->Vertices[3] = S3DVertex(left, down, 0, 0, 0, 1, useColor[1], tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y);\r
281         MBTriangleFanSize4->setDirty(scene::EBT_VERTEX);\r
282 \r
283         drawMeshBuffer(MBTriangleFanSize4);\r
284 \r
285         if (useScissorTest)\r
286                 glDisable(GL_SCISSOR_TEST);\r
287 \r
288         unlockRenderStateMode();\r
289 \r
290         testGLError();\r
291 }\r
292 \r
293 void CWebGL1Driver::draw2DImage(const video::ITexture* texture, u32 layer, bool flip)\r
294 {\r
295         if (!texture )\r
296                 return;\r
297 \r
298         chooseMaterial2D();\r
299         if ( !setMaterialTexture(0, texture) )\r
300                 return;\r
301 \r
302         setRenderStates2DMode(false, true, true);\r
303         lockRenderStateMode();\r
304 \r
305         MBTriangleFanSize4->Vertices[0].Pos = core::vector3df(-1.f, 1.f, 0.f);\r
306         MBTriangleFanSize4->Vertices[1].Pos = core::vector3df(1.f, 1.f, 0.f);\r
307         MBTriangleFanSize4->Vertices[2].Pos = core::vector3df(1.f, -1.f, 0.f);\r
308         MBTriangleFanSize4->Vertices[3].Pos = core::vector3df(-1.f, -1.f, 0.f);\r
309 \r
310         f32 modificator = (flip) ? 1.f : 0.f;\r
311 \r
312         MBTriangleFanSize4->Vertices[0].TCoords = core::vector2df(0.f, 0.f + modificator);\r
313         MBTriangleFanSize4->Vertices[1].TCoords = core::vector2df(1.f, 0.f + modificator);\r
314         MBTriangleFanSize4->Vertices[2].TCoords = core::vector2df(1.f, 1.f - modificator);\r
315         MBTriangleFanSize4->Vertices[3].TCoords = core::vector2df(0.f, 1.f - modificator);\r
316 \r
317         MBTriangleFanSize4->Vertices[0].Color = SColor(0xFFFFFFFF);\r
318         MBTriangleFanSize4->Vertices[1].Color = SColor(0xFFFFFFFF);\r
319         MBTriangleFanSize4->Vertices[2].Color = SColor(0xFFFFFFFF);\r
320         MBTriangleFanSize4->Vertices[3].Color = SColor(0xFFFFFFFF);\r
321 \r
322         MBTriangleFanSize4->setDirty(scene::EBT_VERTEX);\r
323 \r
324         drawMeshBuffer(MBTriangleFanSize4);\r
325 \r
326         unlockRenderStateMode();\r
327 }\r
328 \r
329 void CWebGL1Driver::draw2DImageBatch(const video::ITexture* texture,\r
330                                 const core::position2d<s32>& pos,\r
331                                 const core::array<core::rect<s32> >& sourceRects,\r
332                                 const core::array<s32>& indices, s32 kerningWidth,\r
333                                 const core::rect<s32>* clipRect,\r
334                                 SColor color, bool useAlphaChannelOfTexture)\r
335 {\r
336         if (!texture)\r
337                 return;\r
338 \r
339         chooseMaterial2D();\r
340         if ( !setMaterialTexture(0, texture) )\r
341                 return;\r
342 \r
343         setRenderStates2DMode(color.getAlpha() < 255, true, useAlphaChannelOfTexture);\r
344         lockRenderStateMode();\r
345 \r
346         const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();\r
347 \r
348         bool useScissorTest = false;\r
349         if (clipRect && clipRect->isValid())\r
350         {\r
351                 useScissorTest = true;\r
352                 glEnable(GL_SCISSOR_TEST);\r
353                 glScissor(clipRect->UpperLeftCorner.X, renderTargetSize.Height - clipRect->LowerRightCorner.Y,\r
354                                 clipRect->getWidth(), clipRect->getHeight());\r
355         }\r
356 \r
357         const core::dimension2du& ss = texture->getOriginalSize();\r
358         core::position2d<s32> targetPos(pos);\r
359         // texcoords need to be flipped horizontally for RTTs\r
360         const bool isRTT = texture->isRenderTarget();\r
361         const f32 invW = 1.f / static_cast<f32>(ss.Width);\r
362         const f32 invH = 1.f / static_cast<f32>(ss.Height);\r
363 \r
364         for (u32 i = 0; i < indices.size(); ++i)\r
365         {\r
366                 const s32 currentIndex = indices[i];\r
367                 if (!sourceRects[currentIndex].isValid())\r
368                         break;\r
369 \r
370                 const core::rect<f32> tcoords(\r
371                         sourceRects[currentIndex].UpperLeftCorner.X * invW,\r
372                         (isRTT ? sourceRects[currentIndex].LowerRightCorner.Y : sourceRects[currentIndex].UpperLeftCorner.Y) * invH,\r
373                         sourceRects[currentIndex].LowerRightCorner.X * invW,\r
374                         (isRTT ? sourceRects[currentIndex].UpperLeftCorner.Y : sourceRects[currentIndex].LowerRightCorner.Y) * invH);\r
375 \r
376                 const core::rect<s32> poss(targetPos, sourceRects[currentIndex].getSize());\r
377 \r
378                 f32 left = (f32)poss.UpperLeftCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;\r
379                 f32 right = (f32)poss.LowerRightCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;\r
380                 f32 down = 2.f - (f32)poss.LowerRightCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
381                 f32 top = 2.f - (f32)poss.UpperLeftCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
382 \r
383                 MBTriangleFanSize4->Vertices[0] = S3DVertex(left, top, 0, 0, 0, 1, color, tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y);\r
384                 MBTriangleFanSize4->Vertices[1] = S3DVertex(right, top, 0, 0, 0, 1, color, tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y);\r
385                 MBTriangleFanSize4->Vertices[2] = S3DVertex(right, down, 0, 0, 0, 1, color, tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y);\r
386                 MBTriangleFanSize4->Vertices[3] = S3DVertex(left, down, 0, 0, 0, 1, color, tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y);\r
387                 MBTriangleFanSize4->setDirty(scene::EBT_VERTEX);\r
388 \r
389                 drawMeshBuffer(MBTriangleFanSize4);\r
390 \r
391                 targetPos.X += sourceRects[currentIndex].getWidth();\r
392         }\r
393 \r
394         if (useScissorTest)\r
395                 glDisable(GL_SCISSOR_TEST);\r
396 \r
397         unlockRenderStateMode();\r
398 \r
399         testGLError();\r
400 }\r
401 \r
402 void CWebGL1Driver::draw2DImageBatch(const video::ITexture* texture,\r
403                 const core::array<core::position2d<s32> >& positions,\r
404                 const core::array<core::rect<s32> >& sourceRects,\r
405                 const core::rect<s32>* clipRect,\r
406                 SColor color, bool useAlphaChannelOfTexture)\r
407 {\r
408         if (!texture)\r
409                 return;\r
410 \r
411         const irr::u32 drawCount = core::min_<u32>(positions.size(), sourceRects.size());\r
412         if ( !drawCount )\r
413                 return;\r
414 \r
415         chooseMaterial2D();\r
416         if ( !setMaterialTexture(0, texture) )\r
417                 return;\r
418 \r
419         setRenderStates2DMode(color.getAlpha() < 255, true, useAlphaChannelOfTexture);\r
420         lockRenderStateMode();\r
421 \r
422         for (u32 i = 0; i < drawCount; i++)\r
423         {\r
424                 core::position2d<s32> targetPos = positions[i];\r
425                 core::position2d<s32> sourcePos = sourceRects[i].UpperLeftCorner;\r
426                 // This needs to be signed as it may go negative.\r
427                 core::dimension2d<s32> sourceSize(sourceRects[i].getSize());\r
428 \r
429                 if (clipRect)\r
430                 {\r
431                         if (targetPos.X < clipRect->UpperLeftCorner.X)\r
432                         {\r
433                                 sourceSize.Width += targetPos.X - clipRect->UpperLeftCorner.X;\r
434                                 if (sourceSize.Width <= 0)\r
435                                         continue;\r
436 \r
437                                 sourcePos.X -= targetPos.X - clipRect->UpperLeftCorner.X;\r
438                                 targetPos.X = clipRect->UpperLeftCorner.X;\r
439                         }\r
440 \r
441                         if (targetPos.X + (s32)sourceSize.Width > clipRect->LowerRightCorner.X)\r
442                         {\r
443                                 sourceSize.Width -= (targetPos.X + sourceSize.Width) - clipRect->LowerRightCorner.X;\r
444                                 if (sourceSize.Width <= 0)\r
445                                         continue;\r
446                         }\r
447 \r
448                         if (targetPos.Y < clipRect->UpperLeftCorner.Y)\r
449                         {\r
450                                 sourceSize.Height += targetPos.Y - clipRect->UpperLeftCorner.Y;\r
451                                 if (sourceSize.Height <= 0)\r
452                                         continue;\r
453 \r
454                                 sourcePos.Y -= targetPos.Y - clipRect->UpperLeftCorner.Y;\r
455                                 targetPos.Y = clipRect->UpperLeftCorner.Y;\r
456                         }\r
457 \r
458                         if (targetPos.Y + (s32)sourceSize.Height > clipRect->LowerRightCorner.Y)\r
459                         {\r
460                                 sourceSize.Height -= (targetPos.Y + sourceSize.Height) - clipRect->LowerRightCorner.Y;\r
461                                 if (sourceSize.Height <= 0)\r
462                                         continue;\r
463                         }\r
464                 }\r
465 \r
466                 // clip these coordinates\r
467 \r
468                 if (targetPos.X < 0)\r
469                 {\r
470                         sourceSize.Width += targetPos.X;\r
471                         if (sourceSize.Width <= 0)\r
472                                 continue;\r
473 \r
474                         sourcePos.X -= targetPos.X;\r
475                         targetPos.X = 0;\r
476                 }\r
477 \r
478                 const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();\r
479 \r
480                 if (targetPos.X + sourceSize.Width > (s32)renderTargetSize.Width)\r
481                 {\r
482                         sourceSize.Width -= (targetPos.X + sourceSize.Width) - renderTargetSize.Width;\r
483                         if (sourceSize.Width <= 0)\r
484                                 continue;\r
485                 }\r
486 \r
487                 if (targetPos.Y < 0)\r
488                 {\r
489                         sourceSize.Height += targetPos.Y;\r
490                         if (sourceSize.Height <= 0)\r
491                                 continue;\r
492 \r
493                         sourcePos.Y -= targetPos.Y;\r
494                         targetPos.Y = 0;\r
495                 }\r
496 \r
497                 if (targetPos.Y + sourceSize.Height > (s32)renderTargetSize.Height)\r
498                 {\r
499                         sourceSize.Height -= (targetPos.Y + sourceSize.Height) - renderTargetSize.Height;\r
500                         if (sourceSize.Height <= 0)\r
501                                 continue;\r
502                 }\r
503 \r
504                 // ok, we've clipped everything.\r
505                 // now draw it.\r
506 \r
507                 core::rect<f32> tcoords;\r
508                 tcoords.UpperLeftCorner.X = (((f32)sourcePos.X)) / texture->getOriginalSize().Width ;\r
509                 tcoords.UpperLeftCorner.Y = (((f32)sourcePos.Y)) / texture->getOriginalSize().Height;\r
510                 tcoords.LowerRightCorner.X = tcoords.UpperLeftCorner.X + ((f32)(sourceSize.Width) / texture->getOriginalSize().Width);\r
511                 tcoords.LowerRightCorner.Y = tcoords.UpperLeftCorner.Y + ((f32)(sourceSize.Height) / texture->getOriginalSize().Height);\r
512 \r
513                 const core::rect<s32> poss(targetPos, sourceSize);\r
514 \r
515                 f32 left = (f32)poss.UpperLeftCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;\r
516                 f32 right = (f32)poss.LowerRightCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;\r
517                 f32 down = 2.f - (f32)poss.LowerRightCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
518                 f32 top = 2.f - (f32)poss.UpperLeftCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
519 \r
520                 MBTriangleFanSize4->Vertices[0] = S3DVertex(left, top, 0, 0, 0, 1, color, tcoords.UpperLeftCorner.X, tcoords.UpperLeftCorner.Y);\r
521                 MBTriangleFanSize4->Vertices[1] = S3DVertex(right, top, 0, 0, 0, 1, color, tcoords.LowerRightCorner.X, tcoords.UpperLeftCorner.Y);\r
522                 MBTriangleFanSize4->Vertices[2] = S3DVertex(right, down, 0, 0, 0, 1, color, tcoords.LowerRightCorner.X, tcoords.LowerRightCorner.Y);\r
523                 MBTriangleFanSize4->Vertices[3] = S3DVertex(left, down, 0, 0, 0, 1, color, tcoords.UpperLeftCorner.X, tcoords.LowerRightCorner.Y);\r
524                 MBTriangleFanSize4->setDirty(scene::EBT_VERTEX);\r
525 \r
526                 drawMeshBuffer(MBTriangleFanSize4);\r
527         }\r
528 \r
529         unlockRenderStateMode();\r
530 }\r
531 \r
532 //! draw a 2d rectangle\r
533 void CWebGL1Driver::draw2DRectangle(SColor color,\r
534                 const core::rect<s32>& position,\r
535                 const core::rect<s32>* clip)\r
536 {\r
537         chooseMaterial2D();\r
538         setMaterialTexture(0, 0);\r
539 \r
540         setRenderStates2DMode(color.getAlpha() < 255, false, false);\r
541         lockRenderStateMode();\r
542 \r
543         core::rect<s32> pos = position;\r
544 \r
545         if (clip)\r
546                 pos.clipAgainst(*clip);\r
547 \r
548         if (!pos.isValid())\r
549                 return;\r
550 \r
551         const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();\r
552 \r
553         f32 left = (f32)pos.UpperLeftCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;\r
554         f32 right = (f32)pos.LowerRightCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;\r
555         f32 down = 2.f - (f32)pos.LowerRightCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
556         f32 top = 2.f - (f32)pos.UpperLeftCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
557 \r
558         MBTriangleFanSize4->Vertices[0] = S3DVertex(left, top, 0, 0, 0, 1, color, 0, 0);\r
559         MBTriangleFanSize4->Vertices[1] = S3DVertex(right, top, 0, 0, 0, 1, color, 0, 0);\r
560         MBTriangleFanSize4->Vertices[2] = S3DVertex(right, down, 0, 0, 0, 1, color, 0, 0);\r
561         MBTriangleFanSize4->Vertices[3] = S3DVertex(left, down, 0, 0, 0, 1, color, 0, 0);\r
562         MBTriangleFanSize4->setDirty(scene::EBT_VERTEX);\r
563 \r
564         drawMeshBuffer(MBTriangleFanSize4);\r
565 \r
566         unlockRenderStateMode();\r
567 }\r
568 \r
569 void CWebGL1Driver::draw2DRectangle(const core::rect<s32>& position,\r
570                                 SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown,\r
571                                 const core::rect<s32>* clip)\r
572 {\r
573         core::rect<s32> pos = position;\r
574 \r
575         if (clip)\r
576                 pos.clipAgainst(*clip);\r
577 \r
578         if (!pos.isValid())\r
579                 return;\r
580 \r
581         chooseMaterial2D();\r
582         setMaterialTexture(0, 0);\r
583 \r
584         setRenderStates2DMode(colorLeftUp.getAlpha() < 255 ||\r
585                         colorRightUp.getAlpha() < 255 ||\r
586                         colorLeftDown.getAlpha() < 255 ||\r
587                         colorRightDown.getAlpha() < 255, false, false);\r
588         lockRenderStateMode();\r
589 \r
590         const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();\r
591 \r
592         f32 left = (f32)pos.UpperLeftCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;\r
593         f32 right = (f32)pos.LowerRightCorner.X / (f32)renderTargetSize.Width * 2.f - 1.f;\r
594         f32 down = 2.f - (f32)pos.LowerRightCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
595         f32 top = 2.f - (f32)pos.UpperLeftCorner.Y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
596 \r
597         MBTriangleFanSize4->Vertices[0] = S3DVertex(left, top, 0, 0, 0, 1, colorLeftUp, 0, 0);\r
598         MBTriangleFanSize4->Vertices[1] = S3DVertex(right, top, 0, 0, 0, 1, colorRightUp, 0, 0);\r
599         MBTriangleFanSize4->Vertices[2] = S3DVertex(right, down, 0, 0, 0, 1, colorRightDown, 0, 0);\r
600         MBTriangleFanSize4->Vertices[3] = S3DVertex(left, down, 0, 0, 0, 1, colorLeftDown, 0, 0);\r
601         MBTriangleFanSize4->setDirty(scene::EBT_VERTEX);\r
602 \r
603         drawMeshBuffer(MBTriangleFanSize4);\r
604 \r
605         unlockRenderStateMode();\r
606 }\r
607 \r
608                 //! Draws a 2d line.\r
609 void CWebGL1Driver::draw2DLine(const core::position2d<s32>& start, const core::position2d<s32>& end, SColor color)\r
610 {\r
611         if (start==end)\r
612                 drawPixel(start.X, start.Y, color);\r
613         else\r
614         {\r
615                 chooseMaterial2D();\r
616                 setMaterialTexture(0, 0);\r
617 \r
618                 setRenderStates2DMode(color.getAlpha() < 255, false, false);\r
619                 lockRenderStateMode();\r
620 \r
621                 const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();\r
622 \r
623                 f32 startX = (f32)start.X / (f32)renderTargetSize.Width * 2.f - 1.f;\r
624                 f32 endX = (f32)end.X / (f32)renderTargetSize.Width * 2.f - 1.f;\r
625                 f32 startY = 2.f - (f32)start.Y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
626                 f32 endY = 2.f - (f32)end.Y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
627 \r
628                 MBLinesSize2->Vertices[0] = S3DVertex(startX, startY, 0, 0, 0, 1, color, 0, 0);\r
629                 MBLinesSize2->Vertices[1] = S3DVertex(endX, endY, 0, 0, 0, 1, color, 1, 1);\r
630                 MBLinesSize2->setDirty(scene::EBT_VERTEX);\r
631 \r
632                 drawMeshBuffer(MBLinesSize2);\r
633 \r
634                 unlockRenderStateMode();\r
635         }\r
636 }\r
637 \r
638 void CWebGL1Driver::drawPixel(u32 x, u32 y, const SColor & color)\r
639 {\r
640         const core::dimension2d<u32>& renderTargetSize = getCurrentRenderTargetSize();\r
641         if (x > (u32)renderTargetSize.Width || y > (u32)renderTargetSize.Height)\r
642                 return;\r
643 \r
644         chooseMaterial2D();\r
645         setMaterialTexture(0, 0);\r
646 \r
647         setRenderStates2DMode(color.getAlpha() < 255, false, false);\r
648         lockRenderStateMode();\r
649 \r
650         f32 X = (f32)x / (f32)renderTargetSize.Width * 2.f - 1.f;\r
651         f32 Y = 2.f - (f32)y / (f32)renderTargetSize.Height * 2.f - 1.f;\r
652 \r
653         MBPointsSize1->Vertices[0] = S3DVertex(X, Y, 0, 0, 0, 1, color, 0, 0);\r
654         MBPointsSize1->setDirty(scene::EBT_VERTEX);\r
655 \r
656         drawMeshBuffer(MBPointsSize1);\r
657 \r
658         unlockRenderStateMode();\r
659 }\r
660 \r
661 void CWebGL1Driver::draw3DLine(const core::vector3df& start, const core::vector3df& end, SColor color)\r
662 {\r
663         MBLinesSize2->Vertices[0] = S3DVertex(start.X, start.Y, start.Z, 0, 0, 1, color, 0, 0);\r
664         MBLinesSize2->Vertices[1] = S3DVertex(end.X, end.Y, end.Z, 0, 0, 1, color, 0, 0);\r
665         MBLinesSize2->setDirty(scene::EBT_VERTEX);\r
666 \r
667         drawMeshBuffer(MBLinesSize2);\r
668 }\r
669 \r
670 void CWebGL1Driver::drawStencilShadowVolume(const core::array<core::vector3df>& triangles, bool zfail, u32 debugDataVisible)\r
671 {\r
672         static bool first = true;\r
673         if ( first )\r
674         {\r
675                 first = false;\r
676                 os::Printer::log("WebGL1 driver does not yet support drawStencilShadowVolume", ELL_WARNING);\r
677                 os::Printer::log(__FILE__, irr::core::stringc(__LINE__).c_str(), ELL_WARNING);\r
678         }\r
679 }\r
680 \r
681 void CWebGL1Driver::drawStencilShadow(bool clearStencilBuffer,\r
682         video::SColor leftUpEdge,\r
683         video::SColor rightUpEdge,\r
684         video::SColor leftDownEdge,\r
685         video::SColor rightDownEdge)\r
686 {\r
687         // NOTE: Might work, but untested as drawStencilShadowVolume is not yet supported.\r
688 \r
689         if (!StencilBuffer)\r
690                 return;\r
691 \r
692         chooseMaterial2D();\r
693         setMaterialTexture(0, 0);\r
694 \r
695         setRenderStates2DMode(true, false, false);\r
696         lockRenderStateMode();\r
697 \r
698         CacheHandler->setDepthMask(false);\r
699         CacheHandler->setColorMask(ECP_ALL);\r
700 \r
701         CacheHandler->setBlend(true);\r
702         CacheHandler->setBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\r
703 \r
704         glEnable(GL_STENCIL_TEST);\r
705         glStencilFunc(GL_NOTEQUAL, 0, ~0);\r
706         glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);\r
707 \r
708         MBTriangleFanSize4->Vertices[0] = S3DVertex(-1.f, 1.f, 0.9f, 0, 0, 1, leftDownEdge, 0, 0);\r
709         MBTriangleFanSize4->Vertices[1] = S3DVertex(1.f, 1.f, 0.9f, 0, 0, 1, leftUpEdge, 0, 0);\r
710         MBTriangleFanSize4->Vertices[2] = S3DVertex(1.f, -1.f, 0.9f, 0, 0, 1, rightUpEdge, 0, 0);\r
711         MBTriangleFanSize4->Vertices[3] = S3DVertex(-1.f, -1.f, 0.9f, 0, 0, 1, rightDownEdge, 0, 0);\r
712         MBTriangleFanSize4->setDirty(scene::EBT_VERTEX);\r
713 \r
714         drawMeshBuffer(MBTriangleFanSize4);\r
715 \r
716         unlockRenderStateMode();\r
717 \r
718         if (clearStencilBuffer)\r
719                 glClear(GL_STENCIL_BUFFER_BIT);\r
720 \r
721         glDisable(GL_STENCIL_TEST);\r
722 }\r
723 \r
724 GLenum CWebGL1Driver::getZBufferBits() const\r
725 {\r
726         // TODO: Never used, so not sure what this was really about (zbuffer used by device? Or for RTT's?)\r
727         //       If it's about device it might need a check like: GLint depthBits; glGetIntegerv(GL_DEPTH_BITS, &depthBits);\r
728         //       If it's about textures it might need a check for IRR_WEBGL_depth_texture\r
729 \r
730         GLenum bits = 0;\r
731 \r
732         switch (Params.ZBufferBits)\r
733         {\r
734 #if defined(GL_OES_depth24)\r
735         case 24:\r
736                 bits = GL_DEPTH_COMPONENT24_OES;\r
737                 break;\r
738 #endif\r
739 #if defined(GL_OES_depth32)\r
740         case 32:\r
741                 bits = GL_DEPTH_COMPONENT32_OES;\r
742                 break;\r
743 #endif\r
744         default:\r
745                 bits = GL_DEPTH_COMPONENT16_OES;\r
746                 break;\r
747         }\r
748 \r
749         return bits;\r
750 }\r
751 \r
752 bool CWebGL1Driver::getColorFormatParameters(ECOLOR_FORMAT format, GLint& internalFormat, GLenum& pixelFormat,\r
753         GLenum& pixelType, void(**converter)(const void*, s32, void*)) const\r
754 {\r
755                 bool supported = false;\r
756                 pixelFormat = GL_RGBA;\r
757                 pixelType = GL_UNSIGNED_BYTE;\r
758                 *converter = 0;\r
759 \r
760                 switch (format)\r
761                 {\r
762                 case ECF_A1R5G5B5:\r
763                         supported = true;\r
764                         pixelFormat = GL_RGBA;\r
765                         pixelType = GL_UNSIGNED_SHORT_5_5_5_1;\r
766                         *converter = CColorConverter::convert_A1R5G5B5toR5G5B5A1;\r
767                         break;\r
768                 case ECF_R5G6B5:\r
769                         supported = true;\r
770                         pixelFormat = GL_RGB;\r
771                         pixelType = GL_UNSIGNED_SHORT_5_6_5;\r
772                         break;\r
773                 case ECF_R8G8B8:\r
774                         supported = true;\r
775                         pixelFormat = GL_RGB;\r
776                         pixelType = GL_UNSIGNED_BYTE;\r
777                         break;\r
778                 case ECF_A8R8G8B8:\r
779                         // WebGL doesn't seem to support GL_BGRA so we always convert\r
780                         supported = true;\r
781                         pixelFormat = GL_RGBA;\r
782                         *converter = CColorConverter::convert_A8R8G8B8toA8B8G8R8;\r
783                         pixelType = GL_UNSIGNED_BYTE;\r
784                         break;\r
785 #ifdef GL_EXT_texture_compression_dxt1\r
786                 case ECF_DXT1:\r
787                         if ( WebGLExtensions.queryWebGLFeature(CWebGLExtensionHandler::IRR_WEBGL_compressed_texture_s3tc) )\r
788                         {\r
789                                 supported = true;\r
790                                 pixelFormat = GL_RGBA;\r
791                                 pixelType = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;\r
792                         }\r
793                         break;\r
794 #endif\r
795 #ifdef GL_EXT_texture_compression_s3tc\r
796                 case ECF_DXT2:\r
797                 case ECF_DXT3:\r
798                         if ( WebGLExtensions.queryWebGLFeature(CWebGLExtensionHandler::IRR_WEBGL_compressed_texture_s3tc) )\r
799                         {\r
800                                 supported = true;\r
801                                 pixelFormat = GL_RGBA;\r
802                                 pixelType = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;\r
803                         }\r
804                         break;\r
805 #endif\r
806 #ifdef GL_EXT_texture_compression_s3tc\r
807                 case ECF_DXT4:\r
808                 case ECF_DXT5:\r
809                         if ( WebGLExtensions.queryWebGLFeature(CWebGLExtensionHandler::IRR_WEBGL_compressed_texture_s3tc) )\r
810                         {\r
811                                 supported = true;\r
812                                 pixelFormat = GL_RGBA;\r
813                                 pixelType = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;\r
814                         }\r
815                         break;\r
816 #endif\r
817 #ifdef GL_IMG_texture_compression_pvrtc\r
818                 case ECF_PVRTC_RGB2:\r
819                         if ( WebGLExtensions.queryWebGLFeature(CWebGLExtensionHandler::IRR_WEBGL_compressed_texture_pvrtc) )\r
820                         {\r
821                                 supported = true;\r
822                                 pixelFormat = GL_RGB;\r
823                                 pixelType = GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;\r
824                         }\r
825                         break;\r
826 #endif\r
827 #ifdef GL_IMG_texture_compression_pvrtc\r
828                 case ECF_PVRTC_ARGB2:\r
829                         if ( WebGLExtensions.queryWebGLFeature(CWebGLExtensionHandler::IRR_WEBGL_compressed_texture_pvrtc) )\r
830                         {\r
831                                 supported = true;\r
832                                 pixelFormat = GL_RGBA;\r
833                                 pixelType = GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;\r
834                         }\r
835                         break;\r
836 #endif\r
837 #ifdef GL_IMG_texture_compression_pvrtc\r
838                 case ECF_PVRTC_RGB4:\r
839                         if ( WebGLExtensions.queryWebGLFeature(CWebGLExtensionHandler::IRR_WEBGL_compressed_texture_pvrtc) )\r
840                         {\r
841                                 supported = true;\r
842                                 pixelFormat = GL_RGB;\r
843                                 pixelType = GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;\r
844                         }\r
845                         break;\r
846 #endif\r
847 #ifdef GL_IMG_texture_compression_pvrtc\r
848                 case ECF_PVRTC_ARGB4:\r
849                         if ( WebGLExtensions.queryWebGLFeature(CWebGLExtensionHandler::IRR_WEBGL_compressed_texture_pvrtc) )\r
850                         {\r
851                                 supported = true;\r
852                                 pixelFormat = GL_RGBA;\r
853                                 pixelType = GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;\r
854                         }\r
855                         break;\r
856 #endif\r
857 #ifdef GL_IMG_texture_compression_pvrtc2\r
858                 case ECF_PVRTC2_ARGB2:\r
859                         if ( WebGLExtensions.queryWebGLFeature(CWebGLExtensionHandler::IRR_WEBGL_compressed_texture_pvrtc) )\r
860                         {\r
861                                 supported = true;\r
862                                 pixelFormat = GL_RGBA;\r
863                                 pixelType = GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG;\r
864                         }\r
865                         break;\r
866 #endif\r
867 #ifdef GL_IMG_texture_compression_pvrtc2\r
868                 case ECF_PVRTC2_ARGB4:\r
869                         if ( WebGLExtensions.queryWebGLFeature(CWebGLExtensionHandler::IRR_WEBGL_compressed_texture_pvrtc) )\r
870                         {\r
871                                 supported = true;\r
872                                 pixelFormat = GL_RGBA;\r
873                                 pixelType = GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG;\r
874                         }\r
875                         break;\r
876 #endif\r
877 #ifdef GL_OES_compressed_ETC1_RGB8_texture\r
878                 case ECF_ETC1:\r
879                         if ( WebGLExtensions.queryWebGLFeature(CWebGLExtensionHandler::IRR_WEBGL_compressed_texture_etc1) )\r
880                         {\r
881                                 supported = true;\r
882                                 pixelFormat = GL_RGB;\r
883                                 pixelType = GL_ETC1_RGB8_OES;\r
884                         }\r
885                         break;\r
886 #endif\r
887 #ifdef GL_ES_VERSION_3_0 // TO-DO - fix when extension name will be available\r
888                 case ECF_ETC2_RGB:\r
889                         supported = true;\r
890                         pixelFormat = GL_RGB;\r
891                         pixelType = GL_COMPRESSED_RGB8_ETC2;\r
892                         break;\r
893 #endif\r
894 #ifdef GL_ES_VERSION_3_0 // TO-DO - fix when extension name will be available\r
895                 case ECF_ETC2_ARGB:\r
896                         supported = true;\r
897                         pixelFormat = GL_RGBA;\r
898                         pixelType = GL_COMPRESSED_RGBA8_ETC2_EAC;\r
899                         break;\r
900 #endif\r
901                 case ECF_D16:\r
902                         if (WebGLExtensions.queryWebGLFeature(CWebGLExtensionHandler::IRR_WEBGL_depth_texture))\r
903                         {\r
904                                 supported = true;\r
905                                 pixelFormat = GL_DEPTH_COMPONENT;\r
906                                 pixelType = GL_UNSIGNED_SHORT;\r
907                         }\r
908                         break;\r
909                 case ECF_D32:\r
910                         if (WebGLExtensions.queryWebGLFeature(CWebGLExtensionHandler::IRR_WEBGL_depth_texture))\r
911                         {\r
912                                 // NOTE: There is still no guarantee it will return a 32 bit depth buffer. It might convert stuff internally to 16 bit :-(\r
913                                 supported = true;\r
914                                 pixelFormat = GL_DEPTH_COMPONENT;\r
915                                 pixelType = GL_UNSIGNED_INT;\r
916                         }\r
917                         break;\r
918                 case ECF_D24S8:\r
919                         if (WebGLExtensions.queryWebGLFeature(CWebGLExtensionHandler::IRR_WEBGL_depth_texture))\r
920                         {\r
921                                 supported = true;\r
922                                 pixelFormat = 0x84F9; // GL_DEPTH_STENCIL\r
923                                 pixelType = 0x84FA;       // UNSIGNED_INT_24_8_WEBGL\r
924                         }\r
925                         break;\r
926                 case ECF_R8:\r
927                         // Does not seem to be supported in WebGL so far (missing GL_EXT_texture_rg)\r
928                         break;\r
929                 case ECF_R8G8:\r
930                         // Does not seem to be supported in WebGL so far (missing GL_EXT_texture_rg)\r
931                         break;\r
932                 case ECF_R16:\r
933                         // Does not seem to be supported in WebGL so far\r
934                         break;\r
935                 case ECF_R16G16:\r
936                         // Does not seem to be supported in WebGL so far\r
937                         break;\r
938                 case ECF_R16F:\r
939                         // Does not seem to be supported in WebGL so far (missing GL_EXT_texture_rg)\r
940                         break;\r
941                 case ECF_G16R16F:\r
942                         // Does not seem to be supported in WebGL so far (missing GL_EXT_texture_rg)\r
943                         break;\r
944                 case ECF_A16B16G16R16F:\r
945 #if defined(GL_OES_texture_half_float)\r
946                         if (WebGLExtensions.queryWebGLFeature(CWebGLExtensionHandler::IRR_OES_texture_half_float))\r
947                         {\r
948                                 supported = true;\r
949                                 pixelFormat = GL_RGBA;\r
950                                 pixelType = GL_HALF_FLOAT_OES ;\r
951                         }\r
952 #endif\r
953                         break;\r
954                 case ECF_R32F:\r
955                         // Does not seem to be supported in WebGL so far (missing GL_EXT_texture_rg)\r
956                         break;\r
957                 case ECF_G32R32F:\r
958                         // Does not seem to be supported in WebGL so far (missing GL_EXT_texture_rg)\r
959                         break;\r
960                 case ECF_A32B32G32R32F:\r
961 #if defined(GL_OES_texture_float)\r
962                         if (WebGLExtensions.queryWebGLFeature(CWebGLExtensionHandler::IRR_OES_texture_half_float))\r
963                         {\r
964                                 supported = true;\r
965                                 pixelFormat = GL_RGBA;\r
966                                 pixelType = GL_FLOAT ;\r
967                         }\r
968 #endif\r
969                         break;\r
970                 default:\r
971                         break;\r
972                 }\r
973 \r
974                 // ES 2.0 says internalFormat must match pixelFormat (chapter 3.7.1 in Spec).\r
975                 // Doesn't mention if "match" means "equal" or some other way of matching, but\r
976                 // some bug on Emscripten and browsing discussions by others lead me to believe\r
977                 // it means they have to be equal. Note that this was different in OpenGL.\r
978                 internalFormat = pixelFormat;\r
979 \r
980                 return supported;\r
981 }\r
982 \r
983 \r
984 scene::SMeshBuffer* CWebGL1Driver::createSimpleMeshBuffer(irr::u32 numVertices, scene::E_PRIMITIVE_TYPE primitiveType, scene::E_HARDWARE_MAPPING vertexMappingHint, scene::E_HARDWARE_MAPPING indexMappingHint) const\r
985 {\r
986         scene::SMeshBuffer* mbResult = new scene::SMeshBuffer();\r
987         mbResult->Vertices.set_used(numVertices);\r
988         mbResult->Indices.set_used(numVertices);\r
989         for ( irr::u32 i=0; i < numVertices; ++i )\r
990                 mbResult->Indices[i] = i;\r
991 \r
992         mbResult->setPrimitiveType(primitiveType);\r
993         mbResult->setHardwareMappingHint(vertexMappingHint, scene::EBT_VERTEX);\r
994         mbResult->setHardwareMappingHint(indexMappingHint, scene::EBT_INDEX);\r
995         mbResult->setDirty();\r
996 \r
997         return mbResult;\r
998 }\r
999 \r
1000 bool CWebGL1Driver::genericDriverInit(const core::dimension2d<u32>& screenSize, bool stencilBuffer)\r
1001 {\r
1002         Name = glGetString(GL_VERSION);\r
1003         printVersion();\r
1004 \r
1005         // print renderer information\r
1006         VendorName = glGetString(GL_VENDOR);\r
1007         os::Printer::log(VendorName.c_str(), ELL_INFORMATION);\r
1008 \r
1009         // load extensions\r
1010         initWebGLExtensions();\r
1011 \r
1012         // reset cache handler\r
1013         delete CacheHandler;\r
1014         CacheHandler = new COGLES2CacheHandler(this);\r
1015 \r
1016         StencilBuffer = stencilBuffer;\r
1017 \r
1018         DriverAttributes->setAttribute("MaxTextures", (s32)Feature.MaxTextureUnits);\r
1019         DriverAttributes->setAttribute("MaxSupportedTextures", (s32)Feature.MaxTextureUnits);\r
1020         DriverAttributes->setAttribute("MaxAnisotropy", MaxAnisotropy);\r
1021         DriverAttributes->setAttribute("MaxIndices", (s32)MaxIndices);\r
1022         DriverAttributes->setAttribute("MaxTextureSize", (s32)MaxTextureSize);\r
1023         DriverAttributes->setAttribute("MaxTextureLODBias", MaxTextureLODBias);\r
1024         DriverAttributes->setAttribute("Version", Version);\r
1025         DriverAttributes->setAttribute("AntiAlias", AntiAlias);\r
1026 \r
1027         glPixelStorei(GL_PACK_ALIGNMENT, 1);\r
1028 \r
1029         UserClipPlane.reallocate(0);\r
1030 \r
1031         for (s32 i = 0; i < ETS_COUNT; ++i)\r
1032                 setTransform(static_cast<E_TRANSFORMATION_STATE>(i), core::IdentityMatrix);\r
1033 \r
1034         setAmbientLight(SColorf(0.0f, 0.0f, 0.0f, 0.0f));\r
1035         glClearDepthf(1.0f);\r
1036 \r
1037         glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST);\r
1038         glFrontFace(GL_CW);\r
1039 \r
1040         // create material renderers\r
1041         createMaterialRenderers();\r
1042 \r
1043         // set the renderstates\r
1044         setRenderStates3DMode();\r
1045 \r
1046         // set fog mode\r
1047         setFog(FogColor, FogType, FogStart, FogEnd, FogDensity, PixelFog, RangeFog);\r
1048 \r
1049         // create matrix for flipping textures\r
1050         TextureFlipMatrix.buildTextureTransform(0.0f, core::vector2df(0, 0), core::vector2df(0, 1.0f), core::vector2df(1.0f, -1.0f));\r
1051 \r
1052         // We need to reset once more at the beginning of the first rendering.\r
1053         // This fixes problems with intermediate changes to the material during texture load.\r
1054         ResetRenderStates = true;\r
1055 \r
1056         testGLError(__LINE__);\r
1057 \r
1058         return true;\r
1059 }\r
1060 \r
1061 void CWebGL1Driver::initWebGLExtensions()\r
1062 {\r
1063         // Stuff still a little bit hacky as we derive from ES2Driver with it's own extensions.\r
1064         // We only get the feature-strings from WebGLExtensions.\r
1065 \r
1066         getGLVersion();\r
1067 \r
1068         WebGLExtensions.getGLExtensions();\r
1069 \r
1070         // TODO: basically copied ES2 implementation, so not certain if 100% correct for WebGL\r
1071         GLint val=0;\r
1072         glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &val);\r
1073         Feature.MaxTextureUnits = static_cast<u8>(val);\r
1074 \r
1075 #ifdef GL_EXT_texture_filter_anisotropic\r
1076         if ( WebGLExtensions.queryWebGLFeature(CWebGLExtensionHandler::IRR_EXT_texture_filter_anisotropic) )\r
1077         {\r
1078                 glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &val);\r
1079                 MaxAnisotropy = static_cast<u8>(val);\r
1080         }\r
1081 #endif\r
1082 \r
1083         if ( WebGLExtensions.queryWebGLFeature(CWebGLExtensionHandler::IRR_OES_element_index_uint) )    // note: WebGL2 won't need extension as that got default there\r
1084         {\r
1085                 MaxIndices=0xffffffff;\r
1086         }\r
1087 \r
1088         glGetIntegerv(GL_MAX_TEXTURE_SIZE, &val);\r
1089         MaxTextureSize=static_cast<u32>(val);\r
1090 \r
1091 #ifdef GL_MAX_TEXTURE_LOD_BIAS_EXT\r
1092         // TODO: Found no info about this anywhere. It's no extension in WebGL\r
1093         //       and GL_MAX_TEXTURE_LOD_BIAS_EXT doesn't seem to be part of gl2ext.h in emscripten\r
1094         glGetFloatv(GL_MAX_TEXTURE_LOD_BIAS_EXT, &MaxTextureLODBias);\r
1095 #endif\r
1096 \r
1097         glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, DimAliasedLine);\r
1098         glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE, DimAliasedPoint);\r
1099         Feature.MaxTextureUnits = core::min_(Feature.MaxTextureUnits, static_cast<u8>(MATERIAL_MAX_TEXTURES));\r
1100 \r
1101         Feature.ColorAttachment = 1;\r
1102 }\r
1103 \r
1104 } // end namespace video\r
1105 } // end namespace irr\r
1106 \r
1107 #endif // _IRR_COMPILE_WITH_WEBGL1_\r
1108 \r
1109 namespace irr\r
1110 {\r
1111 #ifndef _IRR_COMPILE_WITH_WEBGL1_\r
1112 namespace io\r
1113 {\r
1114         class IFileSystem;\r
1115 }\r
1116 #endif\r
1117 namespace video\r
1118 {\r
1119 \r
1120 #ifndef _IRR_COMPILE_WITH_WEBGL1_\r
1121 class IVideoDriver;\r
1122 class IContextManager;\r
1123 #endif\r
1124 \r
1125 IVideoDriver* createWebGL1Driver(const SIrrlichtCreationParameters& params, io::IFileSystem* io, IContextManager* contextManager)\r
1126 {\r
1127 #ifdef _IRR_COMPILE_WITH_WEBGL1_\r
1128         CWebGL1Driver* driver = new CWebGL1Driver(params, io, contextManager);\r
1129         driver->genericDriverInit(params.WindowSize, params.Stencilbuffer);     // don't call in constructor, it uses virtual function calls of driver\r
1130         return driver;\r
1131 #else\r
1132         return 0;\r
1133 #endif //  _IRR_COMPILE_WITH_WEBGL1_\r
1134 }\r
1135 \r
1136 } // end namespace\r
1137 } // end namespace\r