From e43f949f8a80611fdfe21068f55dfe9fb7604ae8 Mon Sep 17 00:00:00 2001 From: Tom Englund Date: Tue, 13 Jan 2026 16:42:31 +0100 Subject: [PATCH] shm: ensure we use right gl unpack alignment (#12975) gl defaults to 4 and not all formats is divisible with 4 meaning its going to pad out ouf bounds and cause issues. check if the stride is divisible with 4 otherwise set it to 1, aka disable it. GL_UNPACK_ALIGNMENT only takes 1,2,4,8 but formats like RGB888 has bytesPerBlock 3. --- src/render/Texture.cpp | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/render/Texture.cpp b/src/render/Texture.cpp index 5e8c5d400..0e8074853 100644 --- a/src/render/Texture.cpp +++ b/src/render/Texture.cpp @@ -76,9 +76,19 @@ void CTexture::createFromShm(uint32_t drmFormat, uint8_t* pixels, uint32_t strid if (format->swizzle.has_value()) swizzle(format->swizzle.value()); + bool alignmentChanged = false; + if (format->bytesPerBlock != 4) { + const GLint alignment = (stride % 4 == 0) ? 4 : 1; + GLCALL(glPixelStorei(GL_UNPACK_ALIGNMENT, alignment)); + alignmentChanged = true; + } + GLCALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride / format->bytesPerBlock)); GLCALL(glTexImage2D(GL_TEXTURE_2D, 0, format->glInternalFormat ? format->glInternalFormat : format->glFormat, size_.x, size_.y, 0, format->glFormat, format->glType, pixels)); GLCALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0)); + if (alignmentChanged) + GLCALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 4)); + unbind(); if (m_keepDataCopy) { @@ -130,8 +140,16 @@ void CTexture::update(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, cons if (format->swizzle.has_value()) swizzle(format->swizzle.value()); - damage.copy().intersect(CBox{{}, m_size}).forEachRect([&format, &stride, &pixels](const auto& rect) { - GLCALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride / format->bytesPerBlock)); + bool alignmentChanged = false; + if (format->bytesPerBlock != 4) { + const GLint alignment = (stride % 4 == 0) ? 4 : 1; + GLCALL(glPixelStorei(GL_UNPACK_ALIGNMENT, alignment)); + alignmentChanged = true; + } + + GLCALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride / format->bytesPerBlock)); + + damage.copy().intersect(CBox{{}, m_size}).forEachRect([&format, &pixels](const auto& rect) { GLCALL(glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, rect.x1)); GLCALL(glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, rect.y1)); @@ -140,6 +158,9 @@ void CTexture::update(uint32_t drmFormat, uint8_t* pixels, uint32_t stride, cons GLCALL(glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x1, rect.y1, width, height, format->glFormat, format->glType, pixels)); }); + if (alignmentChanged) + GLCALL(glPixelStorei(GL_UNPACK_ALIGNMENT, 4)); + GLCALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0)); GLCALL(glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0)); GLCALL(glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0));