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