OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2011 Apple Inc. All rights reserved. | 2 * Copyright (C) 2011 Apple Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
11 * documentation and/or other materials provided with the distribution. | 11 * documentation and/or other materials provided with the distribution. |
12 * | 12 * |
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY | 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY |
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR | 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR |
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 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. | 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
24 */ | 24 */ |
25 | 25 |
26 #include "config.h" | 26 #include "config.h" |
27 | 27 |
28 #include "core/html/canvas/WebGLSharedObject.h" | 28 #include "core/html/canvas/WebGLSharedObject.h" |
29 | 29 |
30 #include "core/html/canvas/WebGLAcquireSharedResourceCallback.h" | |
30 #include "core/html/canvas/WebGLContextGroup.h" | 31 #include "core/html/canvas/WebGLContextGroup.h" |
31 #include "core/html/canvas/WebGLRenderingContext.h" | 32 #include "core/html/canvas/WebGLRenderingContext.h" |
32 | 33 |
33 namespace WebCore { | 34 namespace WebCore { |
34 | 35 |
36 bool WebGLSharedObject::IntToAcquireMode(unsigned value, AcquireMode* mode) | |
37 { | |
38 switch (value) { | |
39 case 0: | |
40 *mode = WebGLSharedObject::Unacquired; | |
41 return true; | |
42 case 1: | |
43 *mode = WebGLSharedObject::ReadOnly; | |
44 return true; | |
45 case 4: | |
Ken Russell (switch to Gerrit)
2013/06/19 03:51:24
Should these ints come from WebGLSharedResources.h
greggman
2013/06/21 19:54:21
Done.
| |
46 *mode = WebGLSharedObject::Exclusive; | |
47 return true; | |
48 default: | |
49 return false; | |
50 } | |
51 } | |
52 | |
35 WebGLSharedObject::WebGLSharedObject(WebGLRenderingContext* context) | 53 WebGLSharedObject::WebGLSharedObject(WebGLRenderingContext* context) |
36 : WebGLObject(context), | 54 : WebGLObject(context) |
37 m_contextGroup(context->contextGroup()) | 55 , m_contextGroup(context->contextGroup()) |
56 , m_acquireMode(WebGLSharedObject::Unacquired) | |
38 { | 57 { |
58 acquire(WebGLSharedObject::Exclusive, context); | |
Ken Russell (switch to Gerrit)
2013/06/19 03:51:24
Should there be an ASSERT on the result of this ca
greggman
2013/06/21 19:54:21
Done.
| |
59 | |
60 // We need to mark shaders and programs as bound as there is no way to easy way to bind/attach them. | |
61 markAsBoundSinceLastAcquireForContext(context); | |
39 } | 62 } |
40 | 63 |
41 WebGLSharedObject::~WebGLSharedObject() | 64 WebGLSharedObject::~WebGLSharedObject() |
42 { | 65 { |
43 if (m_contextGroup) | 66 if (m_contextGroup) { |
44 m_contextGroup->removeObject(this); | 67 m_contextGroup->removeObject(this); |
68 } | |
45 } | 69 } |
46 | 70 |
47 void WebGLSharedObject::detachContextGroup() | 71 void WebGLSharedObject::detachContextGroup() |
48 { | 72 { |
49 detach(); | 73 detach(); |
50 if (m_contextGroup) { | 74 if (m_contextGroup) { |
51 deleteObject(0); | 75 deleteObject(0); |
52 m_contextGroup->removeObject(this); | 76 m_contextGroup->removeObject(this); |
53 m_contextGroup = 0; | 77 m_contextGroup = 0; |
54 } | 78 } |
55 } | 79 } |
56 | 80 |
57 GraphicsContext3D* WebGLSharedObject::getAGraphicsContext3D() const | 81 GraphicsContext3D* WebGLSharedObject::getAGraphicsContext3D() const |
58 { | 82 { |
59 return m_contextGroup ? m_contextGroup->getAGraphicsContext3D() : 0; | 83 return m_contextGroup ? m_contextGroup->getAGraphicsContext3D() : 0; |
60 } | 84 } |
61 | 85 |
62 } | 86 bool WebGLSharedObject::isAcquiredForContext(const WebGLRenderingContext* contex t, WebGLSharedObject::AcquireMode neededMode, bool mustBeBoundSinceLastAcquire, bool* hasBeenBoundSinceLastAcquire, const char** reason) const |
87 { | |
88 AcquireContextMap::const_iterator it = m_acquireContextMap.find(context); | |
89 if (it == m_acquireContextMap.end()) { | |
90 *reason = " not acquired in this context"; | |
91 return false; | |
92 } | |
93 | |
94 bool sameMode = m_acquireMode == neededMode; | |
95 bool validCombo = m_acquireMode == WebGLSharedObject::Exclusive && neededMod e == WebGLSharedObject::ReadOnly; | |
96 if (!sameMode && !validCombo) { | |
97 *reason = " not acquired for exclusive access"; | |
98 return false; | |
99 } | |
100 | |
101 if (mustBeBoundSinceLastAcquire && !it->value) { | |
102 *reason = " has not been bound since last acquired"; | |
103 return false; | |
104 } | |
105 | |
106 if (hasBeenBoundSinceLastAcquire) { | |
107 *hasBeenBoundSinceLastAcquire = it->value; | |
108 } | |
109 | |
110 return true; | |
111 } | |
112 | |
113 bool WebGLSharedObject::validate(const char* functionName, WebGLRenderingContext * context, WebGLSharedObject::AcquireMode neededMode, bool mustBeBoundSinceLastA cquire, bool* boundSinceLastAcquire) const | |
114 { | |
115 if (context->contextGroup() != m_contextGroup) { | |
116 String msg(String(typeName()) + " not from this share group"); | |
117 context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functio nName, msg.utf8().data()); | |
118 return false; | |
119 } | |
120 | |
121 const char* reason; | |
122 if (!isAcquiredForContext(context, neededMode, mustBeBoundSinceLastAcquire, boundSinceLastAcquire, &reason)) { | |
123 String msg(String(typeName()) + reason); | |
124 context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functio nName, msg.utf8().data()); | |
125 return false; | |
126 } | |
127 | |
128 return true; | |
129 } | |
130 | |
131 void WebGLSharedObject::markAsBoundSinceLastAcquireForContext(const WebGLRenderi ngContext* context) | |
132 { | |
133 AcquireContextMap::iterator it = m_acquireContextMap.find(context); | |
134 ASSERT(it != m_acquireContextMap.end()); | |
135 it->value = true; | |
136 } | |
137 | |
138 bool WebGLSharedObject::acquire(WebGLSharedObject::AcquireMode desiredMode, cons t WebGLRenderingContext* context) | |
139 { | |
140 AcquireContextMap::const_iterator it = m_acquireContextMap.find(context); | |
141 if (it != m_acquireContextMap.end()) { | |
142 // How can I get here? | |
143 return false; | |
144 } | |
145 | |
146 bool unacquired = m_acquireMode == WebGLSharedObject::Unacquired; | |
147 bool bothReadOnly = m_acquireMode == WebGLSharedObject::ReadOnly && desiredM ode == WebGLSharedObject::ReadOnly; | |
148 if (!unacquired && !bothReadOnly) { | |
149 return false; | |
150 } | |
151 | |
152 // Note: The resource is acquired at this point. The user may still cancel | |
153 // the request though before it the acquire callback is fired. If it is | |
154 // cancelled the cancel acts as a call to release. | |
155 m_acquireMode = desiredMode; | |
156 m_acquireContextMap.add(context, false); | |
157 return true; | |
158 } | |
159 | |
160 bool WebGLSharedObject::addAcquireRequest(WebGLRenderingContext* context, WebGLS haredObject::AcquireMode desiredMode, PassRefPtr<WebGLAcquireSharedResourceCallb ack> callback, long& id) | |
161 { | |
162 switch (desiredMode) { | |
163 case WebGLSharedObject::ReadOnly: | |
164 case WebGLSharedObject::Exclusive: | |
165 break; | |
166 default: | |
167 context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "acquireShar edResource", "mode is not READ_ONLY or EXCLUSIVE"); | |
168 return false; | |
169 } | |
170 | |
171 // Checks the object belonngs to this group. | |
Ken Russell (switch to Gerrit)
2013/06/19 03:51:24
Typo: belonngs
greggman
2013/06/21 19:54:21
Done.
| |
172 if (context->contextGroup() != m_contextGroup) { | |
173 context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "acquir eSharedResource", "object is not from this ShareGroup"); | |
174 return false; | |
175 } | |
176 | |
177 // Checks it is not already acquired by this context. | |
178 AcquireContextMap::iterator it = m_acquireContextMap.find(context); | |
179 if (it != m_acquireContextMap.end()) { | |
180 context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "acquir eSharedResource", "object is already acquired in this context"); | |
181 return false; | |
182 } | |
183 | |
184 // Checks it is not already in one of the queues. | |
185 if (isRequestPending(context)) { | |
186 context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "acquir eSharedResource", "request to acquire this object is already pending in this con text"); | |
187 return false; | |
188 } | |
189 | |
190 // Adds the request. | |
191 m_acquireRequestQueue.append(WebGLAcquireSharedResourceRequest::create(this, callback, desiredMode, context, m_contextGroup->generateAcquireRequestId())); | |
192 processAcquireRequests(); | |
193 return true; | |
194 } | |
195 | |
196 bool WebGLSharedObject::release(WebGLRenderingContext* context) | |
197 { | |
198 AcquireContextMap::iterator it = m_acquireContextMap.find(context); | |
199 if (it == m_acquireContextMap.end()) { | |
200 return false; | |
201 } | |
202 | |
203 m_acquireContextMap.remove(it); | |
204 if (m_acquireContextMap.isEmpty()) { | |
205 if (m_acquireMode == WebGLSharedObject::Exclusive) { | |
206 // TODO: Use flush if on top of virtual contexts (maybe we should ha ve an extension GL_CHROMIUM_flush_sync to mark that only flush is needed) | |
207 // Use sync objects/fences if available. | |
208 // Use glFinish otherwise. | |
209 context->flush(); // Using flush for now. So far only certain Androi d devices need a finish. | |
210 } | |
211 m_acquireMode = WebGLSharedObject::Unacquired; | |
212 processAcquireRequests(); | |
213 } | |
214 | |
215 return true; | |
216 } | |
217 | |
218 void WebGLSharedObject::processAcquireRequests() | |
219 { | |
220 // Queue all the events that could succeed right now. | |
221 while (!m_acquireRequestQueue.isEmpty()) { | |
222 RefPtr<WebGLAcquireSharedResourceRequest> request = m_acquireRequestQueu e.first(); | |
223 if (!acquire(request->acquireMode(), request->context())) { | |
224 break; | |
225 } | |
226 | |
227 m_acquireRequestQueue.removeFirst(); | |
228 m_acquireRequestPostedList.append(request); | |
229 | |
230 // queue event | |
231 ScriptExecutionContext* scriptExecutionContext = request->context()->scr iptExecutionContext(); | |
232 if (scriptExecutionContext) { | |
233 scriptExecutionContext->postTask(adoptPtr(new DispatchCallbackTask(r equest))); | |
234 } | |
Ken Russell (switch to Gerrit)
2013/06/19 03:51:24
Are there any race conditions with these acquire c
| |
235 } | |
236 } | |
237 | |
238 bool WebGLSharedObject::isRequestPending(const WebGLRenderingContext* context) | |
239 { | |
240 for (AcquireRequestQueue::iterator it = m_acquireRequestQueue.begin(); it != m_acquireRequestQueue.end(); ++it) { | |
241 if ((*it)->context() == context) { | |
242 return true; | |
243 } | |
244 } | |
245 for (AcquireRequestList::iterator it = m_acquireRequestPostedList.begin(); i t != m_acquireRequestPostedList.end(); ++it) { | |
246 if ((*it)->context() == context) { | |
247 return true; | |
248 } | |
249 } | |
250 return false; | |
251 } | |
252 | |
253 bool WebGLSharedObject::cancelAcquireRequest(const WebGLRenderingContext* contex t, long id) | |
254 { | |
255 for (AcquireRequestQueue::iterator it = m_acquireRequestQueue.begin(); it != m_acquireRequestQueue.end(); ++it) { | |
256 if ((*it)->id() == id) { | |
257 // Only remove it if it's from this context. | |
258 if ((*it)->context() == context) { | |
259 (*it)->cancel(); | |
260 m_acquireRequestQueue.remove(it); | |
261 processAcquireRequests(); | |
262 } | |
263 return true; | |
264 } | |
265 } | |
266 for (AcquireRequestList::iterator it = m_acquireRequestPostedList.begin(); i t != m_acquireRequestPostedList.end(); ++it) { | |
267 if ((*it)->id() == id) { | |
268 // Only remove it if it's from this context. | |
269 if ((*it)->context() == context) { | |
270 (*it)->cancel(); | |
271 m_acquireRequestPostedList.remove(it); | |
272 processAcquireRequests(); | |
273 } | |
274 return true; | |
275 } | |
276 } | |
277 return false; | |
278 } | |
279 | |
280 void WebGLSharedObject::removePostedAcquireRequest(const WebGLRenderingContext* context, long id) | |
281 { | |
282 for (AcquireRequestList::iterator it = m_acquireRequestPostedList.begin(); i t != m_acquireRequestPostedList.end(); ++it) { | |
283 if ((*it)->id() == id) { | |
284 ASSERT((*it)->context() == context); | |
285 m_acquireRequestPostedList.remove(it); | |
286 return; | |
287 } | |
288 } | |
289 ASSERT(false); // should never get here. | |
290 } | |
291 | |
292 WebGLSharedObject::DispatchCallbackTask::~DispatchCallbackTask() | |
293 { | |
294 } | |
295 | |
296 void WebGLSharedObject::DispatchCallbackTask::performTask(ScriptExecutionContext *) | |
297 { | |
298 m_request->run(); | |
299 } | |
300 | |
301 WebGLAcquireSharedResourceRequest::WebGLAcquireSharedResourceRequest(PassRefPtr< WebGLSharedObject> sharedObject, PassRefPtr<WebGLAcquireSharedResourceCallback> callback, WebGLSharedObject::AcquireMode acquireMode, WebGLRenderingContext* con text, long id) | |
302 : m_sharedObject(sharedObject) | |
303 , m_context(context) | |
304 , m_id(id) | |
305 , m_acquireMode(acquireMode) | |
306 , m_callback(callback) | |
307 { | |
308 } | |
309 | |
310 WebGLAcquireSharedResourceRequest::~WebGLAcquireSharedResourceRequest() | |
311 { | |
312 } | |
313 | |
314 PassRefPtr<WebGLAcquireSharedResourceRequest> WebGLAcquireSharedResourceRequest: :create(PassRefPtr<WebGLSharedObject> sharedObject, PassRefPtr<WebGLAcquireShare dResourceCallback> callback, WebGLSharedObject::AcquireMode acquireMode, WebGLRe nderingContext* context, long id) | |
315 { | |
316 return adoptRef(new WebGLAcquireSharedResourceRequest(sharedObject, callback , acquireMode, context, id)); | |
317 } | |
318 | |
319 void WebGLAcquireSharedResourceRequest::cancel() | |
320 { | |
321 m_acquireMode = WebGLSharedObject::Unacquired; | |
322 m_callback.clear(); | |
323 } | |
324 | |
325 void WebGLAcquireSharedResourceRequest::run() | |
326 { | |
327 if (m_callback) { | |
328 RefPtr<WebGLAcquireSharedResourceRequest> self(this); // Need to keep a reference to ourselves as the next line may remove our last reference. | |
329 m_sharedObject->removePostedAcquireRequest(context(), id()); | |
330 m_callback->handleEvent(m_sharedObject.get()); | |
331 m_callback.clear(); | |
332 } | |
333 } | |
334 | |
335 } // namespace WebCore | |
336 | |
OLD | NEW |