Home | History | Annotate | Download | only in mac
      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 
     54 namespace WebCore {
     55 
     56 static 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 
     81 PassRefPtr<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 
     90 GraphicsContext3D::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 
    224 GraphicsContext3D::~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 
    245 void 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 
    255 bool GraphicsContext3D::isGLES2Compliant() const
    256 {
    257     return false;
    258 }
    259 
    260 void GraphicsContext3D::setContextLostCallback(PassOwnPtr<ContextLostCallback>)
    261 {
    262 }
    263 
    264 }
    265 
    266 #endif // ENABLE(WEBGL)
    267