DirectDraw status updated.
Use cooperative window for drawing in xlib implementation if possible.
Slightly restructured IDirectDrawSurface::Blt so it doesn't crash.
diff --git a/documentation/status/directdraw b/documentation/status/directdraw
index 04b0e1a..a19ca49 100644
--- a/documentation/status/directdraw
+++ b/documentation/status/directdraw
@@ -23,13 +23,6 @@
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 @@
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 @@
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 aa2beba..27fbf4d 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 @@
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 @@
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 @@
}
#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 @@
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 @@
this->s.surface = flipto->s.surface;
flipto->s.surface = surf;
}
-
return 0;
}
@@ -562,11 +562,15 @@
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 @@
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 @@
!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 @@
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 @@
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 @@
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 @@
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 @@
*lpdsf = this->s.backbuffer;
if( this->s.backbuffer )
- {
this->s.backbuffer->lpvtbl->fnAddRef( this->s.backbuffer );
- }
return 0;
}
@@ -1738,6 +1742,10 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
}
}
- }
- 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 0216670..3654cad 100644
--- a/graphics/wing.c
+++ b/graphics/wing.c
@@ -148,7 +148,7 @@
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 2e5d310..8deb38a 100644
--- a/include/ddraw.h
+++ b/include/ddraw.h
@@ -935,34 +935,37 @@
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 */