Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(97)

Side by Side Diff: third_party/WebKit/Source/modules/webgl/WebGL2RenderingContextBase.cpp

Issue 2266563002: Implement buffer{Sub}Data overloads with sub source. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698