1/* 2 * Copyright (C) 2009 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#import "BlockExceptions.h" 33 34#include "ANGLE/ShaderLang.h" 35#include "ArrayBuffer.h" 36#include "ArrayBufferView.h" 37#include "CanvasRenderingContext.h" 38#include <CoreGraphics/CGBitmapContext.h> 39#include "Extensions3DOpenGL.h" 40#include "Float32Array.h" 41#include "GraphicsContext.h" 42#include "HTMLCanvasElement.h" 43#include "ImageBuffer.h" 44#include "Int32Array.h" 45#include "NotImplemented.h" 46#include <OpenGL/CGLRenderers.h> 47#include <OpenGL/gl.h> 48#include "Uint8Array.h" 49#include "WebGLLayer.h" 50#include "WebGLObject.h" 51#include <wtf/UnusedParam.h> 52#include <wtf/text/CString.h> 53 54namespace WebCore { 55 56static void setPixelFormat(Vector<CGLPixelFormatAttribute>& attribs, int colorBits, int depthBits, bool accelerated, bool supersample, bool closest) 57{ 58 attribs.clear(); 59 60 attribs.append(kCGLPFAColorSize); 61 attribs.append(static_cast<CGLPixelFormatAttribute>(colorBits)); 62 attribs.append(kCGLPFADepthSize); 63 attribs.append(static_cast<CGLPixelFormatAttribute>(depthBits)); 64 65 if (accelerated) 66 attribs.append(kCGLPFAAccelerated); 67 else { 68 attribs.append(kCGLPFARendererID); 69 attribs.append(static_cast<CGLPixelFormatAttribute>(kCGLRendererGenericFloatID)); 70 } 71 72 if (supersample) 73 attribs.append(kCGLPFASupersample); 74 75 if (closest) 76 attribs.append(kCGLPFAClosestPolicy); 77 78 attribs.append(static_cast<CGLPixelFormatAttribute>(0)); 79} 80 81PassRefPtr<GraphicsContext3D> GraphicsContext3D::create(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow, GraphicsContext3D::RenderStyle renderStyle) 82{ 83 // This implementation doesn't currently support rendering directly to the HostWindow. 84 if (renderStyle == RenderDirectlyToHostWindow) 85 return 0; 86 RefPtr<GraphicsContext3D> context = adoptRef(new GraphicsContext3D(attrs, hostWindow, false)); 87 return context->m_contextObj ? context.release() : 0; 88} 89 90GraphicsContext3D::GraphicsContext3D(GraphicsContext3D::Attributes attrs, HostWindow* hostWindow, bool) 91 : m_currentWidth(0) 92 , m_currentHeight(0) 93 , m_contextObj(0) 94 , m_attrs(attrs) 95 , m_texture(0) 96 , m_compositorTexture(0) 97 , m_fbo(0) 98 , m_depthStencilBuffer(0) 99 , m_layerComposited(false) 100 , m_internalColorFormat(0) 101 , m_boundFBO(0) 102 , m_activeTexture(0) 103 , m_boundTexture0(0) 104 , m_multisampleFBO(0) 105 , m_multisampleDepthStencilBuffer(0) 106 , m_multisampleColorBuffer(0) 107{ 108 UNUSED_PARAM(hostWindow); 109 110 Vector<CGLPixelFormatAttribute> attribs; 111 CGLPixelFormatObj pixelFormatObj = 0; 112 GLint numPixelFormats = 0; 113 114 // We will try: 115 // 116 // 1) 32 bit RGBA/32 bit depth/accelerated/supersampled 117 // 2) 32 bit RGBA/32 bit depth/accelerated 118 // 3) 32 bit RGBA/16 bit depth/accelerated 119 // 4) closest to 32 bit RGBA/16 bit depth/software renderer 120 // 121 // If none of that works, we simply fail and set m_contextObj to 0. 122 123 setPixelFormat(attribs, 32, 32, true, true, false); 124 CGLChoosePixelFormat(attribs.data(), &pixelFormatObj, &numPixelFormats); 125 if (numPixelFormats == 0) { 126 setPixelFormat(attribs, 32, 32, true, false, false); 127 CGLChoosePixelFormat(attribs.data(), &pixelFormatObj, &numPixelFormats); 128 129 if (numPixelFormats == 0) { 130 setPixelFormat(attribs, 32, 16, true, false, false); 131 CGLChoosePixelFormat(attribs.data(), &pixelFormatObj, &numPixelFormats); 132 133 if (numPixelFormats == 0) { 134 setPixelFormat(attribs, 32, 16, false, false, true); 135 CGLChoosePixelFormat(attribs.data(), &pixelFormatObj, &numPixelFormats); 136 137 if (numPixelFormats == 0) { 138 // Could not find an acceptable renderer - fail 139 return; 140 } 141 } 142 } 143 } 144 145 CGLError err = CGLCreateContext(pixelFormatObj, 0, &m_contextObj); 146 CGLDestroyPixelFormat(pixelFormatObj); 147 148 if (err != kCGLNoError || !m_contextObj) { 149 // Could not create the context - fail 150 m_contextObj = 0; 151 return; 152 } 153 154 // Set the current context to the one given to us. 155 CGLSetCurrentContext(m_contextObj); 156 157 validateAttributes(); 158 159 // Create the WebGLLayer 160 BEGIN_BLOCK_OBJC_EXCEPTIONS 161 m_webGLLayer.adoptNS([[WebGLLayer alloc] initWithGraphicsContext3D:this]); 162#ifndef NDEBUG 163 [m_webGLLayer.get() setName:@"WebGL Layer"]; 164#endif 165 END_BLOCK_OBJC_EXCEPTIONS 166 167 // create a texture to render into 168 ::glGenTextures(1, &m_texture); 169 ::glBindTexture(GL_TEXTURE_2D, m_texture); 170 ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 171 ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 172 ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); 173 ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); 174 ::glGenTextures(1, &m_compositorTexture); 175 ::glBindTexture(GL_TEXTURE_2D, m_compositorTexture); 176 ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 177 ::glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 178 ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); 179 ::glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); 180 ::glBindTexture(GL_TEXTURE_2D, 0); 181 182 // create an FBO 183 ::glGenFramebuffersEXT(1, &m_fbo); 184 ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_fbo); 185 186 m_boundFBO = m_fbo; 187 if (!m_attrs.antialias && (m_attrs.stencil || m_attrs.depth)) 188 ::glGenRenderbuffersEXT(1, &m_depthStencilBuffer); 189 190 // create an multisample FBO 191 if (m_attrs.antialias) { 192 ::glGenFramebuffersEXT(1, &m_multisampleFBO); 193 ::glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_multisampleFBO); 194 m_boundFBO = m_multisampleFBO; 195 ::glGenRenderbuffersEXT(1, &m_multisampleColorBuffer); 196 if (m_attrs.stencil || m_attrs.depth) 197 ::glGenRenderbuffersEXT(1, &m_multisampleDepthStencilBuffer); 198 } 199 200 // ANGLE initialization. 201 202 ShBuiltInResources ANGLEResources; 203 ShInitBuiltInResources(&ANGLEResources); 204 205 getIntegerv(GraphicsContext3D::MAX_VERTEX_ATTRIBS, &ANGLEResources.MaxVertexAttribs); 206 getIntegerv(GraphicsContext3D::MAX_VERTEX_UNIFORM_VECTORS, &ANGLEResources.MaxVertexUniformVectors); 207 getIntegerv(GraphicsContext3D::MAX_VARYING_VECTORS, &ANGLEResources.MaxVaryingVectors); 208 getIntegerv(GraphicsContext3D::MAX_VERTEX_TEXTURE_IMAGE_UNITS, &ANGLEResources.MaxVertexTextureImageUnits); 209 getIntegerv(GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS, &ANGLEResources.MaxCombinedTextureImageUnits); 210 getIntegerv(GraphicsContext3D::MAX_TEXTURE_IMAGE_UNITS, &ANGLEResources.MaxTextureImageUnits); 211 getIntegerv(GraphicsContext3D::MAX_FRAGMENT_UNIFORM_VECTORS, &ANGLEResources.MaxFragmentUniformVectors); 212 213 // Always set to 1 for OpenGL ES. 214 ANGLEResources.MaxDrawBuffers = 1; 215 216 m_compiler.setResources(ANGLEResources); 217 218 ::glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); 219 ::glEnable(GL_POINT_SPRITE); 220 221 ::glClearColor(0, 0, 0, 0); 222} 223 224GraphicsContext3D::~GraphicsContext3D() 225{ 226 if (m_contextObj) { 227 CGLSetCurrentContext(m_contextObj); 228 ::glDeleteTextures(1, &m_texture); 229 ::glDeleteTextures(1, &m_compositorTexture); 230 if (m_attrs.antialias) { 231 ::glDeleteRenderbuffersEXT(1, &m_multisampleColorBuffer); 232 if (m_attrs.stencil || m_attrs.depth) 233 ::glDeleteRenderbuffersEXT(1, &m_multisampleDepthStencilBuffer); 234 ::glDeleteFramebuffersEXT(1, &m_multisampleFBO); 235 } else { 236 if (m_attrs.stencil || m_attrs.depth) 237 ::glDeleteRenderbuffersEXT(1, &m_depthStencilBuffer); 238 } 239 ::glDeleteFramebuffersEXT(1, &m_fbo); 240 CGLSetCurrentContext(0); 241 CGLDestroyContext(m_contextObj); 242 } 243} 244 245void GraphicsContext3D::makeContextCurrent() 246{ 247 if (!m_contextObj) 248 return; 249 250 CGLContextObj currentContext = CGLGetCurrentContext(); 251 if (currentContext != m_contextObj) 252 CGLSetCurrentContext(m_contextObj); 253} 254 255bool GraphicsContext3D::isGLES2Compliant() const 256{ 257 return false; 258} 259 260void GraphicsContext3D::setContextLostCallback(PassOwnPtr<ContextLostCallback>) 261{ 262} 263 264} 265 266#endif // ENABLE(WEBGL) 267