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::linkStatus() 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 GL_VERTEX_SHADER: 113 return m_vertexShader.get(); 114 case GL_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->type()) { 126 case GL_VERTEX_SHADER: 127 if (m_vertexShader) 128 return false; 129 m_vertexShader = shader; 130 return true; 131 case GL_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->type()) { 146 case GL_VERTEX_SHADER: 147 if (m_vertexShader != shader) 148 return false; 149 m_vertexShader = 0; 150 return true; 151 case GL_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(), GL_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(), GL_LINK_STATUS, &linkStatus); 188 m_linkStatus = linkStatus; 189 if (m_linkStatus) 190 cacheActiveAttribLocations(context); 191 m_infoValid = true; 192 } 193 194 } 195