| /* |
| * Copyright (C) 2010 Apple Inc. All rights reserved. |
| * Copyright (C) 2012 ChangSeok Oh <shivamidow@gmail.com> |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
| * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "config.h" |
| |
| #if ENABLE(WEBGL) |
| |
| #include "GraphicsContext3D.h" |
| |
| #include "Extensions3DOpenGL.h" |
| #include "GraphicsContext.h" |
| #include "ImageBuffer.h" |
| #include "ImageData.h" |
| #include "IntRect.h" |
| #include "IntSize.h" |
| #include "NotImplemented.h" |
| #include "WebGLObject.h" |
| #include <cstring> |
| #include <wtf/ArrayBuffer.h> |
| #include <wtf/ArrayBufferView.h> |
| #include <wtf/Float32Array.h> |
| #include <wtf/Int32Array.h> |
| #include <wtf/MainThread.h> |
| #include <wtf/OwnArrayPtr.h> |
| #include <wtf/Uint8Array.h> |
| #include <wtf/UnusedParam.h> |
| #include <wtf/text/CString.h> |
| |
| #if PLATFORM(MAC) |
| #include <OpenGL/gl.h> |
| #elif PLATFORM(GTK) || PLATFORM(EFL) || PLATFORM(QT) |
| #include "OpenGLShims.h" |
| #endif |
| |
| namespace WebCore { |
| |
| static bool systemAllowsMultisamplingOnATICards() |
| { |
| #if PLATFORM(MAC) |
| #if !defined(BUILDING_ON_SNOW_LEOPARD) && !defined(BUILDING_ON_LION) |
| return true; |
| #else |
| ASSERT(isMainThread()); |
| static SInt32 version; |
| if (!version) { |
| if (Gestalt(gestaltSystemVersion, &version) != noErr) |
| return false; |
| } |
| // See https://bugs.webkit.org/show_bug.cgi?id=77922 for more details |
| return version >= 0x1072; |
| #endif // SNOW_LEOPARD and LION |
| #else |
| return false; |
| #endif // PLATFORM(MAC) |
| } |
| |
| void GraphicsContext3D::validateAttributes() |
| { |
| Extensions3D* extensions = getExtensions(); |
| if (m_attrs.stencil) { |
| const char* packedDepthStencilExtension = isGLES2Compliant() ? "GL_OES_packed_depth_stencil" : "GL_EXT_packed_depth_stencil"; |
| if (extensions->supports(packedDepthStencilExtension)) { |
| extensions->ensureEnabled(packedDepthStencilExtension); |
| // Force depth if stencil is true. |
| m_attrs.depth = true; |
| } else |
| m_attrs.stencil = false; |
| } |
| if (m_attrs.antialias) { |
| bool isValidVendor = true; |
| // Currently in Mac we only turn on antialias if vendor is NVIDIA, |
| // or if ATI and on 10.7.2 and above. |
| const char* vendor = reinterpret_cast<const char*>(::glGetString(GL_VENDOR)); |
| if (!vendor || (!std::strstr(vendor, "NVIDIA") && !(std::strstr(vendor, "ATI") && systemAllowsMultisamplingOnATICards()))) |
| isValidVendor = false; |
| if (!isValidVendor || !extensions->supports("GL_ANGLE_framebuffer_multisample") || isGLES2Compliant()) |
| m_attrs.antialias = false; |
| else |
| extensions->ensureEnabled("GL_ANGLE_framebuffer_multisample"); |
| } |
| } |
| |
| bool GraphicsContext3D::isResourceSafe() |
| { |
| return false; |
| } |
| |
| void GraphicsContext3D::paintRenderingResultsToCanvas(ImageBuffer* imageBuffer, DrawingBuffer*) |
| { |
| int rowBytes = m_currentWidth * 4; |
| int totalBytes = rowBytes * m_currentHeight; |
| |
| OwnArrayPtr<unsigned char> pixels = adoptArrayPtr(new unsigned char[totalBytes]); |
| if (!pixels) |
| return; |
| |
| readRenderingResults(pixels.get(), totalBytes); |
| |
| if (!m_attrs.premultipliedAlpha) { |
| for (int i = 0; i < totalBytes; i += 4) { |
| // Premultiply alpha. |
| pixels[i + 0] = std::min(255, pixels[i + 0] * pixels[i + 3] / 255); |
| pixels[i + 1] = std::min(255, pixels[i + 1] * pixels[i + 3] / 255); |
| pixels[i + 2] = std::min(255, pixels[i + 2] * pixels[i + 3] / 255); |
| } |
| } |
| |
| paintToCanvas(pixels.get(), m_currentWidth, m_currentHeight, |
| imageBuffer->internalSize().width(), imageBuffer->internalSize().height(), imageBuffer->context()->platformContext()); |
| } |
| |
| bool GraphicsContext3D::paintCompositedResultsToCanvas(ImageBuffer*) |
| { |
| // Not needed at the moment, so return that nothing was done. |
| return false; |
| } |
| |
| PassRefPtr<ImageData> GraphicsContext3D::paintRenderingResultsToImageData(DrawingBuffer*) |
| { |
| // Reading premultiplied alpha would involve unpremultiplying, which is |
| // lossy. |
| if (m_attrs.premultipliedAlpha) |
| return 0; |
| |
| RefPtr<ImageData> imageData = ImageData::create(IntSize(m_currentWidth, m_currentHeight)); |
| unsigned char* pixels = imageData->data()->data(); |
| int totalBytes = 4 * m_currentWidth * m_currentHeight; |
| |
| readRenderingResults(pixels, totalBytes); |
| |
| // Convert to RGBA. |
| for (int i = 0; i < totalBytes; i += 4) |
| std::swap(pixels[i], pixels[i + 2]); |
| |
| return imageData.release(); |
| } |
| |
| void GraphicsContext3D::prepareTexture() |
| { |
| if (m_layerComposited) |
| return; |
| |
| makeContextCurrent(); |
| if (m_attrs.antialias) |
| resolveMultisamplingIfNecessary(); |
| |
| ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_fbo); |
| ::glActiveTexture(GL_TEXTURE0); |
| ::glBindTexture(GL_TEXTURE_2D, m_compositorTexture); |
| ::glCopyTexImage2D(GL_TEXTURE_2D, 0, m_internalColorFormat, 0, 0, m_currentWidth, m_currentHeight, 0); |
| ::glBindTexture(GL_TEXTURE_2D, m_boundTexture0); |
| ::glActiveTexture(m_activeTexture); |
| ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_boundFBO); |
| ::glFinish(); |
| m_layerComposited = true; |
| } |
| |
| void GraphicsContext3D::readRenderingResults(unsigned char *pixels, int pixelsSize) |
| { |
| if (pixelsSize < m_currentWidth * m_currentHeight * 4) |
| return; |
| |
| makeContextCurrent(); |
| |
| bool mustRestoreFBO = false; |
| if (m_attrs.antialias) { |
| resolveMultisamplingIfNecessary(); |
| ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_fbo); |
| mustRestoreFBO = true; |
| } else { |
| if (m_boundFBO != m_fbo) { |
| mustRestoreFBO = true; |
| ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_fbo); |
| } |
| } |
| |
| GLint packAlignment = 4; |
| bool mustRestorePackAlignment = false; |
| ::glGetIntegerv(GL_PACK_ALIGNMENT, &packAlignment); |
| if (packAlignment > 4) { |
| ::glPixelStorei(GL_PACK_ALIGNMENT, 4); |
| mustRestorePackAlignment = true; |
| } |
| |
| readPixelsAndConvertToBGRAIfNecessary(0, 0, m_currentWidth, m_currentHeight, pixels); |
| |
| if (mustRestorePackAlignment) |
| ::glPixelStorei(GL_PACK_ALIGNMENT, packAlignment); |
| |
| if (mustRestoreFBO) |
| ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_boundFBO); |
| } |
| |
| void GraphicsContext3D::reshape(int width, int height) |
| { |
| if (!platformGraphicsContext3D()) |
| return; |
| |
| if (width == m_currentWidth && height == m_currentHeight) |
| return; |
| |
| #if PLATFORM(QT) && USE(GRAPHICS_SURFACE) |
| ::glFlush(); // Make sure all GL calls have been committed before resizing. |
| createGraphicsSurfaces(IntSize(width, height)); |
| #endif |
| |
| m_currentWidth = width; |
| m_currentHeight = height; |
| |
| makeContextCurrent(); |
| validateAttributes(); |
| |
| bool mustRestoreFBO = reshapeFBOs(IntSize(width, height)); |
| |
| // Initialize renderbuffers to 0. |
| GLfloat clearColor[] = {0, 0, 0, 0}, clearDepth = 0; |
| GLint clearStencil = 0; |
| GLboolean colorMask[] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE}, depthMask = GL_TRUE; |
| GLuint stencilMask = 0xffffffff; |
| GLboolean isScissorEnabled = GL_FALSE; |
| GLboolean isDitherEnabled = GL_FALSE; |
| GLbitfield clearMask = GL_COLOR_BUFFER_BIT; |
| ::glGetFloatv(GL_COLOR_CLEAR_VALUE, clearColor); |
| ::glClearColor(0, 0, 0, 0); |
| ::glGetBooleanv(GL_COLOR_WRITEMASK, colorMask); |
| ::glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); |
| if (m_attrs.depth) { |
| ::glGetFloatv(GL_DEPTH_CLEAR_VALUE, &clearDepth); |
| GraphicsContext3D::clearDepth(1); |
| ::glGetBooleanv(GL_DEPTH_WRITEMASK, &depthMask); |
| ::glDepthMask(GL_TRUE); |
| clearMask |= GL_DEPTH_BUFFER_BIT; |
| } |
| if (m_attrs.stencil) { |
| ::glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &clearStencil); |
| ::glClearStencil(0); |
| ::glGetIntegerv(GL_STENCIL_WRITEMASK, reinterpret_cast<GLint*>(&stencilMask)); |
| ::glStencilMaskSeparate(GL_FRONT, 0xffffffff); |
| clearMask |= GL_STENCIL_BUFFER_BIT; |
| } |
| isScissorEnabled = ::glIsEnabled(GL_SCISSOR_TEST); |
| ::glDisable(GL_SCISSOR_TEST); |
| isDitherEnabled = ::glIsEnabled(GL_DITHER); |
| ::glDisable(GL_DITHER); |
| |
| ::glClear(clearMask); |
| |
| ::glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]); |
| ::glColorMask(colorMask[0], colorMask[1], colorMask[2], colorMask[3]); |
| if (m_attrs.depth) { |
| GraphicsContext3D::clearDepth(clearDepth); |
| ::glDepthMask(depthMask); |
| } |
| if (m_attrs.stencil) { |
| ::glClearStencil(clearStencil); |
| ::glStencilMaskSeparate(GL_FRONT, stencilMask); |
| } |
| if (isScissorEnabled) |
| ::glEnable(GL_SCISSOR_TEST); |
| else |
| ::glDisable(GL_SCISSOR_TEST); |
| if (isDitherEnabled) |
| ::glEnable(GL_DITHER); |
| else |
| ::glDisable(GL_DITHER); |
| |
| if (mustRestoreFBO) |
| ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_boundFBO); |
| |
| ::glFlush(); |
| } |
| |
| IntSize GraphicsContext3D::getInternalFramebufferSize() const |
| { |
| return IntSize(m_currentWidth, m_currentHeight); |
| } |
| |
| void GraphicsContext3D::activeTexture(GC3Denum texture) |
| { |
| makeContextCurrent(); |
| m_activeTexture = texture; |
| ::glActiveTexture(texture); |
| } |
| |
| void GraphicsContext3D::attachShader(Platform3DObject program, Platform3DObject shader) |
| { |
| ASSERT(program); |
| ASSERT(shader); |
| makeContextCurrent(); |
| ::glAttachShader(program, shader); |
| } |
| |
| void GraphicsContext3D::bindAttribLocation(Platform3DObject program, GC3Duint index, const String& name) |
| { |
| ASSERT(program); |
| makeContextCurrent(); |
| ::glBindAttribLocation(program, index, name.utf8().data()); |
| } |
| |
| void GraphicsContext3D::bindBuffer(GC3Denum target, Platform3DObject buffer) |
| { |
| makeContextCurrent(); |
| ::glBindBuffer(target, buffer); |
| } |
| |
| void GraphicsContext3D::bindFramebuffer(GC3Denum target, Platform3DObject buffer) |
| { |
| makeContextCurrent(); |
| GLuint fbo; |
| if (buffer) |
| fbo = buffer; |
| else |
| fbo = (m_attrs.antialias ? m_multisampleFBO : m_fbo); |
| if (fbo != m_boundFBO) { |
| ::glBindFramebufferEXT(target, fbo); |
| m_boundFBO = fbo; |
| } |
| } |
| |
| void GraphicsContext3D::bindRenderbuffer(GC3Denum target, Platform3DObject renderbuffer) |
| { |
| makeContextCurrent(); |
| ::glBindRenderbufferEXT(target, renderbuffer); |
| } |
| |
| |
| void GraphicsContext3D::bindTexture(GC3Denum target, Platform3DObject texture) |
| { |
| makeContextCurrent(); |
| if (m_activeTexture == GL_TEXTURE0 && target == GL_TEXTURE_2D) |
| m_boundTexture0 = texture; |
| ::glBindTexture(target, texture); |
| } |
| |
| void GraphicsContext3D::blendColor(GC3Dclampf red, GC3Dclampf green, GC3Dclampf blue, GC3Dclampf alpha) |
| { |
| makeContextCurrent(); |
| ::glBlendColor(red, green, blue, alpha); |
| } |
| |
| void GraphicsContext3D::blendEquation(GC3Denum mode) |
| { |
| makeContextCurrent(); |
| ::glBlendEquation(mode); |
| } |
| |
| void GraphicsContext3D::blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha) |
| { |
| makeContextCurrent(); |
| ::glBlendEquationSeparate(modeRGB, modeAlpha); |
| } |
| |
| |
| void GraphicsContext3D::blendFunc(GC3Denum sfactor, GC3Denum dfactor) |
| { |
| makeContextCurrent(); |
| ::glBlendFunc(sfactor, dfactor); |
| } |
| |
| void GraphicsContext3D::blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha) |
| { |
| makeContextCurrent(); |
| ::glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); |
| } |
| |
| void GraphicsContext3D::bufferData(GC3Denum target, GC3Dsizeiptr size, GC3Denum usage) |
| { |
| makeContextCurrent(); |
| ::glBufferData(target, size, 0, usage); |
| } |
| |
| void GraphicsContext3D::bufferData(GC3Denum target, GC3Dsizeiptr size, const void* data, GC3Denum usage) |
| { |
| makeContextCurrent(); |
| ::glBufferData(target, size, data, usage); |
| } |
| |
| void GraphicsContext3D::bufferSubData(GC3Denum target, GC3Dintptr offset, GC3Dsizeiptr size, const void* data) |
| { |
| makeContextCurrent(); |
| ::glBufferSubData(target, offset, size, data); |
| } |
| |
| GC3Denum GraphicsContext3D::checkFramebufferStatus(GC3Denum target) |
| { |
| makeContextCurrent(); |
| return ::glCheckFramebufferStatusEXT(target); |
| } |
| |
| void GraphicsContext3D::clearColor(GC3Dclampf r, GC3Dclampf g, GC3Dclampf b, GC3Dclampf a) |
| { |
| makeContextCurrent(); |
| ::glClearColor(r, g, b, a); |
| } |
| |
| void GraphicsContext3D::clear(GC3Dbitfield mask) |
| { |
| makeContextCurrent(); |
| ::glClear(mask); |
| } |
| |
| void GraphicsContext3D::clearStencil(GC3Dint s) |
| { |
| makeContextCurrent(); |
| ::glClearStencil(s); |
| } |
| |
| void GraphicsContext3D::colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha) |
| { |
| makeContextCurrent(); |
| ::glColorMask(red, green, blue, alpha); |
| } |
| |
| void GraphicsContext3D::compileShader(Platform3DObject shader) |
| { |
| ASSERT(shader); |
| makeContextCurrent(); |
| |
| int GLshaderType; |
| ANGLEShaderType shaderType; |
| |
| glGetShaderiv(shader, SHADER_TYPE, &GLshaderType); |
| |
| if (GLshaderType == VERTEX_SHADER) |
| shaderType = SHADER_TYPE_VERTEX; |
| else if (GLshaderType == FRAGMENT_SHADER) |
| shaderType = SHADER_TYPE_FRAGMENT; |
| else |
| return; // Invalid shader type. |
| |
| HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader); |
| |
| if (result == m_shaderSourceMap.end()) |
| return; |
| |
| ShaderSourceEntry& entry = result->second; |
| |
| String translatedShaderSource; |
| String shaderInfoLog; |
| |
| bool isValid = m_compiler.validateShaderSource(entry.source.utf8().data(), shaderType, translatedShaderSource, shaderInfoLog); |
| |
| entry.log = shaderInfoLog; |
| entry.isValid = isValid; |
| |
| if (!isValid) |
| return; // Shader didn't validate, don't move forward with compiling translated source. |
| |
| int translatedShaderLength = translatedShaderSource.length(); |
| |
| const CString& translatedShaderCString = translatedShaderSource.utf8(); |
| const char* translatedShaderPtr = translatedShaderCString.data(); |
| |
| ::glShaderSource(shader, 1, &translatedShaderPtr, &translatedShaderLength); |
| |
| ::glCompileShader(shader); |
| |
| int GLCompileSuccess; |
| |
| ::glGetShaderiv(shader, COMPILE_STATUS, &GLCompileSuccess); |
| |
| // ASSERT that ANGLE generated GLSL will be accepted by OpenGL. |
| ASSERT(GLCompileSuccess == GL_TRUE); |
| } |
| |
| void GraphicsContext3D::copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border) |
| { |
| makeContextCurrent(); |
| if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) { |
| resolveMultisamplingIfNecessary(IntRect(x, y, width, height)); |
| ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_fbo); |
| } |
| ::glCopyTexImage2D(target, level, internalformat, x, y, width, height, border); |
| if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) |
| ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO); |
| } |
| |
| void GraphicsContext3D::copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height) |
| { |
| makeContextCurrent(); |
| if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) { |
| resolveMultisamplingIfNecessary(IntRect(x, y, width, height)); |
| ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_fbo); |
| } |
| ::glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); |
| if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) |
| ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO); |
| } |
| |
| void GraphicsContext3D::cullFace(GC3Denum mode) |
| { |
| makeContextCurrent(); |
| ::glCullFace(mode); |
| } |
| |
| void GraphicsContext3D::depthFunc(GC3Denum func) |
| { |
| makeContextCurrent(); |
| ::glDepthFunc(func); |
| } |
| |
| void GraphicsContext3D::depthMask(GC3Dboolean flag) |
| { |
| makeContextCurrent(); |
| ::glDepthMask(flag); |
| } |
| |
| void GraphicsContext3D::detachShader(Platform3DObject program, Platform3DObject shader) |
| { |
| ASSERT(program); |
| ASSERT(shader); |
| makeContextCurrent(); |
| ::glDetachShader(program, shader); |
| } |
| |
| void GraphicsContext3D::disable(GC3Denum cap) |
| { |
| makeContextCurrent(); |
| ::glDisable(cap); |
| } |
| |
| void GraphicsContext3D::disableVertexAttribArray(GC3Duint index) |
| { |
| makeContextCurrent(); |
| ::glDisableVertexAttribArray(index); |
| } |
| |
| void GraphicsContext3D::drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count) |
| { |
| makeContextCurrent(); |
| ::glDrawArrays(mode, first, count); |
| } |
| |
| void GraphicsContext3D::drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dintptr offset) |
| { |
| makeContextCurrent(); |
| ::glDrawElements(mode, count, type, reinterpret_cast<GLvoid*>(static_cast<intptr_t>(offset))); |
| } |
| |
| void GraphicsContext3D::enable(GC3Denum cap) |
| { |
| makeContextCurrent(); |
| ::glEnable(cap); |
| } |
| |
| void GraphicsContext3D::enableVertexAttribArray(GC3Duint index) |
| { |
| makeContextCurrent(); |
| ::glEnableVertexAttribArray(index); |
| } |
| |
| void GraphicsContext3D::finish() |
| { |
| makeContextCurrent(); |
| ::glFinish(); |
| } |
| |
| void GraphicsContext3D::flush() |
| { |
| makeContextCurrent(); |
| ::glFlush(); |
| } |
| |
| void GraphicsContext3D::framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbuffertarget, Platform3DObject buffer) |
| { |
| makeContextCurrent(); |
| ::glFramebufferRenderbufferEXT(target, attachment, renderbuffertarget, buffer); |
| } |
| |
| void GraphicsContext3D::framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum textarget, Platform3DObject texture, GC3Dint level) |
| { |
| makeContextCurrent(); |
| ::glFramebufferTexture2DEXT(target, attachment, textarget, texture, level); |
| } |
| |
| void GraphicsContext3D::frontFace(GC3Denum mode) |
| { |
| makeContextCurrent(); |
| ::glFrontFace(mode); |
| } |
| |
| void GraphicsContext3D::generateMipmap(GC3Denum target) |
| { |
| makeContextCurrent(); |
| ::glGenerateMipmapEXT(target); |
| } |
| |
| bool GraphicsContext3D::getActiveAttrib(Platform3DObject program, GC3Duint index, ActiveInfo& info) |
| { |
| if (!program) { |
| synthesizeGLError(INVALID_VALUE); |
| return false; |
| } |
| makeContextCurrent(); |
| GLint maxAttributeSize = 0; |
| ::glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxAttributeSize); |
| GLchar name[maxAttributeSize]; // GL_ACTIVE_ATTRIBUTE_MAX_LENGTH includes null termination. |
| GLsizei nameLength = 0; |
| GLint size = 0; |
| GLenum type = 0; |
| ::glGetActiveAttrib(program, index, maxAttributeSize, &nameLength, &size, &type, name); |
| if (!nameLength) |
| return false; |
| info.name = String(name, nameLength); |
| info.type = type; |
| info.size = size; |
| return true; |
| } |
| |
| bool GraphicsContext3D::getActiveUniform(Platform3DObject program, GC3Duint index, ActiveInfo& info) |
| { |
| if (!program) { |
| synthesizeGLError(INVALID_VALUE); |
| return false; |
| } |
| |
| makeContextCurrent(); |
| GLint maxUniformSize = 0; |
| ::glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformSize); |
| |
| OwnArrayPtr<GLchar> name = adoptArrayPtr(new GLchar[maxUniformSize]); // GL_ACTIVE_UNIFORM_MAX_LENGTH includes null termination. |
| GLsizei nameLength = 0; |
| GLint size = 0; |
| GLenum type = 0; |
| ::glGetActiveUniform(program, index, maxUniformSize, &nameLength, &size, &type, name.get()); |
| if (!nameLength) |
| return false; |
| |
| info.name = String(name.get(), nameLength); |
| info.type = type; |
| info.size = size; |
| |
| return true; |
| } |
| |
| void GraphicsContext3D::getAttachedShaders(Platform3DObject program, GC3Dsizei maxCount, GC3Dsizei* count, Platform3DObject* shaders) |
| { |
| if (!program) { |
| synthesizeGLError(INVALID_VALUE); |
| return; |
| } |
| makeContextCurrent(); |
| ::glGetAttachedShaders(program, maxCount, count, shaders); |
| } |
| |
| int GraphicsContext3D::getAttribLocation(Platform3DObject program, const String& name) |
| { |
| if (!program) |
| return -1; |
| |
| makeContextCurrent(); |
| return ::glGetAttribLocation(program, name.utf8().data()); |
| } |
| |
| GraphicsContext3D::Attributes GraphicsContext3D::getContextAttributes() |
| { |
| return m_attrs; |
| } |
| |
| GC3Denum GraphicsContext3D::getError() |
| { |
| if (m_syntheticErrors.size() > 0) { |
| ListHashSet<GC3Denum>::iterator iter = m_syntheticErrors.begin(); |
| GC3Denum err = *iter; |
| m_syntheticErrors.remove(iter); |
| return err; |
| } |
| |
| makeContextCurrent(); |
| return ::glGetError(); |
| } |
| |
| String GraphicsContext3D::getString(GC3Denum name) |
| { |
| makeContextCurrent(); |
| return String(reinterpret_cast<const char*>(::glGetString(name))); |
| } |
| |
| void GraphicsContext3D::hint(GC3Denum target, GC3Denum mode) |
| { |
| makeContextCurrent(); |
| ::glHint(target, mode); |
| } |
| |
| GC3Dboolean GraphicsContext3D::isBuffer(Platform3DObject buffer) |
| { |
| if (!buffer) |
| return GL_FALSE; |
| |
| makeContextCurrent(); |
| return ::glIsBuffer(buffer); |
| } |
| |
| GC3Dboolean GraphicsContext3D::isEnabled(GC3Denum cap) |
| { |
| makeContextCurrent(); |
| return ::glIsEnabled(cap); |
| } |
| |
| GC3Dboolean GraphicsContext3D::isFramebuffer(Platform3DObject framebuffer) |
| { |
| if (!framebuffer) |
| return GL_FALSE; |
| |
| makeContextCurrent(); |
| return ::glIsFramebufferEXT(framebuffer); |
| } |
| |
| GC3Dboolean GraphicsContext3D::isProgram(Platform3DObject program) |
| { |
| if (!program) |
| return GL_FALSE; |
| |
| makeContextCurrent(); |
| return ::glIsProgram(program); |
| } |
| |
| GC3Dboolean GraphicsContext3D::isRenderbuffer(Platform3DObject renderbuffer) |
| { |
| if (!renderbuffer) |
| return GL_FALSE; |
| |
| makeContextCurrent(); |
| return ::glIsRenderbufferEXT(renderbuffer); |
| } |
| |
| GC3Dboolean GraphicsContext3D::isShader(Platform3DObject shader) |
| { |
| if (!shader) |
| return GL_FALSE; |
| |
| makeContextCurrent(); |
| return ::glIsShader(shader); |
| } |
| |
| GC3Dboolean GraphicsContext3D::isTexture(Platform3DObject texture) |
| { |
| if (!texture) |
| return GL_FALSE; |
| |
| makeContextCurrent(); |
| return ::glIsTexture(texture); |
| } |
| |
| void GraphicsContext3D::lineWidth(GC3Dfloat width) |
| { |
| makeContextCurrent(); |
| ::glLineWidth(width); |
| } |
| |
| void GraphicsContext3D::linkProgram(Platform3DObject program) |
| { |
| ASSERT(program); |
| makeContextCurrent(); |
| ::glLinkProgram(program); |
| } |
| |
| void GraphicsContext3D::pixelStorei(GC3Denum pname, GC3Dint param) |
| { |
| makeContextCurrent(); |
| ::glPixelStorei(pname, param); |
| } |
| |
| void GraphicsContext3D::polygonOffset(GC3Dfloat factor, GC3Dfloat units) |
| { |
| makeContextCurrent(); |
| ::glPolygonOffset(factor, units); |
| } |
| |
| void GraphicsContext3D::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, void* data) |
| { |
| // FIXME: remove the two glFlush calls when the driver bug is fixed, i.e., |
| // all previous rendering calls should be done before reading pixels. |
| makeContextCurrent(); |
| ::glFlush(); |
| if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) { |
| resolveMultisamplingIfNecessary(IntRect(x, y, width, height)); |
| ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_fbo); |
| ::glFlush(); |
| } |
| ::glReadPixels(x, y, width, height, format, type, data); |
| if (m_attrs.antialias && m_boundFBO == m_multisampleFBO) |
| ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO); |
| } |
| |
| void GraphicsContext3D::releaseShaderCompiler() |
| { |
| // FIXME: This is not implemented on desktop OpenGL. We need to have ifdefs for the different GL variants. |
| makeContextCurrent(); |
| notImplemented(); |
| } |
| |
| void GraphicsContext3D::sampleCoverage(GC3Dclampf value, GC3Dboolean invert) |
| { |
| makeContextCurrent(); |
| ::glSampleCoverage(value, invert); |
| } |
| |
| void GraphicsContext3D::scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height) |
| { |
| makeContextCurrent(); |
| ::glScissor(x, y, width, height); |
| } |
| |
| void GraphicsContext3D::shaderSource(Platform3DObject shader, const String& string) |
| { |
| ASSERT(shader); |
| |
| makeContextCurrent(); |
| |
| ShaderSourceEntry entry; |
| |
| entry.source = string; |
| |
| m_shaderSourceMap.set(shader, entry); |
| } |
| |
| void GraphicsContext3D::stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask) |
| { |
| makeContextCurrent(); |
| ::glStencilFunc(func, ref, mask); |
| } |
| |
| void GraphicsContext3D::stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask) |
| { |
| makeContextCurrent(); |
| ::glStencilFuncSeparate(face, func, ref, mask); |
| } |
| |
| void GraphicsContext3D::stencilMask(GC3Duint mask) |
| { |
| makeContextCurrent(); |
| ::glStencilMask(mask); |
| } |
| |
| void GraphicsContext3D::stencilMaskSeparate(GC3Denum face, GC3Duint mask) |
| { |
| makeContextCurrent(); |
| ::glStencilMaskSeparate(face, mask); |
| } |
| |
| void GraphicsContext3D::stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zpass) |
| { |
| makeContextCurrent(); |
| ::glStencilOp(fail, zfail, zpass); |
| } |
| |
| void GraphicsContext3D::stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zfail, GC3Denum zpass) |
| { |
| makeContextCurrent(); |
| ::glStencilOpSeparate(face, fail, zfail, zpass); |
| } |
| |
| void GraphicsContext3D::texParameterf(GC3Denum target, GC3Denum pname, GC3Dfloat value) |
| { |
| makeContextCurrent(); |
| ::glTexParameterf(target, pname, value); |
| } |
| |
| void GraphicsContext3D::texParameteri(GC3Denum target, GC3Denum pname, GC3Dint value) |
| { |
| makeContextCurrent(); |
| ::glTexParameteri(target, pname, value); |
| } |
| |
| void GraphicsContext3D::uniform1f(GC3Dint location, GC3Dfloat v0) |
| { |
| makeContextCurrent(); |
| ::glUniform1f(location, v0); |
| } |
| |
| void GraphicsContext3D::uniform1fv(GC3Dint location, GC3Dsizei size, GC3Dfloat* array) |
| { |
| makeContextCurrent(); |
| ::glUniform1fv(location, size, array); |
| } |
| |
| void GraphicsContext3D::uniform2f(GC3Dint location, GC3Dfloat v0, GC3Dfloat v1) |
| { |
| makeContextCurrent(); |
| ::glUniform2f(location, v0, v1); |
| } |
| |
| void GraphicsContext3D::uniform2fv(GC3Dint location, GC3Dsizei size, GC3Dfloat* array) |
| { |
| // FIXME: length needs to be a multiple of 2. |
| makeContextCurrent(); |
| ::glUniform2fv(location, size, array); |
| } |
| |
| void GraphicsContext3D::uniform3f(GC3Dint location, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2) |
| { |
| makeContextCurrent(); |
| ::glUniform3f(location, v0, v1, v2); |
| } |
| |
| void GraphicsContext3D::uniform3fv(GC3Dint location, GC3Dsizei size, GC3Dfloat* array) |
| { |
| // FIXME: length needs to be a multiple of 3. |
| makeContextCurrent(); |
| ::glUniform3fv(location, size, array); |
| } |
| |
| void GraphicsContext3D::uniform4f(GC3Dint location, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3) |
| { |
| makeContextCurrent(); |
| ::glUniform4f(location, v0, v1, v2, v3); |
| } |
| |
| void GraphicsContext3D::uniform4fv(GC3Dint location, GC3Dsizei size, GC3Dfloat* array) |
| { |
| // FIXME: length needs to be a multiple of 4. |
| makeContextCurrent(); |
| ::glUniform4fv(location, size, array); |
| } |
| |
| void GraphicsContext3D::uniform1i(GC3Dint location, GC3Dint v0) |
| { |
| makeContextCurrent(); |
| ::glUniform1i(location, v0); |
| } |
| |
| void GraphicsContext3D::uniform1iv(GC3Dint location, GC3Dsizei size, GC3Dint* array) |
| { |
| makeContextCurrent(); |
| ::glUniform1iv(location, size, array); |
| } |
| |
| void GraphicsContext3D::uniform2i(GC3Dint location, GC3Dint v0, GC3Dint v1) |
| { |
| makeContextCurrent(); |
| ::glUniform2i(location, v0, v1); |
| } |
| |
| void GraphicsContext3D::uniform2iv(GC3Dint location, GC3Dsizei size, GC3Dint* array) |
| { |
| // FIXME: length needs to be a multiple of 2. |
| makeContextCurrent(); |
| ::glUniform2iv(location, size, array); |
| } |
| |
| void GraphicsContext3D::uniform3i(GC3Dint location, GC3Dint v0, GC3Dint v1, GC3Dint v2) |
| { |
| makeContextCurrent(); |
| ::glUniform3i(location, v0, v1, v2); |
| } |
| |
| void GraphicsContext3D::uniform3iv(GC3Dint location, GC3Dsizei size, GC3Dint* array) |
| { |
| // FIXME: length needs to be a multiple of 3. |
| makeContextCurrent(); |
| ::glUniform3iv(location, size, array); |
| } |
| |
| void GraphicsContext3D::uniform4i(GC3Dint location, GC3Dint v0, GC3Dint v1, GC3Dint v2, GC3Dint v3) |
| { |
| makeContextCurrent(); |
| ::glUniform4i(location, v0, v1, v2, v3); |
| } |
| |
| void GraphicsContext3D::uniform4iv(GC3Dint location, GC3Dsizei size, GC3Dint* array) |
| { |
| // FIXME: length needs to be a multiple of 4. |
| makeContextCurrent(); |
| ::glUniform4iv(location, size, array); |
| } |
| |
| void GraphicsContext3D::uniformMatrix2fv(GC3Dint location, GC3Dsizei size, GC3Dboolean transpose, GC3Dfloat* array) |
| { |
| // FIXME: length needs to be a multiple of 4. |
| makeContextCurrent(); |
| ::glUniformMatrix2fv(location, size, transpose, array); |
| } |
| |
| void GraphicsContext3D::uniformMatrix3fv(GC3Dint location, GC3Dsizei size, GC3Dboolean transpose, GC3Dfloat* array) |
| { |
| // FIXME: length needs to be a multiple of 9. |
| makeContextCurrent(); |
| ::glUniformMatrix3fv(location, size, transpose, array); |
| } |
| |
| void GraphicsContext3D::uniformMatrix4fv(GC3Dint location, GC3Dsizei size, GC3Dboolean transpose, GC3Dfloat* array) |
| { |
| // FIXME: length needs to be a multiple of 16. |
| makeContextCurrent(); |
| ::glUniformMatrix4fv(location, size, transpose, array); |
| } |
| |
| void GraphicsContext3D::useProgram(Platform3DObject program) |
| { |
| makeContextCurrent(); |
| ::glUseProgram(program); |
| } |
| |
| void GraphicsContext3D::validateProgram(Platform3DObject program) |
| { |
| ASSERT(program); |
| |
| makeContextCurrent(); |
| ::glValidateProgram(program); |
| } |
| |
| void GraphicsContext3D::vertexAttrib1f(GC3Duint index, GC3Dfloat v0) |
| { |
| makeContextCurrent(); |
| ::glVertexAttrib1f(index, v0); |
| } |
| |
| void GraphicsContext3D::vertexAttrib1fv(GC3Duint index, GC3Dfloat* array) |
| { |
| makeContextCurrent(); |
| ::glVertexAttrib1fv(index, array); |
| } |
| |
| void GraphicsContext3D::vertexAttrib2f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1) |
| { |
| makeContextCurrent(); |
| ::glVertexAttrib2f(index, v0, v1); |
| } |
| |
| void GraphicsContext3D::vertexAttrib2fv(GC3Duint index, GC3Dfloat* array) |
| { |
| makeContextCurrent(); |
| ::glVertexAttrib2fv(index, array); |
| } |
| |
| void GraphicsContext3D::vertexAttrib3f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2) |
| { |
| makeContextCurrent(); |
| ::glVertexAttrib3f(index, v0, v1, v2); |
| } |
| |
| void GraphicsContext3D::vertexAttrib3fv(GC3Duint index, GC3Dfloat* array) |
| { |
| makeContextCurrent(); |
| ::glVertexAttrib3fv(index, array); |
| } |
| |
| void GraphicsContext3D::vertexAttrib4f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3) |
| { |
| makeContextCurrent(); |
| ::glVertexAttrib4f(index, v0, v1, v2, v3); |
| } |
| |
| void GraphicsContext3D::vertexAttrib4fv(GC3Duint index, GC3Dfloat* array) |
| { |
| makeContextCurrent(); |
| ::glVertexAttrib4fv(index, array); |
| } |
| |
| void GraphicsContext3D::vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized, GC3Dsizei stride, GC3Dintptr offset) |
| { |
| makeContextCurrent(); |
| ::glVertexAttribPointer(index, size, type, normalized, stride, reinterpret_cast<GLvoid*>(static_cast<intptr_t>(offset))); |
| } |
| |
| void GraphicsContext3D::viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height) |
| { |
| makeContextCurrent(); |
| ::glViewport(x, y, width, height); |
| } |
| |
| void GraphicsContext3D::getBooleanv(GC3Denum pname, GC3Dboolean* value) |
| { |
| makeContextCurrent(); |
| ::glGetBooleanv(pname, value); |
| } |
| |
| void GraphicsContext3D::getBufferParameteriv(GC3Denum target, GC3Denum pname, GC3Dint* value) |
| { |
| makeContextCurrent(); |
| ::glGetBufferParameteriv(target, pname, value); |
| } |
| |
| void GraphicsContext3D::getFloatv(GC3Denum pname, GC3Dfloat* value) |
| { |
| makeContextCurrent(); |
| ::glGetFloatv(pname, value); |
| } |
| |
| void GraphicsContext3D::getFramebufferAttachmentParameteriv(GC3Denum target, GC3Denum attachment, GC3Denum pname, GC3Dint* value) |
| { |
| makeContextCurrent(); |
| if (attachment == DEPTH_STENCIL_ATTACHMENT) |
| attachment = DEPTH_ATTACHMENT; // Or STENCIL_ATTACHMENT, either works. |
| ::glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, value); |
| } |
| |
| void GraphicsContext3D::getProgramiv(Platform3DObject program, GC3Denum pname, GC3Dint* value) |
| { |
| makeContextCurrent(); |
| ::glGetProgramiv(program, pname, value); |
| } |
| |
| String GraphicsContext3D::getProgramInfoLog(Platform3DObject program) |
| { |
| ASSERT(program); |
| |
| makeContextCurrent(); |
| GLint length = 0; |
| ::glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length); |
| if (!length) |
| return String(); |
| |
| GLsizei size = 0; |
| OwnArrayPtr<GLchar> info = adoptArrayPtr(new GLchar[length]); |
| ::glGetProgramInfoLog(program, length, &size, info.get()); |
| |
| return String(info.get()); |
| } |
| |
| void GraphicsContext3D::getRenderbufferParameteriv(GC3Denum target, GC3Denum pname, GC3Dint* value) |
| { |
| makeContextCurrent(); |
| ::glGetRenderbufferParameterivEXT(target, pname, value); |
| } |
| |
| void GraphicsContext3D::getShaderiv(Platform3DObject shader, GC3Denum pname, GC3Dint* value) |
| { |
| ASSERT(shader); |
| |
| makeContextCurrent(); |
| |
| HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader); |
| |
| switch (pname) { |
| case DELETE_STATUS: |
| case SHADER_TYPE: |
| ::glGetShaderiv(shader, pname, value); |
| break; |
| case COMPILE_STATUS: |
| if (result == m_shaderSourceMap.end()) { |
| *value = static_cast<int>(false); |
| return; |
| } |
| *value = static_cast<int>(result->second.isValid); |
| break; |
| case INFO_LOG_LENGTH: |
| if (result == m_shaderSourceMap.end()) { |
| *value = 0; |
| return; |
| } |
| *value = getShaderInfoLog(shader).length(); |
| break; |
| case SHADER_SOURCE_LENGTH: |
| *value = getShaderSource(shader).length(); |
| break; |
| default: |
| synthesizeGLError(INVALID_ENUM); |
| } |
| } |
| |
| String GraphicsContext3D::getShaderInfoLog(Platform3DObject shader) |
| { |
| ASSERT(shader); |
| |
| makeContextCurrent(); |
| |
| HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader); |
| if (result == m_shaderSourceMap.end()) |
| return String(); |
| |
| ShaderSourceEntry entry = result->second; |
| if (!entry.isValid) |
| return entry.log; |
| |
| GLint length = 0; |
| ::glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length); |
| if (!length) |
| return String(); |
| |
| GLsizei size = 0; |
| OwnArrayPtr<GLchar> info = adoptArrayPtr(new GLchar[length]); |
| ::glGetShaderInfoLog(shader, length, &size, info.get()); |
| |
| return String(info.get()); |
| } |
| |
| String GraphicsContext3D::getShaderSource(Platform3DObject shader) |
| { |
| ASSERT(shader); |
| |
| makeContextCurrent(); |
| |
| HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader); |
| if (result == m_shaderSourceMap.end()) |
| return String(); |
| |
| return result->second.source; |
| } |
| |
| |
| void GraphicsContext3D::getTexParameterfv(GC3Denum target, GC3Denum pname, GC3Dfloat* value) |
| { |
| makeContextCurrent(); |
| ::glGetTexParameterfv(target, pname, value); |
| } |
| |
| void GraphicsContext3D::getTexParameteriv(GC3Denum target, GC3Denum pname, GC3Dint* value) |
| { |
| makeContextCurrent(); |
| ::glGetTexParameteriv(target, pname, value); |
| } |
| |
| void GraphicsContext3D::getUniformfv(Platform3DObject program, GC3Dint location, GC3Dfloat* value) |
| { |
| makeContextCurrent(); |
| ::glGetUniformfv(program, location, value); |
| } |
| |
| void GraphicsContext3D::getUniformiv(Platform3DObject program, GC3Dint location, GC3Dint* value) |
| { |
| makeContextCurrent(); |
| ::glGetUniformiv(program, location, value); |
| } |
| |
| GC3Dint GraphicsContext3D::getUniformLocation(Platform3DObject program, const String& name) |
| { |
| ASSERT(program); |
| |
| makeContextCurrent(); |
| return ::glGetUniformLocation(program, name.utf8().data()); |
| } |
| |
| void GraphicsContext3D::getVertexAttribfv(GC3Duint index, GC3Denum pname, GC3Dfloat* value) |
| { |
| makeContextCurrent(); |
| ::glGetVertexAttribfv(index, pname, value); |
| } |
| |
| void GraphicsContext3D::getVertexAttribiv(GC3Duint index, GC3Denum pname, GC3Dint* value) |
| { |
| makeContextCurrent(); |
| ::glGetVertexAttribiv(index, pname, value); |
| } |
| |
| GC3Dsizeiptr GraphicsContext3D::getVertexAttribOffset(GC3Duint index, GC3Denum pname) |
| { |
| makeContextCurrent(); |
| |
| GLvoid* pointer = 0; |
| ::glGetVertexAttribPointerv(index, pname, &pointer); |
| return static_cast<GC3Dsizeiptr>(reinterpret_cast<intptr_t>(pointer)); |
| } |
| |
| void GraphicsContext3D::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoff, GC3Dint yoff, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, const void* pixels) |
| { |
| makeContextCurrent(); |
| |
| // FIXME: we will need to deal with PixelStore params when dealing with image buffers that differ from the subimage size. |
| ::glTexSubImage2D(target, level, xoff, yoff, width, height, format, type, pixels); |
| } |
| |
| void GraphicsContext3D::compressedTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Dsizei imageSize, const void* data) |
| { |
| makeContextCurrent(); |
| ::glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data); |
| } |
| |
| void GraphicsContext3D::compressedTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Dsizei imageSize, const void* data) |
| { |
| makeContextCurrent(); |
| ::glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data); |
| } |
| |
| Platform3DObject GraphicsContext3D::createBuffer() |
| { |
| makeContextCurrent(); |
| GLuint o = 0; |
| glGenBuffers(1, &o); |
| return o; |
| } |
| |
| Platform3DObject GraphicsContext3D::createFramebuffer() |
| { |
| makeContextCurrent(); |
| GLuint o = 0; |
| glGenFramebuffersEXT(1, &o); |
| return o; |
| } |
| |
| Platform3DObject GraphicsContext3D::createProgram() |
| { |
| makeContextCurrent(); |
| return glCreateProgram(); |
| } |
| |
| Platform3DObject GraphicsContext3D::createRenderbuffer() |
| { |
| makeContextCurrent(); |
| GLuint o = 0; |
| glGenRenderbuffersEXT(1, &o); |
| return o; |
| } |
| |
| Platform3DObject GraphicsContext3D::createShader(GC3Denum type) |
| { |
| makeContextCurrent(); |
| return glCreateShader((type == FRAGMENT_SHADER) ? GL_FRAGMENT_SHADER : GL_VERTEX_SHADER); |
| } |
| |
| Platform3DObject GraphicsContext3D::createTexture() |
| { |
| makeContextCurrent(); |
| GLuint o = 0; |
| glGenTextures(1, &o); |
| return o; |
| } |
| |
| void GraphicsContext3D::deleteBuffer(Platform3DObject buffer) |
| { |
| makeContextCurrent(); |
| glDeleteBuffers(1, &buffer); |
| } |
| |
| void GraphicsContext3D::deleteFramebuffer(Platform3DObject framebuffer) |
| { |
| makeContextCurrent(); |
| glDeleteFramebuffersEXT(1, &framebuffer); |
| } |
| |
| void GraphicsContext3D::deleteProgram(Platform3DObject program) |
| { |
| makeContextCurrent(); |
| glDeleteProgram(program); |
| } |
| |
| void GraphicsContext3D::deleteRenderbuffer(Platform3DObject renderbuffer) |
| { |
| makeContextCurrent(); |
| glDeleteRenderbuffersEXT(1, &renderbuffer); |
| } |
| |
| void GraphicsContext3D::deleteShader(Platform3DObject shader) |
| { |
| makeContextCurrent(); |
| glDeleteShader(shader); |
| } |
| |
| void GraphicsContext3D::deleteTexture(Platform3DObject texture) |
| { |
| makeContextCurrent(); |
| glDeleteTextures(1, &texture); |
| } |
| |
| void GraphicsContext3D::synthesizeGLError(GC3Denum error) |
| { |
| m_syntheticErrors.add(error); |
| } |
| |
| void GraphicsContext3D::markContextChanged() |
| { |
| m_layerComposited = false; |
| } |
| |
| void GraphicsContext3D::markLayerComposited() |
| { |
| m_layerComposited = true; |
| } |
| |
| bool GraphicsContext3D::layerComposited() const |
| { |
| return m_layerComposited; |
| } |
| |
| Extensions3D* GraphicsContext3D::getExtensions() |
| { |
| if (!m_extensions) |
| m_extensions = adoptPtr(new Extensions3DOpenGL(this)); |
| return m_extensions.get(); |
| } |
| |
| } |
| |
| #endif // ENABLE(WEBGL) |