Index: dlls/wined3d/wined3d_private.h
===================================================================
RCS file: /home/wine/wine/dlls/wined3d/wined3d_private.h,v
retrieving revision 1.72
diff -u -r1.72 wined3d_private.h
--- dlls/wined3d/wined3d_private.h	9 Dec 2005 12:18:30 -0000	1.72
+++ dlls/wined3d/wined3d_private.h	3 Feb 2006 21:02:08 -0000
@@ -790,6 +790,17 @@
 } WINED3DSURFACET_DESC;
 
 /*****************************************************************************
+ * Structure for DIB management
+ */
+typedef struct wineD3DSurface_DIB {
+    HBITMAP DIBsection;
+    void* bitmap_data;
+    HGDIOBJ holdbitmap;
+    BOOL client_memory;
+    DWORD d3d_data[4]; /* room for Direct3D driver data */
+} wineD3DSurface_DIB;
+
+/*****************************************************************************
  * IWineD3DSurface implementation structure
  */
 struct IWineD3DSurfaceImpl
@@ -831,10 +842,16 @@
     BOOL                      inPBuffer;
 
     glDescriptor              glDescription;
+    wineD3DSurface_DIB        dib;
+    BOOL                      DC_in_use;
 };
 
 extern const IWineD3DSurfaceVtbl IWineD3DSurface_Vtbl;
 
+const LONG get_bitmask_red(WINED3DFORMAT fmt);
+const LONG get_bitmask_green(WINED3DFORMAT fmt);
+const LONG get_bitmask_blue(WINED3DFORMAT fmt);
+
 /*****************************************************************************
  * IWineD3DVertexDeclaration implementation structure
  */
Index: dlls/wined3d/surface.c
===================================================================
RCS file: /home/wine/wine/dlls/wined3d/surface.c,v
retrieving revision 1.33
diff -u -r1.33 surface.c
--- dlls/wined3d/surface.c	31 Dec 2005 14:22:18 -0000	1.33
+++ dlls/wined3d/surface.c	3 Feb 2006 21:02:13 -0000
@@ -28,6 +28,9 @@
 WINE_DEFAULT_DEBUG_CHANNEL(d3d_surface);
 #define GLINFO_LOCATION ((IWineD3DImpl *)(((IWineD3DDeviceImpl *)This->resource.wineD3DDevice)->wineD3D))->gl_info
 
+extern HBITMAP DIB_CreateDIBSection( HDC hdc, const BITMAPINFO *bmi, UINT usage, VOID **bits,
+                                     HANDLE section, DWORD offset, DWORD ovr_pitch );
+
 /* *******************************************
    IWineD3DSurface IUnknown parts follow
    ******************************************* */
