| <!-- |
| Copyright (c) 2019 The Khronos Group Inc. |
| Use of this source code is governed by an MIT-style license that can be |
| found in the LICENSE.txt file. |
| --> |
| |
| <!DOCTYPE html> |
| <html> |
| <head> |
| <meta charset="utf-8"> |
| <link rel="stylesheet" href="../../resources/js-test-style.css"/> |
| <script src="../../js/js-test-pre.js"></script> |
| <script src="../../js/webgl-test-utils.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"> |
| precision mediump float; |
| varying vec4 color; |
| |
| void main() |
| { |
| gl_FragColor = color; |
| } |
| </script> |
| </head> |
| <body> |
| <canvas id="example" width="32" height="32"></canvas> |
| <canvas id="example2" width="32" height="32"></canvas> |
| <div id="description"></div> |
| <div id="console"></div> |
| <script> |
| "use strict"; |
| |
| // The below declarations need to be global for "shouldBe" to see them |
| var wtu = WebGLTestUtils; |
| 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); |
| wtu.glErrorShouldBe(gl, gl.NO_ERROR); |
| var bytesPerPixel = calculatePixelBytes(format, type); |
| var padding = calculatePaddingBytes(bytesPerPixel, packAlignment, width); |
| var size = bytesPerPixel * width * height + padding * (height - 1); |
| if (type != gl.UNSIGNED_BYTE) { |
| throw "test error: only UNSIGNED_BYTE is valid to ReadPixels"; |
| } |
| if (size < 0) |
| size = 0; |
| array = new Uint8Array(size); |
| gl.readPixels(0, 0, width, height, format, type, array); |
| if (width < 0 || height < 0) { |
| wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); |
| return; |
| } |
| |
| wtu.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; |
| 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.'); |
| |
| |
| debug("<h1>antialias = false</h1>"); |
| shouldBeNonNull("gl = wtu.create3DContext('example', {antialias: false})") |
| var formats = [ gl.RGBA ]; |
| var formatNames = [ "RGBA" ]; |
| runAllIterations(); |
| debug("<h1>antialias = true</h1>"); |
| shouldBeNonNull("gl = wtu.create3DContext('example2', {antialias: true})") |
| runAllIterations(); |
| |
| function runAllIterations() { |
| shouldBeNonNull("program = wtu.setupProgram(gl, ['vshader', 'fshader'], ['pos', 'colorIn'])"); |
| |
| for (var i = 0; i < formats.length; ++i) { |
| var format = formats[i]; |
| |
| debug("Testing format = " + formatNames[i] + " and type = UNSIGNED_BYTE"); |
| runTestIteration(format, gl.UNSIGNED_BYTE, 1, 1, 2); |
| runTestIteration(format, gl.UNSIGNED_BYTE, 2, 1, 2); |
| runTestIteration(format, gl.UNSIGNED_BYTE, 4, 1, 2); |
| runTestIteration(format, gl.UNSIGNED_BYTE, 8, 1, 2); |
| runTestIteration(format, gl.UNSIGNED_BYTE, 4, 2, 2); |
| runTestIteration(format, gl.UNSIGNED_BYTE, 8, 2, 2); |
| runTestIteration(format, gl.UNSIGNED_BYTE, 4, 3, 2); |
| runTestIteration(format, gl.UNSIGNED_BYTE, 8, 3, 2); |
| runTestIteration(format, gl.UNSIGNED_BYTE, 4, 4, 2); |
| runTestIteration(format, gl.UNSIGNED_BYTE, 8, 4, 2); |
| runTestIteration(format, gl.UNSIGNED_BYTE, 8, 5, 1); |
| runTestIteration(format, gl.UNSIGNED_BYTE, 4, 5, 2); |
| runTestIteration(format, gl.UNSIGNED_BYTE, 8, 5, 2); |
| runTestIteration(format, gl.UNSIGNED_BYTE, 8, 6, 2); |
| runTestIteration(format, gl.UNSIGNED_BYTE, 8, 7, 2); |
| runTestIteration(format, gl.UNSIGNED_BYTE, 8, 8, 2); |
| runTestIteration(format, gl.UNSIGNED_BYTE, 1, 0, 0); |
| runTestIteration(format, gl.UNSIGNED_BYTE, 2, 0, 0); |
| runTestIteration(format, gl.UNSIGNED_BYTE, 4, 0, 0); |
| runTestIteration(format, gl.UNSIGNED_BYTE, 8, 0, 0); |
| runTestIteration(format, gl.UNSIGNED_BYTE, 1, -1, 1); |
| runTestIteration(format, gl.UNSIGNED_BYTE, 2, 1, -1); |
| runTestIteration(format, gl.UNSIGNED_BYTE, 4, 0, -1); |
| runTestIteration(format, gl.UNSIGNED_BYTE, 8, -1, -1); |
| } |
| } |
| var successfullyParsed = true; |
| |
| </script> |
| <script src="../../js/js-test-post.js"></script> |
| </body> |
| </html> |