From 53844705a8b7278a0c0fd0dcaf1d899971fbeb36 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Wed, 22 May 2024 10:55:51 -0700 Subject: [PATCH] [webgl] Implement GL_UNPACK_ROW_LENGTH Fixes: #21968 --- src/generated_struct_info32.json | 2 ++ src/generated_struct_info64.json | 2 ++ src/library_webgl.js | 13 ++++++++----- src/struct_info.json | 7 +++++++ test/test_browser.py | 5 +++++ test/third_party/cubegeom/cubegeom_pre_vao_es.c | 15 +++++++++++++-- 6 files changed, 37 insertions(+), 7 deletions(-) diff --git a/src/generated_struct_info32.json b/src/generated_struct_info32.json index dceaadbed8d76..9eab4a9b49a22 100644 --- a/src/generated_struct_info32.json +++ b/src/generated_struct_info32.json @@ -308,6 +308,8 @@ "File::DirectoryKind": 2, "File::SymlinkKind": 3, "File::UnknownKind": 0, + "GL_UNPACK_ALIGNMENT": 3317, + "GL_UNPACK_ROW_LENGTH": 3314, "ICANON": 2, "ICRNL": 256, "IEXTEN": 32768, diff --git a/src/generated_struct_info64.json b/src/generated_struct_info64.json index ef23e32b4a9e0..3e9ded11a0bec 100644 --- a/src/generated_struct_info64.json +++ b/src/generated_struct_info64.json @@ -308,6 +308,8 @@ "File::DirectoryKind": 2, "File::SymlinkKind": 3, "File::UnknownKind": 0, + "GL_UNPACK_ALIGNMENT": 3317, + "GL_UNPACK_ROW_LENGTH": 3314, "ICANON": 2, "ICRNL": 256, "IEXTEN": 32768, diff --git a/src/library_webgl.js b/src/library_webgl.js index b28040859e14c..0c450474d1086 100644 --- a/src/library_webgl.js +++ b/src/library_webgl.js @@ -288,6 +288,7 @@ for (/**@suppress{duplicate}*/var i = 0; i < {{{ GL_POOL_TEMP_BUFFERS_SIZE }}}; #endif unpackAlignment: 4, // default alignment is 4 bytes + unpackRowLength: 0, // Records a GL error condition that occurred, stored until user calls // glGetError() to fetch it. As per GLES2 spec, only the first error is @@ -1235,8 +1236,10 @@ for (/**@suppress{duplicate}*/var i = 0; i < {{{ GL_POOL_TEMP_BUFFERS_SIZE }}}; }, glPixelStorei: (pname, param) => { - if (pname == 0xCF5 /* GL_UNPACK_ALIGNMENT */) { + if (pname == {{{ cDefs.GL_UNPACK_ALIGNMENT }}}) { GL.unpackAlignment = param; + } else if (pname == {{{ cDefs.GL_UNPACK_ROW_LENGTH }}}) { + GL.unpackRowLength = param; } GLctx.pixelStorei(pname, param); }, @@ -1548,15 +1551,15 @@ for (/**@suppress{duplicate}*/var i = 0; i < {{{ GL_POOL_TEMP_BUFFERS_SIZE }}}; GLctx.compressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, data ? {{{ makeHEAPView('U8', 'data', 'data+imageSize') }}} : null); }, - $computeUnpackAlignedImageSize: (width, height, sizePerPixel, alignment) => { + $computeUnpackAlignedImageSize: (width, height, sizePerPixel) => { function roundedToNextMultipleOf(x, y) { #if GL_ASSERTIONS assert((y & (y-1)) === 0, 'Unpack alignment must be a power of 2! (Allowed values per WebGL spec are 1, 2, 4 or 8)'); #endif return (x + y - 1) & -y; } - var plainRowSize = width * sizePerPixel; - var alignedRowSize = roundedToNextMultipleOf(plainRowSize, alignment); + var plainRowSize = (GL.unpackRowLength || width) * sizePerPixel; + var alignedRowSize = roundedToNextMultipleOf(plainRowSize, GL.unpackAlignment); return height * alignedRowSize; }, @@ -1600,7 +1603,7 @@ for (/**@suppress{duplicate}*/var i = 0; i < {{{ GL_POOL_TEMP_BUFFERS_SIZE }}}; $emscriptenWebGLGetTexPixelData: (type, format, width, height, pixels, internalFormat) => { var heap = heapObjectForWebGLType(type); var sizePerPixel = colorChannelsInGlTextureFormat(format) * heap.BYTES_PER_ELEMENT; - var bytes = computeUnpackAlignedImageSize(width, height, sizePerPixel, GL.unpackAlignment); + var bytes = computeUnpackAlignedImageSize(width, height, sizePerPixel); #if GL_ASSERTIONS assert(pixels % heap.BYTES_PER_ELEMENT == 0, 'Pointer to texture data passed to texture get function must be aligned to the byte size of the pixel type!'); #endif diff --git a/src/struct_info.json b/src/struct_info.json index 32e18a0fab008..a74c9378dccca 100644 --- a/src/struct_info.json +++ b/src/struct_info.json @@ -1204,6 +1204,13 @@ "ALC_INVALID_ENUM" ] }, + { + "file": "GL/gl.h", + "defines": [ + "GL_UNPACK_ALIGNMENT", + "GL_UNPACK_ROW_LENGTH" + ] + }, // =========================================== // WebGPU // NOTE: This section is auto-generated. diff --git a/test/test_browser.py b/test/test_browser.py index 53c60fd7888f9..364c64734de24 100644 --- a/test/test_browser.py +++ b/test/test_browser.py @@ -2166,6 +2166,11 @@ def test_cubegeom_pre2_vao2(self): def test_cubegeom_pre_vao_es(self): self.reftest('third_party/cubegeom/cubegeom_pre_vao_es.c', 'third_party/cubegeom/cubegeom_pre_vao.png', args=['-sFULL_ES2', '-lGL', '-lSDL']) + @requires_graphics_hardware + @no_swiftshader + def test_cubegeom_row_length(self): + self.reftest('third_party/cubegeom/cubegeom_pre_vao_es.c', 'third_party/cubegeom/cubegeom_pre_vao.png', args=['-sMIN_WEBGL_VERSION=2', '-sFULL_ES2', '-lGL', '-lSDL', '-DUSE_UNPACK_ROW_LENGTH']) + @requires_graphics_hardware def test_cubegeom_u4fv_2(self): self.reftest('third_party/cubegeom/cubegeom_u4fv_2.c', 'third_party/cubegeom/cubegeom_u4fv_2.png', args=['-sLEGACY_GL_EMULATION', '-lGL', '-lSDL']) diff --git a/test/third_party/cubegeom/cubegeom_pre_vao_es.c b/test/third_party/cubegeom/cubegeom_pre_vao_es.c index fe35315c2f1cf..34400bb4359ec 100644 --- a/test/third_party/cubegeom/cubegeom_pre_vao_es.c +++ b/test/third_party/cubegeom/cubegeom_pre_vao_es.c @@ -55,14 +55,25 @@ int main(int argc, char *argv[]) glBindTexture( GL_TEXTURE_2D, texture ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); - GLubyte textureData[16*16*4]; +#if USE_UNPACK_ROW_LENGTH +#define ROW_SIZE 20 +#else +#define ROW_SIZE 16 +#endif + GLubyte textureData[16*ROW_SIZE*4] = {0}; for (int x = 0; x < 16; x++) { for (int y = 0; y < 16; y++) { - *((int*)&textureData[(x*16 + y) * 4]) = x*16 + ((y*16) << 8); + *((int*)&textureData[(x*ROW_SIZE + y) * 4]) = x*16 + ((y*16) << 8); } } +#if USE_UNPACK_ROW_LENGTH + glPixelStorei(GL_UNPACK_ROW_LENGTH, ROW_SIZE); +#endif glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE, textureData ); +#if USE_UNPACK_ROW_LENGTH + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); +#endif // Create a second texture