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>
23 var wtu
= WebGLTestUtils
;
24 description("This test verifies the functionality of blitFramebuffer for some corner cases.");
29 var gl
= wtu
.create3DContext("example", undefined, 2);
31 testFailed("WebGL context does not exist");
33 testPassed("WebGL context exists");
34 blit_framebuffer_repeated();
35 blit_framebuffer_feedback_loop();
36 blit_framebuffer_multisampling_srgb();
39 function blit_framebuffer_repeated() {
41 debug("This test verifies repeated calls to blitFramebuffer.");
43 // Create offscreen fbo and its color attachment.
44 var tex_2d
= gl
.createTexture();
45 gl
.bindTexture(gl
.TEXTURE_2D
, tex_2d
);
46 gl
.texStorage2D(gl
.TEXTURE_2D
, 1, gl
.RGBA8
, width
, height
);
47 gl
.texParameteri(gl
.TEXTURE_2D
, gl
.TEXTURE_WRAP_S
, gl
.CLAMP_TO_EDGE
);
48 gl
.texParameteri(gl
.TEXTURE_2D
, gl
.TEXTURE_WRAP_T
, gl
.CLAMP_TO_EDGE
);
49 gl
.texParameteri(gl
.TEXTURE_2D
, gl
.TEXTURE_MIN_FILTER
, gl
.LINEAR
);
50 gl
.texParameteri(gl
.TEXTURE_2D
, gl
.TEXTURE_MAG_FILTER
, gl
.LINEAR
);
52 var fb
= gl
.createFramebuffer();
53 gl
.bindFramebuffer(gl
.FRAMEBUFFER
, fb
);
54 gl
.framebufferTexture2D(gl
.FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, gl
.TEXTURE_2D
, tex_2d
, 0);
55 if (gl
.checkFramebufferStatus(gl
.FRAMEBUFFER
) != gl
.FRAMEBUFFER_COMPLETE
) {
56 testFailed("Framebuffer incomplete.");
60 var prog
= wtu
.setupColorQuad(gl
, 0);
61 wtu
.setFloatDrawColor(gl
, [ 1.0, 0.0, 0.0, 1.0 ]);
63 gl
.bindFramebuffer(gl
.READ_FRAMEBUFFER
, fb
);
64 gl
.bindFramebuffer(gl
.DRAW_FRAMEBUFFER
, null);
65 gl
.blitFramebuffer(0, 0, width
, height
, 0, 0, width
, height
, gl
.COLOR_BUFFER_BIT
, gl
.NEAREST
);
66 gl
.bindFramebuffer(gl
.FRAMEBUFFER
, null);
67 wtu
.checkCanvas(gl
, [ 255, 0, 0, 255 ], "should be red at first");
69 gl
.bindFramebuffer(gl
.FRAMEBUFFER
, fb
);
70 wtu
.setFloatDrawColor(gl
, [ 0.0, 1.0, 0.0, 1.0 ]);
72 gl
.bindFramebuffer(gl
.READ_FRAMEBUFFER
, fb
);
73 gl
.bindFramebuffer(gl
.DRAW_FRAMEBUFFER
, null);
74 gl
.blitFramebuffer(0, 0, width
, height
, 0, 0, width
, height
, gl
.COLOR_BUFFER_BIT
, gl
.NEAREST
);
75 gl
.bindFramebuffer(gl
.FRAMEBUFFER
, null);
76 wtu
.checkCanvas(gl
, [ 0, 255, 0, 255 ], "should be green");
79 function blit_framebuffer_feedback_loop() {
82 debug("This test checks whether the src resource and dst resource have identical images.");
83 // Create read fbo and its color attachment.
84 var tex_2d
= gl
.createTexture();
85 gl
.bindTexture(gl
.TEXTURE_2D
, tex_2d
);
86 gl
.texImage2D(gl
.TEXTURE_2D
, 0, gl
.RGBA8
, width
, height
, 0, gl
.RGBA
, gl
.UNSIGNED_BYTE
, null);
87 gl
.generateMipmap(gl
.TEXTURE_2D
);
89 var fb0
= gl
.createFramebuffer();
90 gl
.bindFramebuffer(gl
.READ_FRAMEBUFFER
, fb0
);
91 gl
.framebufferTexture2D(gl
.READ_FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, gl
.TEXTURE_2D
, tex_2d
, 0);
92 if (gl
.checkFramebufferStatus(gl
.READ_FRAMEBUFFER
) != gl
.FRAMEBUFFER_COMPLETE
) {
93 testFailed("Framebuffer incomplete.");
97 // Create draw fbo and its color attachment.
98 var rb0
= gl
.createRenderbuffer();
99 gl
.bindRenderbuffer(gl
.RENDERBUFFER
, rb0
);
100 gl
.renderbufferStorage(gl
.RENDERBUFFER
, gl
.RGBA8
, width
, height
);
102 var fb1
= gl
.createFramebuffer();
103 gl
.bindFramebuffer(gl
.DRAW_FRAMEBUFFER
, fb1
);
104 gl
.framebufferRenderbuffer(gl
.DRAW_FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, gl
.RENDERBUFFER
, rb0
);
105 if (gl
.checkFramebufferStatus(gl
.DRAW_FRAMEBUFFER
) != gl
.FRAMEBUFFER_COMPLETE
) {
106 testFailed("Framebuffer incomplete.");
110 // Blit framebuffer, all conditions are OK.
111 gl
.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl
.COLOR_BUFFER_BIT
, gl
.NEAREST
);
112 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "blitFramebuffer should succeed.");
114 // Blit framebuffer, the src buffer and the dst buffer should not be identical.
115 // Exactly the same read/draw fbo
116 gl
.bindFramebuffer(gl
.READ_FRAMEBUFFER
, fb0
);
117 gl
.bindFramebuffer(gl
.DRAW_FRAMEBUFFER
, fb0
);
118 gl
.blitFramebuffer(0, 0, 2, 2, 4, 4, 6, 6, gl
.COLOR_BUFFER_BIT
, gl
.NEAREST
);
119 wtu
.glErrorShouldBe(gl
, gl
.INVALID_OPERATION
, "blitFramebuffer should generate INVALID_OPERATION if read/draw buffer are identical.");
121 // Exactly the same read/draw framebuffer: default framebuffer
122 gl
.bindFramebuffer(gl
.READ_FRAMEBUFFER
, null);
123 gl
.bindFramebuffer(gl
.DRAW_FRAMEBUFFER
, null);
124 gl
.blitFramebuffer(0, 0, 2, 2, 4, 4, 6, 6, gl
.COLOR_BUFFER_BIT
, gl
.NEAREST
);
125 wtu
.glErrorShouldBe(gl
, gl
.INVALID_OPERATION
, "blitFramebuffer should generate INVALID_OPERATION if read/draw buffer are identical.");
127 // The same image with the same level bound to read/draw buffer.
128 gl
.bindFramebuffer(gl
.READ_FRAMEBUFFER
, fb0
);
129 gl
.framebufferTexture2D(gl
.READ_FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, gl
.TEXTURE_2D
, tex_2d
, 0);
130 gl
.bindFramebuffer(gl
.DRAW_FRAMEBUFFER
, fb1
);
131 gl
.framebufferTexture2D(gl
.DRAW_FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, gl
.TEXTURE_2D
, tex_2d
, 0);
132 if (gl
.checkFramebufferStatus(gl
.READ_FRAMEBUFFER
) != gl
.FRAMEBUFFER_COMPLETE
||
133 gl
.checkFramebufferStatus(gl
.DRAW_FRAMEBUFFER
) != gl
.FRAMEBUFFER_COMPLETE
) {
134 testFailed("Framebuffer incomplete.");
137 gl
.blitFramebuffer(0, 0, 2, 2, 4, 4, 6, 6, gl
.COLOR_BUFFER_BIT
, gl
.NEAREST
);
138 wtu
.glErrorShouldBe(gl
, gl
.INVALID_OPERATION
, "blitFramebuffer should generate INVALID_OPERATION if read/draw color buffer are identical.");
140 // The same image in read/draw buffer, but different levels are bound to read/draw buffer respectively.
141 gl
.bindFramebuffer(gl
.DRAW_FRAMEBUFFER
, fb1
);
142 gl
.framebufferTexture2D(gl
.DRAW_FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, gl
.TEXTURE_2D
, tex_2d
, 1);
143 if (gl
.checkFramebufferStatus(gl
.DRAW_FRAMEBUFFER
) != gl
.FRAMEBUFFER_COMPLETE
) {
144 testFailed("Framebuffer incomplete.");
147 gl
.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl
.COLOR_BUFFER_BIT
, gl
.NEAREST
);
148 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "blitFramebuffer should succeed if read/draw buffer has the same image with different levels.");
150 // The same cube_map image in read/draw buffer, but different faces are bound to read/draw buffer respectively.
151 var tex_cube_map
= gl
.createTexture();
152 gl
.bindTexture(gl
.TEXTURE_CUBE_MAP
, tex_cube_map
);
153 gl
.texImage2D(gl
.TEXTURE_CUBE_MAP_POSITIVE_X
, 0, gl
.RGBA8
, width
, height
, 0, gl
.RGBA
, gl
.UNSIGNED_BYTE
, null);
154 gl
.texImage2D(gl
.TEXTURE_CUBE_MAP_NEGATIVE_X
, 0, gl
.RGBA8
, width
, height
, 0, gl
.RGBA
, gl
.UNSIGNED_BYTE
, null);
155 gl
.texImage2D(gl
.TEXTURE_CUBE_MAP_POSITIVE_Y
, 0, gl
.RGBA8
, width
, height
, 0, gl
.RGBA
, gl
.UNSIGNED_BYTE
, null);
156 gl
.texImage2D(gl
.TEXTURE_CUBE_MAP_NEGATIVE_Y
, 0, gl
.RGBA8
, width
, height
, 0, gl
.RGBA
, gl
.UNSIGNED_BYTE
, null);
157 gl
.texImage2D(gl
.TEXTURE_CUBE_MAP_POSITIVE_Z
, 0, gl
.RGBA8
, width
, height
, 0, gl
.RGBA
, gl
.UNSIGNED_BYTE
, null);
158 gl
.texImage2D(gl
.TEXTURE_CUBE_MAP_NEGATIVE_Z
, 0, gl
.RGBA8
, width
, height
, 0, gl
.RGBA
, gl
.UNSIGNED_BYTE
, null);
159 gl
.bindFramebuffer(gl
.READ_FRAMEBUFFER
, fb0
);
160 gl
.framebufferTexture2D(gl
.READ_FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, gl
.TEXTURE_CUBE_MAP_POSITIVE_X
, tex_cube_map
, 0);
161 gl
.bindFramebuffer(gl
.DRAW_FRAMEBUFFER
, fb1
);
162 gl
.framebufferTexture2D(gl
.DRAW_FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, gl
.TEXTURE_CUBE_MAP_NEGATIVE_X
, tex_cube_map
, 0);
163 if ((gl
.checkFramebufferStatus(gl
.READ_FRAMEBUFFER
) != gl
.FRAMEBUFFER_COMPLETE
) ||
164 (gl
.checkFramebufferStatus(gl
.DRAW_FRAMEBUFFER
) != gl
.FRAMEBUFFER_COMPLETE
)) {
165 testFailed("Framebuffer incomplete.");
168 gl
.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl
.COLOR_BUFFER_BIT
, gl
.NEAREST
);
169 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "blitFramebuffer should succeed if read/draw buffer has the same CUBE_MAP image with different faces.");
171 // The same 3D/2D_ARRAY image in read/draw buffer, but different layers are bound to read/draw buffer respectively.
172 var tex_2d_array
= gl
.createTexture();
173 gl
.bindTexture(gl
.TEXTURE_2D_ARRAY
, tex_2d_array
);
175 gl
.texImage3D(gl
.TEXTURE_2D_ARRAY
, 0, gl
.RGBA8
, width
, height
, depth
, 0, gl
.RGBA
, gl
.UNSIGNED_BYTE
, null);
176 gl
.bindFramebuffer(gl
.READ_FRAMEBUFFER
, fb0
);
177 var level
= 0, layer
= 0;
178 gl
.framebufferTextureLayer(gl
.READ_FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, tex_2d_array
, level
, layer
);
179 gl
.bindFramebuffer(gl
.DRAW_FRAMEBUFFER
, fb1
);
181 gl
.framebufferTextureLayer(gl
.DRAW_FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, tex_2d_array
, level
, layer
);
182 if ((gl
.checkFramebufferStatus(gl
.READ_FRAMEBUFFER
) != gl
.FRAMEBUFFER_COMPLETE
) ||
183 (gl
.checkFramebufferStatus(gl
.DRAW_FRAMEBUFFER
) != gl
.FRAMEBUFFER_COMPLETE
)) {
184 testFailed("Framebuffer incomplete.");
187 gl
.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl
.COLOR_BUFFER_BIT
, gl
.NEAREST
);
188 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "blitFramebuffer should succeed if read/draw buffer has the same 3D/2D_ARRAY image with different layers.");
190 // The same image are bound as depth buffer in both read framebuffer and draw framebuffer
191 var rb1
= gl
.createRenderbuffer();
192 gl
.bindRenderbuffer(gl
.RENDERBUFFER
, rb1
);
193 gl
.renderbufferStorage(gl
.RENDERBUFFER
, gl
.DEPTH24_STENCIL8
, width
, height
);
194 gl
.bindFramebuffer(gl
.READ_FRAMEBUFFER
, fb0
);
195 gl
.framebufferTexture2D(gl
.READ_FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, gl
.TEXTURE_CUBE_MAP_POSITIVE_X
, tex_cube_map
, 0);
196 gl
.framebufferRenderbuffer(gl
.READ_FRAMEBUFFER
, gl
.DEPTH_ATTACHMENT
, gl
.RENDERBUFFER
, rb1
);
197 gl
.bindFramebuffer(gl
.DRAW_FRAMEBUFFER
, fb1
);
198 gl
.framebufferTexture2D(gl
.DRAW_FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, gl
.TEXTURE_CUBE_MAP_NEGATIVE_X
, tex_cube_map
, 0);
199 gl
.framebufferRenderbuffer(gl
.DRAW_FRAMEBUFFER
, gl
.DEPTH_ATTACHMENT
, gl
.RENDERBUFFER
, rb1
);
200 if (gl
.checkFramebufferStatus(gl
.READ_FRAMEBUFFER
) != gl
.FRAMEBUFFER_COMPLETE
||
201 gl
.checkFramebufferStatus(gl
.DRAW_FRAMEBUFFER
) != gl
.FRAMEBUFFER_COMPLETE
) {
202 testFailed("Framebuffer incomplete.");
205 // But the mask doesn't have depth buffer bit.
206 gl
.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl
.COLOR_BUFFER_BIT
, gl
.NEAREST
);
207 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "blitFramebuffer should succeed.");
209 // The mask has depth buffer bit.
210 gl
.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl
.COLOR_BUFFER_BIT
| gl
.DEPTH_BUFFER_BIT
, gl
.NEAREST
);
211 wtu
.glErrorShouldBe(gl
, gl
.INVALID_OPERATION
, "blitFramebuffer should generate INVALID_OPERATION if read/draw framebuffer have identical depth buffer attachment.");
213 // The same image are bound as stencil buffer in both read framebuffer and draw framebuffer
214 gl
.bindFramebuffer(gl
.READ_FRAMEBUFFER
, fb0
);
215 gl
.framebufferRenderbuffer(gl
.READ_FRAMEBUFFER
, gl
.STENCIL_ATTACHMENT
, gl
.RENDERBUFFER
, rb1
);
216 gl
.bindFramebuffer(gl
.DRAW_FRAMEBUFFER
, fb1
);
217 gl
.framebufferRenderbuffer(gl
.DRAW_FRAMEBUFFER
, gl
.STENCIL_ATTACHMENT
, gl
.RENDERBUFFER
, rb1
);
218 if (gl
.checkFramebufferStatus(gl
.READ_FRAMEBUFFER
) != gl
.FRAMEBUFFER_COMPLETE
||
219 gl
.checkFramebufferStatus(gl
.DRAW_FRAMEBUFFER
) != gl
.FRAMEBUFFER_COMPLETE
) {
220 testFailed("Framebuffer incomplete.");
223 // But the mask doesn't have stencil buffer bit.
224 gl
.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl
.COLOR_BUFFER_BIT
, gl
.NEAREST
);
225 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "blitFramebuffer should succeed.");
227 // The mask has stencil buffer bit.
228 gl
.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl
.COLOR_BUFFER_BIT
| gl
.STENCIL_BUFFER_BIT
, gl
.NEAREST
);
229 wtu
.glErrorShouldBe(gl
, gl
.INVALID_OPERATION
, "blitFramebuffer should generate INVALID_OPERATION if read/draw framebuffer have identical stencil buffer attachment.");
231 // The same image are bound as color buffer in both read framebuffer and draw framebuffer
232 var rb2
= gl
.createRenderbuffer();
233 gl
.bindRenderbuffer(gl
.RENDERBUFFER
, rb2
);
234 gl
.renderbufferStorage(gl
.RENDERBUFFER
, gl
.DEPTH24_STENCIL8
, width
, height
);
235 gl
.bindFramebuffer(gl
.READ_FRAMEBUFFER
, fb0
);
236 gl
.framebufferTexture2D(gl
.READ_FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, gl
.TEXTURE_CUBE_MAP_POSITIVE_X
, tex_cube_map
, 0);
237 gl
.framebufferRenderbuffer(gl
.READ_FRAMEBUFFER
, gl
.STENCIL_ATTACHMENT
, gl
.RENDERBUFFER
, null);
238 gl
.framebufferRenderbuffer(gl
.DRAW_FRAMEBUFFER
, gl
.STENCIL_ATTACHMENT
, gl
.RENDERBUFFER
, null);
239 gl
.framebufferRenderbuffer(gl
.READ_FRAMEBUFFER
, gl
.DEPTH_ATTACHMENT
, gl
.RENDERBUFFER
, rb2
);
240 gl
.bindFramebuffer(gl
.DRAW_FRAMEBUFFER
, fb1
);
241 gl
.framebufferTexture2D(gl
.DRAW_FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, gl
.TEXTURE_CUBE_MAP_NEGATIVE_X
, tex_cube_map
, 0);
242 gl
.framebufferTexture2D(gl
.DRAW_FRAMEBUFFER
, gl
.COLOR_ATTACHMENT1
, gl
.TEXTURE_CUBE_MAP_POSITIVE_X
, tex_cube_map
, 0);
243 gl
.framebufferRenderbuffer(gl
.DRAW_FRAMEBUFFER
, gl
.DEPTH_ATTACHMENT
, gl
.RENDERBUFFER
, rb1
);
244 if (gl
.checkFramebufferStatus(gl
.READ_FRAMEBUFFER
) != gl
.FRAMEBUFFER_COMPLETE
||
245 gl
.checkFramebufferStatus(gl
.DRAW_FRAMEBUFFER
) != gl
.FRAMEBUFFER_COMPLETE
) {
246 testFailed("Framebuffer incomplete.");
249 // But the mask doesn't have color buffer bit.
250 gl
.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl
.DEPTH_BUFFER_BIT
, gl
.NEAREST
);
251 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "blitFramebuffer should succeed.");
253 // The mask has color buffer bit, but the same image is not specified as draw buffer.
254 gl
.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl
.COLOR_BUFFER_BIT
| gl
.DEPTH_BUFFER_BIT
, gl
.NEAREST
);
255 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "blitFramebuffer should succeed.");
257 // The mask has color buffer bit, the same image is specified as both read buffer and draw buffer.
258 gl
.drawBuffers([gl
.COLOR_ATTACHENT0
, gl
.COLOR_ATTACHMENT1
]);
259 gl
.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl
.COLOR_BUFFER_BIT
| gl
.DEPTH_BUFFER_BIT
, gl
.NEAREST
);
260 wtu
.glErrorShouldBe(gl
, gl
.INVALID_OPERATION
, "blitFramebuffer should generate INVALID_OPERATION if read/draw buffers have identical color buffer attachment.");
262 gl
.bindTexture(gl
.TEXTURE_2D
, null);
263 gl
.bindTexture(gl
.TEXTURE_CUBE_MAP
, null);
264 gl
.bindTexture(gl
.TEXTURE_2D_ARRAY
, null);
265 gl
.bindRenderbuffer(gl
.RENDERBUFFER
, null);
266 gl
.bindFramebuffer(gl
.READ_FRAMEBUFFER
, null);
267 gl
.bindFramebuffer(gl
.DRAW_FRAMEBUFFER
, null);
268 gl
.deleteTexture(tex_2d
);
269 gl
.deleteTexture(tex_cube_map
);
270 gl
.deleteTexture(tex_2d_array
);
271 gl
.deleteRenderbuffer(rb0
);
272 gl
.deleteRenderbuffer(rb1
);
273 gl
.deleteRenderbuffer(rb2
);
274 gl
.deleteFramebuffer(fb0
);
275 gl
.deleteFramebuffer(fb1
);
278 function blit_framebuffer_multisampling_srgb() {
281 debug("This test vefify the functionality of blitframebuffer from or to a multisampled srgb image.");
283 // Read buffer can have multisampled srgb image, but draw buffers can not.
284 var rb0
= gl
.createRenderbuffer();
285 var fb0
= gl
.createFramebuffer();
286 var rb1
= gl
.createRenderbuffer();
287 var fb1
= gl
.createFramebuffer();
288 var samples
= gl
.getInternalformatParameter(gl
.RENDERBUFFER
, gl
.SRGB8_ALPHA8
, gl
.SAMPLES
);
289 gl
.bindRenderbuffer(gl
.RENDERBUFFER
, rb0
);
290 gl
.renderbufferStorageMultisample(gl
.RENDERBUFFER
, samples
[0], gl
.SRGB8_ALPHA8
, width
, height
);
291 gl
.bindFramebuffer(gl
.READ_FRAMEBUFFER
, fb0
);
292 gl
.framebufferRenderbuffer(gl
.READ_FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, gl
.RENDERBUFFER
, rb0
);
294 gl
.bindRenderbuffer(gl
.RENDERBUFFER
, rb1
);
295 gl
.renderbufferStorage(gl
.RENDERBUFFER
, gl
.SRGB8_ALPHA8
, width
, height
);
296 gl
.bindFramebuffer(gl
.DRAW_FRAMEBUFFER
, fb1
);
297 gl
.framebufferRenderbuffer(gl
.DRAW_FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, gl
.RENDERBUFFER
, rb1
);
298 if (gl
.checkFramebufferStatus(gl
.DRAW_FRAMEBUFFER
) != gl
.FRAMEBUFFER_COMPLETE
||
299 gl
.checkFramebufferStatus(gl
.READ_FRAMEBUFFER
) != gl
.FRAMEBUFFER_COMPLETE
) {
300 testFailed("Framebuffer incomplete.");
303 gl
.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl
.COLOR_BUFFER_BIT
, gl
.LINEAR
);
304 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "blitFramebuffer from multisampled srgb image should succeed.");
306 gl
.bindRenderbuffer(gl
.RENDERBUFFER
, rb1
);
307 gl
.renderbufferStorageMultisample(gl
.RENDERBUFFER
, samples
[0], gl
.SRGB8_ALPHA8
, width
, height
);
308 gl
.bindFramebuffer(gl
.DRAW_FRAMEBUFFER
, fb1
);
309 gl
.framebufferRenderbuffer(gl
.DRAW_FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, gl
.RENDERBUFFER
, rb1
);
310 if (gl
.checkFramebufferStatus(gl
.DRAW_FRAMEBUFFER
) != gl
.FRAMEBUFFER_COMPLETE
) {
311 testFailed("Framebuffer incomplete.");
314 gl
.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl
.COLOR_BUFFER_BIT
, gl
.LINEAR
);
315 wtu
.glErrorShouldBe(gl
, gl
.INVALID_OPERATION
, "blitFramebuffer to a multisampled srgb image should generate INVALID_OPERATION.");
317 // BlitFramebuffer from a multisampled srgb image, the src region and the dst region must be exactly the same.
318 gl
.bindRenderbuffer(gl
.RENDERBUFFER
, rb1
);
319 gl
.renderbufferStorage(gl
.RENDERBUFFER
, gl
.SRGB8_ALPHA8
, width
, height
);
320 gl
.bindFramebuffer(gl
.DRAW_FRAMEBUFFER
, fb1
);
321 gl
.framebufferRenderbuffer(gl
.DRAW_FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, gl
.RENDERBUFFER
, rb1
);
322 if (gl
.checkFramebufferStatus(gl
.DRAW_FRAMEBUFFER
) != gl
.FRAMEBUFFER_COMPLETE
) {
323 testFailed("Framebuffer incomplete.");
326 gl
.blitFramebuffer(0, 0, 2, 2, 2, 2, 4, 4, gl
.COLOR_BUFFER_BIT
, gl
.LINEAR
);
327 wtu
.glErrorShouldBe(gl
, gl
.INVALID_OPERATION
, "blitFramebuffer from a multisampled srgb image, the src region and the dst region must be exactly the same.");
329 gl
.blitFramebuffer(0, 0, 2, 2, 0, 0, 4, 4, gl
.COLOR_BUFFER_BIT
, gl
.LINEAR
);
330 wtu
.glErrorShouldBe(gl
, gl
.INVALID_OPERATION
, "blitFramebuffer from a multisampled srgb image, the src region and the dst region must be exactly the same.");
332 // BlitFramebuffer from a multisampled srgb image, the format/type must be exactly the same. So blit from a multisampled srgb image to a linear image is invalid.
333 var tex
= gl
.createTexture();
334 gl
.bindTexture(gl
.TEXTURE_2D
, tex
);
335 gl
.texImage2D(gl
.TEXTURE_2D
, 0, gl
.RGBA
, width
, height
, 0, gl
.RGBA
, gl
.UNSIGNED_BYTE
, null);
336 gl
.bindFramebuffer(gl
.DRAW_FRAMEBUFFER
, fb1
);
337 gl
.framebufferTexture2D(gl
.DRAW_FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, gl
.TEXTURE_2D
, tex
, 0);
338 if (gl
.checkFramebufferStatus(gl
.DRAW_FRAMEBUFFER
) != gl
.FRAMEBUFFER_COMPLETE
) {
339 testFailed("Framebuffer incomplete.");
342 gl
.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl
.COLOR_BUFFER_BIT
, gl
.LINEAR
);
343 wtu
.glErrorShouldBe(gl
, gl
.INVALID_OPERATION
, "blitFramebuffer from a multisampled srgb image, the format/type must be exactly the same.");
345 gl
.bindRenderbuffer(gl
.RENDERBUFFER
, null);
346 gl
.bindTexture(gl
.TEXTURE_2D
, null);
347 gl
.bindFramebuffer(gl
.READ_FRAMEBUFFER
, null);
348 gl
.bindFramebuffer(gl
.DRAW_FRAMEBUFFER
, null);
349 gl
.deleteRenderbuffer(rb0
);
350 gl
.deleteRenderbuffer(rb1
);
351 gl
.deleteTexture(tex
);
352 gl
.deleteFramebuffer(fb0
);
353 gl
.deleteFramebuffer(fb1
);
356 var successfullyParsed
= true;
358 <script src=
"../../js/js-test-post.js"></script>