> 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; }
pgpg1BdrWdc3l.pgp
Description: PGP signature