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/WebGLRenderingContext.h"
     31 
     32 namespace WebCore {
     33 
     34 PassRefPtr<WebGLProgram> WebGLProgram::create(WebGLRenderingContext* ctx)
     35 {
     36     return adoptRef(new WebGLProgram(ctx));
     37 }
     38 
     39 WebGLProgram::WebGLProgram(WebGLRenderingContext* ctx)
     40     : WebGLSharedObject(ctx)
     41     , m_linkStatus(false)
     42     , m_linkCount(0)
     43     , m_infoValid(true)
     44 {
     45     ScriptWrappable::init(this);
     46     setObject(ctx->graphicsContext3D()->createProgram());
     47 }
     48 
     49 WebGLProgram::~WebGLProgram()
     50 {
     51     deleteObject(0);
     52 }
     53 
     54 void WebGLProgram::deleteObjectImpl(GraphicsContext3D* context3d, Platform3DObject obj)
     55 {
     56     context3d->deleteProgram(obj);
     57     if (m_vertexShader) {
     58         m_vertexShader->onDetached(context3d);
     59         m_vertexShader = 0;
     60     }
     61     if (m_fragmentShader) {
     62         m_fragmentShader->onDetached(context3d);
     63         m_fragmentShader = 0;
     64     }
     65 }
     66 
     67 unsigned WebGLProgram::numActiveAttribLocations()
     68 {
     69     cacheInfoIfNeeded();
     70     return m_activeAttribLocations.size();
     71 }
     72 
     73 GC3Dint WebGLProgram::getActiveAttribLocation(GC3Duint index)
     74 {
     75     cacheInfoIfNeeded();
     76     if (index >= numActiveAttribLocations())
     77         return -1;
     78     return m_activeAttribLocations[index];
     79 }
     80 
     81 bool WebGLProgram::isUsingVertexAttrib0()
     82 {
     83     cacheInfoIfNeeded();
     84     for (unsigned ii = 0; ii < numActiveAttribLocations(); ++ii) {
     85         if (!getActiveAttribLocation(ii))
     86             return true;
     87     }
     88     return false;
     89 }
     90 
     91 bool WebGLProgram::getLinkStatus()
     92 {
     93     cacheInfoIfNeeded();
     94     return m_linkStatus;
     95 }
     96 
     97 void WebGLProgram::setLinkStatus(bool status)
     98 {
     99     cacheInfoIfNeeded();
    100     m_linkStatus = status;
    101 }
    102 
    103 void WebGLProgram::increaseLinkCount()
    104 {
    105     ++m_linkCount;
    106     m_infoValid = false;
    107 }
    108 
    109 WebGLShader* WebGLProgram::getAttachedShader(GC3Denum type)
    110 {
    111     switch (type) {
    112     case GraphicsContext3D::VERTEX_SHADER:
    113         return m_vertexShader.get();
    114     case GraphicsContext3D::FRAGMENT_SHADER:
    115         return m_fragmentShader.get();
    116     default:
    117         return 0;
    118     }
    119 }
    120 
    121 bool WebGLProgram::attachShader(WebGLShader* shader)
    122 {
    123     if (!shader || !shader->object())
    124         return false;
    125     switch (shader->getType()) {
    126     case GraphicsContext3D::VERTEX_SHADER:
    127         if (m_vertexShader)
    128             return false;
    129         m_vertexShader = shader;
    130         return true;
    131     case GraphicsContext3D::FRAGMENT_SHADER:
    132         if (m_fragmentShader)
    133             return false;
    134         m_fragmentShader = shader;
    135         return true;
    136     default:
    137         return false;
    138     }
    139 }
    140 
    141 bool WebGLProgram::detachShader(WebGLShader* shader)
    142 {
    143     if (!shader || !shader->object())
    144         return false;
    145     switch (shader->getType()) {
    146     case GraphicsContext3D::VERTEX_SHADER:
    147         if (m_vertexShader != shader)
    148             return false;
    149         m_vertexShader = 0;
    150         return true;
    151     case GraphicsContext3D::FRAGMENT_SHADER:
    152         if (m_fragmentShader != shader)
    153             return false;
    154         m_fragmentShader = 0;
    155         return true;
    156     default:
    157         return false;
    158     }
    159 }
    160 
    161 void WebGLProgram::cacheActiveAttribLocations(GraphicsContext3D* context3d)
    162 {
    163     m_activeAttribLocations.clear();
    164 
    165     GC3Dint numAttribs = 0;
    166     context3d->getProgramiv(object(), GraphicsContext3D::ACTIVE_ATTRIBUTES, &numAttribs);
    167     m_activeAttribLocations.resize(static_cast<size_t>(numAttribs));
    168     for (int i = 0; i < numAttribs; ++i) {
    169         ActiveInfo info;
    170         context3d->getActiveAttrib(object(), i, info);
    171         m_activeAttribLocations[i] = context3d->getAttribLocation(object(), info.name);
    172     }
    173 }
    174 
    175 void WebGLProgram::cacheInfoIfNeeded()
    176 {
    177     if (m_infoValid)
    178         return;
    179 
    180     if (!object())
    181         return;
    182 
    183     GraphicsContext3D* context = getAGraphicsContext3D();
    184     if (!context)
    185         return;
    186     GC3Dint linkStatus = 0;
    187     context->getProgramiv(object(), GraphicsContext3D::LINK_STATUS, &linkStatus);
    188     m_linkStatus = linkStatus;
    189     if (m_linkStatus)
    190         cacheActiveAttribLocations(context);
    191     m_infoValid = true;
    192 }
    193 
    194 }
    195