read-pixels-pack-alignment.html (7285B)
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 <link rel="stylesheet" href="../../resources/js-test-style.css"/> 12 <script src="../../js/js-test-pre.js"></script> 13 <script src="../../js/webgl-test-utils.js"></script> 14 <script id="vshader" type="x-shader/x-vertex"> 15 attribute vec3 pos; 16 attribute vec4 colorIn; 17 varying vec4 color; 18 19 void main() 20 { 21 color = colorIn; 22 gl_Position = vec4(pos.xyz, 1.0); 23 } 24 </script> 25 26 <script id="fshader" type="x-shader/x-fragment"> 27 precision mediump float; 28 varying vec4 color; 29 30 void main() 31 { 32 gl_FragColor = color; 33 } 34 </script> 35 </head> 36 <body> 37 <canvas id="example" width="32" height="32"></canvas> 38 <canvas id="example2" width="32" height="32"></canvas> 39 <div id="description"></div> 40 <div id="console"></div> 41 <script> 42 "use strict"; 43 44 // The below declarations need to be global for "shouldBe" to see them 45 var wtu = WebGLTestUtils; 46 var gl = null; 47 var array = null; 48 var pixel = [ 0, 0, 0, 0 ]; 49 var expectedColor = [ 0, 0, 0, 0 ]; 50 51 function calculatePixelBytes(format, type) 52 { 53 var size = 0; 54 switch (format) { 55 case gl.ALPHA: 56 size = 1; 57 break; 58 case gl.RGB: 59 size = 3; 60 break; 61 case gl.RGBA: 62 size = 4; 63 break; 64 default: 65 return -1; 66 } 67 switch (type) { 68 case gl.UNSIGNED_BYTE: 69 break; 70 case gl.UNSIGNED_SHORT_5_6_5: 71 if (format != gl.RGB) 72 return -1; 73 size = 2; 74 break; 75 case gl.UNSIGNED_SHORT_4_4_4_4: 76 case gl.UNSIGNED_SHORT_5_5_5_1: 77 if (format != gl.RGBA) 78 return -1; 79 size = 2; 80 break; 81 default: 82 return -1; 83 } 84 return size; 85 } 86 87 function calculatePaddingBytes(bytesPerPixel, packAlignment, width) 88 { 89 var padding = 0; 90 switch (packAlignment) { 91 case 1: 92 case 2: 93 case 4: 94 case 8: 95 padding = (bytesPerPixel * width) % packAlignment; 96 if (padding > 0) 97 padding = packAlignment - padding; 98 break; 99 default: 100 return -1; 101 } 102 return padding; 103 } 104 105 function packColor(format, type, r, g, b, a) 106 { 107 // FIXME: not sure if the color packing is correct for UNSIGNED_SHORT_*. 108 var color = [ 0, 0, 0, 0 ]; 109 switch (type) { 110 case gl.UNSIGNED_BYTE: 111 switch (format) { 112 case gl.ALPHA: 113 color[0] = a; 114 break; 115 case gl.RGB: 116 color[0] = r; 117 color[1] = g; 118 color[2] = b; 119 break; 120 case gl.RGBA: 121 color[0] = r; 122 color[1] = g; 123 color[2] = b; 124 color[3] = a; 125 break; 126 default: 127 return null; 128 } 129 break; 130 case gl.UNSIGNED_SHORT_5_6_5: 131 if (format != gl.RGB) 132 return null; 133 r >>= 3; 134 g >>= 2; 135 b >>= 3; 136 color[0] = (r << 11) + (g << 5) + b; 137 break; 138 case gl.UNSIGNED_SHORT_4_4_4_4: 139 if (format != gl.RGBA) 140 return null; 141 r >>= 4; 142 g >>= 4; 143 b >>= 4; 144 a >>= 4; 145 color[0] = (r << 12) + (g << 8) + (b << 4) + a; 146 break; 147 case gl.UNSIGNED_SHORT_5_5_5_1: 148 if (format != gl.RGBA) 149 return null; 150 r >>= 3; 151 g >>= 3; 152 b >>= 3; 153 a >>= 7; 154 color[0] = (r << 11) + (g << 6) + (b << 1) + a; 155 break; 156 Default: 157 return null; 158 } 159 return color; 160 } 161 162 function runTestIteration(format, type, packAlignment, width, height) 163 { 164 debug("Testing PACK_ALIGNMENT = " + packAlignment + ", width = " + width + ", height = " + height); 165 gl.clearColor(1, 0.4, 0, 1); 166 gl.clear(gl.COLOR_BUFFER_BIT); 167 gl.pixelStorei(gl.PACK_ALIGNMENT, packAlignment); 168 wtu.glErrorShouldBe(gl, gl.NO_ERROR); 169 var bytesPerPixel = calculatePixelBytes(format, type); 170 var padding = calculatePaddingBytes(bytesPerPixel, packAlignment, width); 171 var size = bytesPerPixel * width * height + padding * (height - 1); 172 if (type != gl.UNSIGNED_BYTE) { 173 throw "test error: only UNSIGNED_BYTE is valid to ReadPixels"; 174 } 175 if (size < 0) 176 size = 0; 177 array = new Uint8Array(size); 178 gl.readPixels(0, 0, width, height, format, type, array); 179 if (width < 0 || height < 0) { 180 wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); 181 return; 182 } 183 184 wtu.glErrorShouldBe(gl, gl.NO_ERROR); 185 if (!array.length) 186 return; 187 188 // Check the last pixel of the last row. 189 var bytesPerRow = width * bytesPerPixel + padding; 190 var pos = bytesPerRow * (height - 1) + (width - 1) * bytesPerPixel; 191 var numComponents = bytesPerPixel; 192 for (var i = 0; i < numComponents; ++i) 193 pixel[i] = array[pos + i]; 194 for (var i = numComponents; i < 4; ++i) 195 pixel[i] = 0; 196 expectedColor = packColor(format, type, 255, 102, 0, 255); 197 shouldBeNonNull("expectedColor"); 198 shouldBe("pixel", "expectedColor"); 199 } 200 201 description('Verify readPixels() works fine with various PACK_ALIGNMENT values.'); 202 203 204 debug("<h1>antialias = false</h1>"); 205 shouldBeNonNull("gl = wtu.create3DContext('example', {antialias: false})") 206 var formats = [ gl.RGBA ]; 207 var formatNames = [ "RGBA" ]; 208 runAllIterations(); 209 debug("<h1>antialias = true</h1>"); 210 shouldBeNonNull("gl = wtu.create3DContext('example2', {antialias: true})") 211 runAllIterations(); 212 213 function runAllIterations() { 214 shouldBeNonNull("program = wtu.setupProgram(gl, ['vshader', 'fshader'], ['pos', 'colorIn'])"); 215 216 for (var i = 0; i < formats.length; ++i) { 217 var format = formats[i]; 218 219 debug("Testing format = " + formatNames[i] + " and type = UNSIGNED_BYTE"); 220 runTestIteration(format, gl.UNSIGNED_BYTE, 1, 1, 2); 221 runTestIteration(format, gl.UNSIGNED_BYTE, 2, 1, 2); 222 runTestIteration(format, gl.UNSIGNED_BYTE, 4, 1, 2); 223 runTestIteration(format, gl.UNSIGNED_BYTE, 8, 1, 2); 224 runTestIteration(format, gl.UNSIGNED_BYTE, 4, 2, 2); 225 runTestIteration(format, gl.UNSIGNED_BYTE, 8, 2, 2); 226 runTestIteration(format, gl.UNSIGNED_BYTE, 4, 3, 2); 227 runTestIteration(format, gl.UNSIGNED_BYTE, 8, 3, 2); 228 runTestIteration(format, gl.UNSIGNED_BYTE, 4, 4, 2); 229 runTestIteration(format, gl.UNSIGNED_BYTE, 8, 4, 2); 230 runTestIteration(format, gl.UNSIGNED_BYTE, 8, 5, 1); 231 runTestIteration(format, gl.UNSIGNED_BYTE, 4, 5, 2); 232 runTestIteration(format, gl.UNSIGNED_BYTE, 8, 5, 2); 233 runTestIteration(format, gl.UNSIGNED_BYTE, 8, 6, 2); 234 runTestIteration(format, gl.UNSIGNED_BYTE, 8, 7, 2); 235 runTestIteration(format, gl.UNSIGNED_BYTE, 8, 8, 2); 236 runTestIteration(format, gl.UNSIGNED_BYTE, 1, 0, 0); 237 runTestIteration(format, gl.UNSIGNED_BYTE, 2, 0, 0); 238 runTestIteration(format, gl.UNSIGNED_BYTE, 4, 0, 0); 239 runTestIteration(format, gl.UNSIGNED_BYTE, 8, 0, 0); 240 runTestIteration(format, gl.UNSIGNED_BYTE, 1, -1, 1); 241 runTestIteration(format, gl.UNSIGNED_BYTE, 2, 1, -1); 242 runTestIteration(format, gl.UNSIGNED_BYTE, 4, 0, -1); 243 runTestIteration(format, gl.UNSIGNED_BYTE, 8, -1, -1); 244 } 245 } 246 var successfullyParsed = true; 247 248 </script> 249 <script src="../../js/js-test-post.js"></script> 250 </body> 251 </html>