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