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 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 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 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 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 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 320 IntSize GraphicsContext3D::getInternalFramebufferSize() 321 { 322 return IntSize(m_currentWidth, m_currentHeight); 323 } 324 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 346 void GraphicsContext3D::activeTexture(GC3Denum texture) 347 { 348 makeContextCurrent(); 349 m_activeTexture = texture; 350 ::glActiveTexture(texture); 351 } 352 353 void GraphicsContext3D::attachShader(Platform3DObject program, Platform3DObject shader) 354 { 355 ASSERT(program); 356 ASSERT(shader); 357 makeContextCurrent(); 358 ::glAttachShader(program, shader); 359 } 360 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 368 void GraphicsContext3D::bindBuffer(GC3Denum target, Platform3DObject buffer) 369 { 370 makeContextCurrent(); 371 ::glBindBuffer(target, buffer); 372 } 373 374 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 389 void GraphicsContext3D::bindRenderbuffer(GC3Denum target, Platform3DObject renderbuffer) 390 { 391 makeContextCurrent(); 392 ::glBindRenderbufferEXT(target, renderbuffer); 393 } 394 395 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 404 void GraphicsContext3D::blendColor(GC3Dclampf red, GC3Dclampf green, GC3Dclampf blue, GC3Dclampf alpha) 405 { 406 makeContextCurrent(); 407 ::glBlendColor(red, green, blue, alpha); 408 } 409 410 void GraphicsContext3D::blendEquation(GC3Denum mode) 411 { 412 makeContextCurrent(); 413 ::glBlendEquation(mode); 414 } 415 416 void GraphicsContext3D::blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha) 417 { 418 makeContextCurrent(); 419 ::glBlendEquationSeparate(modeRGB, modeAlpha); 420 } 421 422 423 void GraphicsContext3D::blendFunc(GC3Denum sfactor, GC3Denum dfactor) 424 { 425 makeContextCurrent(); 426 ::glBlendFunc(sfactor, dfactor); 427 } 428 429 void GraphicsContext3D::blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha) 430 { 431 makeContextCurrent(); 432 ::glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); 433 } 434 435 void GraphicsContext3D::bufferData(GC3Denum target, GC3Dsizeiptr size, GC3Denum usage) 436 { 437 makeContextCurrent(); 438 ::glBufferData(target, size, 0, usage); 439 } 440 441 void GraphicsContext3D::bufferData(GC3Denum target, GC3Dsizeiptr size, const void* data, GC3Denum usage) 442 { 443 makeContextCurrent(); 444 ::glBufferData(target, size, data, usage); 445 } 446 447 void GraphicsContext3D::bufferSubData(GC3Denum target, GC3Dintptr offset, GC3Dsizeiptr size, const void* data) 448 { 449 makeContextCurrent(); 450 ::glBufferSubData(target, offset, size, data); 451 } 452 453 GC3Denum GraphicsContext3D::checkFramebufferStatus(GC3Denum target) 454 { 455 makeContextCurrent(); 456 return ::glCheckFramebufferStatusEXT(target); 457 } 458 459 void GraphicsContext3D::clearColor(GC3Dclampf r, GC3Dclampf g, GC3Dclampf b, GC3Dclampf a) 460 { 461 makeContextCurrent(); 462 ::glClearColor(r, g, b, a); 463 } 464 465 void GraphicsContext3D::clear(GC3Dbitfield mask) 466 { 467 makeContextCurrent(); 468 ::glClear(mask); 469 } 470 471 void GraphicsContext3D::clearDepth(GC3Dclampf depth) 472 { 473 makeContextCurrent(); 474 ::glClearDepth(depth); 475 } 476 477 void GraphicsContext3D::clearStencil(GC3Dint s) 478 { 479 makeContextCurrent(); 480 ::glClearStencil(s); 481 } 482 483 void GraphicsContext3D::colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha) 484 { 485 makeContextCurrent(); 486 ::glColorMask(red, green, blue, alpha); 487 } 488 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 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 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 569 void GraphicsContext3D::cullFace(GC3Denum mode) 570 { 571 makeContextCurrent(); 572 ::glCullFace(mode); 573 } 574 575 void GraphicsContext3D::depthFunc(GC3Denum func) 576 { 577 makeContextCurrent(); 578 ::glDepthFunc(func); 579 } 580 581 void GraphicsContext3D::depthMask(GC3Dboolean flag) 582 { 583 makeContextCurrent(); 584 ::glDepthMask(flag); 585 } 586 587 void GraphicsContext3D::depthRange(GC3Dclampf zNear, GC3Dclampf zFar) 588 { 589 makeContextCurrent(); 590 ::glDepthRange(zNear, zFar); 591 } 592 593 void GraphicsContext3D::detachShader(Platform3DObject program, Platform3DObject shader) 594 { 595 ASSERT(program); 596 ASSERT(shader); 597 makeContextCurrent(); 598 ::glDetachShader(program, shader); 599 } 600 601 void GraphicsContext3D::disable(GC3Denum cap) 602 { 603 makeContextCurrent(); 604 ::glDisable(cap); 605 } 606 607 void GraphicsContext3D::disableVertexAttribArray(GC3Duint index) 608 { 609 makeContextCurrent(); 610 ::glDisableVertexAttribArray(index); 611 } 612 613 void GraphicsContext3D::drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count) 614 { 615 makeContextCurrent(); 616 ::glDrawArrays(mode, first, count); 617 } 618 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 625 void GraphicsContext3D::enable(GC3Denum cap) 626 { 627 makeContextCurrent(); 628 ::glEnable(cap); 629 } 630 631 void GraphicsContext3D::enableVertexAttribArray(GC3Duint index) 632 { 633 makeContextCurrent(); 634 ::glEnableVertexAttribArray(index); 635 } 636 637 void GraphicsContext3D::finish() 638 { 639 makeContextCurrent(); 640 ::glFinish(); 641 } 642 643 void GraphicsContext3D::flush() 644 { 645 makeContextCurrent(); 646 ::glFlush(); 647 } 648 649 void GraphicsContext3D::framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbuffertarget, Platform3DObject buffer) 650 { 651 makeContextCurrent(); 652 ::glFramebufferRenderbufferEXT(target, attachment, renderbuffertarget, buffer); 653 } 654 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 661 void GraphicsContext3D::frontFace(GC3Denum mode) 662 { 663 makeContextCurrent(); 664 ::glFrontFace(mode); 665 } 666 667 void GraphicsContext3D::generateMipmap(GC3Denum target) 668 { 669 makeContextCurrent(); 670 ::glGenerateMipmapEXT(target); 671 } 672 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 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 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 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 736 GraphicsContext3D::Attributes GraphicsContext3D::getContextAttributes() 737 { 738 return m_attrs; 739 } 740 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 754 String GraphicsContext3D::getString(GC3Denum name) 755 { 756 makeContextCurrent(); 757 return String((const char*) ::glGetString(name)); 758 } 759 760 void GraphicsContext3D::hint(GC3Denum target, GC3Denum mode) 761 { 762 makeContextCurrent(); 763 ::glHint(target, mode); 764 } 765 766 GC3Dboolean GraphicsContext3D::isBuffer(Platform3DObject buffer) 767 { 768 if (!buffer) 769 return GL_FALSE; 770 771 makeContextCurrent(); 772 return ::glIsBuffer(buffer); 773 } 774 775 GC3Dboolean GraphicsContext3D::isEnabled(GC3Denum cap) 776 { 777 makeContextCurrent(); 778 return ::glIsEnabled(cap); 779 } 780 781 GC3Dboolean GraphicsContext3D::isFramebuffer(Platform3DObject framebuffer) 782 { 783 if (!framebuffer) 784 return GL_FALSE; 785 786 makeContextCurrent(); 787 return ::glIsFramebufferEXT(framebuffer); 788 } 789 790 GC3Dboolean GraphicsContext3D::isProgram(Platform3DObject program) 791 { 792 if (!program) 793 return GL_FALSE; 794 795 makeContextCurrent(); 796 return ::glIsProgram(program); 797 } 798 799 GC3Dboolean GraphicsContext3D::isRenderbuffer(Platform3DObject renderbuffer) 800 { 801 if (!renderbuffer) 802 return GL_FALSE; 803 804 makeContextCurrent(); 805 return ::glIsRenderbufferEXT(renderbuffer); 806 } 807 808 GC3Dboolean GraphicsContext3D::isShader(Platform3DObject shader) 809 { 810 if (!shader) 811 return GL_FALSE; 812 813 makeContextCurrent(); 814 return ::glIsShader(shader); 815 } 816 817 GC3Dboolean GraphicsContext3D::isTexture(Platform3DObject texture) 818 { 819 if (!texture) 820 return GL_FALSE; 821 822 makeContextCurrent(); 823 return ::glIsTexture(texture); 824 } 825 826 void GraphicsContext3D::lineWidth(GC3Dfloat width) 827 { 828 makeContextCurrent(); 829 ::glLineWidth(width); 830 } 831 832 void GraphicsContext3D::linkProgram(Platform3DObject program) 833 { 834 ASSERT(program); 835 makeContextCurrent(); 836 ::glLinkProgram(program); 837 } 838 839 void GraphicsContext3D::pixelStorei(GC3Denum pname, GC3Dint param) 840 { 841 makeContextCurrent(); 842 ::glPixelStorei(pname, param); 843 } 844 845 void GraphicsContext3D::polygonOffset(GC3Dfloat factor, GC3Dfloat units) 846 { 847 makeContextCurrent(); 848 ::glPolygonOffset(factor, units); 849 } 850 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 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 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 897 void GraphicsContext3D::sampleCoverage(GC3Dclampf value, GC3Dboolean invert) 898 { 899 makeContextCurrent(); 900 ::glSampleCoverage(value, invert); 901 } 902 903 void GraphicsContext3D::scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height) 904 { 905 makeContextCurrent(); 906 ::glScissor(x, y, width, height); 907 } 908 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 922 void GraphicsContext3D::stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask) 923 { 924 makeContextCurrent(); 925 ::glStencilFunc(func, ref, mask); 926 } 927 928 void GraphicsContext3D::stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask) 929 { 930 makeContextCurrent(); 931 ::glStencilFuncSeparate(face, func, ref, mask); 932 } 933 934 void GraphicsContext3D::stencilMask(GC3Duint mask) 935 { 936 makeContextCurrent(); 937 ::glStencilMask(mask); 938 } 939 940 void GraphicsContext3D::stencilMaskSeparate(GC3Denum face, GC3Duint mask) 941 { 942 makeContextCurrent(); 943 ::glStencilMaskSeparate(face, mask); 944 } 945 946 void GraphicsContext3D::stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zpass) 947 { 948 makeContextCurrent(); 949 ::glStencilOp(fail, zfail, zpass); 950 } 951 952 void GraphicsContext3D::stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zfail, GC3Denum zpass) 953 { 954 makeContextCurrent(); 955 ::glStencilOpSeparate(face, fail, zfail, zpass); 956 } 957 958 void GraphicsContext3D::texParameterf(GC3Denum target, GC3Denum pname, GC3Dfloat value) 959 { 960 makeContextCurrent(); 961 ::glTexParameterf(target, pname, value); 962 } 963 964 void GraphicsContext3D::texParameteri(GC3Denum target, GC3Denum pname, GC3Dint value) 965 { 966 makeContextCurrent(); 967 ::glTexParameteri(target, pname, value); 968 } 969 970 void GraphicsContext3D::uniform1f(GC3Dint location, GC3Dfloat v0) 971 { 972 makeContextCurrent(); 973 ::glUniform1f(location, v0); 974 } 975 976 void GraphicsContext3D::uniform1fv(GC3Dint location, GC3Dfloat* array, GC3Dsizei size) 977 { 978 makeContextCurrent(); 979 ::glUniform1fv(location, size, array); 980 } 981 982 void GraphicsContext3D::uniform2f(GC3Dint location, GC3Dfloat v0, GC3Dfloat v1) 983 { 984 makeContextCurrent(); 985 ::glUniform2f(location, v0, v1); 986 } 987 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 995 void GraphicsContext3D::uniform3f(GC3Dint location, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2) 996 { 997 makeContextCurrent(); 998 ::glUniform3f(location, v0, v1, v2); 999 } 1000 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 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 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 1021 void GraphicsContext3D::uniform1i(GC3Dint location, GC3Dint v0) 1022 { 1023 makeContextCurrent(); 1024 ::glUniform1i(location, v0); 1025 } 1026 1027 void GraphicsContext3D::uniform1iv(GC3Dint location, GC3Dint* array, GC3Dsizei size) 1028 { 1029 makeContextCurrent(); 1030 ::glUniform1iv(location, size, array); 1031 } 1032 1033 void GraphicsContext3D::uniform2i(GC3Dint location, GC3Dint v0, GC3Dint v1) 1034 { 1035 makeContextCurrent(); 1036 ::glUniform2i(location, v0, v1); 1037 } 1038 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 1046 void GraphicsContext3D::uniform3i(GC3Dint location, GC3Dint v0, GC3Dint v1, GC3Dint v2) 1047 { 1048 makeContextCurrent(); 1049 ::glUniform3i(location, v0, v1, v2); 1050 } 1051 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 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 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 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 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 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 1093 void GraphicsContext3D::useProgram(Platform3DObject program) 1094 { 1095 makeContextCurrent(); 1096 ::glUseProgram(program); 1097 } 1098 1099 void GraphicsContext3D::validateProgram(Platform3DObject program) 1100 { 1101 ASSERT(program); 1102 1103 makeContextCurrent(); 1104 ::glValidateProgram(program); 1105 } 1106 1107 void GraphicsContext3D::vertexAttrib1f(GC3Duint index, GC3Dfloat v0) 1108 { 1109 makeContextCurrent(); 1110 ::glVertexAttrib1f(index, v0); 1111 } 1112 1113 void GraphicsContext3D::vertexAttrib1fv(GC3Duint index, GC3Dfloat* array) 1114 { 1115 makeContextCurrent(); 1116 ::glVertexAttrib1fv(index, array); 1117 } 1118 1119 void GraphicsContext3D::vertexAttrib2f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1) 1120 { 1121 makeContextCurrent(); 1122 ::glVertexAttrib2f(index, v0, v1); 1123 } 1124 1125 void GraphicsContext3D::vertexAttrib2fv(GC3Duint index, GC3Dfloat* array) 1126 { 1127 makeContextCurrent(); 1128 ::glVertexAttrib2fv(index, array); 1129 } 1130 1131 void GraphicsContext3D::vertexAttrib3f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2) 1132 { 1133 makeContextCurrent(); 1134 ::glVertexAttrib3f(index, v0, v1, v2); 1135 } 1136 1137 void GraphicsContext3D::vertexAttrib3fv(GC3Duint index, GC3Dfloat* array) 1138 { 1139 makeContextCurrent(); 1140 ::glVertexAttrib3fv(index, array); 1141 } 1142 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 1149 void GraphicsContext3D::vertexAttrib4fv(GC3Duint index, GC3Dfloat* array) 1150 { 1151 makeContextCurrent(); 1152 ::glVertexAttrib4fv(index, array); 1153 } 1154 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 1161 void GraphicsContext3D::viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height) 1162 { 1163 makeContextCurrent(); 1164 ::glViewport(x, y, width, height); 1165 } 1166 1167 void GraphicsContext3D::getBooleanv(GC3Denum pname, GC3Dboolean* value) 1168 { 1169 makeContextCurrent(); 1170 ::glGetBooleanv(pname, value); 1171 } 1172 1173 void GraphicsContext3D::getBufferParameteriv(GC3Denum target, GC3Denum pname, GC3Dint* value) 1174 { 1175 makeContextCurrent(); 1176 ::glGetBufferParameteriv(target, pname, value); 1177 } 1178 1179 void GraphicsContext3D::getFloatv(GC3Denum pname, GC3Dfloat* value) 1180 { 1181 makeContextCurrent(); 1182 ::glGetFloatv(pname, value); 1183 } 1184 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 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 1218 void GraphicsContext3D::getProgramiv(Platform3DObject program, GC3Denum pname, GC3Dint* value) 1219 { 1220 makeContextCurrent(); 1221 ::glGetProgramiv(program, pname, value); 1222 } 1223 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 1243 void GraphicsContext3D::getRenderbufferParameteriv(GC3Denum target, GC3Denum pname, GC3Dint* value) 1244 { 1245 makeContextCurrent(); 1246 ::glGetRenderbufferParameterivEXT(target, pname, value); 1247 } 1248 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 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 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 1338 void GraphicsContext3D::getTexParameterfv(GC3Denum target, GC3Denum pname, GC3Dfloat* value) 1339 { 1340 makeContextCurrent(); 1341 ::glGetTexParameterfv(target, pname, value); 1342 } 1343 1344 void GraphicsContext3D::getTexParameteriv(GC3Denum target, GC3Denum pname, GC3Dint* value) 1345 { 1346 makeContextCurrent(); 1347 ::glGetTexParameteriv(target, pname, value); 1348 } 1349 1350 void GraphicsContext3D::getUniformfv(Platform3DObject program, GC3Dint location, GC3Dfloat* value) 1351 { 1352 makeContextCurrent(); 1353 ::glGetUniformfv(program, location, value); 1354 } 1355 1356 void GraphicsContext3D::getUniformiv(Platform3DObject program, GC3Dint location, GC3Dint* value) 1357 { 1358 makeContextCurrent(); 1359 ::glGetUniformiv(program, location, value); 1360 } 1361 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 1370 void GraphicsContext3D::getVertexAttribfv(GC3Duint index, GC3Denum pname, GC3Dfloat* value) 1371 { 1372 makeContextCurrent(); 1373 ::glGetVertexAttribfv(index, pname, value); 1374 } 1375 1376 void GraphicsContext3D::getVertexAttribiv(GC3Duint index, GC3Denum pname, GC3Dint* value) 1377 { 1378 makeContextCurrent(); 1379 ::glGetVertexAttribiv(index, pname, value); 1380 } 1381 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 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 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 1418 Platform3DObject GraphicsContext3D::createBuffer() 1419 { 1420 makeContextCurrent(); 1421 GLuint o = 0; 1422 glGenBuffers(1, &o); 1423 return o; 1424 } 1425 1426 Platform3DObject GraphicsContext3D::createFramebuffer() 1427 { 1428 makeContextCurrent(); 1429 GLuint o = 0; 1430 glGenFramebuffersEXT(1, &o); 1431 return o; 1432 } 1433 1434 Platform3DObject GraphicsContext3D::createProgram() 1435 { 1436 makeContextCurrent(); 1437 return glCreateProgram(); 1438 } 1439 1440 Platform3DObject GraphicsContext3D::createRenderbuffer() 1441 { 1442 makeContextCurrent(); 1443 GLuint o = 0; 1444 glGenRenderbuffersEXT(1, &o); 1445 return o; 1446 } 1447 1448 Platform3DObject GraphicsContext3D::createShader(GC3Denum type) 1449 { 1450 makeContextCurrent(); 1451 return glCreateShader((type == FRAGMENT_SHADER) ? GL_FRAGMENT_SHADER : GL_VERTEX_SHADER); 1452 } 1453 1454 Platform3DObject GraphicsContext3D::createTexture() 1455 { 1456 makeContextCurrent(); 1457 GLuint o = 0; 1458 glGenTextures(1, &o); 1459 return o; 1460 } 1461 1462 void GraphicsContext3D::deleteBuffer(Platform3DObject buffer) 1463 { 1464 makeContextCurrent(); 1465 glDeleteBuffers(1, &buffer); 1466 } 1467 1468 void GraphicsContext3D::deleteFramebuffer(Platform3DObject framebuffer) 1469 { 1470 makeContextCurrent(); 1471 glDeleteFramebuffersEXT(1, &framebuffer); 1472 } 1473 1474 void GraphicsContext3D::deleteProgram(Platform3DObject program) 1475 { 1476 makeContextCurrent(); 1477 glDeleteProgram(program); 1478 } 1479 1480 void GraphicsContext3D::deleteRenderbuffer(Platform3DObject renderbuffer) 1481 { 1482 makeContextCurrent(); 1483 glDeleteRenderbuffersEXT(1, &renderbuffer); 1484 } 1485 1486 void GraphicsContext3D::deleteShader(Platform3DObject shader) 1487 { 1488 makeContextCurrent(); 1489 glDeleteShader(shader); 1490 } 1491 1492 void GraphicsContext3D::deleteTexture(Platform3DObject texture) 1493 { 1494 makeContextCurrent(); 1495 glDeleteTextures(1, &texture); 1496 } 1497 1498 void GraphicsContext3D::synthesizeGLError(GC3Denum error) 1499 { 1500 m_syntheticErrors.add(error); 1501 } 1502 1503 void GraphicsContext3D::markContextChanged() 1504 { 1505 m_layerComposited = false; 1506 } 1507 1508 void GraphicsContext3D::markLayerComposited() 1509 { 1510 m_layerComposited = true; 1511 } 1512 1513 bool GraphicsContext3D::layerComposited() const 1514 { 1515 return m_layerComposited; 1516 } 1517 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