6ba381a9dfe5cf82bb165259db1ba8dae3dfcbb2
[WebKit-https.git] / Source / WebCore / html / canvas / WebGLProgram.cpp
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)