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