> Have you got a diff against a current tree anywhere? I can't promise
> I'll be of any help, but I wouldn't mind taking a look sometime when I
> can find the time. A small test program might be usefull as well.

I have attached a diff with my getDC implementation against the current tree, 
and a test application. The GetDC is taken from ddraw, and it's explained in 
http://article.gmane.org/gmane.comp.emulators.wine.devel/38533/ The problem 
of this code is that it crashes with a heap corruption sooner or later :(

The test program can be compiled with winelib, you only have to place a 
image.bmp file into it's folder with the size 640x480 and 24 bit color depth. 
It should show the image after loading. I wasn't able to run this program on 
a windows machine, because I didn't have access to one, but I think it should 
work.

If you have any ideas why GetDC fails, please tell me

Stefan
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;
+
+    }
+}
#include <stdio.h>
#include <windows.h>
#include <d3d9.h>
#include <assert.h>

WNDCLASS wc;
HWND hwnd;
IDirect3D9 *D3D=NULL;
IDirect3DDevice9 *device=NULL;

LRESULT CALLBACK WndProc(HWND hWnd, UINT uiMessage, WPARAM wParam, LPARAM lParam);


static void createwindow(void)
{
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = GetModuleHandleA(0);
    wc.hIcon = LoadIconA(wc.hInstance, IDI_APPLICATION);
    wc.hCursor = LoadCursorA(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = "TestWindowClass";
    if(!RegisterClassA(&wc))
        assert(0);

    hwnd = CreateWindowExA(0, "TestWindowClass", "TestWindowClass",
        WS_POPUP, 0, 0,
        GetSystemMetrics(SM_CXSCREEN),
        GetSystemMetrics(SM_CYSCREEN),
        NULL, NULL, GetModuleHandleA(0), NULL);
    assert(hwnd != NULL);

    ShowWindow(hwnd, SW_HIDE);
    UpdateWindow(hwnd);
    SetFocus(hwnd);

}

LRESULT CALLBACK WndProc(HWND hWnd, UINT uiMessage, WPARAM wParam, LPARAM lParam)
{
//   printf("Message %lx, wparam %lx, lparam %lx\n", uiMessage, wParam, lParam);
  static WPARAM old1 = 0;
  static WPARAM old2 = 0;
  HRESULT hr;
  BYTE *lockedmem;
  long memsize;
  long i;
  IDirect3DSurface9 *BackBuffer;
  D3DLOCKED_RECT rect;

  switch(uiMessage)
  {
    case WM_DESTROY:
      // Close the window, terminate the app
      PostQuitMessage(0);
      return 0;

    case WM_LBUTTONDOWN:
        #if 0
        hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &BackBuffer);
        assert(hr == D3D_OK);

        hr = IDirect3DSurface9_LockRect(BackBuffer, &rect, NULL, 0);
        assert(hr == D3D_OK);
        memset(rect.pBits, 0xff, rect.Pitch * 480);
        hr = IDirect3DSurface9_UnlockRect(BackBuffer);
        assert(hr == D3D_OK);
        hr = IDirect3DDevice9_Present(device, NULL, NULL, 0, NULL);
        assert(hr == D3D_OK);
        #endif
        break;

    case WM_KEYUP:
      if(lParam == 0xc0010001) /* Escape */
      {
        PostQuitMessage(0);
        return 0;
      }
      #if 0
      hr = IDirect3DDevice9_Clear(device,
                             0,
                             NULL, 
                             D3DCLEAR_TARGET ,
                             (old2 << 16) + (old1 << 8) + wParam,
                             0, 0);
      assert(hr == D3D_OK);
      hr = IDirect3DDevice9_Present(device, NULL, NULL, 0, NULL);
      assert(hr == D3D_OK);

      old2 = old1;
      old1 = wParam;
      #endif
      break;
    default:
      return DefWindowProc(hWnd, uiMessage, wParam, lParam);
  }
}

int main()
{
  D3DFORMAT format=D3DFMT_R8G8B8;
  D3DPRESENT_PARAMETERS pp;
  HRESULT hr;
  MSG Message;
  HBITMAP hbm;
  BITMAP bm;
  HDC hdcImage;
  HDC hdc;
  HBITMAP hbmOld;
  int i;
  int n;
  int fh;
  IDirect3DSurface9 *BackBuffer;

  pp.BackBufferCount= 1;
  pp.MultiSampleType=D3DMULTISAMPLE_NONE;
  pp.MultiSampleQuality=0;
  pp.SwapEffect = D3DSWAPEFFECT_DISCARD;
  pp.hDeviceWindow=hwnd;
  pp.Flags=0;
  pp.Windowed          = FALSE;
  pp.BackBufferWidth   = 640;
  pp.BackBufferHeight  = 480;
  pp.FullScreen_RefreshRateInHz=D3DPRESENT_RATE_DEFAULT;
  pp.PresentationInterval=D3DPRESENT_INTERVAL_DEFAULT;
  pp.BackBufferFormat=format;
  pp.EnableAutoDepthStencil=FALSE;

  createwindow();

  D3D = Direct3DCreate9( D3D_SDK_VERSION);

  hr=IDirect3D9_CreateDevice(D3D, D3DADAPTER_DEFAULT,
                          D3DDEVTYPE_HAL,
                          hwnd,
                          D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                          &pp,
                          &device);
  assert(hr == D3D_OK);


  /* Load the image from disc */
  hbm = (HBITMAP) LoadImage(NULL, "image.bmp", IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE|LR_CREATEDIBSECTION);
  assert(hbm != NULL);
  GetObject(hbm, sizeof(bm), &bm);

  hr = IDirect3DDevice9_GetBackBuffer(device, 0, 0, D3DBACKBUFFER_TYPE_MONO, &BackBuffer);

  hdcImage = CreateCompatibleDC(NULL);
  hbmOld =  (HBITMAP)SelectObject(hdcImage, hbm);
  hr = IDirect3DSurface9_GetDC(BackBuffer, &hdc);
  assert(hr == D3D_OK);
  BitBlt(hdc, 0, 0, 640, 480, hdcImage, 0, 0, SRCCOPY);
  IDirect3DSurface9_ReleaseDC(BackBuffer, hdc);
  SelectObject(hdcImage, hbmOld);
  DeleteDC(hdcImage);

  hr = IDirect3DDevice9_Present(device, NULL, NULL, 0, NULL);

  while(GetMessage(&Message, NULL, 0, 0))
  {
    TranslateMessage(&Message);
    DispatchMessage(&Message);
  }

  IDirect3DDevice9_Release(device);
  if(D3D)
  {
    IDirect3D9_Release(D3D);
    D3D=NULL;
  }
  return 0;
}

Attachment: pgpg1BdrWdc3l.pgp
Description: PGP signature



Reply via email to