1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include "config.h"
27 
28 #if ENABLE(WEBGL)
29 
30 #include "GraphicsContext3D.h"
31 
32 #include "ArrayBuffer.h"
33 #include "ArrayBufferView.h"
34 #include "WebGLObject.h"
35 #include "CanvasRenderingContext.h"
36 #include "Extensions3DOpenGL.h"
37 #include "Float32Array.h"
38 #include "GraphicsContext.h"
39 #include "HTMLCanvasElement.h"
40 #include "ImageBuffer.h"
41 #include "ImageData.h"
42 #include "Int32Array.h"
43 #include "NotImplemented.h"
44 #include "Uint8Array.h"
45 #include <cstring>
46 #include <wtf/UnusedParam.h>
47 #include <wtf/text/CString.h>
48 
49 #if PLATFORM(MAC)
50 #include <OpenGL/gl.h>
51 #elif PLATFORM(GTK)
52 #include "OpenGLShims.h"
53 #endif
54 
55 namespace WebCore {
56 
validateAttributes()57 void GraphicsContext3D::validateAttributes()
58 {
59     Extensions3D* extensions = getExtensions();
60     if (m_attrs.stencil) {
61         if (extensions->supports("GL_EXT_packed_depth_stencil")) {
62             extensions->ensureEnabled("GL_EXT_packed_depth_stencil");
63             // Force depth if stencil is true.
64             m_attrs.depth = true;
65         } else
66             m_attrs.stencil = false;
67     }
68     if (m_attrs.antialias) {
69         bool isValidVendor = true;
70         // Currently in Mac we only turn on antialias if vendor is NVIDIA.
71         const char* vendor = reinterpret_cast<const char*>(::glGetString(GL_VENDOR));
72         if (!std::strstr(vendor, "NVIDIA"))
73             isValidVendor = false;
74         if (!isValidVendor || !extensions->supports("GL_ANGLE_framebuffer_multisample"))
75             m_attrs.antialias = false;
76         else
77             extensions->ensureEnabled("GL_ANGLE_framebuffer_multisample");
78     }
79 }
80 
readRenderingResults(unsigned char * pixels,int pixelsSize)81 void GraphicsContext3D::readRenderingResults(unsigned char *pixels, int pixelsSize)
82 {
83     if (pixelsSize < m_currentWidth * m_currentHeight * 4)
84         return;
85 
86     makeContextCurrent();
87 
88     bool mustRestoreFBO = false;
89     if (m_attrs.antialias) {
90         ::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_multisampleFBO);
91         ::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fbo);
92         ::glBlitFramebufferEXT(0, 0, m_currentWidth, m_currentHeight, 0, 0, m_currentWidth, m_currentHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR);
93         ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
94         mustRestoreFBO = true;
95     } else {
96         if (m_boundFBO != m_fbo) {
97             mustRestoreFBO = true;
98             ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
99         }
100     }
101 
102     GLint packAlignment = 4;
103     bool mustRestorePackAlignment = false;
104     ::glGetIntegerv(GL_PACK_ALIGNMENT, &packAlignment);
105     if (packAlignment > 4) {
106         ::glPixelStorei(GL_PACK_ALIGNMENT, 4);
107         mustRestorePackAlignment = true;
108     }
109 
110     ::glReadPixels(0, 0, m_currentWidth, m_currentHeight, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, pixels);
111 
112     if (mustRestorePackAlignment)
113         ::glPixelStorei(GL_PACK_ALIGNMENT, packAlignment);
114 
115     if (mustRestoreFBO)
116         ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_boundFBO);
117 }
118 
paintRenderingResultsToCanvas(CanvasRenderingContext * context)119 void GraphicsContext3D::paintRenderingResultsToCanvas(CanvasRenderingContext* context)
120 {
121     HTMLCanvasElement* canvas = context->canvas();
122     ImageBuffer* imageBuffer = canvas->buffer();
123 
124     int rowBytes = m_currentWidth * 4;
125     int totalBytes = rowBytes * m_currentHeight;
126 
127     OwnArrayPtr<unsigned char> pixels = adoptArrayPtr(new unsigned char[totalBytes]);
128     if (!pixels)
129         return;
130 
131     readRenderingResults(pixels.get(), totalBytes);
132 
133     if (!m_attrs.premultipliedAlpha) {
134         for (int i = 0; i < totalBytes; i += 4) {
135             // Premultiply alpha
136             pixels[i + 0] = std::min(255, pixels[i + 0] * pixels[i + 3] / 255);
137             pixels[i + 1] = std::min(255, pixels[i + 1] * pixels[i + 3] / 255);
138             pixels[i + 2] = std::min(255, pixels[i + 2] * pixels[i + 3] / 255);
139         }
140     }
141 
142     paintToCanvas(pixels.get(), m_currentWidth, m_currentHeight,
143                   canvas->width(), canvas->height(), imageBuffer->context()->platformContext());
144 }
145 
paintRenderingResultsToImageData()146 PassRefPtr<ImageData> GraphicsContext3D::paintRenderingResultsToImageData()
147 {
148     // Reading premultiplied alpha would involve unpremultiplying, which is
149     // lossy
150     if (m_attrs.premultipliedAlpha)
151         return 0;
152 
153     RefPtr<ImageData> imageData = ImageData::create(IntSize(m_currentWidth, m_currentHeight));
154     unsigned char* pixels = imageData->data()->data()->data();
155     int totalBytes = 4 * m_currentWidth * m_currentHeight;
156 
157     readRenderingResults(pixels, totalBytes);
158 
159     // Convert to RGBA
160     for (int i = 0; i < totalBytes; i += 4)
161         std::swap(pixels[i], pixels[i + 2]);
162 
163     return imageData.release();
164 }
165 
reshape(int width,int height)166 void GraphicsContext3D::reshape(int width, int height)
167 {
168     if (!platformGraphicsContext3D())
169         return;
170 
171     if (width == m_currentWidth && height == m_currentHeight)
172         return;
173 
174     m_currentWidth = width;
175     m_currentHeight = height;
176 
177     makeContextCurrent();
178     validateAttributes();
179 
180     GLuint colorFormat, internalDepthStencilFormat = 0;
181     if (m_attrs.alpha) {
182         m_internalColorFormat = GL_RGBA8;
183         colorFormat = GL_RGBA;
184     } else {
185         m_internalColorFormat = GL_RGB8;
186         colorFormat = GL_RGB;
187     }
188     if (m_attrs.stencil || m_attrs.depth) {
189         // We don't allow the logic where stencil is required and depth is not.
190         // See GraphicsContext3D::validateAttributes.
191 
192         Extensions3D* extensions = getExtensions();
193         // Use a 24 bit depth buffer where we know we have it
194         if (extensions->supports("GL_EXT_packed_depth_stencil"))
195             internalDepthStencilFormat = GL_DEPTH24_STENCIL8_EXT;
196         else
197             internalDepthStencilFormat = GL_DEPTH_COMPONENT;
198     }
199 
200     bool mustRestoreFBO = false;
201 
202     // resize multisample FBO
203     if (m_attrs.antialias) {
204         GLint maxSampleCount;
205         ::glGetIntegerv(GL_MAX_SAMPLES_EXT, &maxSampleCount);
206         GLint sampleCount = std::min(8, maxSampleCount);
207         if (sampleCount > maxSampleCount)
208             sampleCount = maxSampleCount;
209         if (m_boundFBO != m_multisampleFBO) {
210             ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO);
211             mustRestoreFBO = true;
212         }
213         ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_multisampleColorBuffer);
214         ::glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, sampleCount, m_internalColorFormat, width, height);
215         ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, m_multisampleColorBuffer);
216         if (m_attrs.stencil || m_attrs.depth) {
217             ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_multisampleDepthStencilBuffer);
218             ::glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, sampleCount, internalDepthStencilFormat, width, height);
219             if (m_attrs.stencil)
220                 ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_multisampleDepthStencilBuffer);
221             if (m_attrs.depth)
222                 ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_multisampleDepthStencilBuffer);
223         }
224         ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
225         if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) {
226             // FIXME: cleanup.
227             notImplemented();
228         }
229     }
230 
231     // resize regular FBO
232     if (m_boundFBO != m_fbo) {
233         mustRestoreFBO = true;
234         ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
235     }
236     ::glBindTexture(GL_TEXTURE_2D, m_texture);
237     ::glTexImage2D(GL_TEXTURE_2D, 0, m_internalColorFormat, width, height, 0, colorFormat, GL_UNSIGNED_BYTE, 0);
238     ::glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_texture, 0);
239     ::glBindTexture(GL_TEXTURE_2D, m_compositorTexture);
240     ::glTexImage2D(GL_TEXTURE_2D, 0, m_internalColorFormat, width, height, 0, colorFormat, GL_UNSIGNED_BYTE, 0);
241     ::glBindTexture(GL_TEXTURE_2D, 0);
242     if (!m_attrs.antialias && (m_attrs.stencil || m_attrs.depth)) {
243         ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_depthStencilBuffer);
244         ::glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, internalDepthStencilFormat, width, height);
245         if (m_attrs.stencil)
246             ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthStencilBuffer);
247         if (m_attrs.depth)
248             ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_depthStencilBuffer);
249         ::glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
250     }
251     if (glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) {
252         // FIXME: cleanup
253         notImplemented();
254     }
255 
256     if (m_attrs.antialias) {
257         ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO);
258         if (m_boundFBO == m_multisampleFBO)
259             mustRestoreFBO = false;
260     }
261 
262     // Initialize renderbuffers to 0.
263     GLfloat clearColor[] = {0, 0, 0, 0}, clearDepth = 0;
264     GLint clearStencil = 0;
265     GLboolean colorMask[] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE}, depthMask = GL_TRUE;
266     GLuint stencilMask = 0xffffffff;
267     GLboolean isScissorEnabled = GL_FALSE;
268     GLboolean isDitherEnabled = GL_FALSE;
269     GLbitfield clearMask = GL_COLOR_BUFFER_BIT;
270     ::glGetFloatv(GL_COLOR_CLEAR_VALUE, clearColor);
271     ::glClearColor(0, 0, 0, 0);
272     ::glGetBooleanv(GL_COLOR_WRITEMASK, colorMask);
273     ::glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
274     if (m_attrs.depth) {
275         ::glGetFloatv(GL_DEPTH_CLEAR_VALUE, &clearDepth);
276         ::glClearDepth(1);
277         ::glGetBooleanv(GL_DEPTH_WRITEMASK, &depthMask);
278         ::glDepthMask(GL_TRUE);
279         clearMask |= GL_DEPTH_BUFFER_BIT;
280     }
281     if (m_attrs.stencil) {
282         ::glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &clearStencil);
283         ::glClearStencil(0);
284         ::glGetIntegerv(GL_STENCIL_WRITEMASK, reinterpret_cast<GLint*>(&stencilMask));
285         ::glStencilMaskSeparate(GL_FRONT, 0xffffffff);
286         clearMask |= GL_STENCIL_BUFFER_BIT;
287     }
288     isScissorEnabled = ::glIsEnabled(GL_SCISSOR_TEST);
289     ::glDisable(GL_SCISSOR_TEST);
290     isDitherEnabled = ::glIsEnabled(GL_DITHER);
291     ::glDisable(GL_DITHER);
292 
293     ::glClear(clearMask);
294 
295     ::glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
296     ::glColorMask(colorMask[0], colorMask[1], colorMask[2], colorMask[3]);
297     if (m_attrs.depth) {
298         ::glClearDepth(clearDepth);
299         ::glDepthMask(depthMask);
300     }
301     if (m_attrs.stencil) {
302         ::glClearStencil(clearStencil);
303         ::glStencilMaskSeparate(GL_FRONT, stencilMask);
304     }
305     if (isScissorEnabled)
306         ::glEnable(GL_SCISSOR_TEST);
307     else
308         ::glDisable(GL_SCISSOR_TEST);
309     if (isDitherEnabled)
310         ::glEnable(GL_DITHER);
311     else
312         ::glDisable(GL_DITHER);
313 
314     if (mustRestoreFBO)
315         ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_boundFBO);
316 
317     ::glFlush();
318 }
319 
getInternalFramebufferSize()320 IntSize GraphicsContext3D::getInternalFramebufferSize()
321 {
322     return IntSize(m_currentWidth, m_currentHeight);
323 }
324 
prepareTexture()325 void GraphicsContext3D::prepareTexture()
326 {
327     if (m_layerComposited)
328         return;
329     makeContextCurrent();
330     if (m_attrs.antialias) {
331         ::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_multisampleFBO);
332         ::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fbo);
333         ::glBlitFramebufferEXT(0, 0, m_currentWidth, m_currentHeight, 0, 0, m_currentWidth, m_currentHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR);
334     }
335     ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
336     ::glActiveTexture(0);
337     ::glBindTexture(GL_TEXTURE_2D, m_compositorTexture);
338     ::glCopyTexImage2D(GL_TEXTURE_2D, 0, m_internalColorFormat, 0, 0, m_currentWidth, m_currentHeight, 0);
339     ::glBindTexture(GL_TEXTURE_2D, m_boundTexture0);
340     ::glActiveTexture(m_activeTexture);
341     ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_boundFBO);
342     ::glFinish();
343     m_layerComposited = true;
344 }
345 
activeTexture(GC3Denum texture)346 void GraphicsContext3D::activeTexture(GC3Denum texture)
347 {
348     makeContextCurrent();
349     m_activeTexture = texture;
350     ::glActiveTexture(texture);
351 }
352 
attachShader(Platform3DObject program,Platform3DObject shader)353 void GraphicsContext3D::attachShader(Platform3DObject program, Platform3DObject shader)
354 {
355     ASSERT(program);
356     ASSERT(shader);
357     makeContextCurrent();
358     ::glAttachShader(program, shader);
359 }
360 
bindAttribLocation(Platform3DObject program,GC3Duint index,const String & name)361 void GraphicsContext3D::bindAttribLocation(Platform3DObject program, GC3Duint index, const String& name)
362 {
363     ASSERT(program);
364     makeContextCurrent();
365     ::glBindAttribLocation(program, index, name.utf8().data());
366 }
367 
bindBuffer(GC3Denum target,Platform3DObject buffer)368 void GraphicsContext3D::bindBuffer(GC3Denum target, Platform3DObject buffer)
369 {
370     makeContextCurrent();
371     ::glBindBuffer(target, buffer);
372 }
373 
374 
bindFramebuffer(GC3Denum target,Platform3DObject buffer)375 void GraphicsContext3D::bindFramebuffer(GC3Denum target, Platform3DObject buffer)
376 {
377     makeContextCurrent();
378     GLuint fbo;
379     if (buffer)
380         fbo = buffer;
381     else
382         fbo = (m_attrs.antialias ? m_multisampleFBO : m_fbo);
383     if (fbo != m_boundFBO) {
384         ::glBindFramebufferEXT(target, fbo);
385         m_boundFBO = fbo;
386     }
387 }
388 
bindRenderbuffer(GC3Denum target,Platform3DObject renderbuffer)389 void GraphicsContext3D::bindRenderbuffer(GC3Denum target, Platform3DObject renderbuffer)
390 {
391     makeContextCurrent();
392     ::glBindRenderbufferEXT(target, renderbuffer);
393 }
394 
395 
bindTexture(GC3Denum target,Platform3DObject texture)396 void GraphicsContext3D::bindTexture(GC3Denum target, Platform3DObject texture)
397 {
398     makeContextCurrent();
399     if (m_activeTexture && target == GL_TEXTURE_2D)
400         m_boundTexture0 = texture;
401     ::glBindTexture(target, texture);
402 }
403 
blendColor(GC3Dclampf red,GC3Dclampf green,GC3Dclampf blue,GC3Dclampf alpha)404 void GraphicsContext3D::blendColor(GC3Dclampf red, GC3Dclampf green, GC3Dclampf blue, GC3Dclampf alpha)
405 {
406     makeContextCurrent();
407     ::glBlendColor(red, green, blue, alpha);
408 }
409 
blendEquation(GC3Denum mode)410 void GraphicsContext3D::blendEquation(GC3Denum mode)
411 {
412     makeContextCurrent();
413     ::glBlendEquation(mode);
414 }
415 
blendEquationSeparate(GC3Denum modeRGB,GC3Denum modeAlpha)416 void GraphicsContext3D::blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha)
417 {
418     makeContextCurrent();
419     ::glBlendEquationSeparate(modeRGB, modeAlpha);
420 }
421 
422 
blendFunc(GC3Denum sfactor,GC3Denum dfactor)423 void GraphicsContext3D::blendFunc(GC3Denum sfactor, GC3Denum dfactor)
424 {
425     makeContextCurrent();
426     ::glBlendFunc(sfactor, dfactor);
427 }
428 
blendFuncSeparate(GC3Denum srcRGB,GC3Denum dstRGB,GC3Denum srcAlpha,GC3Denum dstAlpha)429 void GraphicsContext3D::blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha)
430 {
431     makeContextCurrent();
432     ::glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
433 }
434 
bufferData(GC3Denum target,GC3Dsizeiptr size,GC3Denum usage)435 void GraphicsContext3D::bufferData(GC3Denum target, GC3Dsizeiptr size, GC3Denum usage)
436 {
437     makeContextCurrent();
438     ::glBufferData(target, size, 0, usage);
439 }
440 
bufferData(GC3Denum target,GC3Dsizeiptr size,const void * data,GC3Denum usage)441 void GraphicsContext3D::bufferData(GC3Denum target, GC3Dsizeiptr size, const void* data, GC3Denum usage)
442 {
443     makeContextCurrent();
444     ::glBufferData(target, size, data, usage);
445 }
446 
bufferSubData(GC3Denum target,GC3Dintptr offset,GC3Dsizeiptr size,const void * data)447 void GraphicsContext3D::bufferSubData(GC3Denum target, GC3Dintptr offset, GC3Dsizeiptr size, const void* data)
448 {
449     makeContextCurrent();
450     ::glBufferSubData(target, offset, size, data);
451 }
452 
checkFramebufferStatus(GC3Denum target)453 GC3Denum GraphicsContext3D::checkFramebufferStatus(GC3Denum target)
454 {
455     makeContextCurrent();
456     return ::glCheckFramebufferStatusEXT(target);
457 }
458 
clearColor(GC3Dclampf r,GC3Dclampf g,GC3Dclampf b,GC3Dclampf a)459 void GraphicsContext3D::clearColor(GC3Dclampf r, GC3Dclampf g, GC3Dclampf b, GC3Dclampf a)
460 {
461     makeContextCurrent();
462     ::glClearColor(r, g, b, a);
463 }
464 
clear(GC3Dbitfield mask)465 void GraphicsContext3D::clear(GC3Dbitfield mask)
466 {
467     makeContextCurrent();
468     ::glClear(mask);
469 }
470 
clearDepth(GC3Dclampf depth)471 void GraphicsContext3D::clearDepth(GC3Dclampf depth)
472 {
473     makeContextCurrent();
474     ::glClearDepth(depth);
475 }
476 
clearStencil(GC3Dint s)477 void GraphicsContext3D::clearStencil(GC3Dint s)
478 {
479     makeContextCurrent();
480     ::glClearStencil(s);
481 }
482 
colorMask(GC3Dboolean red,GC3Dboolean green,GC3Dboolean blue,GC3Dboolean alpha)483 void GraphicsContext3D::colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha)
484 {
485     makeContextCurrent();
486     ::glColorMask(red, green, blue, alpha);
487 }
488 
compileShader(Platform3DObject shader)489 void GraphicsContext3D::compileShader(Platform3DObject shader)
490 {
491     ASSERT(shader);
492     makeContextCurrent();
493 
494     int GLshaderType;
495     ANGLEShaderType shaderType;
496 
497     glGetShaderiv(shader, SHADER_TYPE, &GLshaderType);
498 
499     if (GLshaderType == VERTEX_SHADER)
500         shaderType = SHADER_TYPE_VERTEX;
501     else if (GLshaderType == FRAGMENT_SHADER)
502         shaderType = SHADER_TYPE_FRAGMENT;
503     else
504         return; // Invalid shader type.
505 
506     HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader);
507 
508     if (result == m_shaderSourceMap.end())
509         return;
510 
511     ShaderSourceEntry& entry = result->second;
512 
513     String translatedShaderSource;
514     String shaderInfoLog;
515 
516     bool isValid = m_compiler.validateShaderSource(entry.source.utf8().data(), shaderType, translatedShaderSource, shaderInfoLog);
517 
518     entry.log = shaderInfoLog;
519     entry.isValid = isValid;
520 
521     if (!isValid)
522         return; // Shader didn't validate, don't move forward with compiling translated source
523 
524     int translatedShaderLength = translatedShaderSource.length();
525 
526     const CString& translatedShaderCString = translatedShaderSource.utf8();
527     const char* translatedShaderPtr = translatedShaderCString.data();
528 
529     ::glShaderSource(shader, 1, &translatedShaderPtr, &translatedShaderLength);
530 
531     ::glCompileShader(shader);
532 
533     int GLCompileSuccess;
534 
535     ::glGetShaderiv(shader, COMPILE_STATUS, &GLCompileSuccess);
536 
537     // ASSERT that ANGLE generated GLSL will be accepted by OpenGL
538     ASSERT(GLCompileSuccess == GL_TRUE);
539 }
540 
copyTexImage2D(GC3Denum target,GC3Dint level,GC3Denum internalformat,GC3Dint x,GC3Dint y,GC3Dsizei width,GC3Dsizei height,GC3Dint border)541 void GraphicsContext3D::copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border)
542 {
543     makeContextCurrent();
544     if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) {
545         ::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_multisampleFBO);
546         ::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fbo);
547         ::glBlitFramebufferEXT(x, y, x + width, y + height, x, y, x + width, y + height, GL_COLOR_BUFFER_BIT, GL_LINEAR);
548         ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
549     }
550     ::glCopyTexImage2D(target, level, internalformat, x, y, width, height, border);
551     if (m_attrs.antialias && m_boundFBO == m_multisampleFBO)
552         ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO);
553 }
554 
copyTexSubImage2D(GC3Denum target,GC3Dint level,GC3Dint xoffset,GC3Dint yoffset,GC3Dint x,GC3Dint y,GC3Dsizei width,GC3Dsizei height)555 void GraphicsContext3D::copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
556 {
557     makeContextCurrent();
558     if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) {
559         ::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_multisampleFBO);
560         ::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fbo);
561         ::glBlitFramebufferEXT(x, y, x + width, y + height, x, y, x + width, y + height, GL_COLOR_BUFFER_BIT, GL_LINEAR);
562         ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
563     }
564     ::glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
565     if (m_attrs.antialias && m_boundFBO == m_multisampleFBO)
566         ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO);
567 }
568 
cullFace(GC3Denum mode)569 void GraphicsContext3D::cullFace(GC3Denum mode)
570 {
571     makeContextCurrent();
572     ::glCullFace(mode);
573 }
574 
depthFunc(GC3Denum func)575 void GraphicsContext3D::depthFunc(GC3Denum func)
576 {
577     makeContextCurrent();
578     ::glDepthFunc(func);
579 }
580 
depthMask(GC3Dboolean flag)581 void GraphicsContext3D::depthMask(GC3Dboolean flag)
582 {
583     makeContextCurrent();
584     ::glDepthMask(flag);
585 }
586 
depthRange(GC3Dclampf zNear,GC3Dclampf zFar)587 void GraphicsContext3D::depthRange(GC3Dclampf zNear, GC3Dclampf zFar)
588 {
589     makeContextCurrent();
590     ::glDepthRange(zNear, zFar);
591 }
592 
detachShader(Platform3DObject program,Platform3DObject shader)593 void GraphicsContext3D::detachShader(Platform3DObject program, Platform3DObject shader)
594 {
595     ASSERT(program);
596     ASSERT(shader);
597     makeContextCurrent();
598     ::glDetachShader(program, shader);
599 }
600 
disable(GC3Denum cap)601 void GraphicsContext3D::disable(GC3Denum cap)
602 {
603     makeContextCurrent();
604     ::glDisable(cap);
605 }
606 
disableVertexAttribArray(GC3Duint index)607 void GraphicsContext3D::disableVertexAttribArray(GC3Duint index)
608 {
609     makeContextCurrent();
610     ::glDisableVertexAttribArray(index);
611 }
612 
drawArrays(GC3Denum mode,GC3Dint first,GC3Dsizei count)613 void GraphicsContext3D::drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count)
614 {
615     makeContextCurrent();
616     ::glDrawArrays(mode, first, count);
617 }
618 
drawElements(GC3Denum mode,GC3Dsizei count,GC3Denum type,GC3Dintptr offset)619 void GraphicsContext3D::drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dintptr offset)
620 {
621     makeContextCurrent();
622     ::glDrawElements(mode, count, type, reinterpret_cast<GLvoid*>(static_cast<intptr_t>(offset)));
623 }
624 
enable(GC3Denum cap)625 void GraphicsContext3D::enable(GC3Denum cap)
626 {
627     makeContextCurrent();
628     ::glEnable(cap);
629 }
630 
enableVertexAttribArray(GC3Duint index)631 void GraphicsContext3D::enableVertexAttribArray(GC3Duint index)
632 {
633     makeContextCurrent();
634     ::glEnableVertexAttribArray(index);
635 }
636 
finish()637 void GraphicsContext3D::finish()
638 {
639     makeContextCurrent();
640     ::glFinish();
641 }
642 
flush()643 void GraphicsContext3D::flush()
644 {
645     makeContextCurrent();
646     ::glFlush();
647 }
648 
framebufferRenderbuffer(GC3Denum target,GC3Denum attachment,GC3Denum renderbuffertarget,Platform3DObject buffer)649 void GraphicsContext3D::framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbuffertarget, Platform3DObject buffer)
650 {
651     makeContextCurrent();
652     ::glFramebufferRenderbufferEXT(target, attachment, renderbuffertarget, buffer);
653 }
654 
framebufferTexture2D(GC3Denum target,GC3Denum attachment,GC3Denum textarget,Platform3DObject texture,GC3Dint level)655 void GraphicsContext3D::framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum textarget, Platform3DObject texture, GC3Dint level)
656 {
657     makeContextCurrent();
658     ::glFramebufferTexture2DEXT(target, attachment, textarget, texture, level);
659 }
660 
frontFace(GC3Denum mode)661 void GraphicsContext3D::frontFace(GC3Denum mode)
662 {
663     makeContextCurrent();
664     ::glFrontFace(mode);
665 }
666 
generateMipmap(GC3Denum target)667 void GraphicsContext3D::generateMipmap(GC3Denum target)
668 {
669     makeContextCurrent();
670     ::glGenerateMipmapEXT(target);
671 }
672 
getActiveAttrib(Platform3DObject program,GC3Duint index,ActiveInfo & info)673 bool GraphicsContext3D::getActiveAttrib(Platform3DObject program, GC3Duint index, ActiveInfo& info)
674 {
675     if (!program) {
676         synthesizeGLError(INVALID_VALUE);
677         return false;
678     }
679     makeContextCurrent();
680     GLint maxAttributeSize = 0;
681     ::glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxAttributeSize);
682     GLchar name[maxAttributeSize]; // GL_ACTIVE_ATTRIBUTE_MAX_LENGTH includes null termination
683     GLsizei nameLength = 0;
684     GLint size = 0;
685     GLenum type = 0;
686     ::glGetActiveAttrib(program, index, maxAttributeSize, &nameLength, &size, &type, name);
687     if (!nameLength)
688         return false;
689     info.name = String(name, nameLength);
690     info.type = type;
691     info.size = size;
692     return true;
693 }
694 
getActiveUniform(Platform3DObject program,GC3Duint index,ActiveInfo & info)695 bool GraphicsContext3D::getActiveUniform(Platform3DObject program, GC3Duint index, ActiveInfo& info)
696 {
697     if (!program) {
698         synthesizeGLError(INVALID_VALUE);
699         return false;
700     }
701     makeContextCurrent();
702     GLint maxUniformSize = 0;
703     ::glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformSize);
704     GLchar name[maxUniformSize]; // GL_ACTIVE_UNIFORM_MAX_LENGTH includes null termination
705     GLsizei nameLength = 0;
706     GLint size = 0;
707     GLenum type = 0;
708     ::glGetActiveUniform(program, index, maxUniformSize, &nameLength, &size, &type, name);
709     if (!nameLength)
710         return false;
711     info.name = String(name, nameLength);
712     info.type = type;
713     info.size = size;
714     return true;
715 }
716 
getAttachedShaders(Platform3DObject program,GC3Dsizei maxCount,GC3Dsizei * count,Platform3DObject * shaders)717 void GraphicsContext3D::getAttachedShaders(Platform3DObject program, GC3Dsizei maxCount, GC3Dsizei* count, Platform3DObject* shaders)
718 {
719     if (!program) {
720         synthesizeGLError(INVALID_VALUE);
721         return;
722     }
723     makeContextCurrent();
724     ::glGetAttachedShaders(program, maxCount, count, shaders);
725 }
726 
getAttribLocation(Platform3DObject program,const String & name)727 int GraphicsContext3D::getAttribLocation(Platform3DObject program, const String& name)
728 {
729     if (!program)
730         return -1;
731 
732     makeContextCurrent();
733     return ::glGetAttribLocation(program, name.utf8().data());
734 }
735 
getContextAttributes()736 GraphicsContext3D::Attributes GraphicsContext3D::getContextAttributes()
737 {
738     return m_attrs;
739 }
740 
getError()741 GC3Denum GraphicsContext3D::getError()
742 {
743     if (m_syntheticErrors.size() > 0) {
744         ListHashSet<GC3Denum>::iterator iter = m_syntheticErrors.begin();
745         GC3Denum err = *iter;
746         m_syntheticErrors.remove(iter);
747         return err;
748     }
749 
750     makeContextCurrent();
751     return ::glGetError();
752 }
753 
getString(GC3Denum name)754 String GraphicsContext3D::getString(GC3Denum name)
755 {
756     makeContextCurrent();
757     return String((const char*) ::glGetString(name));
758 }
759 
hint(GC3Denum target,GC3Denum mode)760 void GraphicsContext3D::hint(GC3Denum target, GC3Denum mode)
761 {
762     makeContextCurrent();
763     ::glHint(target, mode);
764 }
765 
isBuffer(Platform3DObject buffer)766 GC3Dboolean GraphicsContext3D::isBuffer(Platform3DObject buffer)
767 {
768     if (!buffer)
769         return GL_FALSE;
770 
771     makeContextCurrent();
772     return ::glIsBuffer(buffer);
773 }
774 
isEnabled(GC3Denum cap)775 GC3Dboolean GraphicsContext3D::isEnabled(GC3Denum cap)
776 {
777     makeContextCurrent();
778     return ::glIsEnabled(cap);
779 }
780 
isFramebuffer(Platform3DObject framebuffer)781 GC3Dboolean GraphicsContext3D::isFramebuffer(Platform3DObject framebuffer)
782 {
783     if (!framebuffer)
784         return GL_FALSE;
785 
786     makeContextCurrent();
787     return ::glIsFramebufferEXT(framebuffer);
788 }
789 
isProgram(Platform3DObject program)790 GC3Dboolean GraphicsContext3D::isProgram(Platform3DObject program)
791 {
792     if (!program)
793         return GL_FALSE;
794 
795     makeContextCurrent();
796     return ::glIsProgram(program);
797 }
798 
isRenderbuffer(Platform3DObject renderbuffer)799 GC3Dboolean GraphicsContext3D::isRenderbuffer(Platform3DObject renderbuffer)
800 {
801     if (!renderbuffer)
802         return GL_FALSE;
803 
804     makeContextCurrent();
805     return ::glIsRenderbufferEXT(renderbuffer);
806 }
807 
isShader(Platform3DObject shader)808 GC3Dboolean GraphicsContext3D::isShader(Platform3DObject shader)
809 {
810     if (!shader)
811         return GL_FALSE;
812 
813     makeContextCurrent();
814     return ::glIsShader(shader);
815 }
816 
isTexture(Platform3DObject texture)817 GC3Dboolean GraphicsContext3D::isTexture(Platform3DObject texture)
818 {
819     if (!texture)
820         return GL_FALSE;
821 
822     makeContextCurrent();
823     return ::glIsTexture(texture);
824 }
825 
lineWidth(GC3Dfloat width)826 void GraphicsContext3D::lineWidth(GC3Dfloat width)
827 {
828     makeContextCurrent();
829     ::glLineWidth(width);
830 }
831 
linkProgram(Platform3DObject program)832 void GraphicsContext3D::linkProgram(Platform3DObject program)
833 {
834     ASSERT(program);
835     makeContextCurrent();
836     ::glLinkProgram(program);
837 }
838 
pixelStorei(GC3Denum pname,GC3Dint param)839 void GraphicsContext3D::pixelStorei(GC3Denum pname, GC3Dint param)
840 {
841     makeContextCurrent();
842     ::glPixelStorei(pname, param);
843 }
844 
polygonOffset(GC3Dfloat factor,GC3Dfloat units)845 void GraphicsContext3D::polygonOffset(GC3Dfloat factor, GC3Dfloat units)
846 {
847     makeContextCurrent();
848     ::glPolygonOffset(factor, units);
849 }
850 
readPixels(GC3Dint x,GC3Dint y,GC3Dsizei width,GC3Dsizei height,GC3Denum format,GC3Denum type,void * data)851 void GraphicsContext3D::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, void* data)
852 {
853     // FIXME: remove the two glFlush calls when the driver bug is fixed, i.e.,
854     // all previous rendering calls should be done before reading pixels.
855     makeContextCurrent();
856     ::glFlush();
857     if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) {
858         ::glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_multisampleFBO);
859         ::glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_fbo);
860         ::glBlitFramebufferEXT(x, y, x + width, y + height, x, y, x + width, y + height, GL_COLOR_BUFFER_BIT, GL_LINEAR);
861         ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo);
862         ::glFlush();
863     }
864     ::glReadPixels(x, y, width, height, format, type, data);
865     if (m_attrs.antialias && m_boundFBO == m_multisampleFBO)
866         ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO);
867 }
868 
releaseShaderCompiler()869 void GraphicsContext3D::releaseShaderCompiler()
870 {
871     // FIXME: This is not implemented on desktop OpenGL. We need to have ifdefs for the different GL variants
872     makeContextCurrent();
873     //::glReleaseShaderCompiler();
874 }
875 
renderbufferStorage(GC3Denum target,GC3Denum internalformat,GC3Dsizei width,GC3Dsizei height)876 void GraphicsContext3D::renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height)
877 {
878     makeContextCurrent();
879     switch (internalformat) {
880     case DEPTH_STENCIL:
881         internalformat = GL_DEPTH24_STENCIL8_EXT;
882         break;
883     case DEPTH_COMPONENT16:
884         internalformat = GL_DEPTH_COMPONENT;
885         break;
886     case RGBA4:
887     case RGB5_A1:
888         internalformat = GL_RGBA;
889         break;
890     case RGB565:
891         internalformat = GL_RGB;
892         break;
893     }
894     ::glRenderbufferStorageEXT(target, internalformat, width, height);
895 }
896 
sampleCoverage(GC3Dclampf value,GC3Dboolean invert)897 void GraphicsContext3D::sampleCoverage(GC3Dclampf value, GC3Dboolean invert)
898 {
899     makeContextCurrent();
900     ::glSampleCoverage(value, invert);
901 }
902 
scissor(GC3Dint x,GC3Dint y,GC3Dsizei width,GC3Dsizei height)903 void GraphicsContext3D::scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
904 {
905     makeContextCurrent();
906     ::glScissor(x, y, width, height);
907 }
908 
shaderSource(Platform3DObject shader,const String & string)909 void GraphicsContext3D::shaderSource(Platform3DObject shader, const String& string)
910 {
911     ASSERT(shader);
912 
913     makeContextCurrent();
914 
915     ShaderSourceEntry entry;
916 
917     entry.source = string;
918 
919     m_shaderSourceMap.set(shader, entry);
920 }
921 
stencilFunc(GC3Denum func,GC3Dint ref,GC3Duint mask)922 void GraphicsContext3D::stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask)
923 {
924     makeContextCurrent();
925     ::glStencilFunc(func, ref, mask);
926 }
927 
stencilFuncSeparate(GC3Denum face,GC3Denum func,GC3Dint ref,GC3Duint mask)928 void GraphicsContext3D::stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask)
929 {
930     makeContextCurrent();
931     ::glStencilFuncSeparate(face, func, ref, mask);
932 }
933 
stencilMask(GC3Duint mask)934 void GraphicsContext3D::stencilMask(GC3Duint mask)
935 {
936     makeContextCurrent();
937     ::glStencilMask(mask);
938 }
939 
stencilMaskSeparate(GC3Denum face,GC3Duint mask)940 void GraphicsContext3D::stencilMaskSeparate(GC3Denum face, GC3Duint mask)
941 {
942     makeContextCurrent();
943     ::glStencilMaskSeparate(face, mask);
944 }
945 
stencilOp(GC3Denum fail,GC3Denum zfail,GC3Denum zpass)946 void GraphicsContext3D::stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zpass)
947 {
948     makeContextCurrent();
949     ::glStencilOp(fail, zfail, zpass);
950 }
951 
stencilOpSeparate(GC3Denum face,GC3Denum fail,GC3Denum zfail,GC3Denum zpass)952 void GraphicsContext3D::stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zfail, GC3Denum zpass)
953 {
954     makeContextCurrent();
955     ::glStencilOpSeparate(face, fail, zfail, zpass);
956 }
957 
texParameterf(GC3Denum target,GC3Denum pname,GC3Dfloat value)958 void GraphicsContext3D::texParameterf(GC3Denum target, GC3Denum pname, GC3Dfloat value)
959 {
960     makeContextCurrent();
961     ::glTexParameterf(target, pname, value);
962 }
963 
texParameteri(GC3Denum target,GC3Denum pname,GC3Dint value)964 void GraphicsContext3D::texParameteri(GC3Denum target, GC3Denum pname, GC3Dint value)
965 {
966     makeContextCurrent();
967     ::glTexParameteri(target, pname, value);
968 }
969 
uniform1f(GC3Dint location,GC3Dfloat v0)970 void GraphicsContext3D::uniform1f(GC3Dint location, GC3Dfloat v0)
971 {
972     makeContextCurrent();
973     ::glUniform1f(location, v0);
974 }
975 
uniform1fv(GC3Dint location,GC3Dfloat * array,GC3Dsizei size)976 void GraphicsContext3D::uniform1fv(GC3Dint location, GC3Dfloat* array, GC3Dsizei size)
977 {
978     makeContextCurrent();
979     ::glUniform1fv(location, size, array);
980 }
981 
uniform2f(GC3Dint location,GC3Dfloat v0,GC3Dfloat v1)982 void GraphicsContext3D::uniform2f(GC3Dint location, GC3Dfloat v0, GC3Dfloat v1)
983 {
984     makeContextCurrent();
985     ::glUniform2f(location, v0, v1);
986 }
987 
uniform2fv(GC3Dint location,GC3Dfloat * array,GC3Dsizei size)988 void GraphicsContext3D::uniform2fv(GC3Dint location, GC3Dfloat* array, GC3Dsizei size)
989 {
990     // FIXME: length needs to be a multiple of 2
991     makeContextCurrent();
992     ::glUniform2fv(location, size, array);
993 }
994 
uniform3f(GC3Dint location,GC3Dfloat v0,GC3Dfloat v1,GC3Dfloat v2)995 void GraphicsContext3D::uniform3f(GC3Dint location, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2)
996 {
997     makeContextCurrent();
998     ::glUniform3f(location, v0, v1, v2);
999 }
1000 
uniform3fv(GC3Dint location,GC3Dfloat * array,GC3Dsizei size)1001 void GraphicsContext3D::uniform3fv(GC3Dint location, GC3Dfloat* array, GC3Dsizei size)
1002 {
1003     // FIXME: length needs to be a multiple of 3
1004     makeContextCurrent();
1005     ::glUniform3fv(location, size, array);
1006 }
1007 
uniform4f(GC3Dint location,GC3Dfloat v0,GC3Dfloat v1,GC3Dfloat v2,GC3Dfloat v3)1008 void GraphicsContext3D::uniform4f(GC3Dint location, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3)
1009 {
1010     makeContextCurrent();
1011     ::glUniform4f(location, v0, v1, v2, v3);
1012 }
1013 
uniform4fv(GC3Dint location,GC3Dfloat * array,GC3Dsizei size)1014 void GraphicsContext3D::uniform4fv(GC3Dint location, GC3Dfloat* array, GC3Dsizei size)
1015 {
1016     // FIXME: length needs to be a multiple of 4
1017     makeContextCurrent();
1018     ::glUniform4fv(location, size, array);
1019 }
1020 
uniform1i(GC3Dint location,GC3Dint v0)1021 void GraphicsContext3D::uniform1i(GC3Dint location, GC3Dint v0)
1022 {
1023     makeContextCurrent();
1024     ::glUniform1i(location, v0);
1025 }
1026 
uniform1iv(GC3Dint location,GC3Dint * array,GC3Dsizei size)1027 void GraphicsContext3D::uniform1iv(GC3Dint location, GC3Dint* array, GC3Dsizei size)
1028 {
1029     makeContextCurrent();
1030     ::glUniform1iv(location, size, array);
1031 }
1032 
uniform2i(GC3Dint location,GC3Dint v0,GC3Dint v1)1033 void GraphicsContext3D::uniform2i(GC3Dint location, GC3Dint v0, GC3Dint v1)
1034 {
1035     makeContextCurrent();
1036     ::glUniform2i(location, v0, v1);
1037 }
1038 
uniform2iv(GC3Dint location,GC3Dint * array,GC3Dsizei size)1039 void GraphicsContext3D::uniform2iv(GC3Dint location, GC3Dint* array, GC3Dsizei size)
1040 {
1041     // FIXME: length needs to be a multiple of 2
1042     makeContextCurrent();
1043     ::glUniform2iv(location, size, array);
1044 }
1045 
uniform3i(GC3Dint location,GC3Dint v0,GC3Dint v1,GC3Dint v2)1046 void GraphicsContext3D::uniform3i(GC3Dint location, GC3Dint v0, GC3Dint v1, GC3Dint v2)
1047 {
1048     makeContextCurrent();
1049     ::glUniform3i(location, v0, v1, v2);
1050 }
1051 
uniform3iv(GC3Dint location,GC3Dint * array,GC3Dsizei size)1052 void GraphicsContext3D::uniform3iv(GC3Dint location, GC3Dint* array, GC3Dsizei size)
1053 {
1054     // FIXME: length needs to be a multiple of 3
1055     makeContextCurrent();
1056     ::glUniform3iv(location, size, array);
1057 }
1058 
uniform4i(GC3Dint location,GC3Dint v0,GC3Dint v1,GC3Dint v2,GC3Dint v3)1059 void GraphicsContext3D::uniform4i(GC3Dint location, GC3Dint v0, GC3Dint v1, GC3Dint v2, GC3Dint v3)
1060 {
1061     makeContextCurrent();
1062     ::glUniform4i(location, v0, v1, v2, v3);
1063 }
1064 
uniform4iv(GC3Dint location,GC3Dint * array,GC3Dsizei size)1065 void GraphicsContext3D::uniform4iv(GC3Dint location, GC3Dint* array, GC3Dsizei size)
1066 {
1067     // FIXME: length needs to be a multiple of 4
1068     makeContextCurrent();
1069     ::glUniform4iv(location, size, array);
1070 }
1071 
uniformMatrix2fv(GC3Dint location,GC3Dboolean transpose,GC3Dfloat * array,GC3Dsizei size)1072 void GraphicsContext3D::uniformMatrix2fv(GC3Dint location, GC3Dboolean transpose, GC3Dfloat* array, GC3Dsizei size)
1073 {
1074     // FIXME: length needs to be a multiple of 4
1075     makeContextCurrent();
1076     ::glUniformMatrix2fv(location, size, transpose, array);
1077 }
1078 
uniformMatrix3fv(GC3Dint location,GC3Dboolean transpose,GC3Dfloat * array,GC3Dsizei size)1079 void GraphicsContext3D::uniformMatrix3fv(GC3Dint location, GC3Dboolean transpose, GC3Dfloat* array, GC3Dsizei size)
1080 {
1081     // FIXME: length needs to be a multiple of 9
1082     makeContextCurrent();
1083     ::glUniformMatrix3fv(location, size, transpose, array);
1084 }
1085 
uniformMatrix4fv(GC3Dint location,GC3Dboolean transpose,GC3Dfloat * array,GC3Dsizei size)1086 void GraphicsContext3D::uniformMatrix4fv(GC3Dint location, GC3Dboolean transpose, GC3Dfloat* array, GC3Dsizei size)
1087 {
1088     // FIXME: length needs to be a multiple of 16
1089     makeContextCurrent();
1090     ::glUniformMatrix4fv(location, size, transpose, array);
1091 }
1092 
useProgram(Platform3DObject program)1093 void GraphicsContext3D::useProgram(Platform3DObject program)
1094 {
1095     makeContextCurrent();
1096     ::glUseProgram(program);
1097 }
1098 
validateProgram(Platform3DObject program)1099 void GraphicsContext3D::validateProgram(Platform3DObject program)
1100 {
1101     ASSERT(program);
1102 
1103     makeContextCurrent();
1104     ::glValidateProgram(program);
1105 }
1106 
vertexAttrib1f(GC3Duint index,GC3Dfloat v0)1107 void GraphicsContext3D::vertexAttrib1f(GC3Duint index, GC3Dfloat v0)
1108 {
1109     makeContextCurrent();
1110     ::glVertexAttrib1f(index, v0);
1111 }
1112 
vertexAttrib1fv(GC3Duint index,GC3Dfloat * array)1113 void GraphicsContext3D::vertexAttrib1fv(GC3Duint index, GC3Dfloat* array)
1114 {
1115     makeContextCurrent();
1116     ::glVertexAttrib1fv(index, array);
1117 }
1118 
vertexAttrib2f(GC3Duint index,GC3Dfloat v0,GC3Dfloat v1)1119 void GraphicsContext3D::vertexAttrib2f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1)
1120 {
1121     makeContextCurrent();
1122     ::glVertexAttrib2f(index, v0, v1);
1123 }
1124 
vertexAttrib2fv(GC3Duint index,GC3Dfloat * array)1125 void GraphicsContext3D::vertexAttrib2fv(GC3Duint index, GC3Dfloat* array)
1126 {
1127     makeContextCurrent();
1128     ::glVertexAttrib2fv(index, array);
1129 }
1130 
vertexAttrib3f(GC3Duint index,GC3Dfloat v0,GC3Dfloat v1,GC3Dfloat v2)1131 void GraphicsContext3D::vertexAttrib3f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2)
1132 {
1133     makeContextCurrent();
1134     ::glVertexAttrib3f(index, v0, v1, v2);
1135 }
1136 
vertexAttrib3fv(GC3Duint index,GC3Dfloat * array)1137 void GraphicsContext3D::vertexAttrib3fv(GC3Duint index, GC3Dfloat* array)
1138 {
1139     makeContextCurrent();
1140     ::glVertexAttrib3fv(index, array);
1141 }
1142 
vertexAttrib4f(GC3Duint index,GC3Dfloat v0,GC3Dfloat v1,GC3Dfloat v2,GC3Dfloat v3)1143 void GraphicsContext3D::vertexAttrib4f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3)
1144 {
1145     makeContextCurrent();
1146     ::glVertexAttrib4f(index, v0, v1, v2, v3);
1147 }
1148 
vertexAttrib4fv(GC3Duint index,GC3Dfloat * array)1149 void GraphicsContext3D::vertexAttrib4fv(GC3Duint index, GC3Dfloat* array)
1150 {
1151     makeContextCurrent();
1152     ::glVertexAttrib4fv(index, array);
1153 }
1154 
vertexAttribPointer(GC3Duint index,GC3Dint size,GC3Denum type,GC3Dboolean normalized,GC3Dsizei stride,GC3Dintptr offset)1155 void GraphicsContext3D::vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized, GC3Dsizei stride, GC3Dintptr offset)
1156 {
1157     makeContextCurrent();
1158     ::glVertexAttribPointer(index, size, type, normalized, stride, reinterpret_cast<GLvoid*>(static_cast<intptr_t>(offset)));
1159 }
1160 
viewport(GC3Dint x,GC3Dint y,GC3Dsizei width,GC3Dsizei height)1161 void GraphicsContext3D::viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
1162 {
1163     makeContextCurrent();
1164     ::glViewport(x, y, width, height);
1165 }
1166 
getBooleanv(GC3Denum pname,GC3Dboolean * value)1167 void GraphicsContext3D::getBooleanv(GC3Denum pname, GC3Dboolean* value)
1168 {
1169     makeContextCurrent();
1170     ::glGetBooleanv(pname, value);
1171 }
1172 
getBufferParameteriv(GC3Denum target,GC3Denum pname,GC3Dint * value)1173 void GraphicsContext3D::getBufferParameteriv(GC3Denum target, GC3Denum pname, GC3Dint* value)
1174 {
1175     makeContextCurrent();
1176     ::glGetBufferParameteriv(target, pname, value);
1177 }
1178 
getFloatv(GC3Denum pname,GC3Dfloat * value)1179 void GraphicsContext3D::getFloatv(GC3Denum pname, GC3Dfloat* value)
1180 {
1181     makeContextCurrent();
1182     ::glGetFloatv(pname, value);
1183 }
1184 
getFramebufferAttachmentParameteriv(GC3Denum target,GC3Denum attachment,GC3Denum pname,GC3Dint * value)1185 void GraphicsContext3D::getFramebufferAttachmentParameteriv(GC3Denum target, GC3Denum attachment, GC3Denum pname, GC3Dint* value)
1186 {
1187     makeContextCurrent();
1188     if (attachment == DEPTH_STENCIL_ATTACHMENT)
1189         attachment = DEPTH_ATTACHMENT; // Or STENCIL_ATTACHMENT, either works.
1190     ::glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, value);
1191 }
1192 
getIntegerv(GC3Denum pname,GC3Dint * value)1193 void GraphicsContext3D::getIntegerv(GC3Denum pname, GC3Dint* value)
1194 {
1195     // Need to emulate MAX_FRAGMENT/VERTEX_UNIFORM_VECTORS and MAX_VARYING_VECTORS
1196     // because desktop GL's corresponding queries return the number of components
1197     // whereas GLES2 return the number of vectors (each vector has 4 components).
1198     // Therefore, the value returned by desktop GL needs to be divided by 4.
1199     makeContextCurrent();
1200     switch (pname) {
1201     case MAX_FRAGMENT_UNIFORM_VECTORS:
1202         ::glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, value);
1203         *value /= 4;
1204         break;
1205     case MAX_VERTEX_UNIFORM_VECTORS:
1206         ::glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, value);
1207         *value /= 4;
1208         break;
1209     case MAX_VARYING_VECTORS:
1210         ::glGetIntegerv(GL_MAX_VARYING_FLOATS, value);
1211         *value /= 4;
1212         break;
1213     default:
1214         ::glGetIntegerv(pname, value);
1215     }
1216 }
1217 
getProgramiv(Platform3DObject program,GC3Denum pname,GC3Dint * value)1218 void GraphicsContext3D::getProgramiv(Platform3DObject program, GC3Denum pname, GC3Dint* value)
1219 {
1220     makeContextCurrent();
1221     ::glGetProgramiv(program, pname, value);
1222 }
1223 
getProgramInfoLog(Platform3DObject program)1224 String GraphicsContext3D::getProgramInfoLog(Platform3DObject program)
1225 {
1226     ASSERT(program);
1227 
1228     makeContextCurrent();
1229     GLint length;
1230     ::glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
1231     if (!length)
1232         return "";
1233 
1234     GLsizei size;
1235     GLchar* info = (GLchar*) fastMalloc(length);
1236 
1237     ::glGetProgramInfoLog(program, length, &size, info);
1238     String s(info);
1239     fastFree(info);
1240     return s;
1241 }
1242 
getRenderbufferParameteriv(GC3Denum target,GC3Denum pname,GC3Dint * value)1243 void GraphicsContext3D::getRenderbufferParameteriv(GC3Denum target, GC3Denum pname, GC3Dint* value)
1244 {
1245     makeContextCurrent();
1246     ::glGetRenderbufferParameterivEXT(target, pname, value);
1247 }
1248 
getShaderiv(Platform3DObject shader,GC3Denum pname,GC3Dint * value)1249 void GraphicsContext3D::getShaderiv(Platform3DObject shader, GC3Denum pname, GC3Dint* value)
1250 {
1251     ASSERT(shader);
1252 
1253     makeContextCurrent();
1254 
1255     HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader);
1256 
1257     switch (pname) {
1258         case DELETE_STATUS:
1259         case SHADER_TYPE:
1260             // Let OpenGL handle these.
1261 
1262             ::glGetShaderiv(shader, pname, value);
1263             break;
1264 
1265         case COMPILE_STATUS:
1266             if (result == m_shaderSourceMap.end()) {
1267                 (*value) = static_cast<int>(false);
1268                 return;
1269             }
1270 
1271             (*value) = static_cast<int>(result->second.isValid);
1272             break;
1273 
1274         case INFO_LOG_LENGTH:
1275             if (result == m_shaderSourceMap.end()) {
1276                 (*value) = 0;
1277                 return;
1278             }
1279 
1280             (*value) = getShaderInfoLog(shader).length();
1281             break;
1282 
1283         case SHADER_SOURCE_LENGTH:
1284             (*value) = getShaderSource(shader).length();
1285             break;
1286 
1287         default:
1288             synthesizeGLError(INVALID_ENUM);
1289     }
1290 }
1291 
getShaderInfoLog(Platform3DObject shader)1292 String GraphicsContext3D::getShaderInfoLog(Platform3DObject shader)
1293 {
1294     ASSERT(shader);
1295 
1296     makeContextCurrent();
1297 
1298     HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader);
1299 
1300     if (result == m_shaderSourceMap.end())
1301          return "";
1302 
1303      ShaderSourceEntry entry = result->second;
1304 
1305      if (entry.isValid) {
1306          GLint length;
1307          ::glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
1308          if (!length)
1309              return "";
1310 
1311          GLsizei size;
1312          GLchar* info = (GLchar*) fastMalloc(length);
1313 
1314          ::glGetShaderInfoLog(shader, length, &size, info);
1315 
1316          String s(info);
1317          fastFree(info);
1318          return s;
1319      } else
1320          return entry.log;
1321 }
1322 
getShaderSource(Platform3DObject shader)1323 String GraphicsContext3D::getShaderSource(Platform3DObject shader)
1324 {
1325     ASSERT(shader);
1326 
1327     makeContextCurrent();
1328 
1329     HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader);
1330 
1331     if (result == m_shaderSourceMap.end())
1332         return "";
1333 
1334     return result->second.source;
1335 }
1336 
1337 
getTexParameterfv(GC3Denum target,GC3Denum pname,GC3Dfloat * value)1338 void GraphicsContext3D::getTexParameterfv(GC3Denum target, GC3Denum pname, GC3Dfloat* value)
1339 {
1340     makeContextCurrent();
1341     ::glGetTexParameterfv(target, pname, value);
1342 }
1343 
getTexParameteriv(GC3Denum target,GC3Denum pname,GC3Dint * value)1344 void GraphicsContext3D::getTexParameteriv(GC3Denum target, GC3Denum pname, GC3Dint* value)
1345 {
1346     makeContextCurrent();
1347     ::glGetTexParameteriv(target, pname, value);
1348 }
1349 
getUniformfv(Platform3DObject program,GC3Dint location,GC3Dfloat * value)1350 void GraphicsContext3D::getUniformfv(Platform3DObject program, GC3Dint location, GC3Dfloat* value)
1351 {
1352     makeContextCurrent();
1353     ::glGetUniformfv(program, location, value);
1354 }
1355 
getUniformiv(Platform3DObject program,GC3Dint location,GC3Dint * value)1356 void GraphicsContext3D::getUniformiv(Platform3DObject program, GC3Dint location, GC3Dint* value)
1357 {
1358     makeContextCurrent();
1359     ::glGetUniformiv(program, location, value);
1360 }
1361 
getUniformLocation(Platform3DObject program,const String & name)1362 GC3Dint GraphicsContext3D::getUniformLocation(Platform3DObject program, const String& name)
1363 {
1364     ASSERT(program);
1365 
1366     makeContextCurrent();
1367     return ::glGetUniformLocation(program, name.utf8().data());
1368 }
1369 
getVertexAttribfv(GC3Duint index,GC3Denum pname,GC3Dfloat * value)1370 void GraphicsContext3D::getVertexAttribfv(GC3Duint index, GC3Denum pname, GC3Dfloat* value)
1371 {
1372     makeContextCurrent();
1373     ::glGetVertexAttribfv(index, pname, value);
1374 }
1375 
getVertexAttribiv(GC3Duint index,GC3Denum pname,GC3Dint * value)1376 void GraphicsContext3D::getVertexAttribiv(GC3Duint index, GC3Denum pname, GC3Dint* value)
1377 {
1378     makeContextCurrent();
1379     ::glGetVertexAttribiv(index, pname, value);
1380 }
1381 
getVertexAttribOffset(GC3Duint index,GC3Denum pname)1382 GC3Dsizeiptr GraphicsContext3D::getVertexAttribOffset(GC3Duint index, GC3Denum pname)
1383 {
1384     makeContextCurrent();
1385 
1386     GLvoid* pointer = 0;
1387     ::glGetVertexAttribPointerv(index, pname, &pointer);
1388     return static_cast<GC3Dsizeiptr>(reinterpret_cast<intptr_t>(pointer));
1389 }
1390 
texImage2D(GC3Denum target,GC3Dint level,GC3Denum internalformat,GC3Dsizei width,GC3Dsizei height,GC3Dint border,GC3Denum format,GC3Denum type,const void * pixels)1391 bool GraphicsContext3D::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels)
1392 {
1393     if (width && height && !pixels) {
1394         synthesizeGLError(INVALID_VALUE);
1395         return false;
1396     }
1397     makeContextCurrent();
1398     GC3Denum openGLInternalFormat = internalformat;
1399     if (type == GL_FLOAT) {
1400         if (format == GL_RGBA)
1401             openGLInternalFormat = GL_RGBA32F_ARB;
1402         else if (format == GL_RGB)
1403             openGLInternalFormat = GL_RGB32F_ARB;
1404     }
1405 
1406     ::glTexImage2D(target, level, openGLInternalFormat, width, height, border, format, type, pixels);
1407     return true;
1408 }
1409 
texSubImage2D(GC3Denum target,GC3Dint level,GC3Dint xoff,GC3Dint yoff,GC3Dsizei width,GC3Dsizei height,GC3Denum format,GC3Denum type,const void * pixels)1410 void GraphicsContext3D::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoff, GC3Dint yoff, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, const void* pixels)
1411 {
1412     makeContextCurrent();
1413 
1414     // FIXME: we will need to deal with PixelStore params when dealing with image buffers that differ from the subimage size
1415     ::glTexSubImage2D(target, level, xoff, yoff, width, height, format, type, pixels);
1416 }
1417 
createBuffer()1418 Platform3DObject GraphicsContext3D::createBuffer()
1419 {
1420     makeContextCurrent();
1421     GLuint o = 0;
1422     glGenBuffers(1, &o);
1423     return o;
1424 }
1425 
createFramebuffer()1426 Platform3DObject GraphicsContext3D::createFramebuffer()
1427 {
1428     makeContextCurrent();
1429     GLuint o = 0;
1430     glGenFramebuffersEXT(1, &o);
1431     return o;
1432 }
1433 
createProgram()1434 Platform3DObject GraphicsContext3D::createProgram()
1435 {
1436     makeContextCurrent();
1437     return glCreateProgram();
1438 }
1439 
createRenderbuffer()1440 Platform3DObject GraphicsContext3D::createRenderbuffer()
1441 {
1442     makeContextCurrent();
1443     GLuint o = 0;
1444     glGenRenderbuffersEXT(1, &o);
1445     return o;
1446 }
1447 
createShader(GC3Denum type)1448 Platform3DObject GraphicsContext3D::createShader(GC3Denum type)
1449 {
1450     makeContextCurrent();
1451     return glCreateShader((type == FRAGMENT_SHADER) ? GL_FRAGMENT_SHADER : GL_VERTEX_SHADER);
1452 }
1453 
createTexture()1454 Platform3DObject GraphicsContext3D::createTexture()
1455 {
1456     makeContextCurrent();
1457     GLuint o = 0;
1458     glGenTextures(1, &o);
1459     return o;
1460 }
1461 
deleteBuffer(Platform3DObject buffer)1462 void GraphicsContext3D::deleteBuffer(Platform3DObject buffer)
1463 {
1464     makeContextCurrent();
1465     glDeleteBuffers(1, &buffer);
1466 }
1467 
deleteFramebuffer(Platform3DObject framebuffer)1468 void GraphicsContext3D::deleteFramebuffer(Platform3DObject framebuffer)
1469 {
1470     makeContextCurrent();
1471     glDeleteFramebuffersEXT(1, &framebuffer);
1472 }
1473 
deleteProgram(Platform3DObject program)1474 void GraphicsContext3D::deleteProgram(Platform3DObject program)
1475 {
1476     makeContextCurrent();
1477     glDeleteProgram(program);
1478 }
1479 
deleteRenderbuffer(Platform3DObject renderbuffer)1480 void GraphicsContext3D::deleteRenderbuffer(Platform3DObject renderbuffer)
1481 {
1482     makeContextCurrent();
1483     glDeleteRenderbuffersEXT(1, &renderbuffer);
1484 }
1485 
deleteShader(Platform3DObject shader)1486 void GraphicsContext3D::deleteShader(Platform3DObject shader)
1487 {
1488     makeContextCurrent();
1489     glDeleteShader(shader);
1490 }
1491 
deleteTexture(Platform3DObject texture)1492 void GraphicsContext3D::deleteTexture(Platform3DObject texture)
1493 {
1494     makeContextCurrent();
1495     glDeleteTextures(1, &texture);
1496 }
1497 
synthesizeGLError(GC3Denum error)1498 void GraphicsContext3D::synthesizeGLError(GC3Denum error)
1499 {
1500     m_syntheticErrors.add(error);
1501 }
1502 
markContextChanged()1503 void GraphicsContext3D::markContextChanged()
1504 {
1505     m_layerComposited = false;
1506 }
1507 
markLayerComposited()1508 void GraphicsContext3D::markLayerComposited()
1509 {
1510     m_layerComposited = true;
1511 }
1512 
layerComposited() const1513 bool GraphicsContext3D::layerComposited() const
1514 {
1515     return m_layerComposited;
1516 }
1517 
getExtensions()1518 Extensions3D* GraphicsContext3D::getExtensions()
1519 {
1520     if (!m_extensions)
1521         m_extensions = adoptPtr(new Extensions3DOpenGL(this));
1522     return m_extensions.get();
1523 }
1524 
1525 }
1526 
1527 #endif // ENABLE(WEBGL)
1528