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