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