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
create(WebGLRenderingContextBase * ctx)34 PassRefPtr<WebGLProgram> WebGLProgram::create(WebGLRenderingContextBase* ctx)
35 {
36 return adoptRef(new WebGLProgram(ctx));
37 }
38
WebGLProgram(WebGLRenderingContextBase * ctx)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
~WebGLProgram()49 WebGLProgram::~WebGLProgram()
50 {
51 deleteObject(0);
52 }
53
deleteObjectImpl(blink::WebGraphicsContext3D * context3d,Platform3DObject obj)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
numActiveAttribLocations()67 unsigned WebGLProgram::numActiveAttribLocations()
68 {
69 cacheInfoIfNeeded();
70 return m_activeAttribLocations.size();
71 }
72
getActiveAttribLocation(GLuint index)73 GLint WebGLProgram::getActiveAttribLocation(GLuint index)
74 {
75 cacheInfoIfNeeded();
76 if (index >= numActiveAttribLocations())
77 return -1;
78 return m_activeAttribLocations[index];
79 }
80
isUsingVertexAttrib0()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
linkStatus()91 bool WebGLProgram::linkStatus()
92 {
93 cacheInfoIfNeeded();
94 return m_linkStatus;
95 }
96
increaseLinkCount()97 void WebGLProgram::increaseLinkCount()
98 {
99 ++m_linkCount;
100 m_infoValid = false;
101 }
102
getAttachedShader(GLenum type)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
attachShader(WebGLShader * shader)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
detachShader(WebGLShader * shader)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
cacheActiveAttribLocations(blink::WebGraphicsContext3D * context3d)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
cacheInfoIfNeeded()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