| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "modules/webgl/WebGL2RenderingContextBase.h" | 5 #include "modules/webgl/WebGL2RenderingContextBase.h" |
| 6 | 6 |
| 7 #include "bindings/modules/v8/WebGLAny.h" | 7 #include "bindings/modules/v8/WebGLAny.h" |
| 8 #include "core/dom/DOMException.h" | |
| 9 #include "core/frame/ImageBitmap.h" | 8 #include "core/frame/ImageBitmap.h" |
| 10 #include "core/html/HTMLCanvasElement.h" | 9 #include "core/html/HTMLCanvasElement.h" |
| 11 #include "core/html/HTMLImageElement.h" | 10 #include "core/html/HTMLImageElement.h" |
| 12 #include "core/html/HTMLVideoElement.h" | 11 #include "core/html/HTMLVideoElement.h" |
| 13 #include "core/html/ImageData.h" | 12 #include "core/html/ImageData.h" |
| 14 #include "gpu/GLES2/gl2extchromium.h" | |
| 15 #include "gpu/command_buffer/client/gles2_interface.h" | 13 #include "gpu/command_buffer/client/gles2_interface.h" |
| 16 #include "modules/webgl/WebGLActiveInfo.h" | 14 #include "modules/webgl/WebGLActiveInfo.h" |
| 17 #include "modules/webgl/WebGLBuffer.h" | 15 #include "modules/webgl/WebGLBuffer.h" |
| 18 #include "modules/webgl/WebGLFenceSync.h" | 16 #include "modules/webgl/WebGLFenceSync.h" |
| 19 #include "modules/webgl/WebGLFramebuffer.h" | 17 #include "modules/webgl/WebGLFramebuffer.h" |
| 18 #include "modules/webgl/WebGLGetBufferSubDataAsync.h" |
| 20 #include "modules/webgl/WebGLProgram.h" | 19 #include "modules/webgl/WebGLProgram.h" |
| 21 #include "modules/webgl/WebGLQuery.h" | 20 #include "modules/webgl/WebGLQuery.h" |
| 22 #include "modules/webgl/WebGLRenderbuffer.h" | 21 #include "modules/webgl/WebGLRenderbuffer.h" |
| 23 #include "modules/webgl/WebGLSampler.h" | 22 #include "modules/webgl/WebGLSampler.h" |
| 24 #include "modules/webgl/WebGLSync.h" | 23 #include "modules/webgl/WebGLSync.h" |
| 25 #include "modules/webgl/WebGLTexture.h" | 24 #include "modules/webgl/WebGLTexture.h" |
| 26 #include "modules/webgl/WebGLTransformFeedback.h" | 25 #include "modules/webgl/WebGLTransformFeedback.h" |
| 27 #include "modules/webgl/WebGLUniformLocation.h" | 26 #include "modules/webgl/WebGLUniformLocation.h" |
| 28 #include "modules/webgl/WebGLVertexArrayObject.h" | 27 #include "modules/webgl/WebGLVertexArrayObject.h" |
| 29 #include "public/platform/WebGraphicsContext3DProvider.h" | 28 #include "public/platform/WebGraphicsContext3DProvider.h" |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 134 GL_RGBA16I, | 133 GL_RGBA16I, |
| 135 GL_RGBA32UI, | 134 GL_RGBA32UI, |
| 136 GL_RGBA32I, | 135 GL_RGBA32I, |
| 137 GL_DEPTH_COMPONENT16, | 136 GL_DEPTH_COMPONENT16, |
| 138 GL_DEPTH_COMPONENT24, | 137 GL_DEPTH_COMPONENT24, |
| 139 GL_DEPTH_COMPONENT32F, | 138 GL_DEPTH_COMPONENT32F, |
| 140 GL_DEPTH24_STENCIL8, | 139 GL_DEPTH24_STENCIL8, |
| 141 GL_DEPTH32F_STENCIL8, | 140 GL_DEPTH32F_STENCIL8, |
| 142 }; | 141 }; |
| 143 | 142 |
| 144 class WebGLGetBufferSubDataAsyncCallback | |
| 145 : public GarbageCollected<WebGLGetBufferSubDataAsyncCallback> { | |
| 146 public: | |
| 147 WebGLGetBufferSubDataAsyncCallback( | |
| 148 WebGL2RenderingContextBase* context, | |
| 149 ScriptPromiseResolver* promiseResolver, | |
| 150 void* shmReadbackResultData, | |
| 151 GLuint commandsIssuedQueryID, | |
| 152 DOMArrayBufferView* destinationArrayBufferView, | |
| 153 void* destinationDataPtr, | |
| 154 long long destinationByteLength) | |
| 155 : m_context(context), | |
| 156 m_promiseResolver(promiseResolver), | |
| 157 m_shmReadbackResultData(shmReadbackResultData), | |
| 158 m_commandsIssuedQueryID(commandsIssuedQueryID), | |
| 159 m_destinationArrayBufferView(destinationArrayBufferView), | |
| 160 m_destinationDataPtr(destinationDataPtr), | |
| 161 m_destinationByteLength(destinationByteLength) { | |
| 162 DCHECK(shmReadbackResultData); | |
| 163 DCHECK(destinationDataPtr); | |
| 164 } | |
| 165 | |
| 166 void destroy() { | |
| 167 DCHECK(m_shmReadbackResultData); | |
| 168 m_context->contextGL()->FreeSharedMemory(m_shmReadbackResultData); | |
| 169 m_shmReadbackResultData = nullptr; | |
| 170 DOMException* exception = | |
| 171 DOMException::create(InvalidStateError, "Context lost or destroyed"); | |
| 172 m_promiseResolver->reject(exception); | |
| 173 } | |
| 174 | |
| 175 void resolve() { | |
| 176 if (!m_context || !m_shmReadbackResultData) { | |
| 177 DOMException* exception = | |
| 178 DOMException::create(InvalidStateError, "Context lost or destroyed"); | |
| 179 m_promiseResolver->reject(exception); | |
| 180 return; | |
| 181 } | |
| 182 if (m_destinationArrayBufferView->buffer()->isNeutered()) { | |
| 183 DOMException* exception = DOMException::create( | |
| 184 InvalidStateError, "ArrayBufferView became invalid asynchronously"); | |
| 185 m_promiseResolver->reject(exception); | |
| 186 return; | |
| 187 } | |
| 188 memcpy(m_destinationDataPtr, m_shmReadbackResultData, | |
| 189 m_destinationByteLength); | |
| 190 // TODO(kainino): What would happen if the DOM was suspended when the | |
| 191 // promise became resolved? Could another JS task happen between the memcpy | |
| 192 // and the promise resolution task, which would see the wrong data? | |
| 193 m_promiseResolver->resolve(m_destinationArrayBufferView); | |
| 194 | |
| 195 m_context->contextGL()->DeleteQueriesEXT(1, &m_commandsIssuedQueryID); | |
| 196 this->destroy(); | |
| 197 m_context->unregisterGetBufferSubDataAsyncCallback(this); | |
| 198 } | |
| 199 | |
| 200 DECLARE_TRACE(); | |
| 201 | |
| 202 private: | |
| 203 WeakMember<WebGL2RenderingContextBase> m_context; | |
| 204 Member<ScriptPromiseResolver> m_promiseResolver; | |
| 205 | |
| 206 // Pointer to shared memory where the gpu readback result is stored. | |
| 207 void* m_shmReadbackResultData; | |
| 208 // ID of the GL query used to call this callback. | |
| 209 GLuint m_commandsIssuedQueryID; | |
| 210 | |
| 211 // ArrayBufferView returned from the promise. | |
| 212 Member<DOMArrayBufferView> m_destinationArrayBufferView; | |
| 213 // Pointer into the offset into destinationArrayBufferView. | |
| 214 void* m_destinationDataPtr; | |
| 215 // Size in bytes of the copy operation being performed. | |
| 216 long long m_destinationByteLength; | |
| 217 }; | |
| 218 | |
| 219 DEFINE_TRACE(WebGLGetBufferSubDataAsyncCallback) { | |
| 220 visitor->trace(m_context); | |
| 221 visitor->trace(m_promiseResolver); | |
| 222 visitor->trace(m_destinationArrayBufferView); | |
| 223 } | |
| 224 | |
| 225 WebGL2RenderingContextBase::WebGL2RenderingContextBase( | 143 WebGL2RenderingContextBase::WebGL2RenderingContextBase( |
| 226 HTMLCanvasElement* passedCanvas, | 144 HTMLCanvasElement* passedCanvas, |
| 227 std::unique_ptr<WebGraphicsContext3DProvider> contextProvider, | 145 std::unique_ptr<WebGraphicsContext3DProvider> contextProvider, |
| 228 const CanvasContextCreationAttributes& requestedAttributes) | 146 const CanvasContextCreationAttributes& requestedAttributes) |
| 229 : WebGLRenderingContextBase(passedCanvas, | 147 : WebGLRenderingContextBase(passedCanvas, |
| 230 std::move(contextProvider), | 148 std::move(contextProvider), |
| 231 requestedAttributes, | 149 requestedAttributes, |
| 232 2), | 150 2), |
| 233 m_readFramebufferBinding(this, nullptr), | 151 m_readFramebufferBinding(this, nullptr), |
| 234 m_transformFeedbackBinding(this, nullptr), | 152 m_transformFeedbackBinding(this, nullptr), |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 474 destinationByteLength, GL_MAP_READ_BIT); | 392 destinationByteLength, GL_MAP_READ_BIT); |
| 475 | 393 |
| 476 if (!mappedData) | 394 if (!mappedData) |
| 477 return; | 395 return; |
| 478 | 396 |
| 479 memcpy(destinationDataPtr, mappedData, destinationByteLength); | 397 memcpy(destinationDataPtr, mappedData, destinationByteLength); |
| 480 | 398 |
| 481 contextGL()->UnmapBuffer(target); | 399 contextGL()->UnmapBuffer(target); |
| 482 } | 400 } |
| 483 | 401 |
| 484 ScriptPromise WebGL2RenderingContextBase::getBufferSubDataAsync( | |
| 485 ScriptState* scriptState, | |
| 486 GLenum target, | |
| 487 GLintptr srcByteOffset, | |
| 488 DOMArrayBufferView* dstData, | |
| 489 GLuint dstOffset, | |
| 490 GLuint length) { | |
| 491 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); | |
| 492 ScriptPromise promise = resolver->promise(); | |
| 493 | |
| 494 WebGLBuffer* sourceBuffer = nullptr; | |
| 495 void* destinationDataPtr = nullptr; | |
| 496 long long destinationByteLength = 0; | |
| 497 const char* message = validateGetBufferSubData( | |
| 498 __FUNCTION__, target, srcByteOffset, dstData, dstOffset, length, | |
| 499 &sourceBuffer, &destinationDataPtr, &destinationByteLength); | |
| 500 if (message) { | |
| 501 // If there was a GL error, it was already synthesized in | |
| 502 // validateGetBufferSubData, so it's not done here. | |
| 503 DOMException* exception = DOMException::create(InvalidStateError, message); | |
| 504 resolver->reject(exception); | |
| 505 return promise; | |
| 506 } | |
| 507 | |
| 508 message = validateGetBufferSubDataBounds( | |
| 509 __FUNCTION__, sourceBuffer, srcByteOffset, destinationByteLength); | |
| 510 if (message) { | |
| 511 // If there was a GL error, it was already synthesized in | |
| 512 // validateGetBufferSubDataBounds, so it's not done here. | |
| 513 DOMException* exception = DOMException::create(InvalidStateError, message); | |
| 514 resolver->reject(exception); | |
| 515 return promise; | |
| 516 } | |
| 517 | |
| 518 // If the length of the copy is zero, this is a no-op. | |
| 519 if (!destinationByteLength) { | |
| 520 resolver->resolve(dstData); | |
| 521 return promise; | |
| 522 } | |
| 523 | |
| 524 GLuint queryID; | |
| 525 contextGL()->GenQueriesEXT(1, &queryID); | |
| 526 contextGL()->BeginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM, queryID); | |
| 527 void* mappedData = contextGL()->GetBufferSubDataAsyncCHROMIUM( | |
| 528 target, srcByteOffset, destinationByteLength); | |
| 529 contextGL()->EndQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM); | |
| 530 if (!mappedData) { | |
| 531 DOMException* exception = | |
| 532 DOMException::create(InvalidStateError, "Out of memory"); | |
| 533 resolver->reject(exception); | |
| 534 return promise; | |
| 535 } | |
| 536 | |
| 537 auto callbackObject = new WebGLGetBufferSubDataAsyncCallback( | |
| 538 this, resolver, mappedData, queryID, dstData, destinationDataPtr, | |
| 539 destinationByteLength); | |
| 540 registerGetBufferSubDataAsyncCallback(callbackObject); | |
| 541 auto callback = WTF::bind(&WebGLGetBufferSubDataAsyncCallback::resolve, | |
| 542 wrapPersistent(callbackObject)); | |
| 543 drawingBuffer()->contextProvider()->signalQuery( | |
| 544 queryID, convertToBaseCallback(std::move(callback))); | |
| 545 | |
| 546 return promise; | |
| 547 } | |
| 548 | |
| 549 void WebGL2RenderingContextBase::registerGetBufferSubDataAsyncCallback( | 402 void WebGL2RenderingContextBase::registerGetBufferSubDataAsyncCallback( |
| 550 WebGLGetBufferSubDataAsyncCallback* callback) { | 403 WebGLGetBufferSubDataAsyncCallback* callback) { |
| 551 m_getBufferSubDataAsyncCallbacks.add(callback); | 404 m_getBufferSubDataAsyncCallbacks.add(callback); |
| 552 } | 405 } |
| 553 | 406 |
| 554 void WebGL2RenderingContextBase::unregisterGetBufferSubDataAsyncCallback( | 407 void WebGL2RenderingContextBase::unregisterGetBufferSubDataAsyncCallback( |
| 555 WebGLGetBufferSubDataAsyncCallback* callback) { | 408 WebGLGetBufferSubDataAsyncCallback* callback) { |
| 556 m_getBufferSubDataAsyncCallbacks.remove(callback); | 409 m_getBufferSubDataAsyncCallbacks.remove(callback); |
| 557 } | 410 } |
| 558 | 411 |
| (...skipping 4381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4940 | 4793 |
| 4941 void WebGL2RenderingContextBase:: | 4794 void WebGL2RenderingContextBase:: |
| 4942 DrawingBufferClientRestorePixelUnpackBufferBinding() { | 4795 DrawingBufferClientRestorePixelUnpackBufferBinding() { |
| 4943 if (!contextGL()) | 4796 if (!contextGL()) |
| 4944 return; | 4797 return; |
| 4945 contextGL()->BindBuffer(GL_PIXEL_UNPACK_BUFFER, | 4798 contextGL()->BindBuffer(GL_PIXEL_UNPACK_BUFFER, |
| 4946 objectOrZero(m_boundPixelUnpackBuffer.get())); | 4799 objectOrZero(m_boundPixelUnpackBuffer.get())); |
| 4947 } | 4800 } |
| 4948 | 4801 |
| 4949 } // namespace blink | 4802 } // namespace blink |
| OLD | NEW |