Fixes https://bugs.winehq.org/show_bug.cgi?id=58620
I've made this a separate MR from !8969 because that MR contains a lot of highly debatable architectural decisions (such as FAKE_16BIT_MEMDC_PIXEL_FORMAT and all of its special case branches). This MR is very minimal and straight to the point.
-- v2: win32u: Fix garbled 24-bit bitmap rendering
From: Zowie van Dillen zowie+wine@vandillen.io
--- dlls/win32u/opengl.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/dlls/win32u/opengl.c b/dlls/win32u/opengl.c index efd6ea63b1a..63b378affd8 100644 --- a/dlls/win32u/opengl.c +++ b/dlls/win32u/opengl.c @@ -1251,9 +1251,10 @@ static BOOL flush_memory_dc( struct wgl_context *context, HDC hdc, BOOL write, v
if (!get_image_from_bitmap( bmp, info, &bits, &src )) { - int width = info->bmiHeader.biWidth, height = info->bmiHeader.biSizeImage / 4 / width; - if (write) funcs->p_glDrawPixels( width, height, GL_BGRA, GL_UNSIGNED_BYTE, bits.ptr ); - else funcs->p_glReadPixels( 0, 0, width, height, GL_BGRA, GL_UNSIGNED_BYTE, bits.ptr ); + int width = info->bmiHeader.biWidth, height = abs( info->bmiHeader.biHeight ); + UINT format = (info->bmiHeader.biBitCount == 24 ? GL_BGR : GL_BGRA); + if (write) funcs->p_glDrawPixels( width, height, format, GL_UNSIGNED_BYTE, bits.ptr ); + else funcs->p_glReadPixels( 0, 0, width, height, format, GL_UNSIGNED_BYTE, bits.ptr ); } GDI_ReleaseObj( dc->hBitmap ); }
Rémi Bernon (@rbernon) commented about dlls/win32u/opengl.c:
if (!get_image_from_bitmap( bmp, info, &bits, &src )) {
int width = info->bmiHeader.biWidth, height = info->bmiHeader.biSizeImage / 4 / width;
if (write) funcs->p_glDrawPixels( width, height, GL_BGRA, GL_UNSIGNED_BYTE, bits.ptr );
else funcs->p_glReadPixels( 0, 0, width, height, GL_BGRA, GL_UNSIGNED_BYTE, bits.ptr );
int width = info->bmiHeader.biWidth, height = abs( info->bmiHeader.biHeight );
UINT format = (info->bmiHeader.biBitCount == 24 ? GL_BGR : GL_BGRA);
if (write) funcs->p_glDrawPixels( width, height, format, GL_UNSIGNED_BYTE, bits.ptr );
else funcs->p_glReadPixels( 0, 0, width, height, format, GL_UNSIGNED_BYTE, bits.ptr );
I believe there was a buffer overflow as GL / GDI currently don't agree on whether the bitmap is 16bpp or 32bpp, and `height = info->bmiHeader.biSizeImage / 4 / width` was there to avoid reading / writing past the bitmap buffer. This would probably be fixed with your other 16bpp changes, can we keep it for now or is it part of the fix here?