| 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 size_t getViewTypeSize(WTF::ArrayBufferView::ViewType viewType) |
| 45 { |
| 46 switch (viewType) { |
| 47 case WTF::ArrayBufferView::TypeInt8: |
| 48 case WTF::ArrayBufferView::TypeUint8: |
| 49 case WTF::ArrayBufferView::TypeUint8Clamped: |
| 50 return 1; |
| 51 case WTF::ArrayBufferView::TypeInt16: |
| 52 case WTF::ArrayBufferView::TypeUint16: |
| 53 return 2; |
| 54 case WTF::ArrayBufferView::TypeInt32: |
| 55 case WTF::ArrayBufferView::TypeUint32: |
| 56 case WTF::ArrayBufferView::TypeFloat32: |
| 57 return 4; |
| 58 case WTF::ArrayBufferView::TypeFloat64: |
| 59 return 8; |
| 60 case WTF::ArrayBufferView::TypeDataView: |
| 61 return 1; |
| 62 default: |
| 63 NOTREACHED(); |
| 64 return 0; |
| 65 } |
| 66 } |
| 67 |
| 68 bool validateSubSourceAndGetData(DOMArrayBufferView* view, GLuint subOffset, GLu
int subLength, void** outBaseAddress, long long* outByteLength) |
| 69 { |
| 70 // This is guaranteed to be non-null by DOM. |
| 71 DCHECK(view); |
| 72 |
| 73 size_t typeSize = getViewTypeSize(view->type()); |
| 74 DCHECK_GE(8u, typeSize); |
| 75 long long byteLength = 0; |
| 76 if (subLength) { |
| 77 // type size is at most 8, so no overflow. |
| 78 byteLength = subLength * typeSize; |
| 79 } |
| 80 long long byteOffset = 0; |
| 81 if (subOffset) { |
| 82 // type size is at most 8, so no overflow. |
| 83 byteOffset = subOffset * typeSize; |
| 84 } |
| 85 CheckedInt<long long> total = byteOffset; |
| 86 total += byteLength; |
| 87 if (!total.isValid() || total.value() > view->byteLength()) { |
| 88 return false; |
| 89 } |
| 90 if (!byteLength) { |
| 91 byteLength = view->byteLength() - byteOffset; |
| 92 } |
| 93 uint8_t* data = static_cast<uint8_t*>(view->baseAddress()); |
| 94 data += byteOffset; |
| 95 *outBaseAddress = data; |
| 96 *outByteLength = byteLength; |
| 97 return true; |
| 98 } |
| 99 |
| 44 } // namespace | 100 } // namespace |
| 45 | 101 |
| 46 // These enums are from manual pages for glTexStorage2D/glTexStorage3D. | 102 // These enums are from manual pages for glTexStorage2D/glTexStorage3D. |
| 47 const GLenum kSupportedInternalFormatsStorage[] = { | 103 const GLenum kSupportedInternalFormatsStorage[] = { |
| 48 GL_R8, | 104 GL_R8, |
| 49 GL_R8_SNORM, | 105 GL_R8_SNORM, |
| 50 GL_R16F, | 106 GL_R16F, |
| 51 GL_R32F, | 107 GL_R32F, |
| 52 GL_R8UI, | 108 GL_R8UI, |
| 53 GL_R8I, | 109 GL_R8I, |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 176 m_packSkipRows = 0; | 232 m_packSkipRows = 0; |
| 177 m_unpackRowLength = 0; | 233 m_unpackRowLength = 0; |
| 178 m_unpackImageHeight = 0; | 234 m_unpackImageHeight = 0; |
| 179 m_unpackSkipPixels = 0; | 235 m_unpackSkipPixels = 0; |
| 180 m_unpackSkipRows = 0; | 236 m_unpackSkipRows = 0; |
| 181 m_unpackSkipImages = 0; | 237 m_unpackSkipImages = 0; |
| 182 | 238 |
| 183 WebGLRenderingContextBase::initializeNewContext(); | 239 WebGLRenderingContextBase::initializeNewContext(); |
| 184 } | 240 } |
| 185 | 241 |
| 242 void WebGL2RenderingContextBase::bufferData(GLenum target, DOMArrayBufferView* s
rcData, GLenum usage, GLuint srcOffset, GLuint length) |
| 243 { |
| 244 if (isContextLost()) |
| 245 return; |
| 246 void* subBaseAddress = nullptr; |
| 247 long long subByteLength = 0; |
| 248 if (!validateSubSourceAndGetData(srcData, srcOffset, length, &subBaseAddress
, &subByteLength)) { |
| 249 synthesizeGLError(GL_INVALID_VALUE, "bufferData", "srcOffset + length to
o large"); |
| 250 return; |
| 251 } |
| 252 bufferDataImpl(target, subByteLength, subBaseAddress, usage); |
| 253 } |
| 254 |
| 255 void WebGL2RenderingContextBase::bufferData(GLenum target, long long size, GLenu
m usage) |
| 256 { |
| 257 WebGLRenderingContextBase::bufferData(target, size, usage); |
| 258 } |
| 259 |
| 260 void WebGL2RenderingContextBase::bufferData(GLenum target, DOMArrayBuffer* data,
GLenum usage) |
| 261 { |
| 262 WebGLRenderingContextBase::bufferData(target, data, usage); |
| 263 } |
| 264 |
| 265 void WebGL2RenderingContextBase::bufferData(GLenum target, DOMArrayBufferView* d
ata, GLenum usage) |
| 266 { |
| 267 WebGLRenderingContextBase::bufferData(target, data, usage); |
| 268 } |
| 269 |
| 270 void WebGL2RenderingContextBase::bufferSubData(GLenum target, GLintptr dstByteOf
fset, DOMArrayBufferView* srcData, GLuint srcOffset, GLuint length) |
| 271 { |
| 272 if (isContextLost()) |
| 273 return; |
| 274 void* subBaseAddress = nullptr; |
| 275 long long subByteLength = 0; |
| 276 if (!validateSubSourceAndGetData(srcData, srcOffset, length, &subBaseAddress
, &subByteLength)) { |
| 277 synthesizeGLError(GL_INVALID_VALUE, "bufferSubData", "srcOffset + length
too large"); |
| 278 return; |
| 279 } |
| 280 bufferSubDataImpl(target, dstByteOffset, subByteLength, subBaseAddress); |
| 281 } |
| 282 |
| 283 void WebGL2RenderingContextBase::bufferSubData(GLenum target, long long offset,
DOMArrayBuffer* data) |
| 284 { |
| 285 WebGLRenderingContextBase::bufferSubData(target, offset, data); |
| 286 } |
| 287 |
| 288 void WebGL2RenderingContextBase::bufferSubData(GLenum target, long long offset,
const FlexibleArrayBufferView& data) |
| 289 { |
| 290 WebGLRenderingContextBase::bufferSubData(target, offset, data); |
| 291 } |
| 292 |
| 186 void WebGL2RenderingContextBase::copyBufferSubData(GLenum readTarget, GLenum wri
teTarget, long long readOffset, long long writeOffset, long long size) | 293 void WebGL2RenderingContextBase::copyBufferSubData(GLenum readTarget, GLenum wri
teTarget, long long readOffset, long long writeOffset, long long size) |
| 187 { | 294 { |
| 188 if (isContextLost()) | 295 if (isContextLost()) |
| 189 return; | 296 return; |
| 190 | 297 |
| 191 if (!validateValueFitNonNegInt32("copyBufferSubData", "readOffset", readOffs
et) | 298 if (!validateValueFitNonNegInt32("copyBufferSubData", "readOffset", readOffs
et) |
| 192 || !validateValueFitNonNegInt32("copyBufferSubData", "writeOffset", writ
eOffset) | 299 || !validateValueFitNonNegInt32("copyBufferSubData", "writeOffset", writ
eOffset) |
| 193 || !validateValueFitNonNegInt32("copyBufferSubData", "size", size)) { | 300 || !validateValueFitNonNegInt32("copyBufferSubData", "size", size)) { |
| 194 return; | 301 return; |
| 195 } | 302 } |
| (...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"); | 319 synthesizeGLError(GL_INVALID_OPERATION, "copyBufferSubData", "Cannot cop
y into an element buffer destination from a non-element buffer source"); |
| 213 return; | 320 return; |
| 214 } | 321 } |
| 215 | 322 |
| 216 if (writeBuffer->getInitialTarget() == 0) | 323 if (writeBuffer->getInitialTarget() == 0) |
| 217 writeBuffer->setInitialTarget(readBuffer->getInitialTarget()); | 324 writeBuffer->setInitialTarget(readBuffer->getInitialTarget()); |
| 218 | 325 |
| 219 contextGL()->CopyBufferSubData(readTarget, writeTarget, static_cast<GLintptr
>(readOffset), static_cast<GLintptr>(writeOffset), static_cast<GLsizeiptr>(size)
); | 326 contextGL()->CopyBufferSubData(readTarget, writeTarget, static_cast<GLintptr
>(readOffset), static_cast<GLintptr>(writeOffset), static_cast<GLsizeiptr>(size)
); |
| 220 } | 327 } |
| 221 | 328 |
| 222 void WebGL2RenderingContextBase::getBufferSubData(GLenum target, long long offse
t, DOMArrayBuffer* returnedData) | 329 void WebGL2RenderingContextBase::getBufferSubData(GLenum target, long long srcBy
teOffset, DOMArrayBufferView* dstData, GLuint dstOffset, GLuint length) |
| 223 { | 330 { |
| 331 const char* funcName = "getBufferSubData"; |
| 224 if (isContextLost()) | 332 if (isContextLost()) |
| 225 return; | 333 return; |
| 226 | 334 if (!validateValueFitNonNegInt32(funcName, "srcByteOffset", srcByteOffset))
{ |
| 227 if (!returnedData) { | 335 return; |
| 228 synthesizeGLError(GL_INVALID_VALUE, "getBufferSubData", "ArrayBuffer can
not be null"); | 336 } |
| 337 WebGLBuffer* buffer = validateBufferDataTarget(funcName, target); |
| 338 if (!buffer) |
| 339 return; |
| 340 void* subBaseAddress = nullptr; |
| 341 long long subByteLength = 0; |
| 342 if (!validateSubSourceAndGetData(dstData, dstOffset, length, &subBaseAddress
, &subByteLength)) { |
| 343 synthesizeGLError(GL_INVALID_VALUE, funcName, "buffer overflow"); |
| 229 return; | 344 return; |
| 230 } | 345 } |
| 231 | 346 |
| 232 if (!validateValueFitNonNegInt32("getBufferSubData", "offset", offset)) { | 347 void* mappedData = contextGL()->MapBufferRange(target, static_cast<GLintptr>
(srcByteOffset), subByteLength, 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 | 348 |
| 246 if (!mappedData) | 349 if (!mappedData) |
| 247 return; | 350 return; |
| 248 | 351 |
| 249 memcpy(returnedData->data(), mappedData, returnedData->byteLength()); | 352 memcpy(subBaseAddress, mappedData, subByteLength); |
| 250 | 353 |
| 251 contextGL()->UnmapBuffer(target); | 354 contextGL()->UnmapBuffer(target); |
| 252 } | 355 } |
| 253 | 356 |
| 357 void WebGL2RenderingContextBase::getBufferSubData(GLenum target, long long srcBy
teOffset, DOMArrayBuffer* dstData) |
| 358 { |
| 359 const char* funcName = "getBufferSubData"; |
| 360 if (isContextLost()) |
| 361 return; |
| 362 |
| 363 if (!dstData) { |
| 364 synthesizeGLError(GL_INVALID_VALUE, funcName, "ArrayBuffer can not be nu
ll"); |
| 365 return; |
| 366 } |
| 367 if (!validateValueFitNonNegInt32(funcName, "srcByteOffset", srcByteOffset))
{ |
| 368 return; |
| 369 } |
| 370 WebGLBuffer* buffer = validateBufferDataTarget(funcName, target); |
| 371 if (!buffer) |
| 372 return; |
| 373 if (srcByteOffset + dstData->byteLength() > buffer->getSize()) { |
| 374 synthesizeGLError(GL_INVALID_VALUE, funcName, "buffer overflow"); |
| 375 return; |
| 376 } |
| 377 |
| 378 void* mappedData = contextGL()->MapBufferRange(target, static_cast<GLintptr>
(srcByteOffset), dstData->byteLength(), GL_MAP_READ_BIT); |
| 379 if (!mappedData) |
| 380 return; |
| 381 memcpy(dstData->data(), mappedData, dstData->byteLength()); |
| 382 contextGL()->UnmapBuffer(target); |
| 383 } |
| 384 |
| 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) | 385 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 { | 386 { |
| 256 if (isContextLost()) | 387 if (isContextLost()) |
| 257 return; | 388 return; |
| 258 | 389 |
| 259 contextGL()->BlitFramebufferCHROMIUM(srcX0, srcY0, srcX1, srcY1, dstX0, dstY
0, dstX1, dstY1, mask, filter); | 390 contextGL()->BlitFramebufferCHROMIUM(srcX0, srcY0, srcX1, srcY1, dstX0, dstY
0, dstX1, dstY1, mask, filter); |
| 260 } | 391 } |
| 261 | 392 |
| 262 bool WebGL2RenderingContextBase::validateTexFuncLayer(const char* functionName,
GLenum texTarget, GLint layer) | 393 bool WebGL2RenderingContextBase::validateTexFuncLayer(const char* functionName,
GLenum texTarget, GLint layer) |
| 263 { | 394 { |
| (...skipping 3097 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3361 params.skipPixels = m_unpackSkipPixels; | 3492 params.skipPixels = m_unpackSkipPixels; |
| 3362 params.skipRows = m_unpackSkipRows; | 3493 params.skipRows = m_unpackSkipRows; |
| 3363 if (dimension == Tex3D) { | 3494 if (dimension == Tex3D) { |
| 3364 params.imageHeight = m_unpackImageHeight; | 3495 params.imageHeight = m_unpackImageHeight; |
| 3365 params.skipImages = m_unpackSkipImages; | 3496 params.skipImages = m_unpackSkipImages; |
| 3366 } | 3497 } |
| 3367 return params; | 3498 return params; |
| 3368 } | 3499 } |
| 3369 | 3500 |
| 3370 } // namespace blink | 3501 } // namespace blink |
| OLD | NEW |