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