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 COMPUTER, 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 COMPUTER, 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#if PLATFORM(BLACKBERRY) 39#include "LayerWebKitThread.h" 40#endif 41#include "NotImplemented.h" 42 43namespace WebCore { 44 45void GraphicsContext3D::releaseShaderCompiler() 46{ 47 makeContextCurrent(); 48 ::glReleaseShaderCompiler(); 49} 50 51void GraphicsContext3D::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, void* data) 52{ 53 makeContextCurrent(); 54 // FIXME: remove the two glFlush calls when the driver bug is fixed, i.e., 55 // all previous rendering calls should be done before reading pixels. 56 ::glFlush(); 57#if PLATFORM(BLACKBERRY) 58 if (m_isImaginationHardware && m_fbo == m_state.boundFBO) { 59 // FIXME: This workaround should always be used until the 60 // driver alignment bug is fixed, even when we aren't 61 // drawing to the canvas. 62 readPixelsIMG(x, y, width, height, format, type, data); 63 } else 64 ::glReadPixels(x, y, width, height, format, type, data); 65#else 66 if (m_attrs.antialias && m_state.boundFBO == m_multisampleFBO) { 67 resolveMultisamplingIfNecessary(IntRect(x, y, width, height)); 68 ::glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); 69 ::glFlush(); 70 } 71 72 ::glReadPixels(x, y, width, height, format, type, data); 73 74 if (m_attrs.antialias && m_state.boundFBO == m_multisampleFBO) 75 ::glBindFramebuffer(GL_FRAMEBUFFER, m_multisampleFBO); 76#endif 77} 78 79void GraphicsContext3D::readPixelsAndConvertToBGRAIfNecessary(int x, int y, int width, int height, unsigned char* pixels) 80{ 81#if PLATFORM(BLACKBERRY) 82 if (m_isImaginationHardware && m_fbo == m_state.boundFBO) { 83 // FIXME: This workaround should always be used until the 84 // driver alignment bug is fixed, even when we aren't 85 // drawing to the canvas. 86 readPixelsIMG(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); 87 } else 88 ::glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); 89#else 90 ::glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels); 91#endif 92 int totalBytes = width * height * 4; 93 if (isGLES2Compliant()) { 94 for (int i = 0; i < totalBytes; i += 4) 95 std::swap(pixels[i], pixels[i + 2]); // Convert to BGRA. 96 } 97} 98 99#if !PLATFORM(BLACKBERRY) 100// The BlackBerry port uses a special implementation of reshapeFBOs. See GraphicsContext3DBlackBerry.cpp 101bool GraphicsContext3D::reshapeFBOs(const IntSize& size) 102{ 103 const int width = size.width(); 104 const int height = size.height(); 105 GLuint colorFormat = 0, pixelDataType = 0; 106 if (m_attrs.alpha) { 107 m_internalColorFormat = GL_RGBA; 108 colorFormat = GL_RGBA; 109 pixelDataType = GL_UNSIGNED_BYTE; 110 } else { 111 m_internalColorFormat = GL_RGB; 112 colorFormat = GL_RGB; 113 pixelDataType = GL_UNSIGNED_SHORT_5_6_5; 114 } 115 116 // We don't allow the logic where stencil is required and depth is not. 117 // See GraphicsContext3D::validateAttributes. 118 bool supportPackedDepthStencilBuffer = (m_attrs.stencil || m_attrs.depth) && getExtensions()->supports("GL_OES_packed_depth_stencil"); 119 120 // Resize regular FBO. 121 bool mustRestoreFBO = false; 122 if (m_state.boundFBO != m_fbo) { 123 mustRestoreFBO = true; 124 ::glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); 125 } 126 127 ::glBindTexture(GL_TEXTURE_2D, m_texture); 128 ::glTexImage2D(GL_TEXTURE_2D, 0, m_internalColorFormat, width, height, 0, colorFormat, pixelDataType, 0); 129 ::glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0); 130 131 ::glBindTexture(GL_TEXTURE_2D, m_compositorTexture); 132 ::glTexImage2D(GL_TEXTURE_2D, 0, m_internalColorFormat, width, height, 0, colorFormat, GL_UNSIGNED_BYTE, 0); 133 ::glBindTexture(GL_TEXTURE_2D, 0); 134 135 // We don't support antialiasing yet. See GraphicsContext3D::validateAttributes. 136 ASSERT(!m_attrs.antialias); 137 138 if (m_attrs.stencil || m_attrs.depth) { 139 // Use a 24 bit depth buffer where we know we have it. 140 if (supportPackedDepthStencilBuffer) { 141 ::glBindRenderbuffer(GL_RENDERBUFFER, m_depthStencilBuffer); 142 ::glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, width, height); 143 if (m_attrs.stencil) 144 ::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilBuffer); 145 if (m_attrs.depth) 146 ::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthStencilBuffer); 147 ::glBindRenderbuffer(GL_RENDERBUFFER, 0); 148 } else { 149 if (m_attrs.stencil) { 150 ::glBindRenderbuffer(GL_RENDERBUFFER, m_stencilBuffer); 151 ::glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, width, height); 152 ::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_stencilBuffer); 153 } 154 if (m_attrs.depth) { 155 ::glBindRenderbuffer(GL_RENDERBUFFER, m_depthBuffer); 156 ::glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height); 157 ::glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthBuffer); 158 } 159 ::glBindRenderbuffer(GL_RENDERBUFFER, 0); 160 } 161 } 162 if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) { 163 // FIXME: cleanup 164 notImplemented(); 165 } 166 167 return mustRestoreFBO; 168} 169#endif 170 171void GraphicsContext3D::resolveMultisamplingIfNecessary(const IntRect& rect) 172{ 173 // FIXME: We don't support antialiasing yet. 174 notImplemented(); 175} 176 177void GraphicsContext3D::renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height) 178{ 179 makeContextCurrent(); 180 ::glRenderbufferStorage(target, internalformat, width, height); 181} 182 183void GraphicsContext3D::getIntegerv(GC3Denum pname, GC3Dint* value) 184{ 185 makeContextCurrent(); 186 ::glGetIntegerv(pname, value); 187} 188 189void GraphicsContext3D::getShaderPrecisionFormat(GC3Denum shaderType, GC3Denum precisionType, GC3Dint* range, GC3Dint* precision) 190{ 191 ASSERT(range); 192 ASSERT(precision); 193 194 makeContextCurrent(); 195 ::glGetShaderPrecisionFormat(shaderType, precisionType, range, precision); 196} 197 198bool GraphicsContext3D::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels) 199{ 200 if (width && height && !pixels) { 201 synthesizeGLError(INVALID_VALUE); 202 return false; 203 } 204 205 texImage2DDirect(target, level, internalformat, width, height, border, format, type, pixels); 206 return true; 207} 208 209void GraphicsContext3D::validateAttributes() 210{ 211 validateDepthStencil("GL_OES_packed_depth_stencil"); 212 213 if (m_attrs.antialias) { 214 Extensions3D* extensions = getExtensions(); 215 if (!extensions->supports("GL_IMG_multisampled_render_to_texture")) 216 m_attrs.antialias = false; 217 } 218} 219 220void GraphicsContext3D::depthRange(GC3Dclampf zNear, GC3Dclampf zFar) 221{ 222 makeContextCurrent(); 223 ::glDepthRangef(zNear, zFar); 224} 225 226void GraphicsContext3D::clearDepth(GC3Dclampf depth) 227{ 228 makeContextCurrent(); 229 ::glClearDepthf(depth); 230} 231 232 233Extensions3D* GraphicsContext3D::getExtensions() 234{ 235 if (!m_extensions) 236 m_extensions = adoptPtr(new Extensions3DOpenGLES(this)); 237 return m_extensions.get(); 238} 239 240} 241 242#endif // USE(3D_GRAPHICS) 243