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