@@ -884,14 +887,178 @@
 
 HRESULT WINAPI IWineD3DSurfaceImpl_GetDC(IWineD3DSurface *iface, HDC *pHDC) {
     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
-    FIXME("No support for GetDC yet for surface %p\n", This);
-    return D3DERR_INVALIDCALL;
+    HRESULT hr;
+    D3DLOCKED_RECT lock;
+    UINT usage;
+    BITMAPINFO* b_info;
+    HDC ddc;
+
+    ERR("(%p)->(%p): This does not work yet\n",This,pHDC);
+
+    if (This->DC_in_use)
+        return /*DDERR_DCALREADYCREATED*/ D3DERR_INVALIDCALL /*for now*/;
+
+    /* lock the surface, Create a DIB section and create a DC
+     * One problem: Pow2 size vs real size
+     * Texture repacking
+     * Propably others too. It doesn't work yet
+     */
+
+    memset(&lock, 0, sizeof(lock)); /* To be sure */
+    hr = IWineD3DSurface_LockRect(iface, &lock, NULL, 0);
+    if (FAILED(hr))
+    {
+        return hr;
+    }
+
+    /* Create a DIB section */
+    switch (This->bytesPerPixel)
+    {
+    case 2:
+    case 4:
+        /* Allocate extra space to store the RGB bit masks. */
+        b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD));
+        break;
+
+    case 3:
+        b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER));
+        break;
+
+    default:
+        /* Allocate extra space for a palette. */
+        b_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
+                           sizeof(BITMAPINFOHEADER)
+                           + sizeof(RGBQUAD)
+                           * (1 << (This->bytesPerPixel * 8)));
+        break;
+    }
+
+    b_info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+    b_info->bmiHeader.biWidth = This->currentDesc.Width;
+    b_info->bmiHeader.biHeight = -This->currentDesc.Height;
+    b_info->bmiHeader.biPlanes = 1;
+    b_info->bmiHeader.biBitCount = This->bytesPerPixel * 8;
+
+    b_info->bmiHeader.biSizeImage = This->bytesPerPixel * This->currentDesc.Width * This->currentDesc.Height;
+
+    b_info->bmiHeader.biXPelsPerMeter = 0;
+    b_info->bmiHeader.biYPelsPerMeter = 0;
+    b_info->bmiHeader.biClrUsed = 0;
+    b_info->bmiHeader.biClrImportant = 0;
+
+    TRACE("Creating dip section %dx%dx%d. memory at %p\n", This->currentDesc.Width, This->currentDesc.Height, This->bytesPerPixel * 8, lock.pBits);
+
+    /* Get the bit masks */
+    DWORD *masks = (DWORD *) &(b_info->bmiColors);
+    switch (This->resource.format) {
+    case WINED3DFMT_R8G8B8:
+        /* Nothing to do */
+        usage = DIB_RGB_COLORS;
+        b_info->bmiHeader.biCompression = BI_RGB;
+        break;
+
+    case WINED3DFMT_X1R5G5B5:
+    case WINED3DFMT_A1R5G5B5:
+    case WINED3DFMT_A4R4G4B4:
+    case WINED3DFMT_X4R4G4B4:
+    case WINED3DFMT_R3G3B2:
+    case WINED3DFMT_A8R3G3B2:
+    case WINED3DFMT_A2B10G10R10:
+    case WINED3DFMT_A8B8G8R8:
+    case WINED3DFMT_X8B8G8R8:
+    case WINED3DFMT_A2R10G10B10:
+    case WINED3DFMT_R5G6B5:
+    case WINED3DFMT_A16B16G16R16:
+        usage = 0;
+        b_info->bmiHeader.biCompression = BI_BITFIELDS;
+        masks[0] = get_bitmask_red(This->resource.format);
+        masks[1] = get_bitmask_green(This->resource.format);
+        masks[2] = get_bitmask_blue(This->resource.format);
+        break;
+
+    default:
+        /* Don't know palette */
+        usage = 0;
+        break;
+    }
+
+    ddc = CreateDCA("DISPLAY", NULL, NULL, NULL);
+    if (ddc == 0) {
+        HeapFree(GetProcessHeap(), 0, b_info);
+        return HRESULT_FROM_WIN32(GetLastError());
+    }
+
+    This->dib.DIBsection = DIB_CreateDIBSection(ddc, b_info, usage, &(This->dib.bitmap_data), 0, (DWORD) lock.pBits, lock.Pitch);
+    DeleteDC(ddc);
+
+    HeapFree(GetProcessHeap(), 0, b_info);
+    if (!This->dib.DIBsection) {
+        ERR("CreateDIBSection failed!\n");
+        return HRESULT_FROM_WIN32(GetLastError());
+    }
+
+    TRACE("DIBSection at : %p\n", This->dib.bitmap_data);
+
+    /* Now allocate a HDC */
+    *pHDC = CreateCompatibleDC(0);
+    This->dib.holdbitmap = SelectObject(*pHDC, This->dib.DIBsection);
+    SelectPalette(*pHDC,
+                  0,
+                  FALSE);
+
+#if 0
+    if ((This->resource.format == WINED3DFMT_P8) &&
+        (This->palette == NULL)) {
+        IWineD3DSurfaceImpl *surf = This->resource.wineD3DDevice->ddraw_primary;
+
+
+        if(surf->palette != NULL) {
+            RGBQUAD col[256];
+            IWineD3DPaletteImpl *pal = surf->palette;
+            unsigned int n;
+            for (n=0; n<256; n++) {
+                col[n].rgbRed   = pal->palents[n].peRed;
+                col[n].rgbGreen = pal->palents[n].peGreen;
+                col[n].rgbBlue  = pal->palents[n].peBlue;
+                col[n].rgbReserved = 0;
+            }
+            SetDIBColorTable(*pHDC, 0, 256, col);
+        }
+    }
+#endif
+
+    TRACE("returning %p\n",*pHDC);
+    This->DC_in_use = TRUE;
+
+    return D3D_OK;
 }
 
 HRESULT WINAPI IWineD3DSurfaceImpl_ReleaseDC(IWineD3DSurface *iface, HDC hDC) {
     IWineD3DSurfaceImpl *This = (IWineD3DSurfaceImpl *)iface;
-    FIXME("No support for ReleaseDC yet for surface %p\n", This);
-    return D3DERR_INVALIDCALL;
+    HRESULT hr;
+
+    TRACE("(%p)->(%p)\n",This,hDC);
+
+    if (!This->DC_in_use)
+        return D3DERR_INVALIDCALL;
+
+    TRACE("Selecting the object DC\n");
+    /* Release the DC */
+    SelectObject(hDC, This->dib.holdbitmap);
+    TRACE("DeleteDC\n");
+    DeleteDC(hDC);
+
+    /* Release the DIB section */
+    TRACE("DeleteObject\n");
+    DeleteObject(This->dib.DIBsection);
+
+    /* Unlock the surface */
+    TRACE("UnlockRect\n");
+    hr = IWineD3DSurface_UnlockRect(iface);
+
+    This->DC_in_use = FALSE;
+
+    return D3D_OK;
 }
 
 /* ******************************************************
Index: dlls/wined3d/utils.c
===================================================================
RCS file: /home/wine/wine/dlls/wined3d/utils.c,v
retrieving revision 1.18
diff -u -r1.18 utils.c
--- dlls/wined3d/utils.c	23 Nov 2005 19:29:20 -0000	1.18
+++ dlls/wined3d/utils.c	3 Feb 2006 21:02:19 -0000
@@ -1980,3 +1980,154 @@
 }
 
 #undef GLINFO_LOCATION
+
+const LONG get_bitmask_red(WINED3DFORMAT fmt)
+{
+    switch (fmt) {
+      case WINED3DFMT_R8G8B8:
+      case WINED3DFMT_A8R8G8B8:
+      case WINED3DFMT_X8R8G8B8:
+          return 0x00ff0000;
+
+      case WINED3DFMT_X1R5G5B5:
+      case WINED3DFMT_A1R5G5B5:
+          return 0x7C00;
+
+      case WINED3DFMT_A4R4G4B4:
+      case WINED3DFMT_X4R4G4B4:
+          return 0xF00;
+
+      case WINED3DFMT_R3G3B2:
+      case WINED3DFMT_A8R3G3B2:
+          return 0xE0;
+
+      case WINED3DFMT_A2R10G10B10:
+          return 0x3F0000;
+          break;
+
+      case WINED3DFMT_A2B10G10R10:
+          return 0x3FF;
+
+      case WINED3DFMT_A8B8G8R8:
+      case WINED3DFMT_X8B8G8R8:
+          return 0xff;
+
+      case WINED3DFMT_R5G6B5:
+          return 0xF800;
+
+      case WINED3DFMT_P8:
+          /* No fixed mask for this format */
+          return 0;
+
+#if 0
+      case WINED3DFMT_A16B16G16R16:
+          return 0x00000000ffff;
+          break;
+#endif
+
+      default:
+          ERR("Unknown bitmask for format %d\n", fmt);
+          return 0;
+    }
+}
+
+const LONG get_bitmask_green(WINED3DFORMAT fmt)
+{
+    switch (fmt) {
+      case WINED3DFMT_R8G8B8:
+      case WINED3DFMT_A8R8G8B8:
+      case WINED3DFMT_X8R8G8B8:
+          return 0x0000ff00;
+
+      case WINED3DFMT_X1R5G5B5:
+      case WINED3DFMT_A1R5G5B5:
+          return 0x3E0;
+
+      case WINED3DFMT_A4R4G4B4:
+      case WINED3DFMT_X4R4G4B4:
+          return 0xF0;
+
+      case WINED3DFMT_R3G3B2:
+      case WINED3DFMT_A8R3G3B2:
+          return 0x1C;
+
+      case WINED3DFMT_A2B10G10R10:
+          return 0xFFC00;
+
+      case WINED3DFMT_A8B8G8R8:
+      case WINED3DFMT_X8B8G8R8:
+          return 0xFF00;
+          break;
+
+      case WINED3DFMT_A2R10G10B10:
+          return 0xFFC00;
+          break;
+
+      case WINED3DFMT_R5G6B5:
+          return 0x7E0;
+
+      case WINED3DFMT_P8:
+          /* No fixed mask for this format */
+          return 0;
+
+  #if 0
+      case WINED3DFMT_A16B16G16R16:
+          return 0x0000ffff0000;
+          break;
+  #endif
+
+      default:
+          ERR("Unknown bitmask for format %d\n", fmt);
+          return 0;
+    }
+}
+
+const LONG get_bitmask_blue(WINED3DFORMAT fmt)
+{
+    switch (fmt) {
+      case WINED3DFMT_R8G8B8:
+      case WINED3DFMT_A8R8G8B8:
+      case WINED3DFMT_X8R8G8B8:
+          return 0x000000ff;
+
+      case WINED3DFMT_X1R5G5B5:
+      case WINED3DFMT_A1R5G5B5:
+          return 0x1f;
+
+      case WINED3DFMT_A4R4G4B4:
+      case WINED3DFMT_X4R4G4B4:
+          return 0xF;
+
+      case WINED3DFMT_R3G3B2:
+      case WINED3DFMT_A8R3G3B2:
+          return 0x3;
+
+      case WINED3DFMT_A2B10G10R10:
+          return 0x3F0000;
+
+      case WINED3DFMT_A8B8G8R8:
+      case WINED3DFMT_X8B8G8R8:
+          return 0xFF0000;
+
+      case WINED3DFMT_A2R10G10B10:
+          return 0x3FF;
+
+      case WINED3DFMT_R5G6B5:
+          return 0x1F;
+
+      case WINED3DFMT_P8:
+          /* No fixed mask for this format */
+          return 0;
+
+  #if 0
+      case WINED3DFMT_A16B16G16R16:
+          return 0xffff00000000;
+          break;
+  #endif
+
+      default:
+          ERR("Unknown bitmask for format %d\n", fmt);
+          return 0;
+
+    }
+}
