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

Unified Diff: third_party/WebKit/Source/modules/webgl/WebGLGetBufferSubDataAsync.cpp

Issue 2569863005: Move getBufferSubDataAsync to an extension (Closed)
Patch Set: Created 4 years 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: third_party/WebKit/Source/modules/webgl/WebGLGetBufferSubDataAsync.cpp
diff --git a/third_party/WebKit/Source/modules/webgl/WebGLGetBufferSubDataAsync.cpp b/third_party/WebKit/Source/modules/webgl/WebGLGetBufferSubDataAsync.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..dd6107df253e7853cff4808b5934bf8a66064f4b
--- /dev/null
+++ b/third_party/WebKit/Source/modules/webgl/WebGLGetBufferSubDataAsync.cpp
@@ -0,0 +1,176 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "modules/webgl/WebGLGetBufferSubDataAsync.h"
+
+#include "core/dom/DOMException.h"
+#include "gpu/GLES2/gl2extchromium.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
+#include "modules/webgl/WebGL2RenderingContextBase.h"
+
+namespace blink {
+
+WebGLGetBufferSubDataAsync::WebGLGetBufferSubDataAsync(
+ WebGLRenderingContextBase* context)
+ : WebGLExtension(context) {}
+
+WebGLExtensionName WebGLGetBufferSubDataAsync::name() const {
+ return WebGLGetBufferSubDataAsyncName;
+}
+
+WebGLGetBufferSubDataAsync* WebGLGetBufferSubDataAsync::create(
+ WebGLRenderingContextBase* context) {
+ return new WebGLGetBufferSubDataAsync(context);
+}
+
+bool WebGLGetBufferSubDataAsync::supported(WebGLRenderingContextBase* context) {
+ Extensions3DUtil* extensionsUtil = context->extensionsUtil();
+ return extensionsUtil->supportsExtension(
+ "GL_EXT_texture_compression_s3tc_srgb");
Ken Russell (switch to Gerrit) 2016/12/13 23:17:29 This looks wrong.
Kai Ninomiya 2016/12/13 23:20:30 uh... oops. error in context switch state restorat
+}
+
+const char* WebGLGetBufferSubDataAsync::extensionName() {
+ return "WEBGL_get_buffer_sub_data_async";
+}
+
+ScriptPromise WebGLGetBufferSubDataAsync::getBufferSubDataAsync(
+ ScriptState* scriptState,
+ GLenum target,
+ GLintptr srcByteOffset,
+ DOMArrayBufferView* dstData,
+ GLuint dstOffset,
+ GLuint length) {
+ ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
+ ScriptPromise promise = resolver->promise();
+
+ WebGLExtensionScopedContext scoped(this);
+ if (scoped.isLost()) {
+ DOMException* exception =
+ DOMException::create(InvalidStateError, "context lost");
+ resolver->reject(exception);
+ return promise;
+ }
+
+ WebGL2RenderingContextBase* context = nullptr;
+ {
+ WebGLRenderingContextBase* contextBase = scoped.context();
+ DCHECK_GE(contextBase->version(), 2);
+ context = static_cast<WebGL2RenderingContextBase*>(contextBase);
+ }
+
+ WebGLBuffer* sourceBuffer = nullptr;
+ void* destinationDataPtr = nullptr;
+ long long destinationByteLength = 0;
+ const char* message = context->validateGetBufferSubData(
+ __FUNCTION__, target, srcByteOffset, dstData, dstOffset, length,
+ &sourceBuffer, &destinationDataPtr, &destinationByteLength);
+ if (message) {
+ // If there was a GL error, it was already synthesized in
+ // validateGetBufferSubData, so it's not done here.
+ DOMException* exception = DOMException::create(InvalidStateError, message);
+ resolver->reject(exception);
+ return promise;
+ }
+
+ message = context->validateGetBufferSubDataBounds(
+ __FUNCTION__, sourceBuffer, srcByteOffset, destinationByteLength);
+ if (message) {
+ // If there was a GL error, it was already synthesized in
+ // validateGetBufferSubDataBounds, so it's not done here.
+ DOMException* exception = DOMException::create(InvalidStateError, message);
+ resolver->reject(exception);
+ return promise;
+ }
+
+ // If the length of the copy is zero, this is a no-op.
+ if (!destinationByteLength) {
+ resolver->resolve(dstData);
+ return promise;
+ }
+
+ GLuint queryID;
+ context->contextGL()->GenQueriesEXT(1, &queryID);
+ context->contextGL()->BeginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM, queryID);
+ void* mappedData = context->contextGL()->GetBufferSubDataAsyncCHROMIUM(
+ target, srcByteOffset, destinationByteLength);
+ context->contextGL()->EndQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM);
+ if (!mappedData) {
+ DOMException* exception =
+ DOMException::create(InvalidStateError, "Out of memory");
+ resolver->reject(exception);
+ return promise;
+ }
+
+ auto callbackObject = new WebGLGetBufferSubDataAsyncCallback(
+ context, resolver, mappedData, queryID, dstData, destinationDataPtr,
+ destinationByteLength);
+ context->registerGetBufferSubDataAsyncCallback(callbackObject);
+ auto callback = WTF::bind(&WebGLGetBufferSubDataAsyncCallback::resolve,
+ wrapPersistent(callbackObject));
+ context->drawingBuffer()->contextProvider()->signalQuery(
+ queryID, convertToBaseCallback(std::move(callback)));
+
+ return promise;
+}
+
+WebGLGetBufferSubDataAsyncCallback::WebGLGetBufferSubDataAsyncCallback(
+ WebGL2RenderingContextBase* context,
+ ScriptPromiseResolver* promiseResolver,
+ void* shmReadbackResultData,
+ GLuint commandsIssuedQueryID,
+ DOMArrayBufferView* destinationArrayBufferView,
+ void* destinationDataPtr,
+ long long destinationByteLength)
+ : m_context(context),
+ m_promiseResolver(promiseResolver),
+ m_shmReadbackResultData(shmReadbackResultData),
+ m_commandsIssuedQueryID(commandsIssuedQueryID),
+ m_destinationArrayBufferView(destinationArrayBufferView),
+ m_destinationDataPtr(destinationDataPtr),
+ m_destinationByteLength(destinationByteLength) {
+ DCHECK(shmReadbackResultData);
+ DCHECK(destinationDataPtr);
+}
+
+void WebGLGetBufferSubDataAsyncCallback::destroy() {
+ DCHECK(m_shmReadbackResultData);
+ m_context->contextGL()->FreeSharedMemory(m_shmReadbackResultData);
+ m_shmReadbackResultData = nullptr;
+ DOMException* exception =
+ DOMException::create(InvalidStateError, "Context lost or destroyed");
+ m_promiseResolver->reject(exception);
+}
+
+void WebGLGetBufferSubDataAsyncCallback::resolve() {
+ if (!m_context || !m_shmReadbackResultData) {
+ DOMException* exception =
+ DOMException::create(InvalidStateError, "Context lost or destroyed");
+ m_promiseResolver->reject(exception);
+ return;
+ }
+ if (m_destinationArrayBufferView->buffer()->isNeutered()) {
+ DOMException* exception = DOMException::create(
+ InvalidStateError, "ArrayBufferView became invalid asynchronously");
+ m_promiseResolver->reject(exception);
+ return;
+ }
+ memcpy(m_destinationDataPtr, m_shmReadbackResultData,
+ m_destinationByteLength);
+ // TODO(kainino): What would happen if the DOM was suspended when the
+ // promise became resolved? Could another JS task happen between the memcpy
+ // and the promise resolution task, which would see the wrong data?
+ m_promiseResolver->resolve(m_destinationArrayBufferView);
+
+ m_context->contextGL()->DeleteQueriesEXT(1, &m_commandsIssuedQueryID);
+ this->destroy();
+ m_context->unregisterGetBufferSubDataAsyncCallback(this);
+}
+
+DEFINE_TRACE(WebGLGetBufferSubDataAsyncCallback) {
+ visitor->trace(m_context);
+ visitor->trace(m_promiseResolver);
+ visitor->trace(m_destinationArrayBufferView);
+}
+
+} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698