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 BlitFramebuffer 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=
"8" height=
"8"></canvas>
18 <div id=
"description"></div>
19 <div id=
"console"></div>
24 var wtu
= WebGLTestUtils
;
25 description("This test verifies the functionality of blitFramebuffer.");
27 var gl
= wtu
.create3DContext("example", undefined, 2);
29 function checkPixel(color
, expectedColor
) {
31 return (Math
.abs(color
[0] - expectedColor
[0]) <= tolerance
&&
32 Math
.abs(color
[1] - expectedColor
[1]) <= tolerance
&&
33 Math
.abs(color
[2] - expectedColor
[2]) <= tolerance
&&
34 Math
.abs(color
[3] - expectedColor
[3]) <= tolerance
);
37 function blitframebuffer_outside_readbuffer(readbufferFormat
, drawbufferFormat
) {
39 debug("blitting outside of read framebuffer, read buffer format is: " + wtu
.glEnumToString(gl
, readbufferFormat
) + ", draw buffer format is: " + wtu
.glEnumToString(gl
, drawbufferFormat
));
41 // Initiate data to read framebuffer
43 var uint_read
= new Uint8Array(size_read
* size_read
* 4);
45 for (var ii
= 0; ii
< size_read
* size_read
* 4; ii
+= 4) {
46 for (var jj
= 0; jj
< 3; ++jj
) {
47 uint_read
[ii
+ jj
] = start
;
49 uint_read
[ii
+ 3] = 0xff;
53 // Create read framebuffer and feed data to read buffer
54 // Read buffer may has srgb image
55 var tex_read
= gl
.createTexture();
56 gl
.bindTexture(gl
.TEXTURE_2D
, tex_read
);
57 gl
.texImage2D(gl
.TEXTURE_2D
, 0, readbufferFormat
, size_read
, size_read
, 0, gl
.RGBA
, gl
.UNSIGNED_BYTE
, uint_read
);
59 var fbo_read
= gl
.createFramebuffer();
60 gl
.bindFramebuffer(gl
.READ_FRAMEBUFFER
, fbo_read
);
61 gl
.framebufferTexture2D(gl
.READ_FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, gl
.TEXTURE_2D
, tex_read
, 0);
63 // Initiate data to draw framebuffer
65 var uint_draw
= new Uint8Array(size_draw
* size_draw
* 4);
66 for (var ii
= 0; ii
< size_draw
* size_draw
* 4; ii
+= 4) {
67 for (var jj
= 0; jj
< 3; ++jj
) {
68 uint_draw
[ii
+ jj
] = 0x10;
70 uint_draw
[ii
+ 3] = 0xff;
73 // Create draw framebuffer and feed data to draw buffer
74 // Draw buffer may has srgb image
75 var tex_draw
= gl
.createTexture();
76 gl
.bindTexture(gl
.TEXTURE_2D
, tex_draw
);
77 gl
.texParameteri(gl
.TEXTURE_2D
, gl
.TEXTURE_WRAP_S
, gl
.CLAMP_TO_EDGE
);
78 gl
.texParameteri(gl
.TEXTURE_2D
, gl
.TEXTURE_WRAP_T
, gl
.CLAMP_TO_EDGE
);
79 gl
.texParameteri(gl
.TEXTURE_2D
, gl
.TEXTURE_MIN_FILTER
, gl
.LINEAR
);
80 gl
.texParameteri(gl
.TEXTURE_2D
, gl
.TEXTURE_MAG_FILTER
, gl
.LINEAR
);
82 gl
.texImage2D(gl
.TEXTURE_2D
, 0, drawbufferFormat
, size_draw
, size_draw
, 0, gl
.RGBA
, gl
.UNSIGNED_BYTE
, uint_draw
);
84 var fbo_draw
= gl
.createFramebuffer();
85 gl
.bindFramebuffer(gl
.DRAW_FRAMEBUFFER
, fbo_draw
);
86 gl
.framebufferTexture2D(gl
.DRAW_FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, gl
.TEXTURE_2D
, tex_draw
, 0);
88 if (gl
.checkFramebufferStatus(gl
.READ_FRAMEBUFFER
) == gl
.FRAMEBUFFER_COMPLETE
) {
90 // The reference pixels of the 1st line: (0, 0) ~ (6, 0)
91 [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff],
92 [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff],
94 // The reference pixels of the 2nd line: (0, 1) ~ (6, 1)
95 [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff],
96 [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff],
98 // The reference pixels of the 3rd line: (0, 2) ~ (6, 2)
99 [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff], [0x20, 0x20, 0x20, 0xff], [0x30, 0x30, 0x30, 0xff],
100 [0x40, 0x40, 0x40, 0xff], [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff],
102 // The reference pixels of the 4th line: (0, 3) ~ (6, 3)
103 [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff], [0x50, 0x50, 0x50, 0xff], [0x60, 0x60, 0x60, 0xff],
104 [0x70, 0x70, 0x70, 0xff], [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff],
106 // The reference pixels of the 5th line: (0, 4) ~ (6, 4)
107 [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff], [0x80, 0x80, 0x80, 0xff], [0x90, 0x90, 0x90, 0xff],
108 [0xa0, 0xa0, 0xa0, 0xff], [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff],
110 // The reference pixels of the 6th line: (0, 5) ~ (6, 5)
111 [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff],
112 [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff],
114 // The reference pixels of the 7th line: (0, 6) ~ (6, 6)
115 [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff],
116 [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff], [0x10, 0x10, 0x10, 0xff],
119 // The 1st round test: blit read framebuffer to the image in draw framebuffer
120 // All directions of the read region have pixels outside of the read buffer
121 // The src region and/or dst region may be reversed during blitting.
123 [-1, 4, 1, 6], // reverse neither src nor dst
124 [4, -1, 1, 6], // reverse src only
125 [-1, 4, 6, 1], // reverse dst only
126 [4, -1, 6, 1] // reverse both src and dst
129 var readbufferHasSRGBImage
= (readbufferFormat
== gl
.SRGB8_ALPHA8
);
130 var drawbufferHasSRGBImage
= (drawbufferFormat
== gl
.SRGB8_ALPHA8
);
132 for (var i
= 0; i
< 4; ++i
) {
135 case 0: debug("reverse neither src region nor dst region"); break;
136 case 1: debug("reverse src region only"); break;
137 case 2: debug("reverse dst region only"); break;
138 case 3: debug("reverse both src region and dst region"); break;
140 var srcStart
= test1
[i
][0];
141 var srcEnd
= test1
[i
][1];
142 var dstStart
= test1
[i
][2];
143 var dstEnd
= test1
[i
][3];
144 var realBlittedDstStart
= 2;
145 var realBlittedDstEnd
= 5;
146 gl
.bindFramebuffer(gl
.READ_FRAMEBUFFER
, fbo_read
);
147 gl
.bindFramebuffer(gl
.DRAW_FRAMEBUFFER
, fbo_draw
);
148 gl
.blitFramebuffer(srcStart
, srcStart
, srcEnd
, srcEnd
, dstStart
, dstStart
, dstEnd
, dstEnd
, gl
.COLOR_BUFFER_BIT
, gl
.LINEAR
);
150 // Read pixels and check the correctness.
151 var pixels
= new Uint8Array(size_draw
* size_draw
* 4);
152 gl
.bindFramebuffer(gl
.READ_FRAMEBUFFER
, fbo_draw
);
153 gl
.readPixels(0, 0, size_draw
, size_draw
, gl
.RGBA
, gl
.UNSIGNED_BYTE
, pixels
);
155 for (var ii
= 0; ii
< size_draw
; ++ii
) {
156 for (var jj
= 0; jj
< size_draw
; ++jj
) {
157 var loc
= ii
* size_draw
+ jj
;
158 var color
= [pixels
[loc
* 4], pixels
[loc
* 4 + 1], pixels
[loc
* 4 + 2], pixels
[loc
* 4 + 3]];
160 // We may need to reverse the reference loc if necessary
162 var reverse_src
= (srcStart
< srcEnd
);
163 var reverse_dst
= (dstStart
< dstEnd
);
164 var reversed
= reverse_src
^ reverse_dst
;
166 ref_loc
= (size_draw
- ii
- 1) * size_draw
+ (size_draw
- jj
-1);
168 var expectedColor
= ref
[ref_loc
];
170 // We may need to covert the color space for pixels in blit region
171 if ((readbufferHasSRGBImage
^ drawbufferHasSRGBImage
) &&
172 (ii
>= realBlittedDstStart
&& ii
< realBlittedDstEnd
&& jj
>= realBlittedDstStart
&& jj
< realBlittedDstEnd
)) {
173 if (drawbufferHasSRGBImage
) {
174 expectedColor
= wtu
.linearToSRGB(expectedColor
);
176 expectedColor
= wtu
.sRGBToLinear(expectedColor
);
179 if (checkPixel(color
, expectedColor
) == true) {
180 testPassed("pixel at [" + jj
+ ", " + ii
+ "] is (" + color
+ "). It is correct!");
182 testFailed("pixel at [" + jj
+ ", " + ii
+ "] should be (" + expectedColor
+ "), but the actual color is (" + color
+ ")");
188 // The 2nd round test: blit read framebuffer to the image in draw framebuffer
189 // Only one direction of the read region have pixels outside of the read buffer
191 [-1, 0], // pixels are outside the left edge of the read buffer
192 [0, -1], // pixels are outside the bottom edge of the read buffer
193 [1, 0], // pixels are outside the right edge of the read buffer
194 [0, 1] // pixels are outside the top edge of the read buffer
196 for (var i
= 0; i
< 4; ++i
) {
199 case 0: debug("verify that pixels lying outside the left edge of the read buffer should remain untouched"); break;
200 case 1: debug("verify that pixels lying outside the bottom edge of the read buffer should remain untouched"); break;
201 case 2: debug("verify that pixels lying outside the right edge of the read buffer should remain untouched"); break;
202 case 3: debug("verify that pixels lying outside the top edge of the read buffer should remain untouched"); break;
204 gl
.bindFramebuffer(gl
.READ_FRAMEBUFFER
, fbo_read
);
205 gl
.bindFramebuffer(gl
.DRAW_FRAMEBUFFER
, fbo_draw
);
206 var srcX
= tests
[i
][0];
207 var srcY
= tests
[i
][1];
208 var offset
= dstStart
- srcStart
;
209 gl
.blitFramebuffer(srcX
, srcY
, srcX
+ size_read
, srcY
+ size_read
,
210 srcX
+ offset
, srcY
+ offset
, srcX
+ offset
+ size_read
, srcY
+ offset
+ size_read
,
211 gl
.COLOR_BUFFER_BIT
, gl
.LINEAR
);
213 // Read pixels and check the correctness.
214 var pixels
= new Uint8Array(size_draw
* size_draw
* 4);
215 gl
.bindFramebuffer(gl
.READ_FRAMEBUFFER
, fbo_draw
);
216 gl
.readPixels(0, 0, size_draw
, size_draw
, gl
.RGBA
, gl
.UNSIGNED_BYTE
, pixels
);
217 for (var ii
= srcY
+ offset
; ii
< srcY
+ offset
+ size_read
; ++ii
) {
218 for (var jj
= srcX
+ offset
; jj
< srcX
+ offset
+ size_read
; ++jj
) {
219 var loc
= ii
* size_draw
+ jj
;
220 var color
= [pixels
[loc
* 4], pixels
[loc
* 4 + 1], pixels
[loc
* 4 + 2], pixels
[loc
* 4 + 3]];
221 var expectedColor
= ref
[loc
];
222 // We may need to covert the color space for pixels in blit region
223 if ((readbufferHasSRGBImage
^ drawbufferHasSRGBImage
) &&
224 (ii
>= realBlittedDstStart
&& ii
< realBlittedDstEnd
&& jj
>= realBlittedDstStart
&& jj
< realBlittedDstEnd
)) {
225 if (drawbufferHasSRGBImage
) {
226 expectedColor
= wtu
.linearToSRGB(expectedColor
);
228 expectedColor
= wtu
.sRGBToLinear(expectedColor
);
231 if (checkPixel(color
, expectedColor
) == true) {
232 testPassed("pixel at [" + jj
+ ", " + ii
+ "] is (" + color
+ "). It is correct!");
234 testFailed("pixel at [" + jj
+ ", " + ii
+ "] should be (" + expectedColor
+ "), but the actual color is (" + color
+ ")");
240 testFailed("framebuffer not complete");
243 gl
.bindTexture(gl
.TEXTURE_2D
, null);
244 gl
.bindFramebuffer(gl
.READ_FRAMEBUFFER
, null);
245 gl
.bindFramebuffer(gl
.DRAW_FRAMEBUFFER
, null);
246 gl
.deleteFramebuffer(fbo_read
);
247 gl
.deleteFramebuffer(fbo_draw
);
248 gl
.deleteTexture(tex_read
);
249 gl
.deleteTexture(tex_draw
);
253 testFailed("WebGL context does not exist");
255 testPassed("WebGL context exists");
256 blitframebuffer_outside_readbuffer(gl
.RGBA8
, gl
.RGBA8
);
257 blitframebuffer_outside_readbuffer(gl
.RGBA8
, gl
.SRGB8_ALPHA8
);
258 blitframebuffer_outside_readbuffer(gl
.SRGB8_ALPHA8
, gl
.RGBA8
);
259 blitframebuffer_outside_readbuffer(gl
.SRGB8_ALPHA8
, gl
.SRGB8_ALPHA8
);
262 var successfullyParsed
= true;
264 <script src=
"../../js/js-test-post.js"></script>