From 18a96edf6932f42abca5e327a043ead088c6c8fb Mon Sep 17 00:00:00 2001 From: Huw Davies Date: Fri, 27 May 2011 13:10:29 +0100 Subject: [PATCH] gdi32: Add support for 16 bpp dibs. --- dlls/gdi32/dibdrv/dc.c | 13 +++++ dlls/gdi32/dibdrv/dibdrv.h | 2 + dlls/gdi32/dibdrv/primitives.c | 92 +++++++++++++++++++++++++++++++++- dlls/gdi32/tests/dib.c | 32 ++++++++++++ 4 files changed, 138 insertions(+), 1 deletion(-) diff --git a/dlls/gdi32/dibdrv/dc.c b/dlls/gdi32/dibdrv/dc.c index 6cc1d3314b3..98463b7f2f6 100644 --- a/dlls/gdi32/dibdrv/dc.c +++ b/dlls/gdi32/dibdrv/dc.c @@ -66,6 +66,7 @@ static void init_bit_fields(dib_info *dib, const DWORD *bit_fields) static BOOL init_dib_info(dib_info *dib, const BITMAPINFOHEADER *bi, const DWORD *bit_fields, void *bits) { static const DWORD bit_fields_888[3] = {0xff0000, 0x00ff00, 0x0000ff}; + static const DWORD bit_fields_555[3] = {0x7c00, 0x03e0, 0x001f}; dib->bit_count = bi->biBitCount; dib->width = bi->biWidth; @@ -100,6 +101,18 @@ static BOOL init_dib_info(dib_info *dib, const BITMAPINFOHEADER *bi, const DWORD dib->funcs = &funcs_32; break; + case 16: + if(bi->biCompression == BI_RGB) + bit_fields = bit_fields_555; + + init_bit_fields(dib, bit_fields); + + if(dib->red_mask == 0x7c00 && dib->green_mask == 0x03e0 && dib->blue_mask == 0x001f) + dib->funcs = &funcs_555; + else + dib->funcs = &funcs_16; + break; + default: TRACE("bpp %d not supported, will forward to graphics driver.\n", dib->bit_count); return FALSE; diff --git a/dlls/gdi32/dibdrv/dibdrv.h b/dlls/gdi32/dibdrv/dibdrv.h index ccf9f9a0539..0b5dba313e8 100644 --- a/dlls/gdi32/dibdrv/dibdrv.h +++ b/dlls/gdi32/dibdrv/dibdrv.h @@ -46,6 +46,8 @@ typedef struct primitive_funcs extern const primitive_funcs funcs_8888 DECLSPEC_HIDDEN; extern const primitive_funcs funcs_32 DECLSPEC_HIDDEN; +extern const primitive_funcs funcs_555 DECLSPEC_HIDDEN; +extern const primitive_funcs funcs_16 DECLSPEC_HIDDEN; extern const primitive_funcs funcs_null DECLSPEC_HIDDEN; extern void calc_and_xor_masks(INT rop, DWORD color, DWORD *and, DWORD *xor) DECLSPEC_HIDDEN; diff --git a/dlls/gdi32/dibdrv/primitives.c b/dlls/gdi32/dibdrv/primitives.c index 6dec47883c5..c1d159712a8 100644 --- a/dlls/gdi32/dibdrv/primitives.c +++ b/dlls/gdi32/dibdrv/primitives.c @@ -26,11 +26,21 @@ static inline DWORD *get_pixel_ptr_32(const dib_info *dib, int x, int y) return (DWORD *)((BYTE*)dib->bits + y * dib->stride + x * 4); } +static inline WORD *get_pixel_ptr_16(const dib_info *dib, int x, int y) +{ + return (WORD *)((BYTE*)dib->bits + y * dib->stride + x * 2); +} + static inline void do_rop_32(DWORD *ptr, DWORD and, DWORD xor) { *ptr = (*ptr & and) ^ xor; } +static inline void do_rop_16(WORD *ptr, WORD and, WORD xor) +{ + *ptr = (*ptr & and) ^ xor; +} + static void solid_rects_32(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor) { DWORD *ptr, *start; @@ -38,13 +48,27 @@ static void solid_rects_32(const dib_info *dib, int num, const RECT *rc, DWORD a for(i = 0; i < num; i++, rc++) { - start = ptr = get_pixel_ptr_32(dib, rc->left, rc->top); + start = get_pixel_ptr_32(dib, rc->left, rc->top); for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 4) for(x = rc->left, ptr = start; x < rc->right; x++) do_rop_32(ptr++, and, xor); } } +static void solid_rects_16(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor) +{ + WORD *ptr, *start; + int x, y, i; + + for(i = 0; i < num; i++, rc++) + { + start = get_pixel_ptr_16(dib, rc->left, rc->top); + for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2) + for(x = rc->left, ptr = start; x < rc->right; x++) + do_rop_16(ptr++, and, xor); + } +} + static void solid_rects_null(const dib_info *dib, int num, const RECT *rc, DWORD and, DWORD xor) { return; @@ -120,6 +144,52 @@ static void pattern_rects_32(const dib_info *dib, int num, const RECT *rc, const } } +static void pattern_rects_16(const dib_info *dib, int num, const RECT *rc, const POINT *origin, + const dib_info *brush, void *and_bits, void *xor_bits) +{ + WORD *ptr, *start, *start_and, *and_ptr, *start_xor, *xor_ptr; + int x, y, i; + POINT offset; + + for(i = 0; i < num; i++, rc++) + { + offset = calc_brush_offset(rc, brush, origin); + + start = get_pixel_ptr_16(dib, rc->left, rc->top); + start_and = (WORD*)and_bits + offset.y * brush->stride / 2; + start_xor = (WORD*)xor_bits + offset.y * brush->stride / 2; + + for(y = rc->top; y < rc->bottom; y++, start += dib->stride / 2) + { + and_ptr = start_and + offset.x; + xor_ptr = start_xor + offset.x; + + for(x = rc->left, ptr = start; x < rc->right; x++) + { + do_rop_16(ptr++, *and_ptr++, *xor_ptr++); + if(and_ptr == start_and + brush->width) + { + and_ptr = start_and; + xor_ptr = start_xor; + } + } + + offset.y++; + if(offset.y == brush->height) + { + start_and = and_bits; + start_xor = xor_bits; + offset.y = 0; + } + else + { + start_and += brush->stride / 2; + start_xor += brush->stride / 2; + } + } + } +} + static void pattern_rects_null(const dib_info *dib, int num, const RECT *rc, const POINT *origin, const dib_info *brush, void *and_bits, void *xor_bits) { @@ -156,6 +226,12 @@ static DWORD colorref_to_pixel_masks(const dib_info *dib, COLORREF colour) put_field(b, dib->blue_shift, dib->blue_len); } +static DWORD colorref_to_pixel_555(const dib_info *dib, COLORREF color) +{ + return ( ((color >> 19) & 0x1f) | ((color >> 6) & 0x03e0) | ((color << 7) & 0x7c00) ); +} + + static DWORD colorref_to_pixel_null(const dib_info *dib, COLORREF color) { return 0; @@ -175,6 +251,20 @@ const primitive_funcs funcs_32 = colorref_to_pixel_masks }; +const primitive_funcs funcs_555 = +{ + solid_rects_16, + pattern_rects_16, + colorref_to_pixel_555 +}; + +const primitive_funcs funcs_16 = +{ + solid_rects_16, + pattern_rects_16, + colorref_to_pixel_masks +}; + const primitive_funcs funcs_null = { solid_rects_null, diff --git a/dlls/gdi32/tests/dib.c b/dlls/gdi32/tests/dib.c index 6300398de83..e2fd0ef7a38 100644 --- a/dlls/gdi32/tests/dib.c +++ b/dlls/gdi32/tests/dib.c @@ -99,6 +99,31 @@ static const char *sha1_graphics_a8r8g8b8[] = NULL }; +static const char *sha1_graphics_r5g5b5[] = +{ + "2a2ab8b3c019e70b788ade028b0e9e53ffc529ae", + "847005cf7371f511bcc837251cde07b1796f6113", + "a8f75743a930843ec14d516cd048b6e0468e5d89", + "d094f51ce9b9daa9c1d9594ea88be2a2db651459", + "cf3928e240c9149788e1635b115a4e5baea0dd8f", + "a9034a905daa91757b4f63345c0e40638cd53ca8", + "15ee915d989e49bb9bab5b834d8f355bd067cd8f", + "99474fecf11df7b7035c35be6b8b697be9889418", + "cbc2898717f97ebb07c0c7cc04abde936dc5b584", + "29c896b591fdf4ddd23e5c0da1818c37e4686d94", + "4b5b275d33c1ebfe5bdc61df2ad125e865b800fa", + "92df731fa1f89550d9d4f7ea36c13f2e57c4b02a", + "420e39ff3bdd04c4b6cc2c98e99cb7993c7a0de5", + "1fabf0fdd046857b1974e31c1c1764fa9d1a762f", + "449092689226a1172b6086ba1181d6b6d6499f26", + "5c636ffadec10fbe440b552fe6436f3dbc607dcf", + "4aac89fc18c128eddb69eea658272af53138a1cb", + "3a50ce21b3563a604b4fc9f247a30f5a981f1ba6", + "d7d97e28ed316f6596c737eb83baa5948d86b673", + "ecc2991277d7314f55b00e0f284ae3703aeef81e", + NULL +}; + static inline DWORD get_stride(BITMAPINFO *bmi) { return ((bmi->bmiHeader.biBitCount * bmi->bmiHeader.biWidth + 31) >> 3) & ~3; @@ -623,6 +648,7 @@ static void test_simple_graphics(void) /* r5g5b5 */ + trace("555\n"); bmi->bmiHeader.biBitCount = 16; bmi->bmiHeader.biCompression = BI_RGB; @@ -635,6 +661,12 @@ static void test_simple_graphics(void) todo_wine ok(ds.dsBmih.biCompression == BI_BITFIELDS, "got %x\n", ds.dsBmih.biCompression); + orig_bm = SelectObject(mem_dc, dib); + + sha1 = sha1_graphics_r5g5b5; + draw_graphics(mem_dc, bmi, bits, &sha1); + + SelectObject(mem_dc, orig_bm); DeleteObject(dib); DeleteDC(mem_dc);