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/WebGLRenderingContextBase.h" 31 32 namespace WebCore { 33 34 PassRefPtr<WebGLProgram> WebGLProgram::create(WebGLRenderingContextBase* ctx) 35 { 36 return adoptRef(new WebGLProgram(ctx)); 37 } 38 39 WebGLProgram::WebGLProgram(WebGLRenderingContextBase* ctx) 40 : WebGLSharedObject(ctx) 41 , m_linkStatus(false) 42 , m_linkCount(0) 43 , m_infoValid(true) 44 { 45 ScriptWrappable::init(this); 46 setObject(ctx->webContext()->createProgram()); 47 } 48 49 WebGLProgram::~WebGLProgram() 50 { 51 deleteObject(0); 52 } 53 54 void WebGLProgram::deleteObjectImpl(blink::WebGraphicsContext3D* context3d, Platform3DObject obj) 55 { 56 context3d->deleteProgram(obj); 57 if (m_vertexShader) { 58 m_vertexShader->onDetached(context3d); 59 m_vertexShader = nullptr; 60 } 61 if (m_fragmentShader) { 62 m_fragmentShader->onDetached(context3d); 63 m_fragmentShader = nullptr; 64 } 65 } 66 67 unsigned WebGLProgram::numActiveAttribLocations() 68 { 69 cacheInfoIfNeeded(); 70 return m_activeAttribLocations.size(); 71 } 72 73 GLint WebGLProgram::getActiveAttribLocation(GLuint 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::increaseLinkCount() 98 { 99 ++m_linkCount; 100 m_infoValid = false; 101 } 102 103 WebGLShader* WebGLProgram::getAttachedShader(GLenum type) 104 { 105 switch (type) { 106 case GL_VERTEX_SHADER: 107 return m_vertexShader.get(); 108 case GL_FRAGMENT_SHADER: 109 return m_fragmentShader.get(); 110 default: 111 return 0; 112 } 113 } 114 115 bool WebGLProgram::attachShader(WebGLShader* shader) 116 { 117 if (!shader || !shader->object()) 118 return false; 119 switch (shader->type()) { 120 case GL_VERTEX_SHADER: 121 if (m_vertexShader) 122 return false; 123 m_vertexShader = shader; 124 return true; 125 case GL_FRAGMENT_SHADER: 126 if (m_fragmentShader) 127 return false; 128 m_fragmentShader = shader; 129 return true; 130 default: 131 return false; 132 } 133 } 134 135 bool WebGLProgram::detachShader(WebGLShader* shader) 136 { 137 if (!shader || !shader->object()) 138 return false; 139 switch (shader->type()) { 140 case GL_VERTEX_SHADER: 141 if (m_vertexShader != shader) 142 return false; 143 m_vertexShader = nullptr; 144 return true; 145 case GL_FRAGMENT_SHADER: 146 if (m_fragmentShader != shader) 147 return false; 148 m_fragmentShader = nullptr; 149 return true; 150 default: 151 return false; 152 } 153 } 154 155 void WebGLProgram::cacheActiveAttribLocations(blink::WebGraphicsContext3D* context3d) 156 { 157 m_activeAttribLocations.clear(); 158 159 GLint numAttribs = 0; 160 context3d->getProgramiv(object(), GL_ACTIVE_ATTRIBUTES, &numAttribs); 161 m_activeAttribLocations.resize(static_cast<size_t>(numAttribs)); 162 for (int i = 0; i < numAttribs; ++i) { 163 blink::WebGraphicsContext3D::ActiveInfo info; 164 context3d->getActiveAttrib(object(), i, info); 165 m_activeAttribLocations[i] = context3d->getAttribLocation(object(), info.name.utf8().data()); 166 } 167 } 168 169 void WebGLProgram::cacheInfoIfNeeded() 170 { 171 if (m_infoValid) 172 return; 173 174 if (!object()) 175 return; 176 177 blink::WebGraphicsContext3D* context = getAWebGraphicsContext3D(); 178 if (!context) 179 return; 180 GLint linkStatus = 0; 181 context->getProgramiv(object(), GL_LINK_STATUS, &linkStatus); 182 m_linkStatus = linkStatus; 183 if (m_linkStatus) 184 cacheActiveAttribLocations(context); 185 m_infoValid = true; 186 } 187 188 } 189