From 31f2bf640f75fe7f8137b0628f11e85ed6005ef9 Mon Sep 17 00:00:00 2001 From: George Matsumura Date: Thu, 6 Aug 2020 21:43:33 -0600 Subject: [PATCH] Fix readpixels format endianness This fixes an issue where glReadPixels read components out-of-order on little-endian machines, leading to resulting images with inaccurate color values. To fix this, we make the pixel format value conditional on cpu endianness, which we get CMake to identify at compile time. --- src/CMakeLists.txt | 8 ++++++++ src/shImage.c | 23 ++++++++++++++++++----- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 17bbde1..1afe48b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,5 @@ cmake_minimum_required(VERSION 2.8) +include (TestBigEndian) # TODO headers as dependencies # TODO shared/static switch CMake-style set(libOpenVG_SOURCES @@ -27,6 +28,13 @@ set(libOpenVG_HEADERS shContext.h ) add_definitions(-std=c99 -pedantic -DHAVE_CONFIG_H) + +# Test endianness for pixel packing +TEST_BIG_ENDIAN(BIG_ENDIAN) +if(BIG_ENDIAN) + add_compile_definitions(BIG_ENDIAN) +endif() + include_directories(${OPENGL_INCLUDE_DIR}) # TODO what if OpenGL library has nonstandard location? add_library(OpenVG SHARED ${libOpenVG_SOURCES}) diff --git a/src/shImage.c b/src/shImage.c index 484ae8f..73d5b74 100644 --- a/src/shImage.c +++ b/src/shImage.c @@ -552,10 +552,7 @@ void shUpdateImageTexture(SHImage *i, VGContext *c) glBindTexture(GL_TEXTURE_2D, i->texture); glTexImage2D(GL_TEXTURE_2D, 0, i->fd.glintformat, i->texwidth, i->texheight, 0, - i->fd.glformat, 0x8367/*i->fd.gltype*/, i->data); /* FIXME determine why the format is so silly */ -/* short center=(i->texwidth*i->texheight)*2+2*i->texwidth; -// printf("shUpdateImageTexture: 0x%x 0x%x 0x%x\n",i->fd.glintformat,i->fd.glformat, i->fd.gltype); -// printf("shUpdateImageTexture: %d %d %d %d\n",i->data[center],i->data[center+1],i->data[center+2],i->data[center+3]); */ + i->fd.glformat, i->fd.gltype, i->data); } /*---------------------------------------------------------- @@ -968,7 +965,11 @@ VG_API_CALL void vgSetPixels(VGint dx, VGint dy, /* Setup window image format descriptor */ /* TODO: this actually depends on the target framebuffer type if we really want the copy to be optimized */ +#ifdef BIG_ENDIAN shSetupImageFormat(VG_sRGBA_8888, &winfd); +#else + shSetupImageFormat(VG_sABGR_8888, &winfd); +#endif /* OpenGL doesn't allow us to use random stride. We have to manually copy the image data and write from a copy with @@ -1026,7 +1027,11 @@ VG_API_CALL void vgWritePixels(const void * data, VGint dataStride, /* Setup window image format descriptor */ /* TODO: this actually depends on the target framebuffer type if we really want the copy to be optimized */ +#ifdef BIG_ENDIAN shSetupImageFormat(VG_sRGBA_8888, &winfd); +#else + shSetupImageFormat(VG_sABGR_8888, &winfd); +#endif /* OpenGL doesn't allow us to use random stride. We have to manually copy the image data and write from a copy with @@ -1077,8 +1082,12 @@ VG_API_CALL void vgGetPixels(VGImage dst, VGint dx, VGint dy, /* Setup window image format descriptor */ /* TODO: this actually depends on the target framebuffer type if we really want the copy to be optimized */ +#ifdef BIG_ENDIAN shSetupImageFormat(VG_sRGBA_8888, &winfd); - +#else + shSetupImageFormat(VG_sABGR_8888, &winfd); +#endif + /* OpenGL doesn't allow us to read to random destination coordinates nor using random stride. We have to read first and then manually copy to the image data */ @@ -1138,7 +1147,11 @@ VG_API_CALL void vgReadPixels(void * data, VGint dataStride, /* Setup window image format descriptor */ /* TODO: this actually depends on the target framebuffer type if we really want the copy to be optimized */ +#ifdef BIG_ENDIAN shSetupImageFormat(VG_sRGBA_8888, &winfd); +#else + shSetupImageFormat(VG_sABGR_8888, &winfd); +#endif /* OpenGL doesn't allow random data stride. We have to read first and then manually copy to the output buffer */