Huw Davies : gdi32: Add support for 16 bpp dibs.

Alexandre Julliard julliard at winehq.org
Fri May 27 11:03:42 CDT 2011


Module: wine
Branch: master
Commit: 18a96edf6932f42abca5e327a043ead088c6c8fb
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=18a96edf6932f42abca5e327a043ead088c6c8fb

Author: Huw Davies <huw at codeweavers.com>
Date:   Fri May 27 13:10:29 2011 +0100

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 deletions(-)

diff --git a/dlls/gdi32/dibdrv/dc.c b/dlls/gdi32/dibdrv/dc.c
index 6cc1d33..98463b7 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 ccf9f9a..0b5dba3 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 6dec478..c1d1597 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 6300398..e2fd0ef 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);




More information about the wine-cvs mailing list