From: Huw Davies <huw@codeweavers.com>
Subject: gdi32: Add a skeleton dib driver.
Message-Id: 
Date: Fri, 1 Apr 2011 15:27:48 +0100

---
 dlls/gdi32/bitmap.c        |   21 ++++-
 dlls/gdi32/dc.c            |    2 +
 dlls/gdi32/dibdrv/dc.c     |  221 ++++++++++++++++++++++++++++++++++++++++++++
 dlls/gdi32/dibdrv/dibdrv.h |   24 +++++
 dlls/gdi32/gdi_private.h   |   17 ++++
 5 files changed, 282 insertions(+), 3 deletions(-)
 create mode 100644 dlls/gdi32/dibdrv/dc.c
 create mode 100644 dlls/gdi32/dibdrv/dibdrv.h

diff --git a/dlls/gdi32/bitmap.c b/dlls/gdi32/bitmap.c
index 9f4f737..460f479 100644
--- a/dlls/gdi32/bitmap.c
+++ b/dlls/gdi32/bitmap.c
@@ -592,7 +592,7 @@ BOOL BITMAP_SetOwnerDC( HBITMAP hbitmap, PHYSDEV physdev )
 
     if (!(bitmap = GDI_GetObjPtr( hbitmap, OBJ_BITMAP ))) return FALSE;
 
-    if (bitmap->funcs != physdev->funcs)
+    if (!bitmap->dib && bitmap->funcs != physdev->funcs)
     {
         /* we can only change from the null driver to some other driver */
         if (bitmap->funcs == &null_driver)
@@ -627,7 +627,7 @@ static HGDIOBJ BITMAP_SelectObject( HGDIOBJ handle, HDC hdc )
     HGDIOBJ ret;
     BITMAPOBJ *bitmap;
     DC *dc;
-    PHYSDEV physdev;
+    PHYSDEV physdev = NULL, old_physdev = NULL;
 
     if (!(dc = get_dc_ptr( hdc ))) return 0;
 
@@ -653,7 +653,17 @@ static HGDIOBJ BITMAP_SelectObject( HGDIOBJ handle, HDC hdc )
         goto done;
     }
 
-    physdev = GET_DC_PHYSDEV( dc, pSelectBitmap );
+    old_physdev = GET_DC_PHYSDEV( dc, pSelectBitmap );
+    if(old_physdev == &dc->dibdrv.dev)
+        pop_dc_driver( dc, old_physdev );
+
+    if(bitmap->dib)
+    {
+        physdev = &dc->dibdrv.dev;
+        push_dc_driver( dc, physdev, physdev->funcs );
+    }
+    else
+        physdev = GET_DC_PHYSDEV( dc, pSelectBitmap );
 
     if (!BITMAP_SetOwnerDC( handle, physdev ))
     {
@@ -682,6 +692,11 @@ static HGDIOBJ BITMAP_SelectObject( HGDIOBJ handle, HDC hdc )
     }
 
  done:
+    if(!ret)
+    {
+        if(physdev == &dc->dibdrv.dev) pop_dc_driver( dc, physdev );
+        if(old_physdev == &dc->dibdrv.dev) push_dc_driver( dc, old_physdev, old_physdev->funcs );
+    }
     release_dc_ptr( dc );
     return ret;
 }
diff --git a/dlls/gdi32/dc.c b/dlls/gdi32/dc.c
index 064c9ee..86b6a46 100644
--- a/dlls/gdi32/dc.c
+++ b/dlls/gdi32/dc.c
@@ -79,6 +79,8 @@ DC *alloc_dc_ptr( WORD magic )
 
     dc->nulldrv.funcs       = &null_driver;
     dc->nulldrv.next        = NULL;
+    dc->dibdrv.dev.funcs    = &dib_driver;
+    dc->dibdrv.dev.next     = NULL;
     dc->physDev             = &dc->nulldrv;
     dc->thread              = GetCurrentThreadId();
     dc->refcount            = 1;
