blitframebuffer-srgb-and-linear-drawbuffers.html (9445B)
1 <!-- 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. 5 --> 6 7 <!DOCTYPE html> 8 <html> 9 <head> 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> 15 </head> 16 <body> 17 <canvas id="canvas" width="8" height="8"></canvas> 18 <div id="description"></div> 19 <div id="console"></div> 20 21 <script> 22 "use strict"; 23 24 var wtu = WebGLTestUtils; 25 description("This test verifies the functionality of blitFramebuffer with multiple draw buffers (srgb image and linear image)."); 26 27 var gl = wtu.create3DContext("canvas", undefined, 2); 28 var linearMask = 1; 29 var srgbMask = 2; 30 31 if (!gl) { 32 testFailed("WebGL context does not exist"); 33 } else { 34 testPassed("WebGL context exists"); 35 36 var filters = [gl.LINEAR, gl.NEAREST]; 37 var drawbuffersFormats = [linearMask, srgbMask, linearMask | srgbMask]; 38 for (var ii = 0; ii < filters.length; ++ii) { 39 for (var jj = 0; jj < drawbuffersFormats.length; ++jj) { 40 blitframebuffer_srgb_and_linear_drawbuffers(gl.SRGB8_ALPHA8, drawbuffersFormats[jj], filters[ii]); 41 blitframebuffer_srgb_and_linear_drawbuffers(gl.RGBA8, drawbuffersFormats[jj], filters[ii]); 42 } 43 } 44 } 45 46 function blitframebuffer_srgb_and_linear_drawbuffers(readbufferFormat, drawbuffersFormatMask, filter) { 47 debug(""); 48 debug("The filter is: " + wtu.glEnumToString(gl, filter)); 49 debug("Read buffer format is: " + wtu.glEnumToString(gl, readbufferFormat)); 50 var drawbuffersFormat = "\0"; 51 if (drawbuffersFormatMask & linearMask) { 52 drawbuffersFormat += " linear "; 53 } 54 if (drawbuffersFormatMask & srgbMask) { 55 drawbuffersFormat += " srgb "; 56 } 57 debug("The test have multiple draw buffers, the images are: " + drawbuffersFormat); 58 59 var tex_srgb0 = gl.createTexture(); 60 var tex_srgb1 = gl.createTexture(); 61 var tex_linear0 = gl.createTexture(); 62 var tex_linear1 = gl.createTexture(); 63 var tex_read = gl.createTexture(); 64 var fbo_read = gl.createFramebuffer(); 65 var fbo_draw = gl.createFramebuffer(); 66 67 // Create read buffer and feed data to the read buffer 68 var size = 8; 69 var data = new Uint8Array(size * size * 4); 70 var color = [250, 100, 15, 255]; 71 for (var ii = 0; ii < size * size * 4; ii += 4) { 72 for (var jj = 0; jj < 4; ++jj) { 73 data[ii + jj] = color[jj]; 74 } 75 } 76 gl.bindTexture(gl.TEXTURE_2D, tex_read); 77 gl.texImage2D(gl.TEXTURE_2D, 0, readbufferFormat, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, data); 78 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_read); 79 gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex_read, 0); 80 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "setup read framebuffer should succeed"); 81 82 // Create multiple textures. Attach them as fbo's draw buffers. 83 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo_draw); 84 85 var drawbuffers = [gl.NONE, gl.NONE, gl.NONE, gl.NONE]; 86 if (drawbuffersFormatMask & srgbMask) { 87 gl.bindTexture(gl.TEXTURE_2D, tex_srgb0); 88 gl.texImage2D(gl.TEXTURE_2D, 0, gl.SRGB8_ALPHA8, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 89 gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex_srgb0, 0); 90 gl.bindTexture(gl.TEXTURE_2D, tex_srgb1); 91 gl.texImage2D(gl.TEXTURE_2D, 0, gl.SRGB8_ALPHA8, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 92 gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT2, gl.TEXTURE_2D, tex_srgb1, 0); 93 drawbuffers[0] = gl.COLOR_ATTACHMENT0; 94 drawbuffers[2] = gl.COLOR_ATTACHMENT2; 95 } 96 97 if (drawbuffersFormatMask & linearMask) { 98 gl.bindTexture(gl.TEXTURE_2D, tex_linear0); 99 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 100 gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT1, gl.TEXTURE_2D, tex_linear0, 0); 101 gl.bindTexture(gl.TEXTURE_2D, tex_linear1); 102 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 103 gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT3, gl.TEXTURE_2D, tex_linear1, 0); 104 drawbuffers[1] = gl.COLOR_ATTACHMENT1; 105 drawbuffers[3] = gl.COLOR_ATTACHMENT3; 106 } 107 108 gl.drawBuffers(drawbuffers); 109 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "setup draw framebuffer should succeed"); 110 111 if (gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE || 112 gl.checkFramebufferStatus(gl.READ_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) { 113 testFailed("Framebuffer incomplete when setup draw framebuffer."); 114 return; 115 } 116 117 // Blit to multiple draw buffers with srgb images and linear images 118 var dstSize = size - 1; 119 gl.blitFramebuffer(0, 0, size, size, 0, 0, dstSize, dstSize, gl.COLOR_BUFFER_BIT, filter); 120 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "blitframebuffer should succeed"); 121 122 // Read pixels from srgb images and linear images 123 var srgbPixels0 = new Uint8Array(dstSize * dstSize * 4); 124 var srgbPixels1 = new Uint8Array(dstSize * dstSize * 4); 125 var linearPixels0 = new Uint8Array(dstSize * dstSize * 4); 126 var linearPixels1 = new Uint8Array(dstSize * dstSize * 4); 127 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_draw); 128 if (drawbuffersFormatMask & srgbMask) { 129 gl.readBuffer(gl.COLOR_ATTACHMENT0); 130 gl.readPixels(0, 0, dstSize, dstSize, gl.RGBA, gl.UNSIGNED_BYTE, srgbPixels0); 131 gl.readBuffer(gl.COLOR_ATTACHMENT2); 132 gl.readPixels(0, 0, dstSize, dstSize, gl.RGBA, gl.UNSIGNED_BYTE, srgbPixels1); 133 } 134 135 if (drawbuffersFormatMask & linearMask) { 136 gl.readBuffer(gl.COLOR_ATTACHMENT1); 137 gl.readPixels(0, 0, dstSize, dstSize, gl.RGBA, gl.UNSIGNED_BYTE, linearPixels0); 138 gl.readBuffer(gl.COLOR_ATTACHMENT3); 139 gl.readPixels(0, 0, dstSize, dstSize, gl.RGBA, gl.UNSIGNED_BYTE, linearPixels1); 140 } 141 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "readpixels should succeed"); 142 143 // Compare 144 var expectedSRGBColor = (readbufferFormat == gl.SRGB8_ALPHA8) ? color : wtu.linearToSRGB(color); 145 var expectedLinearColor = (readbufferFormat == gl.SRGB8_ALPHA8) ? wtu.sRGBToLinear(color) : color; 146 var failed = false; 147 for (var ii = 0; ii < dstSize; ++ii) { 148 for (var jj = 0; jj < dstSize; ++jj) { 149 var index = (ii * dstSize + jj) * 4; 150 if (drawbuffersFormatMask & srgbMask) { 151 var srgbColor0 = [srgbPixels0[index], srgbPixels0[index + 1], srgbPixels0[index + 2], srgbPixels0[index + 3]]; 152 if (checkPixel(srgbColor0, expectedSRGBColor) == false) { 153 failed = true; 154 debug("Pixels comparison failed for the 1st sRGB image. Pixel at [" + jj + ", " + ii + "] should be (" + expectedSRGBColor + "), but the actual color is (" + srgbColor0 + ")"); 155 } 156 var srgbColor1 = [srgbPixels1[index], srgbPixels1[index + 1], srgbPixels1[index + 2], srgbPixels1[index + 3]]; 157 if (checkPixel(srgbColor1, expectedSRGBColor) == false) { 158 failed = true; 159 debug("Pixels comparison failed for the 2nd sRGB image. Pixel at [" + jj + ", " + ii + "] should be (" + expectedSRGBColor + "), but the actual color is (" + srgbColor1 + ")"); 160 } 161 } 162 163 if (drawbuffersFormatMask & linearMask) { 164 var linearColor0 = [linearPixels0[index], linearPixels0[index + 1], linearPixels0[index + 2], linearPixels0[index + 3]]; 165 if (checkPixel(linearColor0, expectedLinearColor) == false) { 166 failed = true; 167 debug("Pixel comparison failed for the 1st linear image. Pixel at [" + jj + ", " + ii + "] should be (" + color + "), but the actual color is (" + linearColor0 + ")"); 168 } 169 var linearColor1 = [linearPixels1[index], linearPixels1[index + 1], linearPixels1[index + 2], linearPixels1[index + 3]]; 170 if (checkPixel(linearColor1, expectedLinearColor) == false) { 171 failed = true; 172 debug("Pixel comparison failed for the 2nd linear image. Pixel at [" + jj + ", " + ii + "] should be (" + color + "), but the actual color is (" + linearColor1 + ")"); 173 } 174 } 175 } 176 } 177 if (failed == false) { 178 testPassed("All pixels comparision passed!"); 179 } 180 181 // deinit 182 gl.bindTexture(gl.TEXTURE_2D, null); 183 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null); 184 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null); 185 gl.deleteTexture(tex_srgb0); 186 gl.deleteTexture(tex_linear0); 187 gl.deleteTexture(tex_srgb1); 188 gl.deleteTexture(tex_linear1); 189 gl.deleteTexture(tex_read); 190 gl.deleteFramebuffer(fbo_read); 191 gl.deleteFramebuffer(fbo_draw); 192 } 193 194 function checkPixel(color, expectedColor) { 195 var tolerance = 3; 196 return (Math.abs(color[0] - expectedColor[0]) <= tolerance && 197 Math.abs(color[1] - expectedColor[1]) <= tolerance && 198 Math.abs(color[2] - expectedColor[2]) <= tolerance && 199 Math.abs(color[3] - expectedColor[3]) <= tolerance); 200 } 201 202 var successfullyParsed = true; 203 </script> 204 <script src="../../js/js-test-post.js"></script> 205 206 </body> 207 </html>