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