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 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 382 subByteLength, GL_MAP_READ_BIT); | 393 subByteLength, GL_MAP_READ_BIT); |
| 383 | 394 |
| 384 if (!mappedData) | 395 if (!mappedData) |
| 385 return; | 396 return; |
| 386 | 397 |
| 387 memcpy(subBaseAddress, mappedData, subByteLength); | 398 memcpy(subBaseAddress, mappedData, subByteLength); |
| 388 | 399 |
| 389 contextGL()->UnmapBuffer(target); | 400 contextGL()->UnmapBuffer(target); |
| 390 } | 401 } |
| 391 | 402 |
| 403 WebGL2RenderingContextBase::GetBufferSubDataAsyncCallback:: | |
| 404 GetBufferSubDataAsyncCallback(WebGL2RenderingContextBase* context, | |
| 405 DOMArrayBufferView* dstData, | |
| 406 ScriptPromiseResolver* resolver, | |
| 407 void* subBaseAddress, | |
| 408 void* mappedData, | |
|
esprehn
2016/10/08 03:02:48
What's the purpose and relationship of these two v
Kai Ninomiya
2016/10/11 01:34:13
I've clarified this a lot and added some DCHECKs.
| |
| 409 long long subByteLength) | |
| 410 : context(context), | |
| 411 dstData(dstData), | |
| 412 resolver(resolver), | |
| 413 subBaseAddress(subBaseAddress), | |
| 414 mappedData(mappedData), | |
| 415 subByteLength(subByteLength) {} | |
| 416 | |
| 417 void WebGL2RenderingContextBase::GetBufferSubDataAsyncCallback::destroy() { | |
| 418 context->contextGL()->FreeSharedMemory(mappedData); | |
|
esprehn
2016/10/08 03:02:48
do these fields need to be public?
Kai Ninomiya
2016/10/11 01:34:13
Not sure what you mean. The fields of (WebGL)GetBu
| |
| 419 mappedData = nullptr; | |
|
Ken Russell (switch to Gerrit)
2016/10/10 22:21:30
Upon entry please DCHECK(mappedData != NULL). We s
Kai Ninomiya
2016/10/11 01:34:14
Done.
| |
| 420 DOMException* exception = | |
| 421 DOMException::create(InvalidStateError, "context lost or destroyed"); | |
|
esprehn
2016/10/08 03:02:48
Capitalize error messages. "Context ..."
Kai Ninomiya
2016/10/11 01:34:13
Done.
| |
| 422 this->resolver->reject(exception); | |
| 423 } | |
| 424 | |
| 425 void WebGL2RenderingContextBase::GetBufferSubDataAsyncCallback::resolve( | |
| 426 GetBufferSubDataAsyncCallback* self) { | |
| 427 if (!self->context || !self->mappedData) { | |
|
esprehn
2016/10/08 03:02:48
lets move this into a method instead, you can prox
Ken Russell (switch to Gerrit)
2016/10/10 22:21:30
+1. That would make this code more comprehensible.
Kai Ninomiya
2016/10/11 01:34:14
Done.
| |
| 428 DOMException* exception = | |
| 429 DOMException::create(InvalidStateError, "context lost or destroyed"); | |
|
esprehn
2016/10/08 03:02:48
ditto
Kai Ninomiya
2016/10/11 01:34:14
Done.
| |
| 430 self->resolver->reject(exception); | |
| 431 return; | |
| 432 } | |
| 433 if (self->dstData->buffer()->isNeutered()) { | |
| 434 DOMException* exception = DOMException::create( | |
| 435 InvalidStateError, "ArrayBufferView became invalid asynchronously"); | |
| 436 self->resolver->reject(exception); | |
| 437 return; | |
| 438 } | |
| 439 memcpy(self->subBaseAddress, self->mappedData, self->subByteLength); | |
| 440 // XXX: What would happen if the DOM was suspended when the promise | |
|
Ken Russell (switch to Gerrit)
2016/10/10 22:21:30
It's OK to leave this question in place but please
Kai Ninomiya
2016/10/11 01:34:14
Still working on this issue, will address this com
| |
| 441 // became resolved? Could another JS task happen between the memcpy | |
| 442 // and the promise resolution task? | |
| 443 self->resolver->resolve(self->dstData); | |
| 444 | |
| 445 self->destroy(); | |
| 446 self->context->unregisterGetBufferSubDataAsyncCallback(self); | |
| 447 } | |
| 448 | |
| 449 ScriptPromise WebGL2RenderingContextBase::getBufferSubDataAsync( | |
|
esprehn
2016/10/08 03:02:49
This function is massive, can we make it into smal
Kai Ninomiya
2016/10/11 01:34:14
Great point, thanks. I will work on this tomorrow.
Kai Ninomiya
2016/10/11 21:54:43
I factored out a lot of common validation between
| |
| 450 ScriptState* scriptState, | |
| 451 GLenum target, | |
| 452 GLintptr srcByteOffset, | |
| 453 DOMArrayBufferView* dstData, | |
| 454 GLuint dstOffset, | |
| 455 GLuint length) { | |
| 456 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); | |
| 457 ScriptPromise promise = resolver->promise(); | |
| 458 | |
| 459 const char* funcName = "getBufferSubDataAsync"; | |
|
esprehn
2016/10/08 03:02:48
static ?, probably kFunctionName.
Don't abbreviat
Ken Russell (switch to Gerrit)
2016/10/10 22:21:30
Thanks Elliott for pointing that out. Kai, it does
Kai Ninomiya
2016/10/11 01:34:14
Done. There is future work to do if we want to rem
| |
| 460 if (isContextLost()) { | |
| 461 DOMException* exception = | |
| 462 DOMException::create(InvalidStateError, "context lost"); | |
| 463 resolver->reject(exception); | |
| 464 return promise; | |
| 465 } | |
| 466 if (!validateValueFitNonNegInt32(funcName, "srcByteOffset", srcByteOffset)) { | |
| 467 DOMException* exception = | |
| 468 DOMException::create(InvalidStateError, "invalid value: srcByteOffset"); | |
| 469 resolver->reject(exception); | |
| 470 return promise; | |
| 471 } | |
| 472 if (target == GL_TRANSFORM_FEEDBACK_BUFFER && m_transformFeedbackBinding) { | |
| 473 // XXX: is this restriction enforced in the original getBufferSubData? Does | |
|
Ken Russell (switch to Gerrit)
2016/10/10 22:21:30
It looks like it isn't enforced and it should be.
Kai Ninomiya
2016/10/11 01:34:13
Filed and assigned to myself: http://crbug.com/654
| |
| 474 // it need to be added there, or can it be removed here? | |
| 475 synthesizeGLError(GL_INVALID_OPERATION, funcName, | |
| 476 "targeted transform feedback buffer is bound"); | |
| 477 DOMException* exception = DOMException::create( | |
| 478 InvalidStateError, | |
| 479 "invalid operation: targeted transform feedback buffer is bound"); | |
| 480 resolver->reject(exception); | |
| 481 return promise; | |
| 482 } | |
| 483 WebGLBuffer* buffer = validateBufferDataTarget(funcName, target); | |
| 484 if (!buffer) { | |
| 485 DOMException* exception = DOMException::create( | |
| 486 InvalidStateError, "invalid operation: no buffer bound to target"); | |
| 487 resolver->reject(exception); | |
| 488 return promise; | |
| 489 } | |
| 490 | |
| 491 void* subBaseAddress = nullptr; | |
| 492 long long subByteLength = 0; | |
|
Ken Russell (switch to Gerrit)
2016/10/10 22:21:30
These "sub" names are confusing, especially when u
Kai Ninomiya
2016/10/11 01:34:14
For dstData and dstOffset, I don't want to change
| |
| 493 if (!validateSubSourceAndGetData(dstData, dstOffset, length, &subBaseAddress, | |
| 494 &subByteLength)) { | |
| 495 synthesizeGLError(GL_INVALID_VALUE, funcName, | |
| 496 "dstOffset and length out of bounds of dstData"); | |
| 497 DOMException* exception = | |
| 498 DOMException::create(InvalidStateError, | |
| 499 "invalid value: dstOffset and length " | |
| 500 "out of bounds of dstData"); | |
| 501 resolver->reject(exception); | |
| 502 return promise; | |
| 503 } | |
| 504 if (subByteLength == 0) { | |
|
esprehn
2016/10/08 03:02:48
if (!subByteLength)
Kai Ninomiya
2016/10/11 01:34:14
Done.
| |
| 505 resolver->resolve(dstData); | |
| 506 return promise; | |
| 507 } | |
| 508 | |
| 509 CheckedNumeric<long long> dstEnd = subByteLength; | |
|
esprehn
2016/10/08 03:02:48
everything down here seems like a separate functio
Kai Ninomiya
2016/10/11 21:54:43
Done.
| |
| 510 dstEnd += srcByteOffset; | |
| 511 if (!dstEnd.IsValid() || dstEnd.ValueOrDie() > buffer->getSize()) { | |
| 512 synthesizeGLError( | |
| 513 GL_INVALID_VALUE, funcName, | |
| 514 "offset + numBytes would extend beyond the end of buffer"); | |
| 515 DOMException* exception = | |
| 516 DOMException::create(InvalidStateError, | |
| 517 "invalid value: offset + numBytes would extend " | |
| 518 "beyond the end of buffer"); | |
|
Ken Russell (switch to Gerrit)
2016/10/10 22:21:30
end of -> end of the?
Kai Ninomiya
2016/10/11 01:34:14
Done.
| |
| 519 resolver->reject(exception); | |
| 520 return promise; | |
| 521 } | |
| 522 | |
| 523 GLuint queryID; | |
| 524 contextGL()->GenQueriesEXT(1, &queryID); | |
| 525 contextGL()->BeginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM, queryID); | |
| 526 void* mappedData = contextGL()->GetBufferSubDataAsyncCHROMIUM( | |
| 527 target, srcByteOffset, subByteLength); | |
| 528 if (!mappedData) { | |
| 529 DOMException* exception = | |
| 530 DOMException::create(InvalidStateError, "out of memory"); | |
| 531 resolver->reject(exception); | |
| 532 return promise; | |
| 533 } | |
| 534 contextGL()->EndQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM); | |
| 535 | |
| 536 auto callbackObject = adoptRef(new GetBufferSubDataAsyncCallback( | |
| 537 this, dstData, resolver, subBaseAddress, mappedData, subByteLength)); | |
| 538 registerGetBufferSubDataAsyncCallback(callbackObject.get()); | |
| 539 auto callback = | |
| 540 WTF::bind(&GetBufferSubDataAsyncCallback::resolve, callbackObject); | |
| 541 drawingBuffer()->contextProvider()->signalQuery( | |
| 542 queryID, convertToBaseCallback(std::move(callback))); | |
| 543 contextGL()->DeleteQueriesEXT(1, &queryID); | |
|
Ken Russell (switch to Gerrit)
2016/10/10 22:21:30
It seems incorrect to delete the query here. It se
Kai Ninomiya
2016/10/11 01:34:14
I didn't investigate this previously, but I wrote
| |
| 544 | |
| 545 return promise; | |
| 546 } | |
| 547 | |
| 548 void WebGL2RenderingContextBase::registerGetBufferSubDataAsyncCallback( | |
| 549 GetBufferSubDataAsyncCallback* callback) { | |
| 550 m_getBufferSubDataAsyncCallbacks.insert(callback); | |
| 551 } | |
| 552 | |
| 553 void WebGL2RenderingContextBase::unregisterGetBufferSubDataAsyncCallback( | |
| 554 GetBufferSubDataAsyncCallback* callback) { | |
| 555 m_getBufferSubDataAsyncCallbacks.erase(callback); | |
| 556 } | |
| 557 | |
| 392 void WebGL2RenderingContextBase::blitFramebuffer(GLint srcX0, | 558 void WebGL2RenderingContextBase::blitFramebuffer(GLint srcX0, |
| 393 GLint srcY0, | 559 GLint srcY0, |
| 394 GLint srcX1, | 560 GLint srcX1, |
| 395 GLint srcY1, | 561 GLint srcY1, |
| 396 GLint dstX0, | 562 GLint dstX0, |
| 397 GLint dstY0, | 563 GLint dstY0, |
| 398 GLint dstX1, | 564 GLint dstX1, |
| 399 GLint dstY1, | 565 GLint dstY1, |
| 400 GLbitfield mask, | 566 GLbitfield mask, |
| 401 GLenum filter) { | 567 GLenum filter) { |
| (...skipping 4103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4505 params.skipPixels = m_unpackSkipPixels; | 4671 params.skipPixels = m_unpackSkipPixels; |
| 4506 params.skipRows = m_unpackSkipRows; | 4672 params.skipRows = m_unpackSkipRows; |
| 4507 if (dimension == Tex3D) { | 4673 if (dimension == Tex3D) { |
| 4508 params.imageHeight = m_unpackImageHeight; | 4674 params.imageHeight = m_unpackImageHeight; |
| 4509 params.skipImages = m_unpackSkipImages; | 4675 params.skipImages = m_unpackSkipImages; |
| 4510 } | 4676 } |
| 4511 return params; | 4677 return params; |
| 4512 } | 4678 } |
| 4513 | 4679 |
| 4514 } // namespace blink | 4680 } // namespace blink |
| OLD | NEW |