| <html> |
| <head> |
| <script src="../../../resources/js-test.js"></script> |
| <script src="resources/webgl-test.js"></script> |
| <script id="vshader" type="x-shader/x-vertex"> |
| attribute vec3 pos; |
| attribute vec4 colorIn; |
| varying vec4 color; |
| |
| void main() |
| { |
| color = colorIn; |
| gl_Position = vec4(pos.xyz, 1.0); |
| } |
| </script> |
| |
| <script id="fshader" type="x-shader/x-fragment"> |
| #ifdef GL_ES |
| precision mediump float; |
| #endif |
| varying vec4 color; |
| |
| void main() |
| { |
| gl_FragColor = color; |
| } |
| </script> |
| </head> |
| <body> |
| <canvas id="example" width="32px" height="32px"></canvas> |
| <div id="description"></div> |
| <div id="console"></div> |
| <script> |
| if (window.internals) |
| window.internals.settings.setWebGLErrorsToConsoleEnabled(false); |
| |
| // The below declarations need to be global for "shouldBe" to see them |
| var gl = null; |
| var array = null; |
| var pixel = [ 0, 0, 0, 0 ]; |
| var expectedColor = [ 0, 0, 0, 0 ]; |
| |
| function calculatePixelBytes(format, type) |
| { |
| var size = 0; |
| switch (format) { |
| case gl.ALPHA: |
| size = 1; |
| break; |
| case gl.RGB: |
| size = 3; |
| break; |
| case gl.RGBA: |
| size = 4; |
| break; |
| default: |
| return -1; |
| } |
| switch (type) { |
| case gl.UNSIGNED_BYTE: |
| break; |
| case gl.UNSIGNED_SHORT_5_6_5: |
| if (format != gl.RGB) |
| return -1; |
| size = 2; |
| break; |
| case gl.UNSIGNED_SHORT_4_4_4_4: |
| case gl.UNSIGNED_SHORT_5_5_5_1: |
| if (format != gl.RGBA) |
| return -1; |
| size = 2; |
| break; |
| default: |
| return -1; |
| } |
| return size; |
| } |
| |
| function calculatePaddingBytes(bytesPerPixel, packAlignment, width) |
| { |
| var padding = 0; |
| switch (packAlignment) { |
| case 1: |
| case 2: |
| case 4: |
| case 8: |
| padding = (bytesPerPixel * width) % packAlignment; |
| if (padding > 0) |
| padding = packAlignment - padding; |
| break; |
| default: |
| return -1; |
| } |
| return padding; |
| } |
| |
| function packColor(format, type, r, g, b, a) |
| { |
| // FIXME: not sure if the color packing is correct for UNSIGNED_SHORT_*. |
| var color = [ 0, 0, 0, 0 ]; |
| switch (type) { |
| case gl.UNSIGNED_BYTE: |
| switch (format) { |
| case gl.ALPHA: |
| color[0] = a; |
| break; |
| case gl.RGB: |
| color[0] = r; |
| color[1] = g; |
| color[2] = b; |
| break; |
| case gl.RGBA: |
| color[0] = r; |
| color[1] = g; |
| color[2] = b; |
| color[3] = a; |
| break; |
| default: |
| return null; |
| } |
| break; |
| case gl.UNSIGNED_SHORT_5_6_5: |
| if (format != gl.RGB) |
| return null; |
| r >>= 3; |
| g >>= 2; |
| b >>= 3; |
| color[0] = (r << 11) + (g << 5) + b; |
| break; |
| case gl.UNSIGNED_SHORT_4_4_4_4: |
| if (format != gl.RGBA) |
| return null; |
| r >>= 4; |
| g >>= 4; |
| b >>= 4; |
| a >>= 4; |
| color[0] = (r << 12) + (g << 8) + (b << 4) + a; |
| break; |
| case gl.UNSIGNED_SHORT_5_5_5_1: |
| if (format != gl.RGBA) |
| return null; |
| r >>= 3; |
| g >>= 3; |
| b >>= 3; |
| a >>= 7; |
| color[0] = (r << 11) + (g << 6) + (b << 1) + a; |
| break; |
| Default: |
| return null; |
| } |
| return color; |
| } |
| |
| function runTestIteration(format, type, packAlignment, width, height) |
| { |
| debug("Testing PACK_ALIGNMENT = " + packAlignment + ", width = " + width + ", height = " + height); |
| gl.clearColor(1, 0.4, 0, 1); |
| gl.clear(gl.COLOR_BUFFER_BIT); |
| gl.pixelStorei(gl.PACK_ALIGNMENT, packAlignment); |
| glErrorShouldBe(gl, gl.NO_ERROR); |
| var bytesPerPixel = calculatePixelBytes(format, type); |
| var padding = calculatePaddingBytes(bytesPerPixel, packAlignment, width); |
| var size = bytesPerPixel * width * height + padding * (height - 1); |
| var isShort = false; |
| switch (type) { |
| case gl.UNSIGNED_SHORT_5_6_5: |
| case gl.UNSIGNED_SHORT_4_4_4_4: |
| case gl.UNSIGNED_SHORT_5_5_5_1: |
| isShort = true; |
| } |
| if (isShort) |
| size /= 2; |
| if (size < 0) |
| size = 0; |
| if (type == gl.UNSIGNED_BYTE) |
| array = new Uint8Array(size); |
| else |
| array = new Uint16Array(size); |
| gl.readPixels(0, 0, width, height, format, type, array); |
| if (width < 0 || height < 0) { |
| glErrorShouldBe(gl, gl.INVALID_VALUE); |
| return; |
| } else { |
| glErrorShouldBe(gl, gl.NO_ERROR); |
| if (!array.length) |
| return; |
| } |
| // Check the last pixel of the last row. |
| var bytesPerRow = width * bytesPerPixel + padding; |
| var pos = bytesPerRow * (height - 1) + (width - 1) * bytesPerPixel; |
| var numComponents = bytesPerPixel; |
| if (isShort) { |
| pos /= 2; |
| numComponents /= 2; |
| } |
| for (var i = 0; i < numComponents; ++i) |
| pixel[i] = array[pos + i]; |
| for (var i = numComponents; i < 4; ++i) |
| pixel[i] = 0; |
| expectedColor = packColor(format, type, 255, 102, 0, 255); |
| shouldBeNonNull(expectedColor); |
| shouldBe("pixel", "expectedColor"); |
| } |
| |
| description('Verify readPixels() works fine with various PACK_ALIGNMENT values.'); |
| |
| shouldBeNonNull("gl = initWebGL('example', 'vshader', 'fshader', [ 'pos', 'colorIn' ], [ 0, 0, 0, 1 ], 1)"); |
| gl.disable(gl.BLEND); |
| |
| debug("Testing format = RGBA and type = UNSIGNED_BYTE"); |
| runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 1, 1, 2); |
| runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 2, 1, 2); |
| runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 4, 1, 2); |
| runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 8, 1, 2); |
| runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 4, 2, 2); |
| runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 8, 2, 2); |
| runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 4, 3, 2); |
| runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 8, 3, 2); |
| runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 4, 4, 2); |
| runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 8, 4, 2); |
| runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 8, 5, 1); |
| runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 4, 5, 2); |
| runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 8, 5, 2); |
| runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 8, 6, 2); |
| runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 8, 7, 2); |
| runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 8, 8, 2); |
| runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 1, 0, 0); |
| runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 2, 0, 0); |
| runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 4, 0, 0); |
| runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 8, 0, 0); |
| runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 1, -1, 1); |
| runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 2, 1, -1); |
| runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 4, 0, -1); |
| runTestIteration(gl.RGBA, gl.UNSIGNED_BYTE, 8, -1, -1); |
| </script> |
| </body> |
| </html> |