Home | History | Annotate | Download | only in opengl
      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 
     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 
     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 
    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 
    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 
    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 
    320 IntSize GraphicsContext3D::getInternalFramebufferSize()
    321 {
    322     return IntSize(m_currentWidth, m_currentHeight);
    323 }
    324 
    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 
    346 void GraphicsContext3D::activeTexture(GC3Denum texture)
    347 {
    348     makeContextCurrent();
    349     m_activeTexture = texture;
    350     ::glActiveTexture(texture);
    351 }
    352 
    353 void GraphicsContext3D::attachShader(Platform3DObject program, Platform3DObject shader)
    354 {
    355     ASSERT(program);
    356     ASSERT(shader);
    357     makeContextCurrent();
    358     ::glAttachShader(program, shader);
    359 }
    360 
    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 
    368 void GraphicsContext3D::bindBuffer(GC3Denum target, Platform3DObject buffer)
    369 {
    370     makeContextCurrent();
    371     ::glBindBuffer(target, buffer);
    372 }
    373 
    374 
    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 
    389 void GraphicsContext3D::bindRenderbuffer(GC3Denum target, Platform3DObject renderbuffer)
    390 {
    391     makeContextCurrent();
    392     ::glBindRenderbufferEXT(target, renderbuffer);
    393 }
    394 
    395 
    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 
    404 void GraphicsContext3D::blendColor(GC3Dclampf red, GC3Dclampf green, GC3Dclampf blue, GC3Dclampf alpha)
    405 {
    406     makeContextCurrent();
    407     ::glBlendColor(red, green, blue, alpha);
    408 }
    409 
    410 void GraphicsContext3D::blendEquation(GC3Denum mode)
    411 {
    412     makeContextCurrent();
    413     ::glBlendEquation(mode);
    414 }
    415 
    416 void GraphicsContext3D::blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha)
    417 {
    418     makeContextCurrent();
    419     ::glBlendEquationSeparate(modeRGB, modeAlpha);
    420 }
    421 
    422 
    423 void GraphicsContext3D::blendFunc(GC3Denum sfactor, GC3Denum dfactor)
    424 {
    425     makeContextCurrent();
    426     ::glBlendFunc(sfactor, dfactor);
    427 }
    428 
    429 void GraphicsContext3D::blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha)
    430 {
    431     makeContextCurrent();
    432     ::glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
    433 }
    434 
    435 void GraphicsContext3D::bufferData(GC3Denum target, GC3Dsizeiptr size, GC3Denum usage)
    436 {
    437     makeContextCurrent();
    438     ::glBufferData(target, size, 0, usage);
    439 }
    440 
    441 void GraphicsContext3D::bufferData(GC3Denum target, GC3Dsizeiptr size, const void* data, GC3Denum usage)
    442 {
    443     makeContextCurrent();
    444     ::glBufferData(target, size, data, usage);
    445 }
    446 
    447 void GraphicsContext3D::bufferSubData(GC3Denum target, GC3Dintptr offset, GC3Dsizeiptr size, const void* data)
    448 {
    449     makeContextCurrent();
    450     ::glBufferSubData(target, offset, size, data);
    451 }
    452 
    453 GC3Denum GraphicsContext3D::checkFramebufferStatus(GC3Denum target)
    454 {
    455     makeContextCurrent();
    456     return ::glCheckFramebufferStatusEXT(target);
    457 }
    458 
    459 void GraphicsContext3D::clearColor(GC3Dclampf r, GC3Dclampf g, GC3Dclampf b, GC3Dclampf a)
    460 {
    461     makeContextCurrent();
    462     ::glClearColor(r, g, b, a);
    463 }
    464 
    465 void GraphicsContext3D::clear(GC3Dbitfield mask)
    466 {
    467     makeContextCurrent();
    468     ::glClear(mask);
    469 }
    470 
    471 void GraphicsContext3D::clearDepth(GC3Dclampf depth)
    472 {
    473     makeContextCurrent();
    474     ::glClearDepth(depth);
    475 }
    476 
    477 void GraphicsContext3D::clearStencil(GC3Dint s)
    478 {
    479     makeContextCurrent();
    480     ::glClearStencil(s);
    481 }
    482 
    483 void GraphicsContext3D::colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha)
    484 {
    485     makeContextCurrent();
    486     ::glColorMask(red, green, blue, alpha);
    487 }
    488 
    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 
    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 
    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 
    569 void GraphicsContext3D::cullFace(GC3Denum mode)
    570 {
    571     makeContextCurrent();
    572     ::glCullFace(mode);
    573 }
    574 
    575 void GraphicsContext3D::depthFunc(GC3Denum func)
    576 {
    577     makeContextCurrent();
    578     ::glDepthFunc(func);
    579 }
    580 
    581 void GraphicsContext3D::depthMask(GC3Dboolean flag)
    582 {
    583     makeContextCurrent();
    584     ::glDepthMask(flag);
    585 }
    586 
    587 void GraphicsContext3D::depthRange(GC3Dclampf zNear, GC3Dclampf zFar)
    588 {
    589     makeContextCurrent();
    590     ::glDepthRange(zNear, zFar);
    591 }
    592 
    593 void GraphicsContext3D::detachShader(Platform3DObject program, Platform3DObject shader)
    594 {
    595     ASSERT(program);
    596     ASSERT(shader);
    597     makeContextCurrent();
    598     ::glDetachShader(program, shader);
    599 }
    600 
    601 void GraphicsContext3D::disable(GC3Denum cap)
    602 {
    603     makeContextCurrent();
    604     ::glDisable(cap);
    605 }
    606 
    607 void GraphicsContext3D::disableVertexAttribArray(GC3Duint index)
    608 {
    609     makeContextCurrent();
    610     ::glDisableVertexAttribArray(index);
    611 }
    612 
    613 void GraphicsContext3D::drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count)
    614 {
    615     makeContextCurrent();
    616     ::glDrawArrays(mode, first, count);
    617 }
    618 
    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 
    625 void GraphicsContext3D::enable(GC3Denum cap)
    626 {
    627     makeContextCurrent();
    628     ::glEnable(cap);
    629 }
    630 
    631 void GraphicsContext3D::enableVertexAttribArray(GC3Duint index)
    632 {
    633     makeContextCurrent();
    634     ::glEnableVertexAttribArray(index);
    635 }
    636 
    637 void GraphicsContext3D::finish()
    638 {
    639     makeContextCurrent();
    640     ::glFinish();
    641 }
    642 
    643 void GraphicsContext3D::flush()
    644 {
    645     makeContextCurrent();
    646     ::glFlush();
    647 }
    648 
    649 void GraphicsContext3D::framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbuffertarget, Platform3DObject buffer)
    650 {
    651     makeContextCurrent();
    652     ::glFramebufferRenderbufferEXT(target, attachment, renderbuffertarget, buffer);
    653 }
    654 
    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 
    661 void GraphicsContext3D::frontFace(GC3Denum mode)
    662 {
    663     makeContextCurrent();
    664     ::glFrontFace(mode);
    665 }
    666 
    667 void GraphicsContext3D::generateMipmap(GC3Denum target)
    668 {
    669     makeContextCurrent();
    670     ::glGenerateMipmapEXT(target);
    671 }
    672 
    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 
    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 
    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 
    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 
    736 GraphicsContext3D::Attributes GraphicsContext3D::getContextAttributes()
    737 {
    738     return m_attrs;
    739 }
    740 
    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 
    754 String GraphicsContext3D::getString(GC3Denum name)
    755 {
    756     makeContextCurrent();
    757     return String((const char*) ::glGetString(name));
    758 }
    759 
    760 void GraphicsContext3D::hint(GC3Denum target, GC3Denum mode)
    761 {
    762     makeContextCurrent();
    763     ::glHint(target, mode);
    764 }
    765 
    766 GC3Dboolean GraphicsContext3D::isBuffer(Platform3DObject buffer)
    767 {
    768     if (!buffer)
    769         return GL_FALSE;
    770 
    771     makeContextCurrent();
    772     return ::glIsBuffer(buffer);
    773 }
    774 
    775 GC3Dboolean GraphicsContext3D::isEnabled(GC3Denum cap)
    776 {
    777     makeContextCurrent();
    778     return ::glIsEnabled(cap);
    779 }
    780 
    781 GC3Dboolean GraphicsContext3D::isFramebuffer(Platform3DObject framebuffer)
    782 {
    783     if (!framebuffer)
    784         return GL_FALSE;
    785 
    786     makeContextCurrent();
    787     return ::glIsFramebufferEXT(framebuffer);
    788 }
    789 
    790 GC3Dboolean GraphicsContext3D::isProgram(Platform3DObject program)
    791 {
    792     if (!program)
    793         return GL_FALSE;
    794 
    795     makeContextCurrent();
    796     return ::glIsProgram(program);
    797 }
    798 
    799 GC3Dboolean GraphicsContext3D::isRenderbuffer(Platform3DObject renderbuffer)
    800 {
    801     if (!renderbuffer)
    802         return GL_FALSE;
    803 
    804     makeContextCurrent();
    805     return ::glIsRenderbufferEXT(renderbuffer);
    806 }
    807 
    808 GC3Dboolean GraphicsContext3D::isShader(Platform3DObject shader)
    809 {
    810     if (!shader)
    811         return GL_FALSE;
    812 
    813     makeContextCurrent();
    814     return ::glIsShader(shader);
    815 }
    816 
    817 GC3Dboolean GraphicsContext3D::isTexture(Platform3DObject texture)
    818 {
    819     if (!texture)
    820         return GL_FALSE;
    821 
    822     makeContextCurrent();
    823     return ::glIsTexture(texture);
    824 }
    825 
    826 void GraphicsContext3D::lineWidth(GC3Dfloat width)
    827 {
    828     makeContextCurrent();
    829     ::glLineWidth(width);
    830 }
    831 
    832 void GraphicsContext3D::linkProgram(Platform3DObject program)
    833 {
    834     ASSERT(program);
    835     makeContextCurrent();
    836     ::glLinkProgram(program);
    837 }
    838 
    839 void GraphicsContext3D::pixelStorei(GC3Denum pname, GC3Dint param)
    840 {
    841     makeContextCurrent();
    842     ::glPixelStorei(pname, param);
    843 }
    844 
    845 void GraphicsContext3D::polygonOffset(GC3Dfloat factor, GC3Dfloat units)
    846 {
    847     makeContextCurrent();
    848     ::glPolygonOffset(factor, units);
    849 }
    850 
    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 
    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 
    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 
    897 void GraphicsContext3D::sampleCoverage(GC3Dclampf value, GC3Dboolean invert)
    898 {
    899     makeContextCurrent();
    900     ::glSampleCoverage(value, invert);
    901 }
    902 
    903 void GraphicsContext3D::scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
    904 {
    905     makeContextCurrent();
    906     ::glScissor(x, y, width, height);
    907 }
    908 
    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 
    922 void GraphicsContext3D::stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask)
    923 {
    924     makeContextCurrent();
    925     ::glStencilFunc(func, ref, mask);
    926 }
    927 
    928 void GraphicsContext3D::stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask)
    929 {
    930     makeContextCurrent();
    931     ::glStencilFuncSeparate(face, func, ref, mask);
    932 }
    933 
    934 void GraphicsContext3D::stencilMask(GC3Duint mask)
    935 {
    936     makeContextCurrent();
    937     ::glStencilMask(mask);
    938 }
    939 
    940 void GraphicsContext3D::stencilMaskSeparate(GC3Denum face, GC3Duint mask)
    941 {
    942     makeContextCurrent();
    943     ::glStencilMaskSeparate(face, mask);
    944 }
    945 
    946 void GraphicsContext3D::stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zpass)
    947 {
    948     makeContextCurrent();
    949     ::glStencilOp(fail, zfail, zpass);
    950 }
    951 
    952 void GraphicsContext3D::stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zfail, GC3Denum zpass)
    953 {
    954     makeContextCurrent();
    955     ::glStencilOpSeparate(face, fail, zfail, zpass);
    956 }
    957 
    958 void GraphicsContext3D::texParameterf(GC3Denum target, GC3Denum pname, GC3Dfloat value)
    959 {
    960     makeContextCurrent();
    961     ::glTexParameterf(target, pname, value);
    962 }
    963 
    964 void GraphicsContext3D::texParameteri(GC3Denum target, GC3Denum pname, GC3Dint value)
    965 {
    966     makeContextCurrent();
    967     ::glTexParameteri(target, pname, value);
    968 }
    969 
    970 void GraphicsContext3D::uniform1f(GC3Dint location, GC3Dfloat v0)
    971 {
    972     makeContextCurrent();
    973     ::glUniform1f(location, v0);
    974 }
    975 
    976 void GraphicsContext3D::uniform1fv(GC3Dint location, GC3Dfloat* array, GC3Dsizei size)
    977 {
    978     makeContextCurrent();
    979     ::glUniform1fv(location, size, array);
    980 }
    981 
    982 void GraphicsContext3D::uniform2f(GC3Dint location, GC3Dfloat v0, GC3Dfloat v1)
    983 {
    984     makeContextCurrent();
    985     ::glUniform2f(location, v0, v1);
    986 }
    987 
    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 
    995 void GraphicsContext3D::uniform3f(GC3Dint location, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2)
    996 {
    997     makeContextCurrent();
    998     ::glUniform3f(location, v0, v1, v2);
    999 }
   1000 
   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 
   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 
   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 
   1021 void GraphicsContext3D::uniform1i(GC3Dint location, GC3Dint v0)
   1022 {
   1023     makeContextCurrent();
   1024     ::glUniform1i(location, v0);
   1025 }
   1026 
   1027 void GraphicsContext3D::uniform1iv(GC3Dint location, GC3Dint* array, GC3Dsizei size)
   1028 {
   1029     makeContextCurrent();
   1030     ::glUniform1iv(location, size, array);
   1031 }
   1032 
   1033 void GraphicsContext3D::uniform2i(GC3Dint location, GC3Dint v0, GC3Dint v1)
   1034 {
   1035     makeContextCurrent();
   1036     ::glUniform2i(location, v0, v1);
   1037 }
   1038 
   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 
   1046 void GraphicsContext3D::uniform3i(GC3Dint location, GC3Dint v0, GC3Dint v1, GC3Dint v2)
   1047 {
   1048     makeContextCurrent();
   1049     ::glUniform3i(location, v0, v1, v2);
   1050 }
   1051 
   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 
   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 
   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 
   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 
   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 
   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 
   1093 void GraphicsContext3D::useProgram(Platform3DObject program)
   1094 {
   1095     makeContextCurrent();
   1096     ::glUseProgram(program);
   1097 }
   1098 
   1099 void GraphicsContext3D::validateProgram(Platform3DObject program)
   1100 {
   1101     ASSERT(program);
   1102 
   1103     makeContextCurrent();
   1104     ::glValidateProgram(program);
   1105 }
   1106 
   1107 void GraphicsContext3D::vertexAttrib1f(GC3Duint index, GC3Dfloat v0)
   1108 {
   1109     makeContextCurrent();
   1110     ::glVertexAttrib1f(index, v0);
   1111 }
   1112 
   1113 void GraphicsContext3D::vertexAttrib1fv(GC3Duint index, GC3Dfloat* array)
   1114 {
   1115     makeContextCurrent();
   1116     ::glVertexAttrib1fv(index, array);
   1117 }
   1118 
   1119 void GraphicsContext3D::vertexAttrib2f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1)
   1120 {
   1121     makeContextCurrent();
   1122     ::glVertexAttrib2f(index, v0, v1);
   1123 }
   1124 
   1125 void GraphicsContext3D::vertexAttrib2fv(GC3Duint index, GC3Dfloat* array)
   1126 {
   1127     makeContextCurrent();
   1128     ::glVertexAttrib2fv(index, array);
   1129 }
   1130 
   1131 void GraphicsContext3D::vertexAttrib3f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2)
   1132 {
   1133     makeContextCurrent();
   1134     ::glVertexAttrib3f(index, v0, v1, v2);
   1135 }
   1136 
   1137 void GraphicsContext3D::vertexAttrib3fv(GC3Duint index, GC3Dfloat* array)
   1138 {
   1139     makeContextCurrent();
   1140     ::glVertexAttrib3fv(index, array);
   1141 }
   1142 
   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 
   1149 void GraphicsContext3D::vertexAttrib4fv(GC3Duint index, GC3Dfloat* array)
   1150 {
   1151     makeContextCurrent();
   1152     ::glVertexAttrib4fv(index, array);
   1153 }
   1154 
   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 
   1161 void GraphicsContext3D::viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
   1162 {
   1163     makeContextCurrent();
   1164     ::glViewport(x, y, width, height);
   1165 }
   1166 
   1167 void GraphicsContext3D::getBooleanv(GC3Denum pname, GC3Dboolean* value)
   1168 {
   1169     makeContextCurrent();
   1170     ::glGetBooleanv(pname, value);
   1171 }
   1172 
   1173 void GraphicsContext3D::getBufferParameteriv(GC3Denum target, GC3Denum pname, GC3Dint* value)
   1174 {
   1175     makeContextCurrent();
   1176     ::glGetBufferParameteriv(target, pname, value);
   1177 }
   1178 
   1179 void GraphicsContext3D::getFloatv(GC3Denum pname, GC3Dfloat* value)
   1180 {
   1181     makeContextCurrent();
   1182     ::glGetFloatv(pname, value);
   1183 }
   1184 
   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 
   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 
   1218 void GraphicsContext3D::getProgramiv(Platform3DObject program, GC3Denum pname, GC3Dint* value)
   1219 {
   1220     makeContextCurrent();
   1221     ::glGetProgramiv(program, pname, value);
   1222 }
   1223 
   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 
   1243 void GraphicsContext3D::getRenderbufferParameteriv(GC3Denum target, GC3Denum pname, GC3Dint* value)
   1244 {
   1245     makeContextCurrent();
   1246     ::glGetRenderbufferParameterivEXT(target, pname, value);
   1247 }
   1248 
   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 
   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 
   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 
   1338 void GraphicsContext3D::getTexParameterfv(GC3Denum target, GC3Denum pname, GC3Dfloat* value)
   1339 {
   1340     makeContextCurrent();
   1341     ::glGetTexParameterfv(target, pname, value);
   1342 }
   1343 
   1344 void GraphicsContext3D::getTexParameteriv(GC3Denum target, GC3Denum pname, GC3Dint* value)
   1345 {
   1346     makeContextCurrent();
   1347     ::glGetTexParameteriv(target, pname, value);
   1348 }
   1349 
   1350 void GraphicsContext3D::getUniformfv(Platform3DObject program, GC3Dint location, GC3Dfloat* value)
   1351 {
   1352     makeContextCurrent();
   1353     ::glGetUniformfv(program, location, value);
   1354 }
   1355 
   1356 void GraphicsContext3D::getUniformiv(Platform3DObject program, GC3Dint location, GC3Dint* value)
   1357 {
   1358     makeContextCurrent();
   1359     ::glGetUniformiv(program, location, value);
   1360 }
   1361 
   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 
   1370 void GraphicsContext3D::getVertexAttribfv(GC3Duint index, GC3Denum pname, GC3Dfloat* value)
   1371 {
   1372     makeContextCurrent();
   1373     ::glGetVertexAttribfv(index, pname, value);
   1374 }
   1375 
   1376 void GraphicsContext3D::getVertexAttribiv(GC3Duint index, GC3Denum pname, GC3Dint* value)
   1377 {
   1378     makeContextCurrent();
   1379     ::glGetVertexAttribiv(index, pname, value);
   1380 }
   1381 
   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 
   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 
   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 
   1418 Platform3DObject GraphicsContext3D::createBuffer()
   1419 {
   1420     makeContextCurrent();
   1421     GLuint o = 0;
   1422     glGenBuffers(1, &o);
   1423     return o;
   1424 }
   1425 
   1426 Platform3DObject GraphicsContext3D::createFramebuffer()
   1427 {
   1428     makeContextCurrent();
   1429     GLuint o = 0;
   1430     glGenFramebuffersEXT(1, &o);
   1431     return o;
   1432 }
   1433 
   1434 Platform3DObject GraphicsContext3D::createProgram()
   1435 {
   1436     makeContextCurrent();
   1437     return glCreateProgram();
   1438 }
   1439 
   1440 Platform3DObject GraphicsContext3D::createRenderbuffer()
   1441 {
   1442     makeContextCurrent();
   1443     GLuint o = 0;
   1444     glGenRenderbuffersEXT(1, &o);
   1445     return o;
   1446 }
   1447 
   1448 Platform3DObject GraphicsContext3D::createShader(GC3Denum type)
   1449 {
   1450     makeContextCurrent();
   1451     return glCreateShader((type == FRAGMENT_SHADER) ? GL_FRAGMENT_SHADER : GL_VERTEX_SHADER);
   1452 }
   1453 
   1454 Platform3DObject GraphicsContext3D::createTexture()
   1455 {
   1456     makeContextCurrent();
   1457     GLuint o = 0;
   1458     glGenTextures(1, &o);
   1459     return o;
   1460 }
   1461 
   1462 void GraphicsContext3D::deleteBuffer(Platform3DObject buffer)
   1463 {
   1464     makeContextCurrent();
   1465     glDeleteBuffers(1, &buffer);
   1466 }
   1467 
   1468 void GraphicsContext3D::deleteFramebuffer(Platform3DObject framebuffer)
   1469 {
   1470     makeContextCurrent();
   1471     glDeleteFramebuffersEXT(1, &framebuffer);
   1472 }
   1473 
   1474 void GraphicsContext3D::deleteProgram(Platform3DObject program)
   1475 {
   1476     makeContextCurrent();
   1477     glDeleteProgram(program);
   1478 }
   1479 
   1480 void GraphicsContext3D::deleteRenderbuffer(Platform3DObject renderbuffer)
   1481 {
   1482     makeContextCurrent();
   1483     glDeleteRenderbuffersEXT(1, &renderbuffer);
   1484 }
   1485 
   1486 void GraphicsContext3D::deleteShader(Platform3DObject shader)
   1487 {
   1488     makeContextCurrent();
   1489     glDeleteShader(shader);
   1490 }
   1491 
   1492 void GraphicsContext3D::deleteTexture(Platform3DObject texture)
   1493 {
   1494     makeContextCurrent();
   1495     glDeleteTextures(1, &texture);
   1496 }
   1497 
   1498 void GraphicsContext3D::synthesizeGLError(GC3Denum error)
   1499 {
   1500     m_syntheticErrors.add(error);
   1501 }
   1502 
   1503 void GraphicsContext3D::markContextChanged()
   1504 {
   1505     m_layerComposited = false;
   1506 }
   1507 
   1508 void GraphicsContext3D::markLayerComposited()
   1509 {
   1510     m_layerComposited = true;
   1511 }
   1512 
   1513 bool GraphicsContext3D::layerComposited() const
   1514 {
   1515     return m_layerComposited;
   1516 }
   1517 
   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