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>WebGL CopyTexImage Tests
</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=
"2" height=
"2"></canvas>
18 <div id=
"description"></div>
19 <div id=
"console"></div>
23 var wtu
= WebGLTestUtils
;
24 description("This test verifies the functionality of copyTexImage.");
26 var gl
= wtu
.create3DContext("example", undefined, 2);
28 function copytexsubimage3d_invalid_operation_feedbackloops() {
30 debug("Testing copytexsubimage3d_invalid_operation_feedbackloops");
31 var texture
= gl
.createTexture();
32 gl
.bindTexture(gl
.TEXTURE_3D
, texture
);
33 var uint8
= new Uint8Array(32);
38 gl
.texImage3D(gl
.TEXTURE_3D
, 0, gl
.RGBA
, width
, height
, depth
, 0, gl
.RGBA
, gl
.UNSIGNED_BYTE
, uint8
);
40 var fbo
= gl
.createFramebuffer();
41 gl
.bindFramebuffer(gl
.FRAMEBUFFER
, fbo
);
42 gl
.framebufferTextureLayer(gl
.FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, texture
, 0, layer
);
43 if (gl
.checkFramebufferStatus(gl
.FRAMEBUFFER
) == gl
.FRAMEBUFFER_COMPLETE
) {
44 gl
.copyTexSubImage3D(gl
.TEXTURE_3D
, 0, 0, 0, layer
, 0, 0, width
, height
);
45 wtu
.glErrorShouldBe(gl
, gl
.INVALID_OPERATION
, "gl.INVALID_OPERATION is generated");
47 testFailed("framebuffer not complete");
50 gl
.bindFramebuffer(gl
.FRAMEBUFFER
, null);
51 gl
.deleteFramebuffer(fbo
);
52 gl
.deleteTexture(texture
);
55 function copytexsubimage3d_valid_operation_diff_level() {
57 debug("Testing copytexsubimage3d_valid_operation_diff_level");
58 var texture
= gl
.createTexture();
59 gl
.bindTexture(gl
.TEXTURE_3D
, texture
);
60 var uint8
= new Uint8Array(32);
66 gl
.texImage3D(gl
.TEXTURE_3D
, 0, gl
.RGBA
, width
, height
, depth
, 0, gl
.RGBA
, gl
.UNSIGNED_BYTE
, uint8
);
67 gl
.generateMipmap(gl
.TEXTURE_3D
);
69 var fbo
= gl
.createFramebuffer();
70 gl
.bindFramebuffer(gl
.FRAMEBUFFER
, fbo
);
71 gl
.framebufferTextureLayer(gl
.FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, texture
, level1
, 0);
72 if (gl
.checkFramebufferStatus(gl
.FRAMEBUFFER
) == gl
.FRAMEBUFFER_COMPLETE
) {
73 gl
.copyTexSubImage3D(gl
.TEXTURE_3D
, level2
, 0, 0, 0, 0, 0, width
/2, height/2);
74 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "texImage3D should succeed.");
76 testFailed("framebuffer not complete");
79 gl
.bindFramebuffer(gl
.FRAMEBUFFER
, null);
80 gl
.deleteFramebuffer(fbo
);
81 gl
.deleteTexture(texture
);
84 function copytexsubimage3d_valid_operation_diff_layer() {
86 debug("Testing copytexsubimage3d_valid_operation_diff_layer");
87 var texture
= gl
.createTexture();
88 gl
.bindTexture(gl
.TEXTURE_3D
, texture
);
89 var uint8
= new Uint8Array(32);
95 gl
.texImage3D(gl
.TEXTURE_3D
, 0, gl
.RGBA
, width
, height
, depth
, 0, gl
.RGBA
, gl
.UNSIGNED_BYTE
, uint8
);
97 var fbo
= gl
.createFramebuffer();
98 gl
.bindFramebuffer(gl
.FRAMEBUFFER
, fbo
);
99 gl
.framebufferTextureLayer(gl
.FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, texture
, 0, layer1
);
100 if (gl
.checkFramebufferStatus(gl
.FRAMEBUFFER
) == gl
.FRAMEBUFFER_COMPLETE
) {
101 gl
.copyTexSubImage3D(gl
.TEXTURE_3D
, 0, 0, 0, layer2
, 0, 0, width
, height
);
102 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "texImage3D should succeed.");
104 testFailed("framebuffer not complete");
107 gl
.bindFramebuffer(gl
.FRAMEBUFFER
, null);
108 gl
.deleteFramebuffer(fbo
);
109 gl
.deleteTexture(texture
);
112 function copytexsubimage3d_texture_wrongly_initialized() {
114 debug("Testing copytexsubimage3d_texture_wrongly_initialized");
116 texture
[0] = gl
.createTexture();
117 texture
[1] = gl
.createTexture();
122 gl
.bindTexture(gl
.TEXTURE_2D
, texture
[0]);
123 var uint = new Uint8Array([0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10]);
124 gl
.texImage2D(gl
.TEXTURE_2D
, 0, gl
.RGBA
, width
, height
, 0, gl
.RGBA
, gl
.UNSIGNED_BYTE
, uint);
126 var fbo
= gl
.createFramebuffer();
127 gl
.bindFramebuffer(gl
.FRAMEBUFFER
, fbo
);
128 gl
.framebufferTexture2D(gl
.FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, gl
.TEXTURE_2D
, texture
[0], 0);
129 if (gl
.checkFramebufferStatus(gl
.FRAMEBUFFER
) == gl
.FRAMEBUFFER_COMPLETE
) {
130 gl
.bindTexture(gl
.TEXTURE_3D
, texture
[1]);
131 gl
.texStorage3D(gl
.TEXTURE_3D
, 1, gl
.RGBA8
, width
, height
, depth
);
132 gl
.copyTexSubImage3D(gl
.TEXTURE_3D
, 0, 0, 0, layer
, 0, 0, width
, height
);
133 gl
.framebufferTextureLayer(gl
.FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, texture
[1], 0, layer
);
134 var bytes
= new Uint8Array(width
* height
* 4);
135 gl
.readPixels(0, 0, width
, height
, gl
.RGBA
, gl
.UNSIGNED_BYTE
, bytes
);
136 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "readpixel should succeed.");
137 for (var x
= 0; x
< width
* height
* 4; x
++) {
138 if (bytes
[x
] != uint[x
]) {
139 testFailed("byte comparison failure, byte at "+ x
+ " was " + bytes
[x
] +
140 ", should be " + uint[x
]);
145 testFailed("framebuffer not complete");
148 gl
.bindTexture(gl
.TEXTURE_2D
, null);
149 gl
.bindTexture(gl
.TEXTURE_3D
, null);
150 gl
.bindFramebuffer(gl
.FRAMEBUFFER
, null);
151 gl
.deleteFramebuffer(fbo
);
152 gl
.deleteTexture(texture
[0]);
153 gl
.deleteTexture(texture
[1]);
156 function copytexsubimage3d_out_of_bounds_test_helper(xx
, yy
, copyWidth
, copyHeight
) {
158 texture
[0] = gl
.createTexture();
159 texture
[1] = gl
.createTexture();
168 var uint = new Uint8Array(width
* height
* 4);
169 for (var i
= 0; i
< uint.length
; i
++) {
172 var uint2
= new Uint8Array(width2
* height2
* depth
* 4);
173 for (var i
= 0; i
< uint2
.length
; i
++) {
177 var fbo
= gl
.createFramebuffer();
178 gl
.bindFramebuffer(gl
.FRAMEBUFFER
, fbo
);
180 gl
.bindTexture(gl
.TEXTURE_2D
, texture
[0]);
181 gl
.texImage2D(gl
.TEXTURE_2D
, 0, gl
.RGBA
, width
, height
, 0, gl
.RGBA
, gl
.UNSIGNED_BYTE
, uint);
182 gl
.framebufferTexture2D(gl
.FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, gl
.TEXTURE_2D
, texture
[0], 0);
183 if (gl
.checkFramebufferStatus(gl
.FRAMEBUFFER
) == gl
.FRAMEBUFFER_COMPLETE
) {
184 gl
.bindTexture(gl
.TEXTURE_3D
, texture
[1]);
185 gl
.texImage3D(gl
.TEXTURE_3D
, 0, gl
.RGBA
, width2
, height2
, depth
, 0, gl
.RGBA
, gl
.UNSIGNED_BYTE
, uint2
);
186 gl
.copyTexSubImage3D(gl
.TEXTURE_3D
, 0, xoffset
, yoffset
, layer
, xx
, yy
, copyWidth
, copyHeight
);
187 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "using copyTexSubImage3D: x = " + xx
+ ", y = " + yy
+ " width = " + copyWidth
+ ", height = " + copyHeight
);
189 gl
.framebufferTextureLayer(gl
.FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, texture
[1], 0, layer
);
190 var bytes
= new Uint8Array(width2
* height2
* 4);
191 gl
.readPixels(0, 0, width2
, height2
, gl
.RGBA
, gl
.UNSIGNED_BYTE
, bytes
);
192 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "readpixel should succeed.");
194 var sourceX
= new Object();
195 var sourceY
= new Object();
196 Clip(xx
, copyWidth
, width
, sourceX
);
197 Clip(yy
, copyHeight
, height
, sourceY
);
198 var destX
= sourceX
.start
- xx
+ xoffset
;
199 var rangeX
= sourceX
.range
;
200 var destY
= sourceY
.start
- yy
+ yoffset
;
201 var rangeY
= sourceY
.range
;
202 for (var y
= 0; y
< height2
; y
++) {
203 for (var x
= 0; x
< width2
* 4; x
++) {
204 var current
= y
* height2
* 4 + x
;
205 // pixels copied from read framebuffer should be 0x01
206 if (x
>= destX
* 4 && x
< (destX
+ rangeX
) * 4 && y
>= destY
&& y
< destY
+ rangeY
) {
207 if (bytes
[current
] != 0x01) {
208 testFailed("byte comparison failure, byte at "+ (current
) + " was " +
209 bytes
[current
] +", should be 1");
212 // pixels out-of-bounds should be untouched
214 if (bytes
[current
] != 0xFF) {
215 testFailed("byte comparison failure, byte at "+ (current
) + " was " +
216 bytes
[current
] + ", should be 255");
221 // Test failed; abort
222 if (x
< width2
* 4) {
227 testFailed("framebuffer not complete");
230 gl
.bindTexture(gl
.TEXTURE_2D
, null);
231 gl
.bindTexture(gl
.TEXTURE_3D
, null);
232 gl
.bindFramebuffer(gl
.FRAMEBUFFER
, null);
233 gl
.deleteFramebuffer(fbo
);
234 gl
.deleteTexture(texture
[0]);
235 gl
.deleteTexture(texture
[1]);
238 function copytexsubimage3d_out_of_bounds() {
240 debug("Test pixels outside of read framebuffer for CopyTexSubImage3D");
242 for(var i
=0; i
< testlist
.length
; i
++) {
243 copytexsubimage3d_out_of_bounds_test_helper(testlist
[i
][0], testlist
[i
][1], testlist
[i
][2], testlist
[i
][3]);
248 * This array defines some copy areas for CopyTexSubImage3D.
249 * A copy area is defined by x coordinate, y coordinate, copyWidth and copyHeight.
250 * the source read framebuffer is (0, 0, 2, 2).
274 function Clip(start
, range
, sourceRange
, target
) {
279 var end
= start
+ range
;
280 if(end
> sourceRange
) {
281 range
-= end
- sourceRange
;
283 target
.start
= start
;
284 target
.range
= range
;
288 testFailed("WebGL context does not exist");
290 testPassed("WebGL context exists");
291 copytexsubimage3d_invalid_operation_feedbackloops();
292 copytexsubimage3d_valid_operation_diff_level();
293 copytexsubimage3d_valid_operation_diff_layer();
294 copytexsubimage3d_texture_wrongly_initialized();
295 copytexsubimage3d_out_of_bounds();
298 var successfullyParsed
= true;
300 <script src=
"../../../js/js-test-post.js"></script>