From 1cd70566361dee9de47715c321eee88732e70779 Mon Sep 17 00:00:00 2001 From: Marcus Meissner Date: Sun, 22 Nov 1998 12:33:29 +0000 Subject: [PATCH] DirectDraw status updated. Use cooperative window for drawing in xlib implementation if possible. Slightly restructured IDirectDrawSurface::Blt so it doesn't crash. --- documentation/status/directdraw | 15 +-- graphics/ddraw.c | 176 ++++++++++++++++---------------- graphics/wing.c | 2 +- include/ddraw.h | 55 +++++----- 4 files changed, 120 insertions(+), 128 deletions(-) diff --git a/documentation/status/directdraw b/documentation/status/directdraw index 04b0e1aa46d..a19ca49954c 100644 --- a/documentation/status/directdraw +++ b/documentation/status/directdraw @@ -23,13 +23,6 @@ Problems of the implementation using XFree86-DGA: framebuffer into the addressspace of the process. - Blocks all other X windowed applications. -TODO: - - Add more implementations of the DirectDraw API. - Primary candidate is a raw Xlib implementation (one with/one without - XShm extension). - An additional layer (basically a HAL) will be required to decide on - case-by-case basis which implementation to use. - Status: - Diablo [640x480x8]: The movies play with speed comparable to the MS DDRAW one. @@ -49,12 +42,10 @@ Status: but it crashes as soon as you arrive at Blue Point Station... - Monkey Island 3 [640x480x8]: - Goes to the easy/hard selection screen, then hangs due to multithreaded - windows-messagehandling problems. + WINE-CVS-981116: + Works, using DGA and Xlib. (Mousecontrol is a bit off in windowed mode.) - DiscWorld 2 [640x480x8]: - [Crashes with 'cli' in WINE released version. Yes. Privileged instructions - in 32bit code. Will they ever learn...] Plays through nearly all intro movies. Sound and animation skip a lot of stuff (possible DirectSound asynchronization problem). @@ -68,7 +59,5 @@ Status: DirectInput. - WingCommander Prophecy Demo (using software renderer) [640x480x16]: - [Crashes with an invalid opcode (outb, probably to test for 3dFX) in the - WINE release version.] Plays trailer, hangs in selection screen (no keyboard input, DirectInput problem). diff --git a/graphics/ddraw.c b/graphics/ddraw.c index aa2beba4f86..27fbf4d1cd8 100644 --- a/graphics/ddraw.c +++ b/graphics/ddraw.c @@ -1,8 +1,9 @@ -/* DirectDraw using DGA or Xlib +/* DirectDraw using DGA or Xlib(XSHM) * * Copyright 1997,1998 Marcus Meissner */ -/* When DirectVideo mode is enabled you can no longer use 'normal' X +/* XF86DGA: + * When DirectVideo mode is enabled you can no longer use 'normal' X * applications nor can you switch to a virtual console. Also, enabling * only works, if you have switched to the screen where the application * is running. @@ -10,7 +11,6 @@ * - A terminal connected to the serial port. Can be bought used for cheap. * (This is the method I am using.) * - Another machine connected over some kind of network. - * */ #include "config.h" @@ -49,7 +49,7 @@ /* define this if you want to play Diablo using XF86DGA. (bug workaround) */ #undef DIABLO_HACK -/* restore signal handlers overwritten by XF86DGA +/* Restore signal handlers overwritten by XF86DGA * this is a define, for it will only work in emulator mode */ #undef RESTORE_SIGNALS @@ -350,7 +350,7 @@ static HRESULT WINAPI Xlib_IDirectDrawSurface3_Unlock( return DD_OK; /* Only redraw the screen when unlocking the buffer that is on screen */ - if ((this->t.xlib.image != NULL) && (this->t.xlib.on_screen)) + if ((this->t.xlib.image != NULL) && (this->t.xlib.on_screen)) { #ifdef HAVE_LIBXXSHM if (this->s.ddraw->e.xlib.xshm_active) TSXShmPutImage(display, @@ -370,6 +370,7 @@ static HRESULT WINAPI Xlib_IDirectDrawSurface3_Unlock( 0, 0, 0, 0, this->t.xlib.image->width, this->t.xlib.image->height); + } if (this->s.palette && this->s.palette->cm) TSXSetWindowColormap(display,this->s.ddraw->e.xlib.drawable,this->s.palette->cm); @@ -428,7 +429,7 @@ static HRESULT WINAPI Xlib_IDirectDrawSurface3_Flip( } #ifdef HAVE_LIBXXSHM - if (this->s.ddraw->e.xlib.xshm_active) + if (this->s.ddraw->e.xlib.xshm_active) { TSXShmPutImage(display, this->s.ddraw->e.xlib.drawable, DefaultGCOfScreen(screen), @@ -437,7 +438,7 @@ static HRESULT WINAPI Xlib_IDirectDrawSurface3_Flip( flipto->t.xlib.image->width, flipto->t.xlib.image->height, False); - else + } else #endif TSXPutImage(display, this->s.ddraw->e.xlib.drawable, @@ -460,7 +461,6 @@ static HRESULT WINAPI Xlib_IDirectDrawSurface3_Flip( this->s.surface = flipto->s.surface; flipto->s.surface = surf; } - return 0; } @@ -562,11 +562,15 @@ static HRESULT WINAPI IDirectDrawSurface3_Blt( if (rsrc) { memcpy(&xsrc,rsrc,sizeof(xsrc)); - } else if (src) { + } else { + if (src) { xsrc.top = 0; xsrc.bottom = src->s.height; xsrc.left = 0; xsrc.right = src->s.width; + } else { + memset(&xsrc,0,sizeof(xsrc)); + } } dwFlags &= ~(DDBLT_WAIT|DDBLT_ASYNC);/* FIXME: can't handle right now */ @@ -590,7 +594,15 @@ static HRESULT WINAPI IDirectDrawSurface3_Blt( xline += this->s.lpitch; } dwFlags &= ~(DDBLT_COLORFILL); - } else { /* Once we have done colorfill, we do not do anything else... */ + } + + if (!src) { + if (dwFlags) { + TRACE(ddraw,"\t(src=NULL):Unsupported flags: ");_dump_DDBLT(dwFlags);fprintf(stderr,"\n"); + } + return 0; + } + if ( (xsrc.top ==0) && (xsrc.bottom ==this->s.height) && (xsrc.left==0) && (xsrc.right ==this->s.width) && (xdst.top ==0) && (xdst.bottom ==this->s.height) && @@ -598,11 +610,7 @@ static HRESULT WINAPI IDirectDrawSurface3_Blt( !dwFlags ) { memcpy(this->s.surface,src->s.surface,this->s.height*this->s.lpitch); - return 0; } else { - /* Non full screen Blit. In this case, we need to copy line per line. - WARNING : if the program behaves badly (ie sizes of structures are different - or buffer not big enough) this may crash Wine... */ int bpp = this->s.ddraw->d.depth / 8; int height = xsrc.bottom - xsrc.top; int width = (xsrc.right - xsrc.left) * bpp; @@ -614,12 +622,10 @@ static HRESULT WINAPI IDirectDrawSurface3_Blt( width); } } - } - if (dwFlags) { - TRACE(ddraw,"\tUnsupported flags: ");_dump_DDBLT(dwFlags);fprintf(stderr,"\n"); + if (dwFlags && FIXME_ON(ddraw)) { + FIXME(ddraw,"\tUnsupported flags: ");_dump_DDBLT(dwFlags); } - return 0; } @@ -635,7 +641,7 @@ static HRESULT WINAPI Xlib_IDirectDrawSurface3_Blt( if (!this->s.ddraw->e.xlib.paintable) return ret; - if ((this->t.xlib.image != NULL) && (this->t.xlib.on_screen)) + if ((this->t.xlib.image != NULL) && (this->t.xlib.on_screen)) { #ifdef HAVE_LIBXXSHM if (this->s.ddraw->e.xlib.xshm_active) TSXShmPutImage(display, @@ -655,6 +661,7 @@ static HRESULT WINAPI Xlib_IDirectDrawSurface3_Blt( 0, 0, 0, 0, this->t.xlib.image->width, this->t.xlib.image->height); + } if (this->s.palette && this->s.palette->cm) TSXSetWindowColormap(display,this->s.ddraw->e.xlib.drawable,this->s.palette->cm); @@ -754,9 +761,8 @@ static ULONG WINAPI Xlib_IDirectDrawSurface3_Release(LPDIRECTDRAWSURFACE3 this) if (!--(this->ref)) { this->s.ddraw->lpvtbl->fnRelease(this->s.ddraw); - if( this->s.backbuffer ) { + if( this->s.backbuffer ) this->s.backbuffer->lpvtbl->fnRelease(this->s.backbuffer); - } if (this->t.xlib.image != NULL) { this->t.xlib.image->data = NULL; @@ -809,9 +815,7 @@ static HRESULT WINAPI IDirectDrawSurface3_GetAttachedSurface( *lpdsf = this->s.backbuffer; if( this->s.backbuffer ) - { this->s.backbuffer->lpvtbl->fnAddRef( this->s.backbuffer ); - } return 0; } @@ -1738,6 +1742,10 @@ static HRESULT WINAPI IDirectDraw2_DuplicateSurface( return 0; } +/* + * The Xlib Implementation tries to use the passed hwnd as drawing window, + * even when the approbiate bitmasks are not specified. + */ static HRESULT WINAPI IDirectDraw2_SetCooperativeLevel( LPDIRECTDRAW2 this,HWND32 hwnd,DWORD cooplevel ) { @@ -1769,13 +1777,54 @@ static HRESULT WINAPI IDirectDraw2_SetCooperativeLevel( return 0; } +/* Small helper to either use the cooperative window or create a new + * one (for mouse and keyboard input) and drawing in the Xlib implementation. + */ +static void _common_IDirectDraw_SetDisplayMode(LPDIRECTDRAW this) { + RECT32 rect; + + /* Do not destroy the application supplied cooperative window */ + if (this->d.window && this->d.window != this->d.mainWindow) { + DestroyWindow32(this->d.window); + this->d.window = 0; + } + /* Sanity check cooperative window before assigning it to drawing. */ + if ( IsWindow32(this->d.mainWindow) && + IsWindowVisible32(this->d.mainWindow) + ) { + GetWindowRect32(this->d.mainWindow,&rect); + if (((rect.right-rect.left) >= this->d.width) && + ((rect.bottom-rect.top) >= this->d.height) + ) + this->d.window = this->d.mainWindow; + } + /* ... failed, create new one. */ + if (!this->d.window) { + this->d.window = CreateWindowEx32A( + 0, + "WINE_DirectDraw", + "WINE_DirectDraw", + WS_VISIBLE|WS_SYSMENU|WS_THICKFRAME, + 0,0, + this->d.width, + this->d.height, + 0, + 0, + 0, + NULL + ); + /*Store THIS with the window. We'll use it in the window procedure*/ + SetWindowLong32A(this->d.window,ddrawXlibThisOffset,(LONG)this); + ShowWindow32(this->d.window,TRUE); + UpdateWindow32(this->d.window); + } +} static HRESULT WINAPI DGA_IDirectDraw_SetDisplayMode( LPDIRECTDRAW this,DWORD width,DWORD height,DWORD depth ) { #ifdef HAVE_LIBXXF86DGA int i,*depths,depcount; - HWND32 window; TRACE(ddraw, "(%p)->(%ld,%ld,%ld)\n", this, width, height, depth); @@ -1794,31 +1843,13 @@ static HRESULT WINAPI DGA_IDirectDraw_SetDisplayMode( } this->d.width = width; this->d.height = height; + this->d.depth = depth; + /* adjust fb_height, so we don't overlap */ if (this->e.dga.fb_height < height) this->e.dga.fb_height = height; - this->d.depth = depth; + _common_IDirectDraw_SetDisplayMode(this); - /* First, create a window for this mode. Apparently, some games - (such as Monkey Island III) do not do this properly for themselves. */ - window = CreateWindowEx32A( - 0, - "WINE_DirectDraw", - "WINE_DirectDraw", - WS_VISIBLE|WS_SYSMENU|WS_THICKFRAME, - 0,0, - width, - height, - 0, - 0, - 0, - NULL - ); - SetWindowLong32A(window,ddrawXlibThisOffset,(LONG)this); - ShowWindow32(window,TRUE); - UpdateWindow32(window); - assert(window); - /* FIXME: this function OVERWRITES several signal handlers. * can we save them? and restore them later? In a way that * it works for the library too? @@ -1856,44 +1887,17 @@ static HRESULT WINAPI Xlib_IDirectDraw_SetDisplayMode( MessageBox32A(0,buf,"WINE DirectDraw",MB_OK|MB_ICONSTOP); return DDERR_UNSUPPORTEDMODE; } - - if (this->d.window) - DestroyWindow32(this->d.window); - this->d.window = CreateWindowEx32A( - 0, - "WINE_DirectDraw", - "WINE_DirectDraw", - WS_VISIBLE|WS_SYSMENU|WS_THICKFRAME, - 0,0, - width, - height, - 0, - 0, - 0, - NULL - ); - - /* Store this with the window. We'll use it for the window procedure */ - SetWindowLong32A(this->d.window,ddrawXlibThisOffset,(LONG)this); - - this->e.xlib.paintable = 1; - - ShowWindow32(this->d.window,TRUE); - UpdateWindow32(this->d.window); - - assert(this->d.window); - - this->e.xlib.drawable = WIN_FindWndPtr(this->d.window)->window; - - /* We don't have a context for this window. Host off the desktop */ - if( !this->e.xlib.drawable ) - { - this->e.xlib.drawable = WIN_GetDesktop()->window; - } - this->d.width = width; this->d.height = height; this->d.depth = depth; + + _common_IDirectDraw_SetDisplayMode(this); + + this->e.xlib.paintable = 1; + this->e.xlib.drawable = WIN_FindWndPtr(this->d.window)->window; + /* We don't have a context for this window. Host off the desktop */ + if( !this->e.xlib.drawable ) + this->e.xlib.drawable = WIN_GetDesktop()->window; return 0; } @@ -1922,11 +1926,11 @@ static HRESULT WINAPI Xlib_IDirectDraw2_GetCaps( TRACE(ddraw,"(%p)->GetCaps(%p,%p)\n",this,caps1,caps2); /* FIXME: Xlib */ caps1->dwVidMemTotal = 2048*1024; - caps1->dwCaps = 0xffffffff&~(DDCAPS_BANKSWITCHED); /* we can do anything */ + caps1->dwCaps = 0xffffffff&~(DDCAPS_BANKSWITCHED|DDCAPS_GDI); caps1->ddsCaps.dwCaps = 0xffffffff; /* we can do anything */ if (caps2) { caps2->dwVidMemTotal = 2048*1024; - caps2->dwCaps = 0xffffffff&~(DDCAPS_BANKSWITCHED); /* we can do anything */ + caps2->dwCaps = 0xffffffff&~(DDCAPS_BANKSWITCHED|DDCAPS_GDI); caps2->ddsCaps.dwCaps = 0xffffffff; /* we can do anything */ } /* END FIXME: Xlib */ @@ -2528,15 +2532,11 @@ LRESULT WINAPI Xlib_DDWndProc(HWND32 hwnd,UINT32 msg,WPARAM32 wParam,LPARAM lPar } } - } - else - { + } else { ret = DefWindowProc32A(hwnd, msg, wParam, lParam ); } - } - else - { + } else { ret = DefWindowProc32A(hwnd,msg,wParam,lParam); } diff --git a/graphics/wing.c b/graphics/wing.c index 02166709206..3654cad381e 100644 --- a/graphics/wing.c +++ b/graphics/wing.c @@ -148,7 +148,7 @@ HBITMAP16 WINAPI WinGCreateBitmap16(HDC16 winDC, BITMAPINFO *header, WORD sel = 0; TSXShmAttach(display, &p->si); - bmpObjPtr->pixmap = XShmCreatePixmap(display, rootWindow, + bmpObjPtr->pixmap = TSXShmCreatePixmap(display, rootWindow, p->si.shmaddr, &p->si, bmpObjPtr->bitmap.bmWidth, bmpObjPtr->bitmap.bmHeight, bmpi->biBitCount ); if( bmpObjPtr->pixmap ) diff --git a/include/ddraw.h b/include/ddraw.h index 2e5d310c3c0..8deb38a6d78 100644 --- a/include/ddraw.h +++ b/include/ddraw.h @@ -935,34 +935,37 @@ struct IDirectDraw { typedef struct IDirectDraw2_VTable { /*** IUnknown methods ***/ - STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE; - STDMETHOD_(ULONG,AddRef) (THIS) PURE; - STDMETHOD_(ULONG,Release) (THIS) PURE; +/*00*/ STDMETHOD(QueryInterface) (THIS_ REFIID riid, LPVOID FAR * ppvObj) PURE; +/*04*/ STDMETHOD_(ULONG,AddRef) (THIS) PURE; +/*08*/ STDMETHOD_(ULONG,Release) (THIS) PURE; /*** IDirectDraw methods ***/ - STDMETHOD(Compact)(THIS) PURE; - STDMETHOD(CreateClipper)(THIS_ DWORD, LPDIRECTDRAWCLIPPER FAR*, IUnknown FAR * ) PURE; - STDMETHOD(CreatePalette)(THIS_ DWORD, LPPALETTEENTRY, LPDIRECTDRAWPALETTE FAR*, IUnknown FAR * ) PURE; - STDMETHOD(CreateSurface)(THIS_ LPDDSURFACEDESC, LPDIRECTDRAWSURFACE FAR *, -IUnknown FAR *) PURE; - STDMETHOD(DuplicateSurface)( THIS_ LPDIRECTDRAWSURFACE, LPDIRECTDRAWSURFACE -FAR * ) PURE; - STDMETHOD(EnumDisplayModes)( THIS_ DWORD, LPDDSURFACEDESC, LPVOID, LPDDENUMMODESCALLBACK ) PURE; - STDMETHOD(EnumSurfaces)(THIS_ DWORD, LPDDSURFACEDESC, LPVOID,LPDDENUMSURFACESCALLBACK ) PURE; - STDMETHOD(FlipToGDISurface)(THIS) PURE; - STDMETHOD(GetCaps)( THIS_ LPDDCAPS, LPDDCAPS) PURE; - STDMETHOD(GetDisplayMode)( THIS_ LPDDSURFACEDESC) PURE; - STDMETHOD(GetFourCCCodes)(THIS_ LPDWORD, LPDWORD ) PURE; - STDMETHOD(GetGDISurface)(THIS_ LPDIRECTDRAWSURFACE FAR *) PURE; - STDMETHOD(GetMonitorFrequency)(THIS_ LPDWORD) PURE; - STDMETHOD(GetScanLine)(THIS_ LPDWORD) PURE; - STDMETHOD(GetVerticalBlankStatus)(THIS_ BOOL32* ) PURE; - STDMETHOD(Initialize)(THIS_ GUID FAR *) PURE; - STDMETHOD(RestoreDisplayMode)(THIS) PURE; - STDMETHOD(SetCooperativeLevel)(THIS_ HWND32, DWORD) PURE; - STDMETHOD(SetDisplayMode)(THIS_ DWORD, DWORD, DWORD, DWORD, DWORD) PURE; - STDMETHOD(WaitForVerticalBlank)(THIS_ DWORD, HANDLE32 ) PURE; +/*0C*/ STDMETHOD(Compact)(THIS) PURE; +/*10*/ STDMETHOD(CreateClipper)(THIS_ DWORD, LPDIRECTDRAWCLIPPER FAR*, IUnknown FAR * ) PURE; +/*14*/ STDMETHOD(CreatePalette)(THIS_ DWORD,LPPALETTEENTRY, + LPDIRECTDRAWPALETTE FAR*, IUnknown FAR *) PURE; +/*18*/ STDMETHOD(CreateSurface)(THIS_ LPDDSURFACEDESC,LPDIRECTDRAWSURFACE + FAR *, IUnknown FAR *) PURE; +/*1C*/ STDMETHOD(DuplicateSurface)(THIS_ LPDIRECTDRAWSURFACE, + LPDIRECTDRAWSURFACE FAR * ) PURE; +/*20*/ STDMETHOD(EnumDisplayModes)(THIS_ DWORD, LPDDSURFACEDESC, LPVOID, + LPDDENUMMODESCALLBACK ) PURE; +/*24*/ STDMETHOD(EnumSurfaces)(THIS_ DWORD, LPDDSURFACEDESC, LPVOID, + LPDDENUMSURFACESCALLBACK ) PURE; +/*28*/ STDMETHOD(FlipToGDISurface)(THIS) PURE; +/*2C*/ STDMETHOD(GetCaps)( THIS_ LPDDCAPS, LPDDCAPS) PURE; +/*30*/ STDMETHOD(GetDisplayMode)( THIS_ LPDDSURFACEDESC) PURE; +/*34*/ STDMETHOD(GetFourCCCodes)(THIS_ LPDWORD, LPDWORD ) PURE; +/*38*/ STDMETHOD(GetGDISurface)(THIS_ LPDIRECTDRAWSURFACE FAR *) PURE; +/*3C*/ STDMETHOD(GetMonitorFrequency)(THIS_ LPDWORD) PURE; +/*40*/ STDMETHOD(GetScanLine)(THIS_ LPDWORD) PURE; +/*44*/ STDMETHOD(GetVerticalBlankStatus)(THIS_ BOOL32* ) PURE; +/*48*/ STDMETHOD(Initialize)(THIS_ GUID FAR *) PURE; +/*4C*/ STDMETHOD(RestoreDisplayMode)(THIS) PURE; +/*50*/ STDMETHOD(SetCooperativeLevel)(THIS_ HWND32, DWORD) PURE; +/*54*/ STDMETHOD(SetDisplayMode)(THIS_ DWORD, DWORD, DWORD, DWORD, DWORD) PURE; +/*58*/ STDMETHOD(WaitForVerticalBlank)(THIS_ DWORD, HANDLE32 ) PURE; /*** Added in the v2 interface ***/ - STDMETHOD(GetAvailableVidMem)(THIS_ LPDDSCAPS, LPDWORD, LPDWORD) PURE; +/*5C*/ STDMETHOD(GetAvailableVidMem)(THIS_ LPDDSCAPS, LPDWORD, LPDWORD) PURE; } IDirectDraw2_VTable,*LPDIRECTDRAW2_VTABLE; /* MUST HAVE THE SAME LAYOUT AS struct IDirectDraw */