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/frame/ImageBitmap.h" | 8 #include "core/frame/ImageBitmap.h" |
| 9 #include "core/html/HTMLCanvasElement.h" | 9 #include "core/html/HTMLCanvasElement.h" |
| 10 #include "core/html/HTMLImageElement.h" | 10 #include "core/html/HTMLImageElement.h" |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 34 | 34 |
| 35 namespace blink { | 35 namespace blink { |
| 36 | 36 |
| 37 namespace { | 37 namespace { |
| 38 | 38 |
| 39 GLsync syncObjectOrZero(const WebGLSync* object) | 39 GLsync syncObjectOrZero(const WebGLSync* object) |
| 40 { | 40 { |
| 41 return object ? object->object() : nullptr; | 41 return object ? object->object() : nullptr; |
| 42 } | 42 } |
| 43 | 43 |
| 44 class SubArrayBufferView { | |
| 45 public: | |
| 46 SubArrayBufferView(WTF::ArrayBufferView::ViewType viewType, void* viewBaseAd dress, long long viewByteLength, GLuint subOffset, GLuint subLength) | |
|
Ken Russell (switch to Gerrit)
2016/08/20 03:05:35
Is "long long" the best type to use for viewByteLe
Zhenyao Mo
2016/08/20 03:44:23
This is to match all the other byteLength types in
| |
| 47 : m_viewType(viewType) | |
| 48 , m_viewBaseAddress(viewBaseAddress) | |
| 49 , m_viewByteLength(viewByteLength) | |
| 50 , m_subOffset(subOffset) | |
| 51 , m_subLength(subLength) | |
|
Ken Russell (switch to Gerrit)
2016/08/20 03:05:35
Since initialize() returns void, what about moving
Zhenyao Mo
2016/08/20 03:44:23
That was my original design, but I remmebered we a
Ken Russell (switch to Gerrit)
2016/08/20 04:03:34
I think it'd be OK, and quite a bit simpler.
Zhenyao Mo
2016/08/23 00:22:42
Done.
| |
| 52 , m_initialized(false) | |
| 53 , m_subBaseAddress(nullptr) | |
| 54 , m_subByteLength(0) | |
| 55 , m_valid(false) | |
| 56 { | |
| 57 } | |
| 58 | |
| 59 bool isValid() | |
| 60 { | |
| 61 initialize(); | |
|
Ken Russell (switch to Gerrit)
2016/08/20 03:05:35
Per above, suggest moving the call to initialize()
| |
| 62 return m_valid; | |
| 63 } | |
| 64 | |
| 65 void* baseAddress() const | |
| 66 { | |
| 67 DCHECK(m_initialized); | |
| 68 return m_subBaseAddress; | |
| 69 } | |
| 70 | |
| 71 long long byteLength() const | |
| 72 { | |
| 73 DCHECK(m_initialized); | |
| 74 return m_subByteLength; | |
| 75 } | |
| 76 | |
| 77 private: | |
| 78 void initialize() | |
| 79 { | |
| 80 if (m_initialized) | |
| 81 return; | |
| 82 m_initialized = true; | |
| 83 size_t typeSize = getViewTypeSize(m_viewType); | |
| 84 DCHECK_GE(8u, typeSize); | |
| 85 long long byteLength = 0; | |
| 86 if (m_subLength) { | |
| 87 // type size is at most 8, so no overflow. | |
| 88 byteLength = m_subLength * typeSize; | |
| 89 } | |
| 90 long long byteOffset = 0; | |
| 91 if (m_subOffset) { | |
| 92 // type size is at most 8, so no overflow. | |
| 93 byteOffset = m_subOffset * typeSize; | |
| 94 } | |
| 95 CheckedInt<long long> total = byteOffset; | |
| 96 total += byteLength; | |
| 97 if (!total.isValid() || total.value() > m_viewByteLength) { | |
| 98 return; | |
| 99 } | |
|
Ken Russell (switch to Gerrit)
2016/08/20 03:05:35
Should there be a separate check like:
if (!byt
Zhenyao Mo
2016/08/20 03:44:23
Looking at bufferSubData, where the offset is beyo
Ken Russell (switch to Gerrit)
2016/08/20 04:05:55
As long as the tests verify this, sounds good. It'
| |
| 100 if (!byteLength) { | |
| 101 byteLength = m_viewByteLength - byteOffset; | |
| 102 } | |
| 103 uint8_t* data = static_cast<uint8_t*>(m_viewBaseAddress); | |
| 104 data += byteOffset; | |
|
Ken Russell (switch to Gerrit)
2016/08/20 03:05:35
Any possibility of overflow on the address? Should
Zhenyao Mo
2016/08/20 03:44:23
We already checked byteOffset is within the ArrayB
| |
| 105 m_subBaseAddress = data; | |
| 106 m_subByteLength = byteLength; | |
| 107 m_valid = true; | |
| 108 } | |
| 109 | |
| 110 static size_t getViewTypeSize(WTF::ArrayBufferView::ViewType viewType) | |
| 111 { | |
| 112 switch (viewType) { | |
| 113 case WTF::ArrayBufferView::TypeInt8: | |
| 114 case WTF::ArrayBufferView::TypeUint8: | |
| 115 case WTF::ArrayBufferView::TypeUint8Clamped: | |
| 116 return 1; | |
| 117 case WTF::ArrayBufferView::TypeInt16: | |
| 118 case WTF::ArrayBufferView::TypeUint16: | |
| 119 return 2; | |
| 120 case WTF::ArrayBufferView::TypeInt32: | |
| 121 case WTF::ArrayBufferView::TypeUint32: | |
| 122 case WTF::ArrayBufferView::TypeFloat32: | |
| 123 return 4; | |
| 124 case WTF::ArrayBufferView::TypeFloat64: | |
| 125 return 8; | |
| 126 case WTF::ArrayBufferView::TypeDataView: | |
| 127 return 1; | |
| 128 default: | |
| 129 NOTREACHED(); | |
| 130 return 0; | |
| 131 } | |
| 132 } | |
| 133 | |
| 134 WTF::ArrayBufferView::ViewType m_viewType; | |
| 135 void* m_viewBaseAddress; | |
| 136 long long m_viewByteLength; | |
| 137 GLuint m_subOffset; | |
| 138 GLuint m_subLength; | |
| 139 | |
| 140 bool m_initialized; | |
|
Ken Russell (switch to Gerrit)
2016/08/20 03:05:35
I think it's possible and desirable to eliminate a
Zhenyao Mo
2016/08/20 03:44:23
Now I think again, we can actually just do this in
| |
| 141 | |
| 142 void* m_subBaseAddress; | |
| 143 long long m_subByteLength; | |
| 144 bool m_valid; | |
| 145 }; | |
| 146 | |
| 44 } // namespace | 147 } // namespace |
| 45 | 148 |
| 46 // These enums are from manual pages for glTexStorage2D/glTexStorage3D. | 149 // These enums are from manual pages for glTexStorage2D/glTexStorage3D. |
| 47 const GLenum kSupportedInternalFormatsStorage[] = { | 150 const GLenum kSupportedInternalFormatsStorage[] = { |
| 48 GL_R8, | 151 GL_R8, |
| 49 GL_R8_SNORM, | 152 GL_R8_SNORM, |
| 50 GL_R16F, | 153 GL_R16F, |
| 51 GL_R32F, | 154 GL_R32F, |
| 52 GL_R8UI, | 155 GL_R8UI, |
| 53 GL_R8I, | 156 GL_R8I, |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 176 m_packSkipRows = 0; | 279 m_packSkipRows = 0; |
| 177 m_unpackRowLength = 0; | 280 m_unpackRowLength = 0; |
| 178 m_unpackImageHeight = 0; | 281 m_unpackImageHeight = 0; |
| 179 m_unpackSkipPixels = 0; | 282 m_unpackSkipPixels = 0; |
| 180 m_unpackSkipRows = 0; | 283 m_unpackSkipRows = 0; |
| 181 m_unpackSkipImages = 0; | 284 m_unpackSkipImages = 0; |
| 182 | 285 |
| 183 WebGLRenderingContextBase::initializeNewContext(); | 286 WebGLRenderingContextBase::initializeNewContext(); |
| 184 } | 287 } |
| 185 | 288 |
| 289 void WebGL2RenderingContextBase::bufferData(GLenum target, DOMArrayBufferView* s rcData, GLenum usage, GLuint srcOffset, GLuint length) | |
| 290 { | |
| 291 if (isContextLost()) | |
| 292 return; | |
| 293 DCHECK(srcData); | |
|
Ken Russell (switch to Gerrit)
2016/08/20 03:05:35
Maybe worth adding a comment that this is guarante
Zhenyao Mo
2016/08/20 03:44:23
Will do.
| |
| 294 SubArrayBufferView subView(srcData->type(), srcData->baseAddress(), srcData- >byteLength(), srcOffset, length); | |
|
Ken Russell (switch to Gerrit)
2016/08/20 03:05:35
Perhaps the SubArrayBufferView constructor should
Zhenyao Mo
2016/08/20 03:44:23
The reason I didn't pass DOMArrayBufferView is tha
| |
| 295 if (!subView.isValid()) { | |
| 296 synthesizeGLError(GL_INVALID_VALUE, "bufferData", "srcOffset + length to o large"); | |
| 297 return; | |
| 298 } | |
| 299 bufferDataImpl(target, subView.byteLength(), subView.baseAddress(), usage); | |
| 300 } | |
| 301 | |
| 302 void WebGL2RenderingContextBase::bufferData(GLenum target, long long size, GLenu m usage) | |
| 303 { | |
| 304 WebGLRenderingContextBase::bufferData(target, size, usage); | |
| 305 } | |
| 306 | |
| 307 void WebGL2RenderingContextBase::bufferData(GLenum target, DOMArrayBuffer* data, GLenum usage) | |
| 308 { | |
| 309 WebGLRenderingContextBase::bufferData(target, data, usage); | |
| 310 } | |
| 311 | |
| 312 void WebGL2RenderingContextBase::bufferData(GLenum target, DOMArrayBufferView* d ata, GLenum usage) | |
| 313 { | |
| 314 WebGLRenderingContextBase::bufferData(target, data, usage); | |
| 315 } | |
| 316 | |
| 317 void WebGL2RenderingContextBase::bufferSubData(GLenum target, GLintptr dstByteOf fset, DOMArrayBufferView* srcData, GLuint srcOffset, GLuint length) | |
| 318 { | |
| 319 if (isContextLost()) | |
| 320 return; | |
| 321 DCHECK(srcData); | |
| 322 SubArrayBufferView subView(srcData->type(), srcData->baseAddress(), srcData- >byteLength(), srcOffset, length); | |
| 323 if (!subView.isValid()) { | |
| 324 synthesizeGLError(GL_INVALID_VALUE, "bufferSubData", "srcOffset + length too large"); | |
| 325 return; | |
| 326 } | |
| 327 bufferSubDataImpl(target, dstByteOffset, subView.byteLength(), subView.baseA ddress()); | |
| 328 } | |
| 329 | |
| 330 void WebGL2RenderingContextBase::bufferSubData(GLenum target, long long offset, DOMArrayBuffer* data) | |
| 331 { | |
| 332 WebGLRenderingContextBase::bufferSubData(target, offset, data); | |
| 333 } | |
| 334 | |
| 335 void WebGL2RenderingContextBase::bufferSubData(GLenum target, long long offset, const FlexibleArrayBufferView& data) | |
| 336 { | |
| 337 WebGLRenderingContextBase::bufferSubData(target, offset, data); | |
| 338 } | |
| 339 | |
| 186 void WebGL2RenderingContextBase::copyBufferSubData(GLenum readTarget, GLenum wri teTarget, long long readOffset, long long writeOffset, long long size) | 340 void WebGL2RenderingContextBase::copyBufferSubData(GLenum readTarget, GLenum wri teTarget, long long readOffset, long long writeOffset, long long size) |
| 187 { | 341 { |
| 188 if (isContextLost()) | 342 if (isContextLost()) |
| 189 return; | 343 return; |
| 190 | 344 |
| 191 if (!validateValueFitNonNegInt32("copyBufferSubData", "readOffset", readOffs et) | 345 if (!validateValueFitNonNegInt32("copyBufferSubData", "readOffset", readOffs et) |
| 192 || !validateValueFitNonNegInt32("copyBufferSubData", "writeOffset", writ eOffset) | 346 || !validateValueFitNonNegInt32("copyBufferSubData", "writeOffset", writ eOffset) |
| 193 || !validateValueFitNonNegInt32("copyBufferSubData", "size", size)) { | 347 || !validateValueFitNonNegInt32("copyBufferSubData", "size", size)) { |
| 194 return; | 348 return; |
| 195 } | 349 } |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 212 synthesizeGLError(GL_INVALID_OPERATION, "copyBufferSubData", "Cannot cop y into an element buffer destination from a non-element buffer source"); | 366 synthesizeGLError(GL_INVALID_OPERATION, "copyBufferSubData", "Cannot cop y into an element buffer destination from a non-element buffer source"); |
| 213 return; | 367 return; |
| 214 } | 368 } |
| 215 | 369 |
| 216 if (writeBuffer->getInitialTarget() == 0) | 370 if (writeBuffer->getInitialTarget() == 0) |
| 217 writeBuffer->setInitialTarget(readBuffer->getInitialTarget()); | 371 writeBuffer->setInitialTarget(readBuffer->getInitialTarget()); |
| 218 | 372 |
| 219 contextGL()->CopyBufferSubData(readTarget, writeTarget, static_cast<GLintptr >(readOffset), static_cast<GLintptr>(writeOffset), static_cast<GLsizeiptr>(size) ); | 373 contextGL()->CopyBufferSubData(readTarget, writeTarget, static_cast<GLintptr >(readOffset), static_cast<GLintptr>(writeOffset), static_cast<GLsizeiptr>(size) ); |
| 220 } | 374 } |
| 221 | 375 |
| 222 void WebGL2RenderingContextBase::getBufferSubData(GLenum target, long long offse t, DOMArrayBuffer* returnedData) | 376 void WebGL2RenderingContextBase::getBufferSubData(GLenum target, long long srcBy teOffset, DOMArrayBufferView* dstData, GLuint dstOffset, GLuint length) |
| 223 { | 377 { |
| 378 const char* funcName = "getBufferSubData"; | |
| 224 if (isContextLost()) | 379 if (isContextLost()) |
| 225 return; | 380 return; |
| 381 if (!validateValueFitNonNegInt32(funcName, "srcByteOffset", srcByteOffset)) { | |
| 382 return; | |
| 383 } | |
| 384 WebGLBuffer* buffer = validateBufferDataTarget(funcName, target); | |
| 385 if (!buffer) | |
| 386 return; | |
| 387 DCHECK(dstData); | |
| 388 SubArrayBufferView subView(dstData->type(), dstData->baseAddress(), dstData- >byteLength(), dstOffset, length); | |
| 389 if (!subView.isValid()) { | |
| 390 synthesizeGLError(GL_INVALID_VALUE, funcName, "dstOffset + length too la rge"); | |
|
Ken Russell (switch to Gerrit)
2016/08/20 03:05:35
Return too, correct?
Zhenyao Mo
2016/08/20 03:44:23
Ah thanks for catching this.
| |
| 391 } | |
| 226 | 392 |
| 227 if (!returnedData) { | 393 if (srcByteOffset + subView.byteLength() > buffer->getSize()) { |
| 228 synthesizeGLError(GL_INVALID_VALUE, "getBufferSubData", "ArrayBuffer can not be null"); | 394 synthesizeGLError(GL_INVALID_VALUE, funcName, "buffer overflow"); |
| 229 return; | 395 return; |
| 230 } | 396 } |
| 231 | 397 |
| 232 if (!validateValueFitNonNegInt32("getBufferSubData", "offset", offset)) { | 398 void* mappedData = contextGL()->MapBufferRange(target, static_cast<GLintptr> (srcByteOffset), subView.byteLength(), GL_MAP_READ_BIT); |
| 233 return; | |
| 234 } | |
| 235 | |
| 236 WebGLBuffer* buffer = validateBufferDataTarget("getBufferSubData", target); | |
| 237 if (!buffer) | |
| 238 return; | |
| 239 if (offset + returnedData->byteLength() > buffer->getSize()) { | |
| 240 synthesizeGLError(GL_INVALID_VALUE, "getBufferSubData", "buffer overflow "); | |
| 241 return; | |
| 242 } | |
| 243 | |
| 244 void* mappedData = contextGL()->MapBufferRange(target, static_cast<GLintptr> (offset), returnedData->byteLength(), GL_MAP_READ_BIT); | |
| 245 | 399 |
| 246 if (!mappedData) | 400 if (!mappedData) |
| 247 return; | 401 return; |
| 248 | 402 |
| 249 memcpy(returnedData->data(), mappedData, returnedData->byteLength()); | 403 memcpy(subView.baseAddress(), mappedData, subView.byteLength()); |
| 250 | 404 |
| 251 contextGL()->UnmapBuffer(target); | 405 contextGL()->UnmapBuffer(target); |
| 252 } | 406 } |
| 253 | 407 |
| 254 void WebGL2RenderingContextBase::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfi eld mask, GLenum filter) | 408 void WebGL2RenderingContextBase::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfi eld mask, GLenum filter) |
| 255 { | 409 { |
| 256 if (isContextLost()) | 410 if (isContextLost()) |
| 257 return; | 411 return; |
| 258 | 412 |
| 259 contextGL()->BlitFramebufferCHROMIUM(srcX0, srcY0, srcX1, srcY1, dstX0, dstY 0, dstX1, dstY1, mask, filter); | 413 contextGL()->BlitFramebufferCHROMIUM(srcX0, srcY0, srcX1, srcY1, dstX0, dstY 0, dstX1, dstY1, mask, filter); |
| (...skipping 3101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3361 params.skipPixels = m_unpackSkipPixels; | 3515 params.skipPixels = m_unpackSkipPixels; |
| 3362 params.skipRows = m_unpackSkipRows; | 3516 params.skipRows = m_unpackSkipRows; |
| 3363 if (dimension == Tex3D) { | 3517 if (dimension == Tex3D) { |
| 3364 params.imageHeight = m_unpackImageHeight; | 3518 params.imageHeight = m_unpackImageHeight; |
| 3365 params.skipImages = m_unpackSkipImages; | 3519 params.skipImages = m_unpackSkipImages; |
| 3366 } | 3520 } |
| 3367 return params; | 3521 return params; |
| 3368 } | 3522 } |
| 3369 | 3523 |
| 3370 } // namespace blink | 3524 } // namespace blink |
| OLD | NEW |