Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(825)

Unified Diff: Source/core/html/canvas/WebGLSharedObject.cpp

Issue 17230006: Implement WEBGL_shared_resources Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: Source/core/html/canvas/WebGLSharedObject.cpp
diff --git a/Source/core/html/canvas/WebGLSharedObject.cpp b/Source/core/html/canvas/WebGLSharedObject.cpp
index f5d63651ff51b90d8b53a0cebd5009cb176f1560..2c29c8298b200fc067e03c266a2bdfa80806d595 100644
--- a/Source/core/html/canvas/WebGLSharedObject.cpp
+++ b/Source/core/html/canvas/WebGLSharedObject.cpp
@@ -27,21 +27,45 @@
#include "core/html/canvas/WebGLSharedObject.h"
+#include "core/html/canvas/WebGLAcquireSharedResourceCallback.h"
#include "core/html/canvas/WebGLContextGroup.h"
#include "core/html/canvas/WebGLRenderingContext.h"
namespace WebCore {
+bool WebGLSharedObject::IntToAcquireMode(unsigned value, AcquireMode* mode)
+{
+ switch (value) {
+ case 0:
+ *mode = WebGLSharedObject::Unacquired;
+ return true;
+ case 1:
+ *mode = WebGLSharedObject::ReadOnly;
+ return true;
+ 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.
+ *mode = WebGLSharedObject::Exclusive;
+ return true;
+ default:
+ return false;
+ }
+}
+
WebGLSharedObject::WebGLSharedObject(WebGLRenderingContext* context)
- : WebGLObject(context),
- m_contextGroup(context->contextGroup())
+ : WebGLObject(context)
+ , m_contextGroup(context->contextGroup())
+ , m_acquireMode(WebGLSharedObject::Unacquired)
{
+ 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.
+
+ // We need to mark shaders and programs as bound as there is no way to easy way to bind/attach them.
+ markAsBoundSinceLastAcquireForContext(context);
}
WebGLSharedObject::~WebGLSharedObject()
{
- if (m_contextGroup)
+ if (m_contextGroup) {
m_contextGroup->removeObject(this);
+ }
}
void WebGLSharedObject::detachContextGroup()
@@ -59,4 +83,254 @@ GraphicsContext3D* WebGLSharedObject::getAGraphicsContext3D() const
return m_contextGroup ? m_contextGroup->getAGraphicsContext3D() : 0;
}
+bool WebGLSharedObject::isAcquiredForContext(const WebGLRenderingContext* context, WebGLSharedObject::AcquireMode neededMode, bool mustBeBoundSinceLastAcquire, bool* hasBeenBoundSinceLastAcquire, const char** reason) const
+{
+ AcquireContextMap::const_iterator it = m_acquireContextMap.find(context);
+ if (it == m_acquireContextMap.end()) {
+ *reason = " not acquired in this context";
+ return false;
+ }
+
+ bool sameMode = m_acquireMode == neededMode;
+ bool validCombo = m_acquireMode == WebGLSharedObject::Exclusive && neededMode == WebGLSharedObject::ReadOnly;
+ if (!sameMode && !validCombo) {
+ *reason = " not acquired for exclusive access";
+ return false;
+ }
+
+ if (mustBeBoundSinceLastAcquire && !it->value) {
+ *reason = " has not been bound since last acquired";
+ return false;
+ }
+
+ if (hasBeenBoundSinceLastAcquire) {
+ *hasBeenBoundSinceLastAcquire = it->value;
+ }
+
+ return true;
+}
+
+bool WebGLSharedObject::validate(const char* functionName, WebGLRenderingContext* context, WebGLSharedObject::AcquireMode neededMode, bool mustBeBoundSinceLastAcquire, bool* boundSinceLastAcquire) const
+{
+ if (context->contextGroup() != m_contextGroup) {
+ String msg(String(typeName()) + " not from this share group");
+ context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, msg.utf8().data());
+ return false;
+ }
+
+ const char* reason;
+ if (!isAcquiredForContext(context, neededMode, mustBeBoundSinceLastAcquire, boundSinceLastAcquire, &reason)) {
+ String msg(String(typeName()) + reason);
+ context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, functionName, msg.utf8().data());
+ return false;
+ }
+
+ return true;
+}
+
+void WebGLSharedObject::markAsBoundSinceLastAcquireForContext(const WebGLRenderingContext* context)
+{
+ AcquireContextMap::iterator it = m_acquireContextMap.find(context);
+ ASSERT(it != m_acquireContextMap.end());
+ it->value = true;
+}
+
+bool WebGLSharedObject::acquire(WebGLSharedObject::AcquireMode desiredMode, const WebGLRenderingContext* context)
+{
+ AcquireContextMap::const_iterator it = m_acquireContextMap.find(context);
+ if (it != m_acquireContextMap.end()) {
+ // How can I get here?
+ return false;
+ }
+
+ bool unacquired = m_acquireMode == WebGLSharedObject::Unacquired;
+ bool bothReadOnly = m_acquireMode == WebGLSharedObject::ReadOnly && desiredMode == WebGLSharedObject::ReadOnly;
+ if (!unacquired && !bothReadOnly) {
+ return false;
+ }
+
+ // Note: The resource is acquired at this point. The user may still cancel
+ // the request though before it the acquire callback is fired. If it is
+ // cancelled the cancel acts as a call to release.
+ m_acquireMode = desiredMode;
+ m_acquireContextMap.add(context, false);
+ return true;
+}
+
+bool WebGLSharedObject::addAcquireRequest(WebGLRenderingContext* context, WebGLSharedObject::AcquireMode desiredMode, PassRefPtr<WebGLAcquireSharedResourceCallback> callback, long& id)
+{
+ switch (desiredMode) {
+ case WebGLSharedObject::ReadOnly:
+ case WebGLSharedObject::Exclusive:
+ break;
+ default:
+ context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM, "acquireSharedResource", "mode is not READ_ONLY or EXCLUSIVE");
+ return false;
+ }
+
+ // 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.
+ if (context->contextGroup() != m_contextGroup) {
+ context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "acquireSharedResource", "object is not from this ShareGroup");
+ return false;
+ }
+
+ // Checks it is not already acquired by this context.
+ AcquireContextMap::iterator it = m_acquireContextMap.find(context);
+ if (it != m_acquireContextMap.end()) {
+ context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "acquireSharedResource", "object is already acquired in this context");
+ return false;
+ }
+
+ // Checks it is not already in one of the queues.
+ if (isRequestPending(context)) {
+ context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION, "acquireSharedResource", "request to acquire this object is already pending in this context");
+ return false;
+ }
+
+ // Adds the request.
+ m_acquireRequestQueue.append(WebGLAcquireSharedResourceRequest::create(this, callback, desiredMode, context, m_contextGroup->generateAcquireRequestId()));
+ processAcquireRequests();
+ return true;
}
+
+bool WebGLSharedObject::release(WebGLRenderingContext* context)
+{
+ AcquireContextMap::iterator it = m_acquireContextMap.find(context);
+ if (it == m_acquireContextMap.end()) {
+ return false;
+ }
+
+ m_acquireContextMap.remove(it);
+ if (m_acquireContextMap.isEmpty()) {
+ if (m_acquireMode == WebGLSharedObject::Exclusive) {
+ // TODO: Use flush if on top of virtual contexts (maybe we should have an extension GL_CHROMIUM_flush_sync to mark that only flush is needed)
+ // Use sync objects/fences if available.
+ // Use glFinish otherwise.
+ context->flush(); // Using flush for now. So far only certain Android devices need a finish.
+ }
+ m_acquireMode = WebGLSharedObject::Unacquired;
+ processAcquireRequests();
+ }
+
+ return true;
+}
+
+void WebGLSharedObject::processAcquireRequests()
+{
+ // Queue all the events that could succeed right now.
+ while (!m_acquireRequestQueue.isEmpty()) {
+ RefPtr<WebGLAcquireSharedResourceRequest> request = m_acquireRequestQueue.first();
+ if (!acquire(request->acquireMode(), request->context())) {
+ break;
+ }
+
+ m_acquireRequestQueue.removeFirst();
+ m_acquireRequestPostedList.append(request);
+
+ // queue event
+ ScriptExecutionContext* scriptExecutionContext = request->context()->scriptExecutionContext();
+ if (scriptExecutionContext) {
+ scriptExecutionContext->postTask(adoptPtr(new DispatchCallbackTask(request)));
+ }
Ken Russell (switch to Gerrit) 2013/06/19 03:51:24 Are there any race conditions with these acquire c
+ }
+}
+
+bool WebGLSharedObject::isRequestPending(const WebGLRenderingContext* context)
+{
+ for (AcquireRequestQueue::iterator it = m_acquireRequestQueue.begin(); it != m_acquireRequestQueue.end(); ++it) {
+ if ((*it)->context() == context) {
+ return true;
+ }
+ }
+ for (AcquireRequestList::iterator it = m_acquireRequestPostedList.begin(); it != m_acquireRequestPostedList.end(); ++it) {
+ if ((*it)->context() == context) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool WebGLSharedObject::cancelAcquireRequest(const WebGLRenderingContext* context, long id)
+{
+ for (AcquireRequestQueue::iterator it = m_acquireRequestQueue.begin(); it != m_acquireRequestQueue.end(); ++it) {
+ if ((*it)->id() == id) {
+ // Only remove it if it's from this context.
+ if ((*it)->context() == context) {
+ (*it)->cancel();
+ m_acquireRequestQueue.remove(it);
+ processAcquireRequests();
+ }
+ return true;
+ }
+ }
+ for (AcquireRequestList::iterator it = m_acquireRequestPostedList.begin(); it != m_acquireRequestPostedList.end(); ++it) {
+ if ((*it)->id() == id) {
+ // Only remove it if it's from this context.
+ if ((*it)->context() == context) {
+ (*it)->cancel();
+ m_acquireRequestPostedList.remove(it);
+ processAcquireRequests();
+ }
+ return true;
+ }
+ }
+ return false;
+}
+
+void WebGLSharedObject::removePostedAcquireRequest(const WebGLRenderingContext* context, long id)
+{
+ for (AcquireRequestList::iterator it = m_acquireRequestPostedList.begin(); it != m_acquireRequestPostedList.end(); ++it) {
+ if ((*it)->id() == id) {
+ ASSERT((*it)->context() == context);
+ m_acquireRequestPostedList.remove(it);
+ return;
+ }
+ }
+ ASSERT(false); // should never get here.
+}
+
+WebGLSharedObject::DispatchCallbackTask::~DispatchCallbackTask()
+{
+}
+
+void WebGLSharedObject::DispatchCallbackTask::performTask(ScriptExecutionContext*)
+{
+ m_request->run();
+}
+
+WebGLAcquireSharedResourceRequest::WebGLAcquireSharedResourceRequest(PassRefPtr<WebGLSharedObject> sharedObject, PassRefPtr<WebGLAcquireSharedResourceCallback> callback, WebGLSharedObject::AcquireMode acquireMode, WebGLRenderingContext* context, long id)
+ : m_sharedObject(sharedObject)
+ , m_context(context)
+ , m_id(id)
+ , m_acquireMode(acquireMode)
+ , m_callback(callback)
+{
+}
+
+WebGLAcquireSharedResourceRequest::~WebGLAcquireSharedResourceRequest()
+{
+}
+
+PassRefPtr<WebGLAcquireSharedResourceRequest> WebGLAcquireSharedResourceRequest::create(PassRefPtr<WebGLSharedObject> sharedObject, PassRefPtr<WebGLAcquireSharedResourceCallback> callback, WebGLSharedObject::AcquireMode acquireMode, WebGLRenderingContext* context, long id)
+{
+ return adoptRef(new WebGLAcquireSharedResourceRequest(sharedObject, callback, acquireMode, context, id));
+}
+
+void WebGLAcquireSharedResourceRequest::cancel()
+{
+ m_acquireMode = WebGLSharedObject::Unacquired;
+ m_callback.clear();
+}
+
+void WebGLAcquireSharedResourceRequest::run()
+{
+ if (m_callback) {
+ RefPtr<WebGLAcquireSharedResourceRequest> self(this); // Need to keep a reference to ourselves as the next line may remove our last reference.
+ m_sharedObject->removePostedAcquireRequest(context(), id());
+ m_callback->handleEvent(m_sharedObject.get());
+ m_callback.clear();
+ }
+}
+
+} // namespace WebCore
+

Powered by Google App Engine
This is Rietveld 408576698