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

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

Issue 2379203002: implement getBufferSubDataAsync prototype (Closed)
Patch Set: hide getBufferSubDataAsync behind ExperimentalCanvasFeatures Created 4 years, 2 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: third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp
diff --git a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp
index 318f736275a6bf75ab5f87817a84479e61da748a..f04e2d6c9d62b806602fc08a830adf0abcbde2be 100644
--- a/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp
+++ b/third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp
@@ -5,11 +5,13 @@
#include "modules/webgl/WebGL2RenderingContextBase.h"
#include "bindings/modules/v8/WebGLAny.h"
+#include "core/dom/DOMException.h"
#include "core/frame/ImageBitmap.h"
#include "core/html/HTMLCanvasElement.h"
#include "core/html/HTMLImageElement.h"
#include "core/html/HTMLVideoElement.h"
#include "core/html/ImageData.h"
+#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "modules/webgl/WebGLActiveInfo.h"
#include "modules/webgl/WebGLBuffer.h"
@@ -187,6 +189,15 @@ WebGL2RenderingContextBase::~WebGL2RenderingContextBase() {
m_currentTransformFeedbackPrimitivesWrittenQuery = nullptr;
}
+void WebGL2RenderingContextBase::destroyContext() {
+ for (auto& callback : m_getBufferSubDataAsyncCallbacks) {
+ callback->destroy();
+ }
+ m_getBufferSubDataAsyncCallbacks.clear();
+
+ WebGLRenderingContextBase::destroyContext();
+}
+
void WebGL2RenderingContextBase::initializeNewContext() {
ASSERT(!isContextLost());
ASSERT(drawingBuffer());
@@ -386,6 +397,161 @@ void WebGL2RenderingContextBase::getBufferSubData(GLenum target,
contextGL()->UnmapBuffer(target);
}
+WebGL2RenderingContextBase::GetBufferSubDataAsyncCallback::
+ GetBufferSubDataAsyncCallback(WebGL2RenderingContextBase* context,
+ DOMArrayBufferView* dstData,
+ ScriptPromiseResolver* resolver,
+ void* subBaseAddress,
+ void* mappedData,
+ long long subByteLength)
+ : context(context),
+ dstData(dstData),
+ resolver(resolver),
+ subBaseAddress(subBaseAddress),
+ mappedData(mappedData),
+ subByteLength(subByteLength) {}
+
+void WebGL2RenderingContextBase::GetBufferSubDataAsyncCallback::destroy() {
+ context->contextGL()->FreeSharedMemory(mappedData);
+ mappedData = nullptr;
+ DOMException* exception =
+ DOMException::create(InvalidStateError, "context lost or destroyed");
+ this->resolver->reject(exception);
+}
+
+void WebGL2RenderingContextBase::GetBufferSubDataAsyncCallback::resolve(
+ GetBufferSubDataAsyncCallback* self) {
+ if (!self->context || !self->mappedData) {
+ DOMException* exception =
+ DOMException::create(InvalidStateError, "context lost or destroyed");
+ self->resolver->reject(exception);
+ return;
+ }
+ if (self->dstData->buffer()->isNeutered()) {
+ // XXX: should this set a GL error? No, according to current spec draft.
+ DOMException* exception = DOMException::create(
+ InvalidStateError, "ArrayBufferView became invalid asynchronously");
+ self->resolver->reject(exception);
+ return;
+ }
+ memcpy(self->subBaseAddress, self->mappedData, self->subByteLength);
+ // XXX: 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?
+ self->resolver->resolve(self->dstData);
adamk 2016/10/07 23:00:43 My knowledge of the Blink event loop is a little r
yhirano 2016/10/12 09:32:02 When the window is suspended, ScriptPromiseResolve
tyoshino (SeeGerritForStatus) 2016/10/12 10:00:39 As this looked related to promises, I asked yhiran
+
+ self->destroy();
+ self->context->unregisterGetBufferSubDataAsyncCallback(self);
+}
+
+ScriptPromise WebGL2RenderingContextBase::getBufferSubDataAsync(
+ ScriptState* scriptState,
+ GLenum target,
+ GLintptr srcByteOffset,
+ DOMArrayBufferView* dstData,
+ GLuint dstOffset,
+ GLuint length) {
+ ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState);
+ ScriptPromise promise = resolver->promise();
+
+ const char* funcName = "getBufferSubDataAsync";
+ if (isContextLost()) {
+ DOMException* exception =
+ DOMException::create(InvalidStateError, "context lost");
+ resolver->reject(exception);
+ return promise;
+ }
+ if (!validateValueFitNonNegInt32(funcName, "srcByteOffset", srcByteOffset)) {
+ DOMException* exception =
+ DOMException::create(InvalidStateError, "invalid value: srcByteOffset");
+ resolver->reject(exception);
+ return promise;
+ }
+ if (target == GL_TRANSFORM_FEEDBACK_BUFFER && m_transformFeedbackBinding) {
+ // XXX: is this restriction enforced in the original getBufferSubData? Does it need to be added there, or can it be removed here?
+ synthesizeGLError(GL_INVALID_OPERATION, funcName,
+ "targeted transform feedback buffer is bound");
+ DOMException* exception = DOMException::create(
+ InvalidStateError,
+ "invalid operation: targeted transform feedback buffer is bound");
+ resolver->reject(exception);
+ return promise;
+ }
+ WebGLBuffer* buffer = validateBufferDataTarget(funcName, target);
+ if (!buffer) {
+ DOMException* exception = DOMException::create(
+ InvalidStateError, "invalid operation: no buffer bound to target");
+ resolver->reject(exception);
+ return promise;
+ }
+
+ void* subBaseAddress = nullptr;
+ long long subByteLength = 0;
+ if (!validateSubSourceAndGetData(dstData, dstOffset, length, &subBaseAddress,
+ &subByteLength)) {
+ synthesizeGLError(GL_INVALID_VALUE, funcName,
+ "dstOffset and length out of bounds of dstData");
+ DOMException* exception =
+ DOMException::create(InvalidStateError,
+ "invalid value: dstOffset and length "
+ "out of bounds of dstData");
+ resolver->reject(exception);
+ return promise;
+ }
+ if (subByteLength == 0) {
+ resolver->resolve(dstData);
+ return promise;
+ }
+
+ CheckedNumeric<long long> dstEnd = subByteLength;
+ dstEnd += srcByteOffset;
+ if (!dstEnd.IsValid() || dstEnd.ValueOrDie() > buffer->getSize()) {
+ synthesizeGLError(
+ GL_INVALID_VALUE, funcName,
+ "offset + numBytes would extend beyond the end of buffer");
+ DOMException* exception =
+ DOMException::create(InvalidStateError,
+ "invalid value: offset + numBytes would extend "
+ "beyond the end of buffer");
+ resolver->reject(exception);
+ return promise;
+ }
+
+ GLuint queryID;
+ contextGL()->GenQueriesEXT(1, &queryID);
+ contextGL()->BeginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM, queryID);
+ void* mappedData = contextGL()->GetBufferSubDataAsyncCHROMIUM(
+ target, srcByteOffset, subByteLength);
+ if (!mappedData) {
+ DOMException* exception =
+ DOMException::create(InvalidStateError, "out of memory");
+ resolver->reject(exception);
+ return promise;
+ }
+ contextGL()->EndQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM);
+
+ auto callbackObject = adoptRef(new GetBufferSubDataAsyncCallback(
+ this, dstData, resolver, subBaseAddress, mappedData, subByteLength));
+ registerGetBufferSubDataAsyncCallback(callbackObject.get());
+ auto callback =
+ WTF::bind(&GetBufferSubDataAsyncCallback::resolve, callbackObject);
+ drawingBuffer()->contextProvider()->signalQuery(
+ queryID, convertToBaseCallback(std::move(callback)));
+ contextGL()->DeleteQueriesEXT(1, &queryID);
+
+ return promise;
+}
+
+void WebGL2RenderingContextBase::registerGetBufferSubDataAsyncCallback(
+ GetBufferSubDataAsyncCallback* callback) {
+ m_getBufferSubDataAsyncCallbacks.insert(callback);
+}
+
+void WebGL2RenderingContextBase::unregisterGetBufferSubDataAsyncCallback(
+ GetBufferSubDataAsyncCallback* callback) {
+ m_getBufferSubDataAsyncCallbacks.erase(callback);
+}
+
void WebGL2RenderingContextBase::blitFramebuffer(GLint srcX0,
GLint srcY0,
GLint srcX1,

Powered by Google App Engine
This is Rietveld 408576698