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