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