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