1/* 2 * Copyright (C) 2010 Apple Inc. All rights reserved. 3 * Copyright (C) 2011 Google Inc. All rights reserved. 4 * Copyright (C) 2012 ChangSeok Oh <shivamidow@gmail.com> 5 * Copyright (C) 2012 Research In Motion Limited. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 20 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 21 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 24 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29#include "config.h" 30 31#if USE(3D_GRAPHICS) 32 33#include "GraphicsContext3D.h" 34 35#include "Extensions3DOpenGLES.h" 36#include "IntRect.h" 37#include "IntSize.h" 38#include "NotImplemented.h" 39 40namespace WebCore { 41 42void GraphicsContext3D::releaseShaderCompiler() 43{ 44 makeContextCurrent(); 45 ::glReleaseShaderCompiler(); 46} 47 48void GraphicsContext3D::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, void* data) 49{ 50 makeContextCurrent(); 51 // FIXME: remove the two glFlush calls when the driver bug is fixed, i.e., 52 // all previous rendering calls should be done before reading pixels. 53 ::glFlush(); 54 if (m_attrs.antialias && m_state.boundFBO == m_multisampleFBO) { 55 resolveMultisamplingIfNecessary(IntRect(x, y, width, height)); 56 ::glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); 57 ::glFlush(); 58 } 59 60 ::glReadPixels(x, y, width, height, format, type, data); 61 62 if (m_attrs.antialias && m_state.boundFBO == m_multisampleFBO) 63 ::glBindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO); 64} 65 66void GraphicsContext3D::readPixelsAndConvertToBGRAIfNecessary(int x, int y, int width, int height, unsigned char* pixels) 67{ 68 ::glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); 69 int totalBytes = width * height * 4; 70 if (isGLES2Compliant()) { 71 for (int i = 0; i < totalBytes; i += 4) 72 std::swap(pixels[i], pixels[i + 2]); // Convert to BGRA. 73 } 74} 75 76bool GraphicsContext3D::reshapeFBOs(const IntSize& size) 77{ 78 const int width = size.width(); 79 const int height = size.height(); 80 GLuint colorFormat = 0, pixelDataType = 0; 81 if (m_attrs.alpha) { 82 m_internalColorFormat = GL_RGBA; 83 colorFormat = GL_RGBA; 84 pixelDataType = GL_UNSIGNED_BYTE; 85 } else { 86 m_internalColorFormat = GL_RGB; 87 colorFormat = GL_RGB; 88 pixelDataType = GL_UNSIGNED_SHORT_5_6_5; 89 } 90 91 // We don't allow the logic where stencil is required and depth is not. 92 // See GraphicsContext3D::validateAttributes. 93 bool supportPackedDepthStencilBuffer = (m_attrs.stencil || m_attrs.depth) && getExtensions()->supports("GL_OES_packed_depth_stencil"); 94 95 // Resize regular FBO. 96 bool mustRestoreFBO = false; 97 if (m_state.boundFBO != m_fbo) { 98 mustRestoreFBO = true; 99 ::glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); 100 } 101 102 ASSERT(m_texture); 103 ::glBindTexture(GL_TEXTURE_2D, m_texture); 104 ::glTexImage2D(GL_TEXTURE_2D, 0, m_internalColorFormat, width, height, 0, colorFormat, pixelDataType, 0); 105 ::glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0); 106 107 if (m_compositorTexture) { 108 ::glBindTexture(GL_TEXTURE_2D, m_compositorTexture); 109 ::glTexImage2D(GL_TEXTURE_2D, 0, m_internalColorFormat, width, height, 0, colorFormat, GL_UNSIGNED_BYTE, 0); 110 ::glBindTexture(GL_TEXTURE_2D, 0); 111 } 112 113 Extensions3DOpenGLES* extensions = static_cast<Extensions3DOpenGLES*>(getExtensions()); 114 if (extensions->isImagination() && m_attrs.antialias) { 115 GLint maxSampleCount; 116 ::glGetIntegerv(Extensions3D::MAX_SAMPLES_IMG, &maxSampleCount); 117 GLint sampleCount = std::min(8, maxSampleCount); 118 119 extensions->framebufferTexture2DMultisampleIMG(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0, sampleCount); 120 121 if (m_attrs.stencil || m_attrs.depth) { 122 // Use a 24 bit depth buffer where we know we have it. 123 if (supportPackedDepthStencilBuffer) { 124 ::glBindRenderbuffer(GL_RENDERBUFFER, m_depthStencilBuffer); 125 extensions->renderbufferStorageMultisample(GL_RENDERBUFFER, sampleCount, GL_DEPTH24_STENCIL8_OES, width, height); 126 if (m_attrs.stencil) 127 ::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilBuffer); 128 if (m_attrs.depth) 129 ::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilBuffer); 130 } else { 131 if (m_attrs.stencil) { 132 ::glBindRenderbuffer(GL_RENDERBUFFER, m_stencilBuffer); 133 extensions->renderbufferStorageMultisample(GL_RENDERBUFFER, sampleCount, GL_STENCIL_INDEX8, width, height); 134 ::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_stencilBuffer); 135 } 136 if (m_attrs.depth) { 137 ::glBindRenderbuffer(GL_RENDERBUFFER, m_depthBuffer); 138 extensions->renderbufferStorageMultisample(GL_RENDERBUFFER, sampleCount, GL_DEPTH_COMPONENT16, width, height); 139 ::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthBuffer); 140 } 141 } 142 ::glBindRenderbuffer(GL_RENDERBUFFER, 0); 143 } 144 } else { 145 if (m_attrs.stencil || m_attrs.depth) { 146 // Use a 24 bit depth buffer where we know we have it. 147 if (supportPackedDepthStencilBuffer) { 148 ::glBindRenderbuffer(GL_RENDERBUFFER, m_depthStencilBuffer); 149 ::glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, width, height); 150 if (m_attrs.stencil) 151 ::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilBuffer); 152 if (m_attrs.depth) 153 ::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilBuffer); 154 } else { 155 if (m_attrs.stencil) { 156 ::glBindRenderbuffer(GL_RENDERBUFFER, m_stencilBuffer); 157 ::glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, width, height); 158 ::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_stencilBuffer); 159 } 160 if (m_attrs.depth) { 161 ::glBindRenderbuffer(GL_RENDERBUFFER, m_depthBuffer); 162 ::glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height); 163 ::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthBuffer); 164 } 165 } 166 ::glBindRenderbuffer(GL_RENDERBUFFER, 0); 167 } 168 } 169 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { 170 // FIXME: cleanup 171 notImplemented(); 172 } 173 174 return mustRestoreFBO; 175} 176 177void GraphicsContext3D::resolveMultisamplingIfNecessary(const IntRect& rect) 178{ 179 // FIXME: We don't support antialiasing yet. 180 notImplemented(); 181} 182 183void GraphicsContext3D::renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height) 184{ 185 makeContextCurrent(); 186 ::glRenderbufferStorage(target, internalformat, width, height); 187} 188 189void GraphicsContext3D::getIntegerv(GC3Denum pname, GC3Dint* value) 190{ 191 makeContextCurrent(); 192 ::glGetIntegerv(pname, value); 193} 194 195void GraphicsContext3D::getShaderPrecisionFormat(GC3Denum shaderType, GC3Denum precisionType, GC3Dint* range, GC3Dint* precision) 196{ 197 ASSERT(range); 198 ASSERT(precision); 199 200 makeContextCurrent(); 201 ::glGetShaderPrecisionFormat(shaderType, precisionType, range, precision); 202} 203 204bool GraphicsContext3D::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels) 205{ 206 if (width && height && !pixels) { 207 synthesizeGLError(INVALID_VALUE); 208 return false; 209 } 210 211 texImage2DDirect(target, level, internalformat, width, height, border, format, type, pixels); 212 return true; 213} 214 215void GraphicsContext3D::validateAttributes() 216{ 217 validateDepthStencil("GL_OES_packed_depth_stencil"); 218 219 if (m_attrs.antialias) { 220 Extensions3D* extensions = getExtensions(); 221 if (!extensions->supports("GL_IMG_multisampled_render_to_texture")) 222 m_attrs.antialias = false; 223 } 224} 225 226void GraphicsContext3D::depthRange(GC3Dclampf zNear, GC3Dclampf zFar) 227{ 228 makeContextCurrent(); 229 ::glDepthRangef(zNear, zFar); 230} 231 232void GraphicsContext3D::clearDepth(GC3Dclampf depth) 233{ 234 makeContextCurrent(); 235 ::glClearDepthf(depth); 236} 237 238Extensions3D* GraphicsContext3D::getExtensions() 239{ 240 if (!m_extensions) 241 m_extensions = adoptPtr(new Extensions3DOpenGLES(this)); 242 return m_extensions.get(); 243} 244 245} 246 247#endif // USE(3D_GRAPHICS) 248