Home | History | Annotate | Download | only in canvas
      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 #include "core/html/canvas/WebGLProgram.h"
     29 
     30 #include "core/html/canvas/WebGLContextGroup.h"
     31 #include "core/html/canvas/WebGLRenderingContextBase.h"
     32 
     33 namespace blink {
     34 
     35 PassRefPtrWillBeRawPtr<WebGLProgram> WebGLProgram::create(WebGLRenderingContextBase* ctx)
     36 {
     37     return adoptRefWillBeNoop(new WebGLProgram(ctx));
     38 }
     39 
     40 WebGLProgram::WebGLProgram(WebGLRenderingContextBase* ctx)
     41     : WebGLSharedObject(ctx)
     42     , m_linkStatus(false)
     43     , m_linkCount(0)
     44     , m_infoValid(true)
     45 {
     46     setObject(ctx->webContext()->createProgram());
     47 }
     48 
     49 WebGLProgram::~WebGLProgram()
     50 {
     51 #if ENABLE(OILPAN)
     52     // These heap objects handle detachment on their own. Clear out
     53     // the references to prevent deleteObjectImpl() from trying to do
     54     // same, as we cannot safely access other heap objects from this
     55     // destructor.
     56     m_vertexShader = nullptr;
     57     m_fragmentShader = nullptr;
     58 #endif
     59     // Always call detach here to ensure that platform object deletion
     60     // happens with Oilpan enabled. It keeps the code regular to do it
     61     // with or without Oilpan enabled.
     62     //
     63     // See comment in WebGLBuffer's destructor for additional
     64     // information on why this is done for WebGLSharedObject-derived
     65     // objects.
     66     detachAndDeleteObject();
     67 }
     68 
     69 void WebGLProgram::deleteObjectImpl(blink::WebGraphicsContext3D* context3d, Platform3DObject obj)
     70 {
     71     context3d->deleteProgram(obj);
     72     if (m_vertexShader) {
     73         m_vertexShader->onDetached(context3d);
     74         m_vertexShader = nullptr;
     75     }
     76     if (m_fragmentShader) {
     77         m_fragmentShader->onDetached(context3d);
     78         m_fragmentShader = nullptr;
     79     }
     80 }
     81 
     82 unsigned WebGLProgram::numActiveAttribLocations()
     83 {
     84     cacheInfoIfNeeded();
     85     return m_activeAttribLocations.size();
     86 }
     87 
     88 GLint WebGLProgram::getActiveAttribLocation(GLuint index)
     89 {
     90     cacheInfoIfNeeded();
     91     if (index >= numActiveAttribLocations())
     92         return -1;
     93     return m_activeAttribLocations[index];
     94 }
     95 
     96 bool WebGLProgram::isUsingVertexAttrib0()
     97 {
     98     cacheInfoIfNeeded();
     99     for (unsigned ii = 0; ii < numActiveAttribLocations(); ++ii) {
    100         if (!getActiveAttribLocation(ii))
    101             return true;
    102     }
    103     return false;
    104 }
    105 
    106 bool WebGLProgram::linkStatus()
    107 {
    108     cacheInfoIfNeeded();
    109     return m_linkStatus;
    110 }
    111 
    112 void WebGLProgram::increaseLinkCount()
    113 {
    114     ++m_linkCount;
    115     m_infoValid = false;
    116 }
    117 
    118 WebGLShader* WebGLProgram::getAttachedShader(GLenum type)
    119 {
    120     switch (type) {
    121     case GL_VERTEX_SHADER:
    122         return m_vertexShader.get();
    123     case GL_FRAGMENT_SHADER:
    124         return m_fragmentShader.get();
    125     default:
    126         return 0;
    127     }
    128 }
    129 
    130 bool WebGLProgram::attachShader(WebGLShader* shader)
    131 {
    132     if (!shader || !shader->object())
    133         return false;
    134     switch (shader->type()) {
    135     case GL_VERTEX_SHADER:
    136         if (m_vertexShader)
    137             return false;
    138         m_vertexShader = shader;
    139         return true;
    140     case GL_FRAGMENT_SHADER:
    141         if (m_fragmentShader)
    142             return false;
    143         m_fragmentShader = shader;
    144         return true;
    145     default:
    146         return false;
    147     }
    148 }
    149 
    150 bool WebGLProgram::detachShader(WebGLShader* shader)
    151 {
    152     if (!shader || !shader->object())
    153         return false;
    154     switch (shader->type()) {
    155     case GL_VERTEX_SHADER:
    156         if (m_vertexShader != shader)
    157             return false;
    158         m_vertexShader = nullptr;
    159         return true;
    160     case GL_FRAGMENT_SHADER:
    161         if (m_fragmentShader != shader)
    162             return false;
    163         m_fragmentShader = nullptr;
    164         return true;
    165     default:
    166         return false;
    167     }
    168 }
    169 
    170 void WebGLProgram::cacheActiveAttribLocations(blink::WebGraphicsContext3D* context3d)
    171 {
    172     m_activeAttribLocations.clear();
    173 
    174     GLint numAttribs = 0;
    175     context3d->getProgramiv(object(), GL_ACTIVE_ATTRIBUTES, &numAttribs);
    176     m_activeAttribLocations.resize(static_cast<size_t>(numAttribs));
    177     for (int i = 0; i < numAttribs; ++i) {
    178         blink::WebGraphicsContext3D::ActiveInfo info;
    179         context3d->getActiveAttrib(object(), i, info);
    180         m_activeAttribLocations[i] = context3d->getAttribLocation(object(), info.name.utf8().data());
    181     }
    182 }
    183 
    184 void WebGLProgram::cacheInfoIfNeeded()
    185 {
    186     if (m_infoValid)
    187         return;
    188 
    189     if (!object())
    190         return;
    191 
    192     if (!contextGroup())
    193         return;
    194     blink::WebGraphicsContext3D* context = contextGroup()->getAWebGraphicsContext3D();
    195     if (!context)
    196         return;
    197     GLint linkStatus = 0;
    198     context->getProgramiv(object(), GL_LINK_STATUS, &linkStatus);
    199     m_linkStatus = linkStatus;
    200     if (m_linkStatus)
    201         cacheActiveAttribLocations(context);
    202     m_infoValid = true;
    203 }
    204 
    205 void WebGLProgram::trace(Visitor* visitor)
    206 {
    207     visitor->trace(m_vertexShader);
    208     visitor->trace(m_fragmentShader);
    209     WebGLSharedObject::trace(visitor);
    210 }
    211 
    212 }
    213