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