diff --git a/dlls/gdi32/dibdrv/dc.c b/dlls/gdi32/dibdrv/dc.c
new file mode 100644
index 0000000..d105f60
--- /dev/null
+++ b/dlls/gdi32/dibdrv/dc.c
@@ -0,0 +1,221 @@
+/*
+ * DIB driver initialization and DC functions.
+ *
+ * Copyright 2011 Huw Davies
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <assert.h>
+
+#include "gdi_private.h"
+#include "dibdrv.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dib);
+
+/***********************************************************************
+ *           dibdrv_DeleteDC
+ */
+static BOOL CDECL dibdrv_DeleteDC( PHYSDEV dev )
+{
+    TRACE("(%p)\n", dev);
+    return 0;
+}
+
+static BOOL init_dib(dib_info *dib, const BITMAPINFOHEADER *bi, const DWORD *bit_fields, void *bits)
+{
+    dib->bit_count = bi->biBitCount;
+    dib->width     = bi->biWidth;
+    dib->height    = bi->biHeight;
+    dib->stride    = ((dib->width * dib->bit_count + 31) >> 3) & ~3;
+    dib->bits      = bits;
+
+    if(dib->height < 0) /* top-down */
+    {
+        dib->height = -dib->height;
+    }
+    else /* bottom-up */
+    {
+        /* bits always points to the top-left corner and the stride is -ve */
+        dib->bits    = (BYTE*)dib->bits + (dib->height - 1) * dib->stride;
+        dib->stride  = -dib->stride;
+    }
+
+    switch(dib->bit_count)
+    {
+    default:
+        TRACE("bpp %d not supported, will forward to graphics driver.\n", dib->bit_count);
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+/***********************************************************************
+ *           dibdrv_SelectBitmap
+ */
+static HBITMAP CDECL dibdrv_SelectBitmap( PHYSDEV dev, HBITMAP bitmap )
+{
+    PHYSDEV next = GET_NEXT_PHYSDEV( dev, pSelectBitmap );
+    dibdrv_physdev *pdev = get_dibdrv_pdev(dev);
+    BITMAPOBJ *bmp = GDI_GetObjPtr( bitmap, OBJ_BITMAP );
+    TRACE("(%p, %p)\n", dev, bitmap);
+
+    if (!bmp) return 0;
+    assert(bmp->dib);
+
+    init_dib(&pdev->dib, &bmp->dib->dsBmih, bmp->dib->dsBitfields, bmp->dib->dsBm.bmBits);
+
+    GDI_ReleaseObj( bitmap );
+
+    return next->funcs->pSelectBitmap( next, bitmap );
+}
+
+const DC_FUNCTIONS dib_driver =
+{
+    NULL,                               /* pAbortDoc */
+    NULL,                               /* pAbortPath */
+    NULL,                               /* pAlphaBlend */
+    NULL,                               /* pAngleArc */
+    NULL,                               /* pArc */
+    NULL,                               /* pArcTo */
+    NULL,                               /* pBeginPath */
+    NULL,                               /* pChoosePixelFormat */
+    NULL,                               /* pChord */
+    NULL,                               /* pCloseFigure */
+    NULL,                               /* pCreateBitmap */
+    NULL,                               /* pCreateDC */
+    NULL,                               /* pCreateDIBSection */
+    NULL,                               /* pDeleteBitmap */
+    dibdrv_DeleteDC,                    /* pDeleteDC */
+    NULL,                               /* pDeleteObject */
+    NULL,                               /* pDescribePixelFormat */
+    NULL,                               /* pDeviceCapabilities */
+    NULL,                               /* pEllipse */
+    NULL,                               /* pEndDoc */
+    NULL,                               /* pEndPage */
+    NULL,                               /* pEndPath */
+    NULL,                               /* pEnumDeviceFonts */
+    NULL,                               /* pEnumICMProfiles */
+    NULL,                               /* pExcludeClipRect */
+    NULL,                               /* pExtDeviceMode */
+    NULL,                               /* pExtEscape */
+    NULL,                               /* pExtFloodFill */
+    NULL,                               /* pExtSelectClipRgn */
+    NULL,                               /* pExtTextOut */
+    NULL,                               /* pFillPath */
+    NULL,                               /* pFillRgn */
+    NULL,                               /* pFlattenPath */
+    NULL,                               /* pFrameRgn */
+    NULL,                               /* pGdiComment */
+    NULL,                               /* pGetBitmapBits */
+    NULL,                               /* pGetCharWidth */
+    NULL,                               /* pGetDIBits */
+    NULL,                               /* pGetDeviceCaps */
+    NULL,                               /* pGetDeviceGammaRamp */
+    NULL,                               /* pGetICMProfile */
+    NULL,                               /* pGetNearestColor */
+    NULL,                               /* pGetPixel */
+    NULL,                               /* pGetPixelFormat */
+    NULL,                               /* pGetSystemPaletteEntries */
+    NULL,                               /* pGetTextExtentExPoint */
+    NULL,                               /* pGetTextMetrics */
+    NULL,                               /* pIntersectClipRect */
+    NULL,                               /* pInvertRgn */
+    NULL,                               /* pLineTo */
+    NULL,                               /* pModifyWorldTransform */
+    NULL,                               /* pMoveTo */
+    NULL,                               /* pOffsetClipRgn */
+    NULL,                               /* pOffsetViewportOrg */
+    NULL,                               /* pOffsetWindowOrg */
+    NULL,                               /* pPaintRgn */
+    NULL,                               /* pPatBlt */
+    NULL,                               /* pPie */
+    NULL,                               /* pPolyBezier */
+    NULL,                               /* pPolyBezierTo */
+    NULL,                               /* pPolyDraw */
+    NULL,                               /* pPolyPolygon */
+    NULL,                               /* pPolyPolyline */
+    NULL,                               /* pPolygon */
+    NULL,                               /* pPolyline */
+    NULL,                               /* pPolylineTo */
+    NULL,                               /* pRealizeDefaultPalette */
+    NULL,                               /* pRealizePalette */
+    NULL,                               /* pRectangle */
+    NULL,                               /* pResetDC */
+    NULL,                               /* pRestoreDC */
+    NULL,                               /* pRoundRect */
+    NULL,                               /* pSaveDC */
+    NULL,                               /* pScaleViewportExt */
+    NULL,                               /* pScaleWindowExt */
+    dibdrv_SelectBitmap,                /* pSelectBitmap */
+    NULL,                               /* pSelectBrush */
+    NULL,                               /* pSelectClipPath */
+    NULL,                               /* pSelectFont */
+    NULL,                               /* pSelectPalette */
+    NULL,                               /* pSelectPen */
+    NULL,                               /* pSetArcDirection */
+    NULL,                               /* pSetBitmapBits */
+    NULL,                               /* pSetBkColor */
+    NULL,                               /* pSetBkMode */
+    NULL,                               /* pSetDCBrushColor */
+    NULL,                               /* pSetDCPenColor */
+    NULL,                               /* pSetDIBColorTable */
+    NULL,                               /* pSetDIBits */
+    NULL,                               /* pSetDIBitsToDevice */
+    NULL,                               /* pSetDeviceClipping */
+    NULL,                               /* pSetDeviceGammaRamp */
+    NULL,                               /* pSetLayout */
+    NULL,                               /* pSetMapMode */
+    NULL,                               /* pSetMapperFlags */
+    NULL,                               /* pSetPixel */
+    NULL,                               /* pSetPixelFormat */
+    NULL,                               /* pSetPolyFillMode */
+    NULL,                               /* pSetROP2 */
+    NULL,                               /* pSetRelAbs */
+    NULL,                               /* pSetStretchBltMode */
+    NULL,                               /* pSetTextAlign */
+    NULL,                               /* pSetTextCharacterExtra */
+    NULL,                               /* pSetTextColor */
+    NULL,                               /* pSetTextJustification */
+    NULL,                               /* pSetViewportExt */
+    NULL,                               /* pSetViewportOrg */
+    NULL,                               /* pSetWindowExt */
+    NULL,                               /* pSetWindowOrg */
+    NULL,                               /* pSetWorldTransform */
+    NULL,                               /* pStartDoc */
+    NULL,                               /* pStartPage */
+    NULL,                               /* pStretchBlt */
+    NULL,                               /* pStretchDIBits */
+    NULL,                               /* pStrokeAndFillPath */
+    NULL,                               /* pStrokePath */
+    NULL,                               /* pSwapBuffers */
+    NULL,                               /* pUnrealizePalette */
+    NULL,                               /* pWidenPath */
+    NULL,                               /* pwglCopyContext */
+    NULL,                               /* pwglCreateContext */
+    NULL,                               /* pwglCreateContextAttribsARB */
+    NULL,                               /* pwglDeleteContext */
+    NULL,                               /* pwglGetProcAddress */
+    NULL,                               /* pwglGetPbufferDCARB */
+    NULL,                               /* pwglMakeCurrent */
+    NULL,                               /* pwglMakeContextCurrentARB */
+    NULL,                               /* pwglSetPixelFormatWINE */
+    NULL,                               /* pwglShareLists */
+    NULL,                               /* pwglUseFontBitmapsA */
+    NULL                                /* pwglUseFontBitmapsW */
+};
diff --git a/dlls/gdi32/dibdrv/dibdrv.h b/dlls/gdi32/dibdrv/dibdrv.h
new file mode 100644
index 0000000..9dca50f
--- /dev/null
+++ b/dlls/gdi32/dibdrv/dibdrv.h
@@ -0,0 +1,24 @@
+/*
+ * DIB driver include file.
+ *
+ * Copyright 2011 Huw Davies
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+static inline dibdrv_physdev *get_dibdrv_pdev( PHYSDEV dev )
+{
+    return (dibdrv_physdev *)dev;
+}
diff --git a/dlls/gdi32/gdi_private.h b/dlls/gdi32/gdi_private.h
index abb9588..5849d88 100644
--- a/dlls/gdi32/gdi_private.h
+++ b/dlls/gdi32/gdi_private.h
@@ -79,6 +79,21 @@ typedef struct gdi_physdev
     HDC                       hdc;
 } *PHYSDEV;
 
+typedef struct
+{
+    int bit_count, width, height;
+    int stride; /* stride in bytes.  Will be -ve for bottom-up dibs (see bits). */
+    void *bits; /* points to the top-left corner of the dib. */
+
+    DWORD red_mask, green_mask, blue_mask;
+} dib_info;
+
+typedef struct dibdrv_physdev
+{
+    struct gdi_physdev dev;
+    dib_info dib;
+} dibdrv_physdev;
+
 typedef struct tagDC_FUNCS
 {
     INT      (CDECL *pAbortDoc)(PHYSDEV);
@@ -246,6 +261,7 @@ typedef struct tagDC
     GDIOBJHDR    header;
     HDC          hSelf;            /* Handle to this DC */
     struct gdi_physdev nulldrv;    /* physdev for the null driver */
+    struct dibdrv_physdev dibdrv;  /* physdev for the dib driver */
     PHYSDEV      physDev;         /* Physical device (driver-specific) */
     DWORD        thread;          /* thread owning the DC */
     LONG         refcount;        /* thread refcount */
@@ -391,6 +407,7 @@ extern int DIB_GetBitmapInfo( const BITMAPINFOHEADER *header, LONG *width,
 
 /* driver.c */
 extern const DC_FUNCTIONS null_driver DECLSPEC_HIDDEN;
+extern const DC_FUNCTIONS dib_driver DECLSPEC_HIDDEN;
 extern const DC_FUNCTIONS *DRIVER_get_display_driver(void) DECLSPEC_HIDDEN;
 extern const DC_FUNCTIONS *DRIVER_load_driver( LPCWSTR name ) DECLSPEC_HIDDEN;
 extern BOOL DRIVER_GetDriverName( LPCWSTR device, LPWSTR driver, DWORD size ) DECLSPEC_HIDDEN;