2 Copyright (c) 2019 The Khronos Group Inc.
3 Use of this source code is governed by an MIT-style license that can be
4 found in the LICENSE.txt file.
10 <meta charset=
"utf-8">
11 <title>WebGL2 texture unpack parameters with FLIP_Y / PREMULTIPLY_ALPHA conformance test.
</title>
12 <link rel=
"stylesheet" href=
"../../../resources/js-test-style.css"/>
13 <script src=
"../../../js/js-test-pre.js"></script>
14 <script src=
"../../../js/webgl-test-utils.js"></script>
17 <canvas id=
"example" width=
"4" height=
"4"></canvas>
18 <div id=
"description"></div>
19 <div id=
"console"></div>
23 var wtu
= WebGLTestUtils
;
24 var __verbose__
= false;
26 // Some drivers (for example, NVIDIA Linux) incorrectly require padding for
27 // the last row. The below flag is only for testing convenience. Browsers should
28 // work around the bug.
29 var __apply_alignment_workaround__
= false;
31 function setupArrayBuffer(size
, initData
) {
32 var array
= new Uint8Array(size
);
34 for (var ii
= 0; ii
< size
; ++ii
) {
41 function calculatePaddingBytes(bytesPerPixel
, alignment
, width
) {
48 padding
= (bytesPerPixel
* width
) % alignment
;
50 padding
= alignment
- padding
;
53 testFailed("should not reach here");
58 function computeImageSizes2D(width
, height
, testCase
) {
59 // Assume RGBA8/UNSIGNED_BYTE
60 var bytesPerPixel
= 4;
61 var actualWidth
= testCase
.rowLength
== 0 ? width
: testCase
.rowLength
;
62 var padding
= calculatePaddingBytes(bytesPerPixel
, testCase
.alignment
, actualWidth
);
63 var bytesPerRow
= actualWidth
* bytesPerPixel
+ padding
;
64 var bytesLastRow
= bytesPerPixel
* width
;
65 var size
= bytesPerRow
* (height
- 1) + bytesLastRow
;
67 if (testCase
.skipPixels
> 0)
68 skipSize
+= bytesPerPixel
* testCase
.skipPixels
;
69 if (testCase
.skipRows
> 0)
70 skipSize
+= bytesPerRow
* testCase
.skipRows
;
72 bytesPerRow
: bytesPerRow
,
73 bytesLastRow
: bytesLastRow
,
76 totalSize
: size
+ skipSize
};
79 function copyData(srcData
, srcIndex
, dstData
, dstIndex
, size
, premultiply_alpha
) {
80 for (var ii
= 0; ii
< size
/ 4; ++ii
) {
82 if (premultiply_alpha
)
83 factor
= srcData
[srcIndex
+ ii
* 4 + 3] / 255.0;
84 dstData
[dstIndex
+ ii
* 4] = srcData
[srcIndex
+ ii
* 4] * factor
;
85 dstData
[dstIndex
+ ii
* 4 + 1] = srcData
[srcIndex
+ ii
* 4 + 1] * factor
;
86 dstData
[dstIndex
+ ii
* 4 + 2] = srcData
[srcIndex
+ ii
* 4 + 2] * factor
;
87 dstData
[dstIndex
+ ii
* 4 + 3] = srcData
[srcIndex
+ ii
* 4 + 3];
91 function unpackPixels(srcData
, width
, height
, imageSizes
, flip_y
, premultiply_alpha
) {
92 var bytesPerPixel
= 4;
93 var unpackedSize
= width
* height
* bytesPerPixel
;
94 var dstData
= setupArrayBuffer(unpackedSize
, false);
95 var srcIndex
= imageSizes
.skipSize
;
97 var inc
= width
* bytesPerPixel
;
99 dstIndex
+= (height
- 1) * inc
;
100 for (var y
= 0; y
< height
; ++y
) {
101 copyData(srcData
, srcIndex
, dstData
, dstIndex
, width
* bytesPerPixel
, premultiply_alpha
);
102 srcIndex
+= imageSizes
.bytesPerRow
;
109 dstIndex
+= height
* inc
;
113 function getPixelsFromTexture2D(gl
, tex
, xoffset
, yoffset
, width
, height
) {
114 var fbo
= gl
.createFramebuffer();
115 gl
.bindFramebuffer(gl
.FRAMEBUFFER
, fbo
);
116 gl
.framebufferTexture2D(gl
.FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, gl
.TEXTURE_2D
, tex
, 0);
117 var bytesPerReadbackPixel
= 4;
118 var readbackBuffer
= setupArrayBuffer(width
* height
* bytesPerReadbackPixel
, false);
119 gl
.readPixels(xoffset
, yoffset
, width
, height
, gl
.RGBA
, gl
.UNSIGNED_BYTE
, readbackBuffer
);
120 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "read back texture pixels should succeed");
121 gl
.bindFramebuffer(gl
.FRAMEBUFFER
, null);
122 gl
.deleteFramebuffer(fbo
);
123 return readbackBuffer
;
126 function comparePixels(buffer1
, buffer2
, tolerance
) {
127 if (buffer1
.length
!= buffer2
.length
|| buffer1
.length
% 4 != 0) {
128 testFailed("compare pixels: invalid buffer size");
132 for (var ii
= 0; ii
< buffer1
.length
/ 4; ++ii
) {
134 for (var jj
= 0; jj
< 4; ++jj
) {
135 var diff
= buffer1
[ii
* 4 + jj
] - buffer2
[ii
* 4 + jj
];
136 distance
+= diff
* diff
;
138 if (Math
.sqrt(diff
) > tolerance
) {
140 debug("Pixel " + ii
+ ": expected (" +
141 [buffer1
[ii
* 4], buffer1
[ii
* 4 + 1], buffer1
[ii
* 4 + 2], buffer1
[ii
* 4 + 3]] + "), got (" +
142 [buffer2
[ii
* 4], buffer2
[ii
* 4 + 1], buffer2
[ii
* 4 + 2], buffer2
[ii
* 4 + 3]] + ")");
148 testFailed("compare pixels: " + count
+ " pixels differ");
150 testPassed("compare pixels: as expected");
154 function runTestIteration2D(gl
, testCase
, flip_y
, premultiply_alpha
) {
156 debug("Texture upload with : flip_y = " + flip_y
+ ", premultiply_alpha = " + premultiply_alpha
+
157 ", alignment = " + testCase
.alignment
+ ", rowLength = " + testCase
.rowLength
+
158 ", skipPixels = " + testCase
.skipPixels
+ ", skipRows = " + testCase
.skipRows
);
159 debug("TexImage2D : size = (" + testCase
.width
+ ", " + testCase
.height
+ ")");
160 gl
.pixelStorei(gl
.UNPACK_ALIGNMENT
, testCase
.alignment
);
161 gl
.pixelStorei(gl
.UNPACK_ROW_LENGTH
, testCase
.rowLength
);
162 gl
.pixelStorei(gl
.UNPACK_SKIP_PIXELS
, testCase
.skipPixels
);
163 gl
.pixelStorei(gl
.UNPACK_SKIP_ROWS
, testCase
.skipRows
);
164 gl
.pixelStorei(gl
.UNPACK_FLIP_Y_WEBGL
, flip_y
);
165 gl
.pixelStorei(gl
.UNPACK_PREMULTIPLY_ALPHA_WEBGL
, premultiply_alpha
);
166 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "Set up pixel store parameters should succeed");
170 var tex
= gl
.createTexture();
171 gl
.bindTexture(gl
.TEXTURE_2D
, tex
);
173 var imageSizes
= computeImageSizes2D(testCase
.width
, testCase
.height
, testCase
);
174 var bufferSize
= imageSizes
.totalSize
;
177 // Verify buffer with less than enough size will fail.
178 array
= setupArrayBuffer(bufferSize
- 1, false);
179 gl
.texImage2D(gl
.TEXTURE_2D
, 0, gl
.RGBA8
, testCase
.width
, testCase
.height
, 0,
180 gl
.RGBA
, gl
.UNSIGNED_BYTE
, array
);
181 wtu
.glErrorShouldBe(gl
, gl
.INVALID_OPERATION
, "buffer too small");
183 if (__apply_alignment_workaround__
)
184 bufferSize
+= imageSizes
.padding
;
185 array
= setupArrayBuffer(bufferSize
, true);
186 gl
.texImage2D(gl
.TEXTURE_2D
, 0, gl
.RGBA8
, testCase
.width
, testCase
.height
, 0,
187 gl
.RGBA
, gl
.UNSIGNED_BYTE
, array
);
188 if (testCase
.validUnpackParams2D
) {
189 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "texImage2D with correct buffer size should succeed");
191 wtu
.glErrorShouldBe(gl
, gl
.INVALID_OPERATION
, "invalid unpack params combination");
192 gl
.texImage2D(gl
.TEXTURE_2D
, 0, gl
.RGBA8
, testCase
.width
, testCase
.height
, 0,
193 gl
.RGBA
, gl
.UNSIGNED_BYTE
, null);
194 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "unpack param constraints do not apply if no data are uploaded.");
198 var buffer1
= unpackPixels(array
, testCase
.width
, testCase
.height
, imageSizes
, flip_y
, premultiply_alpha
);
199 var buffer2
= getPixelsFromTexture2D(gl
, tex
, 0, 0, testCase
.width
, testCase
.height
);
200 comparePixels(buffer1
, buffer2
, tol
);
202 var subWidth
= testCase
.width
- testCase
.xoffset
;
203 var subHeight
= testCase
.height
- testCase
.yoffset
;
204 debug("TexSubImage2D : offset = (" + testCase
.xoffset
+ ", " + testCase
.yoffset
+
205 "), size = (" + subWidth
+ ", " + subHeight
+ ")");
206 imageSizes
= computeImageSizes2D(subWidth
, subHeight
, testCase
);
207 bufferSize
= imageSizes
.totalSize
;
209 array
= setupArrayBuffer(bufferSize
- 1, false);
210 gl
.texSubImage2D(gl
.TEXTURE_2D
, 0, testCase
.xoffset
, testCase
.yoffset
,
211 subWidth
, subHeight
, gl
.RGBA
, gl
.UNSIGNED_BYTE
, array
);
212 wtu
.glErrorShouldBe(gl
, gl
.INVALID_OPERATION
, "buffer too small");
214 if (__apply_alignment_workaround__
)
215 bufferSize
+= imageSizes
.padding
;
216 array
= setupArrayBuffer(bufferSize
, true);
217 gl
.texSubImage2D(gl
.TEXTURE_2D
, 0, testCase
.xoffset
, testCase
.yoffset
, subWidth
, subHeight
,
218 gl
.RGBA
, gl
.UNSIGNED_BYTE
, array
);
219 if (testCase
.validUnpackParamsForSub2D
) {
220 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "texSubImage2D with correct buffer size should succeed");
222 wtu
.glErrorShouldBe(gl
, gl
.INVALID_OPERATION
, "invalid unpack params combination");
226 var buffer1
= unpackPixels(array
, subWidth
, subHeight
, imageSizes
, flip_y
, premultiply_alpha
);
227 var buffer2
= getPixelsFromTexture2D(
228 gl
, tex
, testCase
.xoffset
, testCase
.yoffset
, subWidth
, subHeight
);
229 comparePixels(buffer1
, buffer2
, tol
);
231 gl
.bindTexture(gl
.TEXTURE_2D
, null);
232 gl
.deleteTexture(tex
);
233 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "no error");
236 function runTests(gl
) {
238 { width
: 5, height
: 7, xoffset
: 2, yoffset
: 3,
239 alignment
: 1, rowLength
: 0, skipPixels
: 0, skipRows
: 0,
240 validUnpackParams2D
: true, validUnpackParamsForSub2D
: true },
241 { width
: 5, height
: 7, xoffset
: 2, yoffset
: 3,
242 alignment
: 2, rowLength
: 0, skipPixels
: 0, skipRows
: 0,
243 validUnpackParams2D
: true, validUnpackParamsForSub2D
: true },
244 { width
: 6, height
: 7, xoffset
: 2, yoffset
: 3,
245 alignment
: 4, rowLength
: 0, skipPixels
: 0, skipRows
: 0,
246 validUnpackParams2D
: true, validUnpackParamsForSub2D
: true },
247 { width
: 5, height
: 8, xoffset
: 2, yoffset
: 3,
248 alignment
: 8, rowLength
: 0, skipPixels
: 0, skipRows
: 0,
249 validUnpackParams2D
: true, validUnpackParamsForSub2D
: true },
251 // ROW_LENGTH == width
252 { width
: 10, height
: 9, xoffset
: 2, yoffset
: 3,
253 alignment
: 4, rowLength
: 10, skipPixels
: 0, skipRows
: 0,
254 validUnpackParams2D
: true, validUnpackParamsForSub2D
: true },
256 // ROW_LENGTH < width
257 { width
: 5, height
: 7, xoffset
: 2, yoffset
: 3,
258 alignment
: 1, rowLength
: 4, skipPixels
: 0, skipRows
: 0,
259 validUnpackParams2D
: false },
260 { width
: 5, height
: 7, xoffset
: 2, yoffset
: 3,
261 alignment
: 2, rowLength
: 4, skipPixels
: 0, skipRows
: 0,
262 validUnpackParams2D
: false },
263 { width
: 5, height
: 7, xoffset
: 2, yoffset
: 3,
264 alignment
: 4, rowLength
: 4, skipPixels
: 0, skipRows
: 0,
265 validUnpackParams2D
: false },
266 { width
: 5, height
: 7, xoffset
: 2, yoffset
: 3,
267 alignment
: 8, rowLength
: 4, skipPixels
: 0, skipRows
: 0,
268 validUnpackParams2D
: false },
270 // ROW_LENGTH > width
271 { width
: 5, height
: 7, xoffset
: 2, yoffset
: 3,
272 alignment
: 1, rowLength
: 6, skipPixels
: 0, skipRows
: 0,
273 validUnpackParams2D
: true, validUnpackParamsForSub2D
: true },
274 { width
: 5, height
: 7, xoffset
: 2, yoffset
: 3,
275 alignment
: 2, rowLength
: 7, skipPixels
: 0, skipRows
: 0,
276 validUnpackParams2D
: true, validUnpackParamsForSub2D
: true },
277 { width
: 5, height
: 7, xoffset
: 2, yoffset
: 3,
278 alignment
: 4, rowLength
: 8, skipPixels
: 0, skipRows
: 0,
279 validUnpackParams2D
: true, validUnpackParamsForSub2D
: true },
280 { width
: 5, height
: 7, xoffset
: 2, yoffset
: 3,
281 alignment
: 8, rowLength
: 9, skipPixels
: 0, skipRows
: 0,
282 validUnpackParams2D
: true, validUnpackParamsForSub2D
: true },
284 // IMAGE_HEIGHT == height
285 { width
: 6, height
: 7, xoffset
: 2, yoffset
: 3,
286 alignment
: 8, rowLength
: 0, skipPixels
: 0, skipRows
: 0,
287 validUnpackParams2D
: true, validUnpackParamsForSub2D
: true },
289 // IMAGE_HEIGHT < height
290 { width
: 5, height
: 7, xoffset
: 2, yoffset
: 3,
291 alignment
: 1, rowLength
: 0, skipPixels
: 0, skipRows
: 0,
292 validUnpackParams2D
: true, validUnpackParamsForSub2D
: true },
293 { width
: 5, height
: 7, xoffset
: 2, yoffset
: 3,
294 alignment
: 2, rowLength
: 0, skipPixels
: 0, skipRows
: 0,
295 validUnpackParams2D
: true, validUnpackParamsForSub2D
: true },
296 { width
: 5, height
: 7, xoffset
: 2, yoffset
: 3,
297 alignment
: 4, rowLength
: 0, skipPixels
: 0, skipRows
: 0,
298 validUnpackParams2D
: true, validUnpackParamsForSub2D
: true },
299 { width
: 5, height
: 7, xoffset
: 2, yoffset
: 3,
300 alignment
: 8, rowLength
: 0, skipPixels
: 0, skipRows
: 0,
301 validUnpackParams2D
: true, validUnpackParamsForSub2D
: true },
303 // IMAGE_HEIGHT > height
304 { width
: 5, height
: 7, xoffset
: 2, yoffset
: 3,
305 alignment
: 1, rowLength
: 0, skipPixels
: 0, skipRows
: 0,
306 validUnpackParams2D
: true, validUnpackParamsForSub2D
: true },
307 { width
: 6, height
: 7, xoffset
: 2, yoffset
: 2,
308 alignment
: 2, rowLength
: 0, skipPixels
: 0, skipRows
: 0,
309 validUnpackParams2D
: true, validUnpackParamsForSub2D
: true },
310 { width
: 7, height
: 7, xoffset
: 2, yoffset
: 4,
311 alignment
: 4, rowLength
: 0, skipPixels
: 0, skipRows
: 0,
312 validUnpackParams2D
: true, validUnpackParamsForSub2D
: true },
313 { width
: 8, height
: 7, xoffset
: 2, yoffset
: 3,
314 alignment
: 8, rowLength
: 0, skipPixels
: 0, skipRows
: 0,
315 validUnpackParams2D
: true, validUnpackParamsForSub2D
: true },
318 { width
: 5, height
: 7, xoffset
: 2, yoffset
: 3,
319 alignment
: 1, rowLength
: 0, skipPixels
: 10, skipRows
: 0,
320 validUnpackParams2D
: false },
321 { width
: 5, height
: 7, xoffset
: 2, yoffset
: 3,
322 alignment
: 2, rowLength
: 0, skipPixels
: 2, skipRows
: 8,
323 validUnpackParams2D
: false },
324 { width
: 5, height
: 7, xoffset
: 2, yoffset
: 3,
325 alignment
: 4, rowLength
: 0, skipPixels
: 3, skipRows
: 5,
326 validUnpackParams2D
: false },
327 { width
: 5, height
: 7, xoffset
: 2, yoffset
: 3,
328 alignment
: 8, rowLength
: 0, skipPixels
: 7, skipRows
: 0,
329 validUnpackParams2D
: false },
332 { width
: 5, height
: 7, xoffset
: 2, yoffset
: 3,
333 alignment
: 1, rowLength
: 6, skipPixels
: 3, skipRows
: 5,
334 validUnpackParams2D
: false },
335 { width
: 5, height
: 7, xoffset
: 2, yoffset
: 3,
336 alignment
: 2, rowLength
: 4, skipPixels
: 7, skipRows
: 2,
337 validUnpackParams2D
: false },
338 { width
: 5, height
: 7, xoffset
: 2, yoffset
: 3,
339 alignment
: 4, rowLength
: 10, skipPixels
: 0, skipRows
: 3,
340 validUnpackParams2D
: true, validUnpackParamsForSub2D
: true },
341 { width
: 1, height
: 1, xoffset
: 0, yoffset
: 0,
342 alignment
: 2, rowLength
: 3, skipPixels
: 3, skipRows
: 5,
343 validUnpackParams2D
: false },
344 { width
: 17, height
: 6, xoffset
: 12, yoffset
: 3,
345 alignment
: 2, rowLength
: 4, skipPixels
: 1, skipRows
: 4,
346 validUnpackParams2D
: false },
347 { width
: 8, height
: 17, xoffset
: 2, yoffset
: 13,
348 alignment
: 4, rowLength
: 9, skipPixels
: 0, skipRows
: 3,
349 validUnpackParams2D
: true, validUnpackParamsForSub2D
: true },
353 // { flip_y: false, premultiply_alpha: false },
354 { flip_y
: true, premultiply_alpha
: false },
355 { flip_y
: false, premultiply_alpha
: true },
356 { flip_y
: true, premultiply_alpha
: true },
359 for (var jj
= 0; jj
< groups
.length
; ++jj
) {
360 var group
= groups
[jj
];
361 for (var ii
= 0; ii
< testCases
.length
; ++ii
) {
362 var testCase
= testCases
[ii
];
363 runTestIteration2D(gl
, testCase
, group
.flip_y
, group
.premultiply_alpha
);
368 function runNegativeTests(gl
) {
370 debug("Test tex{Sub}Image2D from pbo fails with FLIP_Y = true or PREMULTIPLY_ALPHA = true");
372 var width
= 16, height
= 16, depth
= 2;
374 // Restore default values.
375 gl
.pixelStorei(gl
.UNPACK_ALIGNMENT
, 4);
376 gl
.pixelStorei(gl
.UNPACK_ROW_LENGTH
, 0);
377 gl
.pixelStorei(gl
.UNPACK_IMAGE_HEIGHT
, 0);
378 gl
.pixelStorei(gl
.UNPACK_SKIP_PIXELS
, 0);
379 gl
.pixelStorei(gl
.UNPACK_SKIP_ROWS
, 0);
380 gl
.pixelStorei(gl
.UNPACK_SKIP_IMAGES
, 0);
381 gl
.pixelStorei(gl
.UNPACK_FLIP_Y_WEBGL
, false);
382 gl
.pixelStorei(gl
.UNPACK_PREMULTIPLY_ALPHA_WEBGL
, false);
384 var tex
= gl
.createTexture();
385 gl
.bindTexture(gl
.TEXTURE_2D
, tex
);
387 var bufferSize
= width
* height
* 4; // RGBA8
388 var buffer
= gl
.createBuffer();
389 gl
.bindBuffer(gl
.PIXEL_UNPACK_BUFFER
, buffer
);
390 gl
.bufferData(gl
.PIXEL_UNPACK_BUFFER
, bufferSize
, gl
.DYNAMIC_DRAW
);
392 gl
.texImage2D(gl
.TEXTURE_2D
, 0, gl
.RGBA8
, width
, height
, 0, gl
.RGBA
, gl
.UNSIGNED_BYTE
, 0);
393 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "texImage2D from pbo works with default pixel store settings");
394 gl
.texSubImage2D(gl
.TEXTURE_2D
, 0, 0, 0, width
, height
, gl
.RGBA
, gl
.UNSIGNED_BYTE
, 0);
395 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "texSubImage2D from pbo works with default pixel store settings");
397 gl
.pixelStorei(gl
.UNPACK_FLIP_Y_WEBGL
, true);
398 gl
.texImage2D(gl
.TEXTURE_2D
, 0, gl
.RGBA8
, width
, height
, 0, gl
.RGBA
, gl
.UNSIGNED_BYTE
, 0);
399 wtu
.glErrorShouldBe(gl
, gl
.INVALID_OPERATION
, "texImage2D from pbo with FLIP_Y=true should fail");
400 gl
.texSubImage2D(gl
.TEXTURE_2D
, 0, 0, 0, width
, height
, gl
.RGBA
, gl
.UNSIGNED_BYTE
, 0);
401 wtu
.glErrorShouldBe(gl
, gl
.INVALID_OPERATION
, "texSubImage2D from pbo with FLIP_Y=true should fail");
402 gl
.pixelStorei(gl
.UNPACK_FLIP_Y_WEBGL
, false);
404 gl
.pixelStorei(gl
.UNPACK_PREMULTIPLY_ALPHA_WEBGL
, true);
405 gl
.texImage2D(gl
.TEXTURE_2D
, 0, gl
.RGBA8
, width
, height
, 0, gl
.RGBA
, gl
.UNSIGNED_BYTE
, 0);
406 wtu
.glErrorShouldBe(gl
, gl
.INVALID_OPERATION
, "texImage2D from pbo with PREMULTIPLY_ALPHA=true should fail");
407 gl
.texSubImage2D(gl
.TEXTURE_2D
, 0, 0, 0, width
, height
, gl
.RGBA
, gl
.UNSIGNED_BYTE
, 0);
408 wtu
.glErrorShouldBe(gl
, gl
.INVALID_OPERATION
, "texSubImage2D from pbo with PREMULTIPLY_ALPHA=true should fail");
409 gl
.pixelStorei(gl
.UNPACK_PREMULTIPLY_ALPHA_WEBGL
, false);
412 debug("Test tex{Sub}Image3D from pbo fails with FLIP_Y = true or PREMULTIPLY_ALPHA = true");
414 gl
.deleteTexture(tex
);
415 tex
= gl
.createTexture();
416 gl
.bindTexture(gl
.TEXTURE_3D
, tex
);
418 bufferSize
= width
* height
* depth
* 4; // RGBA8
419 gl
.bindBuffer(gl
.PIXEL_UNPACK_BUFFER
, buffer
);
420 gl
.bufferData(gl
.PIXEL_UNPACK_BUFFER
, bufferSize
, gl
.DYNAMIC_DRAW
);
422 gl
.texImage3D(gl
.TEXTURE_3D
, 0, gl
.RGBA8
, width
, height
, depth
, 0, gl
.RGBA
, gl
.UNSIGNED_BYTE
, 0);
423 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "texImage3D from pbo works with default pixel store settings");
424 gl
.texSubImage3D(gl
.TEXTURE_3D
, 0, 0, 0, 0, width
, height
, depth
, gl
.RGBA
, gl
.UNSIGNED_BYTE
, 0);
425 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "texSubImage3D from pbo works with default pixel store settings");
427 gl
.pixelStorei(gl
.UNPACK_FLIP_Y_WEBGL
, true);
428 gl
.texImage3D(gl
.TEXTURE_3D
, 0, gl
.RGBA8
, width
, height
, depth
, 0, gl
.RGBA
, gl
.UNSIGNED_BYTE
, 0);
429 wtu
.glErrorShouldBe(gl
, gl
.INVALID_OPERATION
, "texImage3D from pbo with FLIP_Y=true should fail");
430 gl
.texSubImage3D(gl
.TEXTURE_3D
, 0, 0, 0, 0, width
, height
, depth
, gl
.RGBA
, gl
.UNSIGNED_BYTE
, 0);
431 wtu
.glErrorShouldBe(gl
, gl
.INVALID_OPERATION
, "texSubImage3D from pbo with FLIP_Y=true should fail");
432 gl
.pixelStorei(gl
.UNPACK_FLIP_Y_WEBGL
, false);
434 gl
.pixelStorei(gl
.UNPACK_PREMULTIPLY_ALPHA_WEBGL
, true);
435 gl
.texImage3D(gl
.TEXTURE_3D
, 0, gl
.RGBA8
, width
, height
, depth
, 0, gl
.RGBA
, gl
.UNSIGNED_BYTE
, 0);
436 wtu
.glErrorShouldBe(gl
, gl
.INVALID_OPERATION
, "texImage3D from pbo with PREMULTIPLY_ALPHA=true should fail");
437 gl
.texSubImage3D(gl
.TEXTURE_3D
, 0, 0, 0, 0, width
, height
, depth
, gl
.RGBA
, gl
.UNSIGNED_BYTE
, 0);
438 wtu
.glErrorShouldBe(gl
, gl
.INVALID_OPERATION
, "texSubImage3D from pbo with PREMULTIPLY_ALPHA=true should fail");
439 gl
.pixelStorei(gl
.UNPACK_PREMULTIPLY_ALPHA_WEBGL
, false);
442 debug("Test tex{Sub}Image3D from client array fails with FLIP_Y = true or PREMULTIPLY_ALPHA = true");
444 gl
.bindBuffer(gl
.PIXEL_UNPACK_BUFFER
, null);
445 gl
.deleteBuffer(buffer
);
447 var array
= setupArrayBuffer(bufferSize
, false);
449 gl
.texImage3D(gl
.TEXTURE_3D
, 0, gl
.RGBA8
, width
, height
, depth
, 0, gl
.RGBA
, gl
.UNSIGNED_BYTE
, array
);
450 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "texImage3D from client array works with default pixel store settings");
451 gl
.texSubImage3D(gl
.TEXTURE_3D
, 0, 0, 0, 0, width
, height
, depth
, gl
.RGBA
, gl
.UNSIGNED_BYTE
, array
);
452 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "texSubImage3D from client array works with default pixel store settings");
454 gl
.pixelStorei(gl
.UNPACK_FLIP_Y_WEBGL
, true);
455 gl
.texImage3D(gl
.TEXTURE_3D
, 0, gl
.RGBA8
, width
, height
, depth
, 0, gl
.RGBA
, gl
.UNSIGNED_BYTE
, array
);
456 wtu
.glErrorShouldBe(gl
, gl
.INVALID_OPERATION
, "texImage3D from client array with FLIP_Y=true should fail");
457 gl
.texSubImage3D(gl
.TEXTURE_3D
, 0, 0, 0, 0, width
, height
, depth
, gl
.RGBA
, gl
.UNSIGNED_BYTE
, array
);
458 wtu
.glErrorShouldBe(gl
, gl
.INVALID_OPERATION
, "texSubImage3D from client array with FLIP_Y=true should fail");
459 gl
.pixelStorei(gl
.UNPACK_FLIP_Y_WEBGL
, false);
461 gl
.pixelStorei(gl
.UNPACK_PREMULTIPLY_ALPHA_WEBGL
, true);
462 gl
.texImage3D(gl
.TEXTURE_3D
, 0, gl
.RGBA8
, width
, height
, depth
, 0, gl
.RGBA
, gl
.UNSIGNED_BYTE
, array
);
463 wtu
.glErrorShouldBe(gl
, gl
.INVALID_OPERATION
, "texImage3D from pbo with PREMULTIPLY_ALPHA=true should fail");
464 gl
.texSubImage3D(gl
.TEXTURE_3D
, 0, 0, 0, 0, width
, height
, depth
, gl
.RGBA
, gl
.UNSIGNED_BYTE
, array
);
465 wtu
.glErrorShouldBe(gl
, gl
.INVALID_OPERATION
, "texSubImage3D from pbo with PREMULTIPLY_ALPHA=true should fail");
466 gl
.pixelStorei(gl
.UNPACK_PREMULTIPLY_ALPHA_WEBGL
, false);
469 function runRegressionTests(gl
) {
471 debug("The following test serves as a regression test for crbug.com/774174");
472 var array
= new Uint16Array(32);
473 gl
.pixelStorei(gl
.UNPACK_ROW_LENGTH
, 4);
474 gl
.pixelStorei(gl
.UNPACK_PREMULTIPLY_ALPHA_WEBGL
, 6);
475 var tex
= gl
.createTexture();
476 gl
.bindTexture(gl
.TEXTURE_2D
, tex
);
477 gl
.texSubImage2D(gl
.TEXTURE_2D
, 4, 7, 5, 8, 5, gl
.RGB
, gl
.UNSIGNED_SHORT_5_5_5_1
, array
);
478 // At this point, the Chrome ASAN build used to crash.
479 testPassed("The regression test for crbug.com/774174 doesn't crash");
480 wtu
.glErrorShouldBe(gl
, gl
.INVALID_OPERATION
, "Calling texSubImage2D without initializing the texture is illegal");
481 gl
.pixelStorei(gl
.UNPACK_ROW_LENGTH
, 0);
482 gl
.pixelStorei(gl
.UNPACK_PREMULTIPLY_ALPHA_WEBGL
, false);
485 var gl
= wtu
.create3DContext("example", undefined, 2);
487 testFailed("Fail to get a WebGL context");
490 runNegativeTests(gl
);
491 runRegressionTests(gl
);
495 var successfullyParsed
= true;
497 <script src=
"../../../js/js-test-post.js"></script>