| 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 10 matching lines...) Expand all Loading... |
| 33 using WTF::String; | 35 using WTF::String; |
| 34 | 36 |
| 35 namespace blink { | 37 namespace blink { |
| 36 | 38 |
| 37 namespace { | 39 namespace { |
| 38 | 40 |
| 39 GLsync syncObjectOrZero(const WebGLSync* object) { | 41 GLsync syncObjectOrZero(const WebGLSync* object) { |
| 40 return object ? object->object() : nullptr; | 42 return object ? object->object() : nullptr; |
| 41 } | 43 } |
| 42 | 44 |
| 45 // TODO(kainino): Change outByteLength to GLuint and change the associated |
| 46 // range checking (and all uses) - overflow becomes possible in cases below |
| 43 bool validateSubSourceAndGetData(DOMArrayBufferView* view, | 47 bool validateSubSourceAndGetData(DOMArrayBufferView* view, |
| 44 GLuint subOffset, | 48 GLuint subOffset, |
| 45 GLuint subLength, | 49 GLuint subLength, |
| 46 void** outBaseAddress, | 50 void** outBaseAddress, |
| 47 long long* outByteLength) { | 51 long long* outByteLength) { |
| 48 // This is guaranteed to be non-null by DOM. | 52 // This is guaranteed to be non-null by DOM. |
| 49 DCHECK(view); | 53 DCHECK(view); |
| 50 | 54 |
| 51 size_t typeSize = view->typeSize(); | 55 size_t typeSize = view->typeSize(); |
| 52 DCHECK_GE(8u, typeSize); | 56 DCHECK_GE(8u, typeSize); |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 128 GL_RGBA16I, | 132 GL_RGBA16I, |
| 129 GL_RGBA32UI, | 133 GL_RGBA32UI, |
| 130 GL_RGBA32I, | 134 GL_RGBA32I, |
| 131 GL_DEPTH_COMPONENT16, | 135 GL_DEPTH_COMPONENT16, |
| 132 GL_DEPTH_COMPONENT24, | 136 GL_DEPTH_COMPONENT24, |
| 133 GL_DEPTH_COMPONENT32F, | 137 GL_DEPTH_COMPONENT32F, |
| 134 GL_DEPTH24_STENCIL8, | 138 GL_DEPTH24_STENCIL8, |
| 135 GL_DEPTH32F_STENCIL8, | 139 GL_DEPTH32F_STENCIL8, |
| 136 }; | 140 }; |
| 137 | 141 |
| 142 class WebGLGetBufferSubDataAsyncCallback |
| 143 : public GarbageCollected<WebGLGetBufferSubDataAsyncCallback> { |
| 144 public: |
| 145 WebGLGetBufferSubDataAsyncCallback( |
| 146 WebGL2RenderingContextBase* context, |
| 147 ScriptPromiseResolver* promiseResolver, |
| 148 void* shmReadbackResultData, |
| 149 GLuint commandsIssuedQueryID, |
| 150 DOMArrayBufferView* destinationArrayBufferView, |
| 151 void* destinationDataPtr, |
| 152 long long destinationByteLength) |
| 153 : m_context(context), |
| 154 m_promiseResolver(promiseResolver), |
| 155 m_shmReadbackResultData(shmReadbackResultData), |
| 156 m_commandsIssuedQueryID(commandsIssuedQueryID), |
| 157 m_destinationArrayBufferView(destinationArrayBufferView), |
| 158 m_destinationDataPtr(destinationDataPtr), |
| 159 m_destinationByteLength(destinationByteLength) { |
| 160 DCHECK(shmReadbackResultData); |
| 161 DCHECK(destinationDataPtr); |
| 162 } |
| 163 |
| 164 void destroy() { |
| 165 DCHECK(m_shmReadbackResultData); |
| 166 m_context->contextGL()->FreeSharedMemory(m_shmReadbackResultData); |
| 167 m_shmReadbackResultData = nullptr; |
| 168 DOMException* exception = |
| 169 DOMException::create(InvalidStateError, "Context lost or destroyed"); |
| 170 m_promiseResolver->reject(exception); |
| 171 } |
| 172 |
| 173 void resolve() { |
| 174 if (!m_context || !m_shmReadbackResultData) { |
| 175 DOMException* exception = |
| 176 DOMException::create(InvalidStateError, "Context lost or destroyed"); |
| 177 m_promiseResolver->reject(exception); |
| 178 return; |
| 179 } |
| 180 if (m_destinationArrayBufferView->buffer()->isNeutered()) { |
| 181 DOMException* exception = DOMException::create( |
| 182 InvalidStateError, "ArrayBufferView became invalid asynchronously"); |
| 183 m_promiseResolver->reject(exception); |
| 184 return; |
| 185 } |
| 186 memcpy(m_destinationDataPtr, m_shmReadbackResultData, |
| 187 m_destinationByteLength); |
| 188 // TODO(kainino): What would happen if the DOM was suspended when the |
| 189 // promise became resolved? Could another JS task happen between the memcpy |
| 190 // and the promise resolution task, which would see the wrong data? |
| 191 m_promiseResolver->resolve(m_destinationArrayBufferView); |
| 192 |
| 193 m_context->contextGL()->DeleteQueriesEXT(1, &m_commandsIssuedQueryID); |
| 194 this->destroy(); |
| 195 m_context->unregisterGetBufferSubDataAsyncCallback(this); |
| 196 } |
| 197 |
| 198 DECLARE_TRACE(); |
| 199 |
| 200 private: |
| 201 WeakMember<WebGL2RenderingContextBase> m_context; |
| 202 Member<ScriptPromiseResolver> m_promiseResolver; |
| 203 |
| 204 // Pointer to shared memory where the gpu readback result is stored. |
| 205 void* m_shmReadbackResultData; |
| 206 // ID of the GL query used to call this callback. |
| 207 GLuint m_commandsIssuedQueryID; |
| 208 |
| 209 // ArrayBufferView returned from the promise. |
| 210 Member<DOMArrayBufferView> m_destinationArrayBufferView; |
| 211 // Pointer into the offset into destinationArrayBufferView. |
| 212 void* m_destinationDataPtr; |
| 213 // Size in bytes of the copy operation being performed. |
| 214 long long m_destinationByteLength; |
| 215 }; |
| 216 |
| 217 DEFINE_TRACE(WebGLGetBufferSubDataAsyncCallback) { |
| 218 visitor->trace(m_context); |
| 219 visitor->trace(m_promiseResolver); |
| 220 visitor->trace(m_destinationArrayBufferView); |
| 221 } |
| 222 |
| 138 WebGL2RenderingContextBase::WebGL2RenderingContextBase( | 223 WebGL2RenderingContextBase::WebGL2RenderingContextBase( |
| 139 HTMLCanvasElement* passedCanvas, | 224 HTMLCanvasElement* passedCanvas, |
| 140 std::unique_ptr<WebGraphicsContext3DProvider> contextProvider, | 225 std::unique_ptr<WebGraphicsContext3DProvider> contextProvider, |
| 141 const CanvasContextCreationAttributes& requestedAttributes) | 226 const CanvasContextCreationAttributes& requestedAttributes) |
| 142 : WebGLRenderingContextBase(passedCanvas, | 227 : WebGLRenderingContextBase(passedCanvas, |
| 143 std::move(contextProvider), | 228 std::move(contextProvider), |
| 144 requestedAttributes, | 229 requestedAttributes, |
| 145 2) { | 230 2) { |
| 146 m_supportedInternalFormatsStorage.insert( | 231 m_supportedInternalFormatsStorage.insert( |
| 147 kSupportedInternalFormatsStorage, | 232 kSupportedInternalFormatsStorage, |
| 148 kSupportedInternalFormatsStorage + | 233 kSupportedInternalFormatsStorage + |
| 149 WTF_ARRAY_LENGTH(kSupportedInternalFormatsStorage)); | 234 WTF_ARRAY_LENGTH(kSupportedInternalFormatsStorage)); |
| 150 } | 235 } |
| 151 | 236 |
| 152 WebGL2RenderingContextBase::~WebGL2RenderingContextBase() { | 237 WebGL2RenderingContextBase::~WebGL2RenderingContextBase() { |
| 153 m_readFramebufferBinding = nullptr; | 238 m_readFramebufferBinding = nullptr; |
| 154 | 239 |
| 155 m_boundCopyReadBuffer = nullptr; | 240 m_boundCopyReadBuffer = nullptr; |
| 156 m_boundCopyWriteBuffer = nullptr; | 241 m_boundCopyWriteBuffer = nullptr; |
| 157 m_boundPixelPackBuffer = nullptr; | 242 m_boundPixelPackBuffer = nullptr; |
| 158 m_boundPixelUnpackBuffer = nullptr; | 243 m_boundPixelUnpackBuffer = nullptr; |
| 159 m_boundTransformFeedbackBuffer = nullptr; | 244 m_boundTransformFeedbackBuffer = nullptr; |
| 160 m_boundUniformBuffer = nullptr; | 245 m_boundUniformBuffer = nullptr; |
| 161 | 246 |
| 162 m_currentBooleanOcclusionQuery = nullptr; | 247 m_currentBooleanOcclusionQuery = nullptr; |
| 163 m_currentTransformFeedbackPrimitivesWrittenQuery = nullptr; | 248 m_currentTransformFeedbackPrimitivesWrittenQuery = nullptr; |
| 164 } | 249 } |
| 165 | 250 |
| 251 void WebGL2RenderingContextBase::destroyContext() { |
| 252 for (auto& callback : m_getBufferSubDataAsyncCallbacks) { |
| 253 callback->destroy(); |
| 254 } |
| 255 m_getBufferSubDataAsyncCallbacks.clear(); |
| 256 |
| 257 WebGLRenderingContextBase::destroyContext(); |
| 258 } |
| 259 |
| 166 void WebGL2RenderingContextBase::initializeNewContext() { | 260 void WebGL2RenderingContextBase::initializeNewContext() { |
| 167 ASSERT(!isContextLost()); | 261 ASSERT(!isContextLost()); |
| 168 ASSERT(drawingBuffer()); | 262 ASSERT(drawingBuffer()); |
| 169 | 263 |
| 170 m_readFramebufferBinding = nullptr; | 264 m_readFramebufferBinding = nullptr; |
| 171 | 265 |
| 172 m_boundCopyReadBuffer = nullptr; | 266 m_boundCopyReadBuffer = nullptr; |
| 173 m_boundCopyWriteBuffer = nullptr; | 267 m_boundCopyWriteBuffer = nullptr; |
| 174 m_boundPixelPackBuffer = nullptr; | 268 m_boundPixelPackBuffer = nullptr; |
| 175 m_boundPixelUnpackBuffer = nullptr; | 269 m_boundPixelUnpackBuffer = nullptr; |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 326 contextGL()->CopyBufferSubData( | 420 contextGL()->CopyBufferSubData( |
| 327 readTarget, writeTarget, static_cast<GLintptr>(readOffset), | 421 readTarget, writeTarget, static_cast<GLintptr>(readOffset), |
| 328 static_cast<GLintptr>(writeOffset), static_cast<GLsizeiptr>(size)); | 422 static_cast<GLintptr>(writeOffset), static_cast<GLsizeiptr>(size)); |
| 329 } | 423 } |
| 330 | 424 |
| 331 void WebGL2RenderingContextBase::getBufferSubData(GLenum target, | 425 void WebGL2RenderingContextBase::getBufferSubData(GLenum target, |
| 332 long long srcByteOffset, | 426 long long srcByteOffset, |
| 333 DOMArrayBufferView* dstData, | 427 DOMArrayBufferView* dstData, |
| 334 GLuint dstOffset, | 428 GLuint dstOffset, |
| 335 GLuint length) { | 429 GLuint length) { |
| 336 const char* funcName = "getBufferSubData"; | 430 WebGLBuffer* sourceBuffer = nullptr; |
| 337 if (isContextLost()) | 431 void* destinationDataPtr = nullptr; |
| 338 return; | 432 long long destinationByteLength = 0; |
| 339 if (!validateValueFitNonNegInt32(funcName, "srcByteOffset", srcByteOffset)) { | 433 const char* message = validateGetBufferSubData( |
| 434 __FUNCTION__, target, srcByteOffset, dstData, dstOffset, length, |
| 435 &sourceBuffer, &destinationDataPtr, &destinationByteLength); |
| 436 if (message) { |
| 437 // If there was a GL error, it was already synthesized in |
| 438 // validateGetBufferSubData, so it's not done here. |
| 340 return; | 439 return; |
| 341 } | 440 } |
| 342 WebGLBuffer* buffer = validateBufferDataTarget(funcName, target); | 441 |
| 343 if (!buffer) | 442 // If the length of the copy is zero, this is a no-op. |
| 344 return; | 443 if (!destinationByteLength) { |
| 345 void* subBaseAddress = nullptr; | |
| 346 long long subByteLength = 0; | |
| 347 if (!validateSubSourceAndGetData(dstData, dstOffset, length, &subBaseAddress, | |
| 348 &subByteLength)) { | |
| 349 synthesizeGLError(GL_INVALID_VALUE, funcName, "buffer overflow"); | |
| 350 return; | |
| 351 } | |
| 352 if (subByteLength == 0) { | |
| 353 return; | 444 return; |
| 354 } | 445 } |
| 355 | 446 |
| 356 void* mappedData = | 447 void* mappedData = |
| 357 contextGL()->MapBufferRange(target, static_cast<GLintptr>(srcByteOffset), | 448 contextGL()->MapBufferRange(target, static_cast<GLintptr>(srcByteOffset), |
| 358 subByteLength, GL_MAP_READ_BIT); | 449 destinationByteLength, GL_MAP_READ_BIT); |
| 359 | 450 |
| 360 if (!mappedData) | 451 if (!mappedData) |
| 361 return; | 452 return; |
| 362 | 453 |
| 363 memcpy(subBaseAddress, mappedData, subByteLength); | 454 memcpy(destinationDataPtr, mappedData, destinationByteLength); |
| 364 | 455 |
| 365 contextGL()->UnmapBuffer(target); | 456 contextGL()->UnmapBuffer(target); |
| 366 } | 457 } |
| 367 | 458 |
| 459 ScriptPromise WebGL2RenderingContextBase::getBufferSubDataAsync( |
| 460 ScriptState* scriptState, |
| 461 GLenum target, |
| 462 GLintptr srcByteOffset, |
| 463 DOMArrayBufferView* dstData, |
| 464 GLuint dstOffset, |
| 465 GLuint length) { |
| 466 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState); |
| 467 ScriptPromise promise = resolver->promise(); |
| 468 |
| 469 WebGLBuffer* sourceBuffer = nullptr; |
| 470 void* destinationDataPtr = nullptr; |
| 471 long long destinationByteLength = 0; |
| 472 const char* message = validateGetBufferSubData( |
| 473 __FUNCTION__, target, srcByteOffset, dstData, dstOffset, length, |
| 474 &sourceBuffer, &destinationDataPtr, &destinationByteLength); |
| 475 if (message) { |
| 476 // If there was a GL error, it was already synthesized in |
| 477 // validateGetBufferSubData, so it's not done here. |
| 478 DOMException* exception = DOMException::create(InvalidStateError, message); |
| 479 resolver->reject(exception); |
| 480 return promise; |
| 481 } |
| 482 |
| 483 message = validateGetBufferSubDataBounds( |
| 484 __FUNCTION__, sourceBuffer, srcByteOffset, destinationByteLength); |
| 485 if (message) { |
| 486 // If there was a GL error, it was already synthesized in |
| 487 // validateGetBufferSubDataBounds, so it's not done here. |
| 488 DOMException* exception = DOMException::create(InvalidStateError, message); |
| 489 resolver->reject(exception); |
| 490 return promise; |
| 491 } |
| 492 |
| 493 // If the length of the copy is zero, this is a no-op. |
| 494 if (!destinationByteLength) { |
| 495 resolver->resolve(dstData); |
| 496 return promise; |
| 497 } |
| 498 |
| 499 GLuint queryID; |
| 500 contextGL()->GenQueriesEXT(1, &queryID); |
| 501 contextGL()->BeginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM, queryID); |
| 502 void* mappedData = contextGL()->GetBufferSubDataAsyncCHROMIUM( |
| 503 target, srcByteOffset, destinationByteLength); |
| 504 contextGL()->EndQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM); |
| 505 if (!mappedData) { |
| 506 DOMException* exception = |
| 507 DOMException::create(InvalidStateError, "Out of memory"); |
| 508 resolver->reject(exception); |
| 509 return promise; |
| 510 } |
| 511 |
| 512 auto callbackObject = new WebGLGetBufferSubDataAsyncCallback( |
| 513 this, resolver, mappedData, queryID, dstData, destinationDataPtr, |
| 514 destinationByteLength); |
| 515 registerGetBufferSubDataAsyncCallback(callbackObject); |
| 516 auto callback = WTF::bind(&WebGLGetBufferSubDataAsyncCallback::resolve, |
| 517 wrapPersistent(callbackObject)); |
| 518 drawingBuffer()->contextProvider()->signalQuery( |
| 519 queryID, convertToBaseCallback(std::move(callback))); |
| 520 |
| 521 return promise; |
| 522 } |
| 523 |
| 524 void WebGL2RenderingContextBase::registerGetBufferSubDataAsyncCallback( |
| 525 WebGLGetBufferSubDataAsyncCallback* callback) { |
| 526 m_getBufferSubDataAsyncCallbacks.add(callback); |
| 527 } |
| 528 |
| 529 void WebGL2RenderingContextBase::unregisterGetBufferSubDataAsyncCallback( |
| 530 WebGLGetBufferSubDataAsyncCallback* callback) { |
| 531 m_getBufferSubDataAsyncCallbacks.remove(callback); |
| 532 } |
| 533 |
| 368 void WebGL2RenderingContextBase::blitFramebuffer(GLint srcX0, | 534 void WebGL2RenderingContextBase::blitFramebuffer(GLint srcX0, |
| 369 GLint srcY0, | 535 GLint srcY0, |
| 370 GLint srcX1, | 536 GLint srcX1, |
| 371 GLint srcY1, | 537 GLint srcY1, |
| 372 GLint dstX0, | 538 GLint dstX0, |
| 373 GLint dstY0, | 539 GLint dstY0, |
| 374 GLint dstX1, | 540 GLint dstX1, |
| 375 GLint dstY1, | 541 GLint dstY1, |
| 376 GLbitfield mask, | 542 GLbitfield mask, |
| 377 GLenum filter) { | 543 GLenum filter) { |
| (...skipping 3852 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4230 visitor->trace(m_boundCopyWriteBuffer); | 4396 visitor->trace(m_boundCopyWriteBuffer); |
| 4231 visitor->trace(m_boundPixelPackBuffer); | 4397 visitor->trace(m_boundPixelPackBuffer); |
| 4232 visitor->trace(m_boundPixelUnpackBuffer); | 4398 visitor->trace(m_boundPixelUnpackBuffer); |
| 4233 visitor->trace(m_boundTransformFeedbackBuffer); | 4399 visitor->trace(m_boundTransformFeedbackBuffer); |
| 4234 visitor->trace(m_boundUniformBuffer); | 4400 visitor->trace(m_boundUniformBuffer); |
| 4235 visitor->trace(m_boundIndexedTransformFeedbackBuffers); | 4401 visitor->trace(m_boundIndexedTransformFeedbackBuffers); |
| 4236 visitor->trace(m_boundIndexedUniformBuffers); | 4402 visitor->trace(m_boundIndexedUniformBuffers); |
| 4237 visitor->trace(m_currentBooleanOcclusionQuery); | 4403 visitor->trace(m_currentBooleanOcclusionQuery); |
| 4238 visitor->trace(m_currentTransformFeedbackPrimitivesWrittenQuery); | 4404 visitor->trace(m_currentTransformFeedbackPrimitivesWrittenQuery); |
| 4239 visitor->trace(m_samplerUnits); | 4405 visitor->trace(m_samplerUnits); |
| 4406 visitor->trace(m_getBufferSubDataAsyncCallbacks); |
| 4240 WebGLRenderingContextBase::trace(visitor); | 4407 WebGLRenderingContextBase::trace(visitor); |
| 4241 } | 4408 } |
| 4242 | 4409 |
| 4243 DEFINE_TRACE_WRAPPERS(WebGL2RenderingContextBase) { | 4410 DEFINE_TRACE_WRAPPERS(WebGL2RenderingContextBase) { |
| 4244 if (isContextLost()) { | 4411 if (isContextLost()) { |
| 4245 return; | 4412 return; |
| 4246 } | 4413 } |
| 4247 | 4414 |
| 4248 visitor->traceWrappers(m_transformFeedbackBinding); | 4415 visitor->traceWrappers(m_transformFeedbackBinding); |
| 4249 visitor->traceWrappers(m_readFramebufferBinding); | 4416 visitor->traceWrappers(m_readFramebufferBinding); |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4388 case GL_STATIC_COPY: | 4555 case GL_STATIC_COPY: |
| 4389 case GL_DYNAMIC_READ: | 4556 case GL_DYNAMIC_READ: |
| 4390 case GL_DYNAMIC_COPY: | 4557 case GL_DYNAMIC_COPY: |
| 4391 return true; | 4558 return true; |
| 4392 default: | 4559 default: |
| 4393 return WebGLRenderingContextBase::validateBufferDataUsage(functionName, | 4560 return WebGLRenderingContextBase::validateBufferDataUsage(functionName, |
| 4394 usage); | 4561 usage); |
| 4395 } | 4562 } |
| 4396 } | 4563 } |
| 4397 | 4564 |
| 4565 const char* WebGL2RenderingContextBase::validateGetBufferSubData( |
| 4566 const char* functionName, |
| 4567 GLenum target, |
| 4568 GLintptr sourceByteOffset, |
| 4569 DOMArrayBufferView* destinationArrayBufferView, |
| 4570 GLuint destinationOffset, |
| 4571 GLuint length, |
| 4572 WebGLBuffer** outSourceBuffer, |
| 4573 void** outDestinationDataPtr, |
| 4574 long long* outDestinationByteLength) { |
| 4575 if (isContextLost()) { |
| 4576 return "Context lost"; |
| 4577 } |
| 4578 |
| 4579 if (!validateValueFitNonNegInt32(functionName, "srcByteOffset", |
| 4580 sourceByteOffset)) { |
| 4581 return "Invalid value: srcByteOffset"; |
| 4582 } |
| 4583 if (target == GL_TRANSFORM_FEEDBACK_BUFFER && m_currentProgram && |
| 4584 m_currentProgram->activeTransformFeedbackCount()) { |
| 4585 synthesizeGLError(GL_INVALID_OPERATION, functionName, |
| 4586 "targeted transform feedback buffer is active"); |
| 4587 return "Invalid operation: targeted transform feedback buffer is active"; |
| 4588 } |
| 4589 |
| 4590 WebGLBuffer* sourceBuffer = validateBufferDataTarget(functionName, target); |
| 4591 if (!sourceBuffer) { |
| 4592 return "Invalid operation: no buffer bound to target"; |
| 4593 } |
| 4594 *outSourceBuffer = sourceBuffer; |
| 4595 |
| 4596 if (!validateSubSourceAndGetData( |
| 4597 destinationArrayBufferView, destinationOffset, length, |
| 4598 outDestinationDataPtr, outDestinationByteLength)) { |
| 4599 synthesizeGLError(GL_INVALID_VALUE, functionName, "overflow of dstData"); |
| 4600 return "Invalid value: overflow of dstData"; |
| 4601 } |
| 4602 |
| 4603 return nullptr; |
| 4604 } |
| 4605 |
| 4606 const char* WebGL2RenderingContextBase::validateGetBufferSubDataBounds( |
| 4607 const char* functionName, |
| 4608 WebGLBuffer* sourceBuffer, |
| 4609 GLintptr sourceByteOffset, |
| 4610 long long destinationByteLength) { |
| 4611 CheckedNumeric<long long> srcEnd = sourceByteOffset; |
| 4612 srcEnd += destinationByteLength; |
| 4613 if (!srcEnd.IsValid() || srcEnd.ValueOrDie() > sourceBuffer->getSize()) { |
| 4614 synthesizeGLError(GL_INVALID_VALUE, functionName, |
| 4615 "overflow of bound buffer"); |
| 4616 return "Invalid value: overflow of bound buffer"; |
| 4617 } |
| 4618 |
| 4619 return nullptr; |
| 4620 } |
| 4621 |
| 4398 void WebGL2RenderingContextBase::removeBoundBuffer(WebGLBuffer* buffer) { | 4622 void WebGL2RenderingContextBase::removeBoundBuffer(WebGLBuffer* buffer) { |
| 4399 if (m_boundCopyReadBuffer == buffer) | 4623 if (m_boundCopyReadBuffer == buffer) |
| 4400 m_boundCopyReadBuffer = nullptr; | 4624 m_boundCopyReadBuffer = nullptr; |
| 4401 if (m_boundCopyWriteBuffer == buffer) | 4625 if (m_boundCopyWriteBuffer == buffer) |
| 4402 m_boundCopyWriteBuffer = nullptr; | 4626 m_boundCopyWriteBuffer = nullptr; |
| 4403 if (m_boundPixelPackBuffer == buffer) | 4627 if (m_boundPixelPackBuffer == buffer) |
| 4404 m_boundPixelPackBuffer = nullptr; | 4628 m_boundPixelPackBuffer = nullptr; |
| 4405 if (m_boundPixelUnpackBuffer == buffer) | 4629 if (m_boundPixelUnpackBuffer == buffer) |
| 4406 m_boundPixelUnpackBuffer = nullptr; | 4630 m_boundPixelUnpackBuffer = nullptr; |
| 4407 if (m_boundTransformFeedbackBuffer == buffer) | 4631 if (m_boundTransformFeedbackBuffer == buffer) |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4481 params.skipPixels = m_unpackSkipPixels; | 4705 params.skipPixels = m_unpackSkipPixels; |
| 4482 params.skipRows = m_unpackSkipRows; | 4706 params.skipRows = m_unpackSkipRows; |
| 4483 if (dimension == Tex3D) { | 4707 if (dimension == Tex3D) { |
| 4484 params.imageHeight = m_unpackImageHeight; | 4708 params.imageHeight = m_unpackImageHeight; |
| 4485 params.skipImages = m_unpackSkipImages; | 4709 params.skipImages = m_unpackSkipImages; |
| 4486 } | 4710 } |
| 4487 return params; | 4711 return params; |
| 4488 } | 4712 } |
| 4489 | 4713 |
| 4490 } // namespace blink | 4714 } // namespace blink |
| OLD | NEW |