Chromium Code Reviews| 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" | |
| 8 #include "core/frame/ImageBitmap.h" | 9 #include "core/frame/ImageBitmap.h" |
| 9 #include "core/html/HTMLCanvasElement.h" | 10 #include "core/html/HTMLCanvasElement.h" |
| 10 #include "core/html/HTMLImageElement.h" | 11 #include "core/html/HTMLImageElement.h" |
| 11 #include "core/html/HTMLVideoElement.h" | 12 #include "core/html/HTMLVideoElement.h" |
| 12 #include "core/html/ImageData.h" | 13 #include "core/html/ImageData.h" |
| 14 #include "gpu/GLES2/gl2extchromium.h" | |
| 13 #include "gpu/command_buffer/client/gles2_interface.h" | 15 #include "gpu/command_buffer/client/gles2_interface.h" |
| 14 #include "modules/webgl/WebGLActiveInfo.h" | 16 #include "modules/webgl/WebGLActiveInfo.h" |
| 15 #include "modules/webgl/WebGLBuffer.h" | 17 #include "modules/webgl/WebGLBuffer.h" |
| 16 #include "modules/webgl/WebGLFenceSync.h" | 18 #include "modules/webgl/WebGLFenceSync.h" |
| 17 #include "modules/webgl/WebGLFramebuffer.h" | 19 #include "modules/webgl/WebGLFramebuffer.h" |
| 18 #include "modules/webgl/WebGLProgram.h" | 20 #include "modules/webgl/WebGLProgram.h" |
| 19 #include "modules/webgl/WebGLQuery.h" | 21 #include "modules/webgl/WebGLQuery.h" |
| 20 #include "modules/webgl/WebGLRenderbuffer.h" | 22 #include "modules/webgl/WebGLRenderbuffer.h" |
| 21 #include "modules/webgl/WebGLSampler.h" | 23 #include "modules/webgl/WebGLSampler.h" |
| 22 #include "modules/webgl/WebGLSync.h" | 24 #include "modules/webgl/WebGLSync.h" |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 180 m_boundCopyWriteBuffer = nullptr; | 182 m_boundCopyWriteBuffer = nullptr; |
| 181 m_boundPixelPackBuffer = nullptr; | 183 m_boundPixelPackBuffer = nullptr; |
| 182 m_boundPixelUnpackBuffer = nullptr; | 184 m_boundPixelUnpackBuffer = nullptr; |
| 183 m_boundTransformFeedbackBuffer = nullptr; | 185 m_boundTransformFeedbackBuffer = nullptr; |
| 184 m_boundUniformBuffer = nullptr; | 186 m_boundUniformBuffer = nullptr; |
| 185 | 187 |
| 186 m_currentBooleanOcclusionQuery = nullptr; | 188 m_currentBooleanOcclusionQuery = nullptr; |
| 187 m_currentTransformFeedbackPrimitivesWrittenQuery = nullptr; | 189 m_currentTransformFeedbackPrimitivesWrittenQuery = nullptr; |
| 188 } | 190 } |
| 189 | 191 |
| 192 void WebGL2RenderingContextBase::destroyContext() { | |
| 193 for (auto& callback : m_getBufferSubDataAsyncCallbacks) { | |
| 194 callback->destroy(); | |
| 195 } | |
| 196 m_getBufferSubDataAsyncCallbacks.clear(); | |
| 197 | |
| 198 WebGLRenderingContextBase::destroyContext(); | |
| 199 } | |
| 200 | |
| 190 void WebGL2RenderingContextBase::initializeNewContext() { | 201 void WebGL2RenderingContextBase::initializeNewContext() { |
| 191 ASSERT(!isContextLost()); | 202 ASSERT(!isContextLost()); |
| 192 ASSERT(drawingBuffer()); | 203 ASSERT(drawingBuffer()); |
| 193 | 204 |
| 194 m_readFramebufferBinding = nullptr; | 205 m_readFramebufferBinding = nullptr; |
| 195 | 206 |
| 196 m_boundCopyReadBuffer = nullptr; | 207 m_boundCopyReadBuffer = nullptr; |
| 197 m_boundCopyWriteBuffer = nullptr; | 208 m_boundCopyWriteBuffer = nullptr; |
| 198 m_boundPixelPackBuffer = nullptr; | 209 m_boundPixelPackBuffer = nullptr; |
| 199 m_boundPixelUnpackBuffer = nullptr; | 210 m_boundPixelUnpackBuffer = nullptr; |
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 379 subByteLength, GL_MAP_READ_BIT); | 390 subByteLength, GL_MAP_READ_BIT); |
| 380 | 391 |
| 381 if (!mappedData) | 392 if (!mappedData) |
| 382 return; | 393 return; |
| 383 | 394 |
| 384 memcpy(subBaseAddress, mappedData, subByteLength); | 395 memcpy(subBaseAddress, mappedData, subByteLength); |
| 385 | 396 |
| 386 contextGL()->UnmapBuffer(target); | 397 contextGL()->UnmapBuffer(target); |
| 387 } | 398 } |
| 388 | 399 |
| 400 WebGL2RenderingContextBase::GetBufferSubDataAsyncCallback:: | |
| 401 GetBufferSubDataAsyncCallback(WebGL2RenderingContextBase* context, | |
| 402 DOMArrayBufferView* dstData, | |
| 403 ScriptPromiseResolver* resolver, | |
| 404 void* subBaseAddress, | |
| 405 void* mappedData, | |
| 406 long long subByteLength) | |
| 407 : context(context), | |
| 408 dstData(dstData), | |
| 409 resolver(resolver), | |
| 410 subBaseAddress(subBaseAddress), | |
| 411 mappedData(mappedData), | |
| 412 subByteLength(subByteLength) {} | |
| 413 | |
| 414 void WebGL2RenderingContextBase::GetBufferSubDataAsyncCallback::destroy() { | |
| 415 context->contextGL()->FreeSharedMemory(mappedData); | |
| 416 mappedData = nullptr; | |
| 417 DOMException* exception = | |
| 418 DOMException::create(InvalidStateError, "context lost or destroyed"); | |
| 419 this->resolver->reject(exception); | |
| 420 } | |
| 421 | |
| 422 void WebGL2RenderingContextBase::GetBufferSubDataAsyncCallback::resolve( | |
| 423 GetBufferSubDataAsyncCallback* self) { | |
| 424 if (!self->context || !self->mappedData) { | |
| 425 DOMException* exception = | |
| 426 DOMException::create(InvalidStateError, "context lost or destroyed"); | |
| 427 self->resolver->reject(exception); | |
| 428 return; | |
| 429 } | |
| 430 if (self->dstData->buffer()->isNeutered()) { | |
| 431 // XXX: should this set a GL error? No, according to current spec draft. | |
| 432 DOMException* exception = DOMException::create( | |
| 433 InvalidStateError, "ArrayBufferView became invalid asynchronously"); | |
| 434 self->resolver->reject(exception); | |
| 435 return; | |
| 436 } | |
| 437 memcpy(self->subBaseAddress, self->mappedData, self->subByteLength); | |
| 438 // XXX: What would happen if the DOM was suspended when the promise | |
| 439 // became resolved? Could another JS task happen between the memcpy | |
| 440 // and the promise resolution task? | |
| 441 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
| |
| 442 | |
| 443 self->destroy(); | |
| 444 self->context->unregisterGetBufferSubDataAsyncCallback(self); | |
| 445 } | |
| 446 | |
| 447 ScriptPromise WebGL2RenderingContextBase::getBufferSubDataAsync( | |
| 448 ScriptState* scriptState, | |
| 449 GLenum target, | |
| 450 GLintptr srcByteOffset, | |
| 451 DOMArrayBufferView* dstData, | |
| 452 GLuint dstOffset, | |
| 453 GLuint length) { | |
| 454 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); | |
| 455 ScriptPromise promise = resolver->promise(); | |
| 456 | |
| 457 const char* funcName = "getBufferSubDataAsync"; | |
| 458 if (isContextLost()) { | |
| 459 DOMException* exception = | |
| 460 DOMException::create(InvalidStateError, "context lost"); | |
| 461 resolver->reject(exception); | |
| 462 return promise; | |
| 463 } | |
| 464 if (!validateValueFitNonNegInt32(funcName, "srcByteOffset", srcByteOffset)) { | |
| 465 DOMException* exception = | |
| 466 DOMException::create(InvalidStateError, "invalid value: srcByteOffset"); | |
| 467 resolver->reject(exception); | |
| 468 return promise; | |
| 469 } | |
| 470 if (target == GL_TRANSFORM_FEEDBACK_BUFFER && m_transformFeedbackBinding) { | |
| 471 // XXX: is this restriction enforced in the original getBufferSubData? Does it need to be added there, or can it be removed here? | |
| 472 synthesizeGLError(GL_INVALID_OPERATION, funcName, | |
| 473 "targeted transform feedback buffer is bound"); | |
| 474 DOMException* exception = DOMException::create( | |
| 475 InvalidStateError, | |
| 476 "invalid operation: targeted transform feedback buffer is bound"); | |
| 477 resolver->reject(exception); | |
| 478 return promise; | |
| 479 } | |
| 480 WebGLBuffer* buffer = validateBufferDataTarget(funcName, target); | |
| 481 if (!buffer) { | |
| 482 DOMException* exception = DOMException::create( | |
| 483 InvalidStateError, "invalid operation: no buffer bound to target"); | |
| 484 resolver->reject(exception); | |
| 485 return promise; | |
| 486 } | |
| 487 | |
| 488 void* subBaseAddress = nullptr; | |
| 489 long long subByteLength = 0; | |
| 490 if (!validateSubSourceAndGetData(dstData, dstOffset, length, &subBaseAddress, | |
| 491 &subByteLength)) { | |
| 492 synthesizeGLError(GL_INVALID_VALUE, funcName, | |
| 493 "dstOffset and length out of bounds of dstData"); | |
| 494 DOMException* exception = | |
| 495 DOMException::create(InvalidStateError, | |
| 496 "invalid value: dstOffset and length " | |
| 497 "out of bounds of dstData"); | |
| 498 resolver->reject(exception); | |
| 499 return promise; | |
| 500 } | |
| 501 if (subByteLength == 0) { | |
| 502 resolver->resolve(dstData); | |
| 503 return promise; | |
| 504 } | |
| 505 | |
| 506 CheckedNumeric<long long> dstEnd = subByteLength; | |
| 507 dstEnd += srcByteOffset; | |
| 508 if (!dstEnd.IsValid() || dstEnd.ValueOrDie() > buffer->getSize()) { | |
| 509 synthesizeGLError( | |
| 510 GL_INVALID_VALUE, funcName, | |
| 511 "offset + numBytes would extend beyond the end of buffer"); | |
| 512 DOMException* exception = | |
| 513 DOMException::create(InvalidStateError, | |
| 514 "invalid value: offset + numBytes would extend " | |
| 515 "beyond the end of buffer"); | |
| 516 resolver->reject(exception); | |
| 517 return promise; | |
| 518 } | |
| 519 | |
| 520 GLuint queryID; | |
| 521 contextGL()->GenQueriesEXT(1, &queryID); | |
| 522 contextGL()->BeginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM, queryID); | |
| 523 void* mappedData = contextGL()->GetBufferSubDataAsyncCHROMIUM( | |
| 524 target, srcByteOffset, subByteLength); | |
| 525 if (!mappedData) { | |
| 526 DOMException* exception = | |
| 527 DOMException::create(InvalidStateError, "out of memory"); | |
| 528 resolver->reject(exception); | |
| 529 return promise; | |
| 530 } | |
| 531 contextGL()->EndQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM); | |
| 532 | |
| 533 auto callbackObject = adoptRef(new GetBufferSubDataAsyncCallback( | |
| 534 this, dstData, resolver, subBaseAddress, mappedData, subByteLength)); | |
| 535 registerGetBufferSubDataAsyncCallback(callbackObject.get()); | |
| 536 auto callback = | |
| 537 WTF::bind(&GetBufferSubDataAsyncCallback::resolve, callbackObject); | |
| 538 drawingBuffer()->contextProvider()->signalQuery( | |
| 539 queryID, convertToBaseCallback(std::move(callback))); | |
| 540 contextGL()->DeleteQueriesEXT(1, &queryID); | |
| 541 | |
| 542 return promise; | |
| 543 } | |
| 544 | |
| 545 void WebGL2RenderingContextBase::registerGetBufferSubDataAsyncCallback( | |
| 546 GetBufferSubDataAsyncCallback* callback) { | |
| 547 m_getBufferSubDataAsyncCallbacks.insert(callback); | |
| 548 } | |
| 549 | |
| 550 void WebGL2RenderingContextBase::unregisterGetBufferSubDataAsyncCallback( | |
| 551 GetBufferSubDataAsyncCallback* callback) { | |
| 552 m_getBufferSubDataAsyncCallbacks.erase(callback); | |
| 553 } | |
| 554 | |
| 389 void WebGL2RenderingContextBase::blitFramebuffer(GLint srcX0, | 555 void WebGL2RenderingContextBase::blitFramebuffer(GLint srcX0, |
| 390 GLint srcY0, | 556 GLint srcY0, |
| 391 GLint srcX1, | 557 GLint srcX1, |
| 392 GLint srcY1, | 558 GLint srcY1, |
| 393 GLint dstX0, | 559 GLint dstX0, |
| 394 GLint dstY0, | 560 GLint dstY0, |
| 395 GLint dstX1, | 561 GLint dstX1, |
| 396 GLint dstY1, | 562 GLint dstY1, |
| 397 GLbitfield mask, | 563 GLbitfield mask, |
| 398 GLenum filter) { | 564 GLenum filter) { |
| (...skipping 4090 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4489 params.skipPixels = m_unpackSkipPixels; | 4655 params.skipPixels = m_unpackSkipPixels; |
| 4490 params.skipRows = m_unpackSkipRows; | 4656 params.skipRows = m_unpackSkipRows; |
| 4491 if (dimension == Tex3D) { | 4657 if (dimension == Tex3D) { |
| 4492 params.imageHeight = m_unpackImageHeight; | 4658 params.imageHeight = m_unpackImageHeight; |
| 4493 params.skipImages = m_unpackSkipImages; | 4659 params.skipImages = m_unpackSkipImages; |
| 4494 } | 4660 } |
| 4495 return params; | 4661 return params; |
| 4496 } | 4662 } |
| 4497 | 4663 |
| 4498 } // namespace blink | 4664 } // namespace blink |
| OLD | NEW |