Sweden-Number/graphics/ddraw.c

4163 lines
123 KiB
C

/* DirectDraw using DGA or Xlib(XSHM)
*
* Copyright 1997,1998 Marcus Meissner
* Copyright 1998 Lionel Ulmer (most of Direct3D stuff)
*/
/* 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.
* Some ways to debug this stuff are:
* - 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"
#include "ts_xlib.h"
#include "ts_xutil.h"
#ifdef HAVE_LIBXXSHM
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include "ts_xshm.h"
#endif /* defined(HAVE_LIBXXSHM) */
#ifdef HAVE_LIBXXF86DGA
#include "ts_xf86dga.h"
#endif /* defined(HAVE_LIBXXF86DGA) */
#ifdef HAVE_LIBXXF86VM
/* X is retarted and insists on declaring INT32, INT16 etc in Xmd.h,
this is a crude hack to get around it */
#define XMD_H
typedef int INT32;
#include "ts_xf86vmode.h"
#endif /* defined(HAVE_LIBXXF86VM) */
#include "x11drv.h"
#include <unistd.h>
#include <assert.h>
#include <sys/signal.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include "winerror.h"
#include "gdi.h"
#include "heap.h"
#include "dc.h"
#include "win.h"
#include "miscemu.h"
#include "ddraw.h"
#include "d3d.h"
#include "debug.h"
#include "spy.h"
#include "message.h"
#include "options.h"
#include "monitor.h"
/* This for all the enumeration and creation of D3D-related objects */
#include "d3d_private.h"
/* define this if you want to play Diablo using XF86DGA. (bug workaround) */
#undef DIABLO_HACK
/* Restore signal handlers overwritten by XF86DGA
*/
#define RESTORE_SIGNALS
/* Where do these GUIDs come from? mkuuid.
* They exist solely to distinguish between the targets Wine support,
* and should be different than any other GUIDs in existence.
*/
static GUID DGA_DirectDraw_GUID = { /* e2dcb020-dc60-11d1-8407-9714f5d50802 */
0xe2dcb020,
0xdc60,
0x11d1,
{0x84, 0x07, 0x97, 0x14, 0xf5, 0xd5, 0x08, 0x02}
};
static GUID XLIB_DirectDraw_GUID = { /* 1574a740-dc61-11d1-8407-f7875a7d1879 */
0x1574a740,
0xdc61,
0x11d1,
{0x84, 0x07, 0xf7, 0x87, 0x5a, 0x7d, 0x18, 0x79}
};
static struct IDirectDrawSurface4_VTable dga_dds4vt, xlib_dds4vt;
static struct IDirectDraw_VTable dga_ddvt, xlib_ddvt;
static struct IDirectDraw2_VTable dga_dd2vt, xlib_dd2vt;
static struct IDirectDraw4_VTable dga_dd4vt, xlib_dd4vt;
static struct IDirectDrawClipper_VTable ddclipvt;
static struct IDirectDrawPalette_VTable dga_ddpalvt, xlib_ddpalvt;
static struct IDirect3D_VTable d3dvt;
static struct IDirect3D2_VTable d3d2vt;
#ifdef HAVE_LIBXXF86VM
static XF86VidModeModeInfo *orig_mode = NULL;
#endif
#ifdef HAVE_LIBXXSHM
static int XShmErrorFlag = 0;
#endif
BOOL
DDRAW_DGA_Available(void)
{
#ifdef HAVE_LIBXXF86DGA
int evbase, evret, fd;
if (Options.noDGA)
return 0;
/* You don't have to be root to use DGA extensions. Simply having access to /dev/mem will do the trick */
/* This can be achieved by adding the user to the "kmem" group on Debian 2.x systems, don't know about */
/* others. --stephenc */
if ((fd = open("/dev/mem", O_RDWR)) != -1)
close(fd);
return (fd != -1) && TSXF86DGAQueryExtension(display,&evbase,&evret);
#else /* defined(HAVE_LIBXXF86DGA) */
return 0;
#endif /* defined(HAVE_LIBXXF86DGA) */
}
HRESULT WINAPI
DirectDrawEnumerateA(LPDDENUMCALLBACKA ddenumproc,LPVOID data) {
TRACE(ddraw, "(%p,%p)\n", ddenumproc, data);
if (DDRAW_DGA_Available()) {
TRACE(ddraw, "Enumerating DGA interface\n");
if (!ddenumproc(&DGA_DirectDraw_GUID,"WINE with XFree86 DGA","display",data))
return DD_OK;
}
TRACE(ddraw, "Enumerating Xlib interface\n");
if (!ddenumproc(&XLIB_DirectDraw_GUID,"WINE with Xlib","display",data))
return DD_OK;
TRACE(ddraw, "Enumerating Default interface\n");
if (!ddenumproc(NULL,"WINE (default)","display",data))
return DD_OK;
return DD_OK;
}
HRESULT WINAPI
DirectDrawEnumerateExA(LPDDENUMCALLBACKEXA ddenumproc,LPVOID data, DWORD dwFlags) {
TRACE(ddraw, "(%p,%p, %08lx)\n", ddenumproc, data, dwFlags);
if (TRACE_ON(ddraw)) {
DUMP(" Flags : ");
if (dwFlags & DDENUM_ATTACHEDSECONDARYDEVICES)
DUMP("DDENUM_ATTACHEDSECONDARYDEVICES ");
if (dwFlags & DDENUM_DETACHEDSECONDARYDEVICES)
DUMP("DDENUM_DETACHEDSECONDARYDEVICES ");
if (dwFlags & DDENUM_NONDISPLAYDEVICES)
DUMP("DDENUM_NONDISPLAYDEVICES ");
DUMP("\n");
}
if (dwFlags & DDENUM_NONDISPLAYDEVICES) {
/* For the moment, Wine does not support any 3D only accelerators */
return DD_OK;
}
if (DDRAW_DGA_Available()) {
TRACE(ddraw, "Enumerating DGA interface\n");
if (!ddenumproc(&DGA_DirectDraw_GUID,"WINE with XFree86 DGA","display",data, NULL))
return DD_OK;
}
TRACE(ddraw, "Enumerating Xlib interface\n");
if (!ddenumproc(&XLIB_DirectDraw_GUID,"WINE with Xlib","display",data, NULL))
return DD_OK;
TRACE(ddraw, "Enumerating Default interface\n");
if (!ddenumproc(NULL,"WINE (default)","display",data, NULL))
return DD_OK;
return DD_OK;
}
/* What is this doing here? */
HRESULT WINAPI
DSoundHelp(DWORD x,DWORD y,DWORD z) {
FIXME(ddraw,"(0x%08lx,0x%08lx,0x%08lx),stub!\n",x,y,z);
return 0;
}
/******************************************************************************
* internal helper functions
*/
static void _dump_DDBLTFX(DWORD flagmask) {
int i;
const struct {
DWORD mask;
char *name;
} flags[] = {
#define FE(x) { x, #x},
FE(DDBLTFX_ARITHSTRETCHY)
FE(DDBLTFX_MIRRORLEFTRIGHT)
FE(DDBLTFX_MIRRORUPDOWN)
FE(DDBLTFX_NOTEARING)
FE(DDBLTFX_ROTATE180)
FE(DDBLTFX_ROTATE270)
FE(DDBLTFX_ROTATE90)
FE(DDBLTFX_ZBUFFERRANGE)
FE(DDBLTFX_ZBUFFERBASEDEST)
};
for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
if (flags[i].mask & flagmask) {
DUMP("%s ",flags[i].name);
};
DUMP("\n");
}
static void _dump_DDBLTFAST(DWORD flagmask) {
int i;
const struct {
DWORD mask;
char *name;
} flags[] = {
#define FE(x) { x, #x},
FE(DDBLTFAST_NOCOLORKEY)
FE(DDBLTFAST_SRCCOLORKEY)
FE(DDBLTFAST_DESTCOLORKEY)
FE(DDBLTFAST_WAIT)
};
for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
if (flags[i].mask & flagmask)
DUMP("%s ",flags[i].name);
DUMP("\n");
}
static void _dump_DDBLT(DWORD flagmask) {
int i;
const struct {
DWORD mask;
char *name;
} flags[] = {
#define FE(x) { x, #x},
FE(DDBLT_ALPHADEST)
FE(DDBLT_ALPHADESTCONSTOVERRIDE)
FE(DDBLT_ALPHADESTNEG)
FE(DDBLT_ALPHADESTSURFACEOVERRIDE)
FE(DDBLT_ALPHAEDGEBLEND)
FE(DDBLT_ALPHASRC)
FE(DDBLT_ALPHASRCCONSTOVERRIDE)
FE(DDBLT_ALPHASRCNEG)
FE(DDBLT_ALPHASRCSURFACEOVERRIDE)
FE(DDBLT_ASYNC)
FE(DDBLT_COLORFILL)
FE(DDBLT_DDFX)
FE(DDBLT_DDROPS)
FE(DDBLT_KEYDEST)
FE(DDBLT_KEYDESTOVERRIDE)
FE(DDBLT_KEYSRC)
FE(DDBLT_KEYSRCOVERRIDE)
FE(DDBLT_ROP)
FE(DDBLT_ROTATIONANGLE)
FE(DDBLT_ZBUFFER)
FE(DDBLT_ZBUFFERDESTCONSTOVERRIDE)
FE(DDBLT_ZBUFFERDESTOVERRIDE)
FE(DDBLT_ZBUFFERSRCCONSTOVERRIDE)
FE(DDBLT_ZBUFFERSRCOVERRIDE)
FE(DDBLT_WAIT)
FE(DDBLT_DEPTHFILL)
};
for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
if (flags[i].mask & flagmask)
DUMP("%s ",flags[i].name);
DUMP("\n");
}
static void _dump_DDSCAPS(DWORD flagmask) {
int i;
const struct {
DWORD mask;
char *name;
} flags[] = {
#define FE(x) { x, #x},
FE(DDSCAPS_RESERVED1)
FE(DDSCAPS_ALPHA)
FE(DDSCAPS_BACKBUFFER)
FE(DDSCAPS_COMPLEX)
FE(DDSCAPS_FLIP)
FE(DDSCAPS_FRONTBUFFER)
FE(DDSCAPS_OFFSCREENPLAIN)
FE(DDSCAPS_OVERLAY)
FE(DDSCAPS_PALETTE)
FE(DDSCAPS_PRIMARYSURFACE)
FE(DDSCAPS_PRIMARYSURFACELEFT)
FE(DDSCAPS_SYSTEMMEMORY)
FE(DDSCAPS_TEXTURE)
FE(DDSCAPS_3DDEVICE)
FE(DDSCAPS_VIDEOMEMORY)
FE(DDSCAPS_VISIBLE)
FE(DDSCAPS_WRITEONLY)
FE(DDSCAPS_ZBUFFER)
FE(DDSCAPS_OWNDC)
FE(DDSCAPS_LIVEVIDEO)
FE(DDSCAPS_HWCODEC)
FE(DDSCAPS_MODEX)
FE(DDSCAPS_MIPMAP)
FE(DDSCAPS_RESERVED2)
FE(DDSCAPS_ALLOCONLOAD)
FE(DDSCAPS_VIDEOPORT)
FE(DDSCAPS_LOCALVIDMEM)
FE(DDSCAPS_NONLOCALVIDMEM)
FE(DDSCAPS_STANDARDVGAMODE)
FE(DDSCAPS_OPTIMIZED)
};
for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
if (flags[i].mask & flagmask)
DUMP("%s ",flags[i].name);
DUMP("\n");
}
static void _dump_DDSD(DWORD flagmask) {
int i;
const struct {
DWORD mask;
char *name;
} flags[] = {
FE(DDSD_CAPS)
FE(DDSD_HEIGHT)
FE(DDSD_WIDTH)
FE(DDSD_PITCH)
FE(DDSD_BACKBUFFERCOUNT)
FE(DDSD_ZBUFFERBITDEPTH)
FE(DDSD_ALPHABITDEPTH)
FE(DDSD_PIXELFORMAT)
FE(DDSD_CKDESTOVERLAY)
FE(DDSD_CKDESTBLT)
FE(DDSD_CKSRCOVERLAY)
FE(DDSD_CKSRCBLT)
FE(DDSD_MIPMAPCOUNT)
FE(DDSD_REFRESHRATE)
FE(DDSD_LINEARSIZE)
FE(DDSD_LPSURFACE)
};
for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
if (flags[i].mask & flagmask)
DUMP("%s ",flags[i].name);
DUMP("\n");
}
static void _dump_DDCOLORKEY(DWORD flagmask) {
int i;
const struct {
DWORD mask;
char *name;
} flags[] = {
#define FE(x) { x, #x},
FE(DDPF_ALPHAPIXELS)
FE(DDPF_ALPHA)
FE(DDPF_FOURCC)
FE(DDPF_PALETTEINDEXED4)
FE(DDPF_PALETTEINDEXEDTO8)
FE(DDPF_PALETTEINDEXED8)
FE(DDPF_RGB)
FE(DDPF_COMPRESSED)
FE(DDPF_RGBTOYUV)
FE(DDPF_YUV)
FE(DDPF_ZBUFFER)
FE(DDPF_PALETTEINDEXED1)
FE(DDPF_PALETTEINDEXED2)
FE(DDPF_ZPIXELS)
};
for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
if (flags[i].mask & flagmask)
DUMP("%s ",flags[i].name);
DUMP("\n");
}
static void _dump_paletteformat(DWORD dwFlags) {
int i;
const struct {
DWORD mask;
char *name;
} flags[] = {
#define FE(x) { x, #x},
FE(DDPCAPS_4BIT)
FE(DDPCAPS_8BITENTRIES)
FE(DDPCAPS_8BIT)
FE(DDPCAPS_INITIALIZE)
FE(DDPCAPS_PRIMARYSURFACE)
FE(DDPCAPS_PRIMARYSURFACELEFT)
FE(DDPCAPS_ALLOW256)
FE(DDPCAPS_VSYNC)
FE(DDPCAPS_1BIT)
FE(DDPCAPS_2BIT)
FE(DDPCAPS_ALPHA)
};
for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
if (flags[i].mask & dwFlags)
DUMP("%s ",flags[i].name);
DUMP("\n");
}
static void _dump_pixelformat(LPDDPIXELFORMAT pf) {
DUMP("Size : %ld\n", pf->dwSize);
if (pf->dwFlags)
_dump_DDCOLORKEY(pf->dwFlags);
DUMP("dwFourCC : %ld\n", pf->dwFourCC);
DUMP("RGB bit count : %ld\n", pf->x.dwRGBBitCount);
DUMP("Masks : R %08lx G %08lx B %08lx A %08lx\n",
pf->y.dwRBitMask, pf->z.dwGBitMask, pf->xx.dwBBitMask, pf->xy.dwRGBAlphaBitMask);
}
/******************************************************************************
* IDirectDrawSurface methods
*
* Since DDS3 and DDS2 are supersets of DDS, we implement DDS3 and let
* DDS and DDS2 use those functions. (Function calls did not change (except
* using different DirectDrawSurfaceX version), just added flags and functions)
*/
static HRESULT WINAPI IDirectDrawSurface4_Lock(
LPDIRECTDRAWSURFACE4 this,LPRECT lprect,LPDDSURFACEDESC lpddsd,DWORD flags, HANDLE hnd
) {
TRACE(ddraw, "(%p)->Lock(%p,%p,%08lx,%08lx)\n",
this,lprect,lpddsd,flags,(DWORD)hnd);
if (flags & ~(DDLOCK_WAIT|DDLOCK_READONLY|DDLOCK_WRITEONLY))
WARN(ddraw, "(%p)->Lock(%p,%p,%08lx,%08lx)\n",
this,lprect,lpddsd,flags,(DWORD)hnd);
/* First, copy the Surface description */
*lpddsd = this->s.surface_desc;
TRACE(ddraw,"locked surface: height=%ld, width=%ld, pitch=%ld\n",
lpddsd->dwHeight,lpddsd->dwWidth,lpddsd->lPitch);
/* If asked only for a part, change the surface pointer */
if (lprect) {
FIXME(ddraw," lprect: %dx%d-%dx%d\n",
lprect->top,lprect->left,lprect->bottom,lprect->right
);
lpddsd->y.lpSurface = this->s.surface_desc.y.lpSurface +
(lprect->top*this->s.surface_desc.lPitch) +
(lprect->left*(this->s.surface_desc.ddpfPixelFormat.x.dwRGBBitCount / 8));
} else {
assert(this->s.surface_desc.y.lpSurface);
}
return DD_OK;
}
static HRESULT WINAPI DGA_IDirectDrawSurface4_Unlock(
LPDIRECTDRAWSURFACE4 this,LPVOID surface
) {
TRACE(ddraw,"(%p)->Unlock(%p)\n",this,surface);
return DD_OK;
}
static void Xlib_copy_surface_on_screen(LPDIRECTDRAWSURFACE4 this) {
if (this->s.ddraw->d.pixel_convert != NULL)
this->s.ddraw->d.pixel_convert(this->s.surface_desc.y.lpSurface,
this->t.xlib.image->data,
this->s.surface_desc.dwWidth,
this->s.surface_desc.dwHeight,
this->s.surface_desc.lPitch,
this->s.palette);
#ifdef HAVE_LIBXXSHM
if (this->s.ddraw->e.xlib.xshm_active)
TSXShmPutImage(display,
this->s.ddraw->d.drawable,
DefaultGCOfScreen(X11DRV_GetXScreen()),
this->t.xlib.image,
0, 0, 0, 0,
this->t.xlib.image->width,
this->t.xlib.image->height,
False);
else
#endif
TSXPutImage( display,
this->s.ddraw->d.drawable,
DefaultGCOfScreen(X11DRV_GetXScreen()),
this->t.xlib.image,
0, 0, 0, 0,
this->t.xlib.image->width,
this->t.xlib.image->height);
}
static HRESULT WINAPI Xlib_IDirectDrawSurface4_Unlock(
LPDIRECTDRAWSURFACE4 this,LPVOID surface)
{
TRACE(ddraw,"(%p)->Unlock(%p)\n",this,surface);
if (!this->s.ddraw->d.paintable)
return DD_OK;
/* Only redraw the screen when unlocking the buffer that is on screen */
if ((this->t.xlib.image != NULL) &&
(this->s.surface_desc.ddsCaps.dwCaps & DDSCAPS_VISIBLE)) {
Xlib_copy_surface_on_screen(this);
if (this->s.palette && this->s.palette->cm)
TSXSetWindowColormap(display,this->s.ddraw->d.drawable,this->s.palette->cm);
}
return DD_OK;
}
static HRESULT WINAPI DGA_IDirectDrawSurface4_Flip(
LPDIRECTDRAWSURFACE4 this,LPDIRECTDRAWSURFACE4 flipto,DWORD dwFlags
) {
#ifdef HAVE_LIBXXF86DGA
TRACE(ddraw,"(%p)->Flip(%p,%08lx)\n",this,flipto,dwFlags);
if (!flipto) {
if (this->s.backbuffer)
flipto = this->s.backbuffer;
else
flipto = this;
}
TSXF86DGASetViewPort(display,DefaultScreen(display),0,flipto->t.dga.fb_height);
if (flipto->s.palette && flipto->s.palette->cm) {
TSXF86DGAInstallColormap(display,DefaultScreen(display),flipto->s.palette->cm);
}
while (!TSXF86DGAViewPortChanged(display,DefaultScreen(display),2)) {
}
if (flipto!=this) {
int tmp;
LPVOID ptmp;
tmp = this->t.dga.fb_height;
this->t.dga.fb_height = flipto->t.dga.fb_height;
flipto->t.dga.fb_height = tmp;
ptmp = this->s.surface_desc.y.lpSurface;
this->s.surface_desc.y.lpSurface = flipto->s.surface_desc.y.lpSurface;
flipto->s.surface_desc.y.lpSurface = ptmp;
}
return DD_OK;
#else /* defined(HAVE_LIBXXF86DGA) */
return E_UNEXPECTED;
#endif /* defined(HAVE_LIBXXF86DGA) */
}
static HRESULT WINAPI Xlib_IDirectDrawSurface4_Flip(
LPDIRECTDRAWSURFACE4 this,LPDIRECTDRAWSURFACE4 flipto,DWORD dwFlags
) {
TRACE(ddraw,"(%p)->Flip(%p,%08lx)\n",this,flipto,dwFlags);
if (!this->s.ddraw->d.paintable)
return DD_OK;
if (!flipto) {
if (this->s.backbuffer)
flipto = this->s.backbuffer;
else
flipto = this;
}
Xlib_copy_surface_on_screen(this);
if (flipto->s.palette && flipto->s.palette->cm) {
TSXSetWindowColormap(display,this->s.ddraw->d.drawable,flipto->s.palette->cm);
}
if (flipto!=this) {
XImage *tmp;
LPVOID *surf;
tmp = this->t.xlib.image;
this->t.xlib.image = flipto->t.xlib.image;
flipto->t.xlib.image = tmp;
surf = this->s.surface_desc.y.lpSurface;
this->s.surface_desc.y.lpSurface = flipto->s.surface_desc.y.lpSurface;
flipto->s.surface_desc.y.lpSurface = surf;
}
return DD_OK;
}
/* The IDirectDrawSurface4::SetPalette method attaches the specified
* DirectDrawPalette object to a surface. The surface uses this palette for all
* subsequent operations. The palette change takes place immediately.
*/
static HRESULT WINAPI Xlib_IDirectDrawSurface4_SetPalette(
LPDIRECTDRAWSURFACE4 this,LPDIRECTDRAWPALETTE pal
) {
int i;
TRACE(ddraw,"(%p)->(%p)\n",this,pal);
if (pal == NULL) {
if( this->s.palette != NULL )
this->s.palette->lpvtbl->fnRelease( this->s.palette );
this->s.palette = pal;
return DD_OK;
}
if( !(pal->cm) && (this->s.ddraw->d.screen_pixelformat.x.dwRGBBitCount<=8))
{
pal->cm = TSXCreateColormap(display,this->s.ddraw->d.drawable,
DefaultVisualOfScreen(X11DRV_GetXScreen()),AllocAll);
if (!Options.managed)
TSXInstallColormap(display,pal->cm);
for (i=0;i<256;i++) {
XColor xc;
xc.red = pal->palents[i].peRed<<8;
xc.blue = pal->palents[i].peBlue<<8;
xc.green = pal->palents[i].peGreen<<8;
xc.flags = DoRed|DoBlue|DoGreen;
xc.pixel = i;
TSXStoreColor(display,pal->cm,&xc);
}
TSXInstallColormap(display,pal->cm);
}
/* According to spec, we are only supposed to
* AddRef if this is not the same palette.
*/
if( this->s.palette != pal )
{
if( pal != NULL )
pal->lpvtbl->fnAddRef( pal );
if( this->s.palette != NULL )
this->s.palette->lpvtbl->fnRelease( this->s.palette );
this->s.palette = pal;
/* I think that we need to attach it to all backbuffers...*/
if( this->s.backbuffer ) {
if( this->s.backbuffer->s.palette )
this->s.backbuffer->s.palette->lpvtbl->fnRelease(
this->s.backbuffer->s.palette );
this->s.backbuffer->s.palette = pal;
if( pal )
pal->lpvtbl->fnAddRef( pal );
}
/* Perform the refresh */
TSXSetWindowColormap(display,this->s.ddraw->d.drawable,this->s.palette->cm);
}
return DD_OK;
}
static HRESULT WINAPI DGA_IDirectDrawSurface4_SetPalette(
LPDIRECTDRAWSURFACE4 this,LPDIRECTDRAWPALETTE pal
) {
TRACE(ddraw,"(%p)->(%p)\n",this,pal);
#ifdef HAVE_LIBXXF86DGA
/* According to spec, we are only supposed to
* AddRef if this is not the same palette.
*/
if( this->s.palette != pal )
{
if( pal != NULL )
pal->lpvtbl->fnAddRef( pal );
if( this->s.palette != NULL )
this->s.palette->lpvtbl->fnRelease( this->s.palette );
this->s.palette = pal;
/* I think that we need to attach it to all backbuffers...*/
if( this->s.backbuffer ) {
if( this->s.backbuffer->s.palette )
this->s.backbuffer->s.palette->lpvtbl->fnRelease(this->s.backbuffer->s.palette );
this->s.backbuffer->s.palette = pal;
if( pal ) pal->lpvtbl->fnAddRef( pal );
}
TSXF86DGAInstallColormap(display,DefaultScreen(display),this->s.palette->cm);
}
return DD_OK;
#else /* defined(HAVE_LIBXXF86DGA) */
return E_UNEXPECTED;
#endif /* defined(HAVE_LIBXXF86DGA) */
}
static HRESULT WINAPI IDirectDrawSurface4_Blt(
LPDIRECTDRAWSURFACE4 this,LPRECT rdst,LPDIRECTDRAWSURFACE4 src,LPRECT rsrc,DWORD dwFlags,LPDDBLTFX lpbltfx
) {
RECT xdst,xsrc;
DDSURFACEDESC ddesc,sdesc;
int i,j;
TRACE(ddraw,"(%p)->(%p,%p,%p,%08lx,%p)\n",
this,rdst,src,rsrc,dwFlags,lpbltfx);
if (src != NULL)
src ->lpvtbl->fnLock(src, NULL,&sdesc,0,0);
this->lpvtbl->fnLock(this,NULL,&ddesc,0,0);
if (TRACE_ON(ddraw)) {
if (rdst) TRACE(ddraw," destrect :%dx%d-%dx%d\n",rdst->left,rdst->top,rdst->right,rdst->bottom);
if (rsrc) TRACE(ddraw," srcrect :%dx%d-%dx%d\n",rsrc->left,rsrc->top,rsrc->right,rsrc->bottom);
TRACE(ddraw,"\tflags: "); _dump_DDBLT(dwFlags);
if (dwFlags & DDBLT_DDFX) {
TRACE(ddraw," blitfx: \n");_dump_DDBLTFX(lpbltfx->dwDDFX);
}
}
if (rdst) {
memcpy(&xdst,rdst,sizeof(xdst));
} else {
xdst.top = 0;
xdst.bottom = ddesc.dwHeight;
xdst.left = 0;
xdst.right = ddesc.dwWidth;
}
if (rsrc) {
memcpy(&xsrc,rsrc,sizeof(xsrc));
} else {
if (src) {
xsrc.top = 0;
xsrc.bottom = sdesc.dwHeight;
xsrc.left = 0;
xsrc.right = sdesc.dwWidth;
} else {
memset(&xsrc,0,sizeof(xsrc));
}
}
dwFlags &= ~(DDBLT_WAIT|DDBLT_ASYNC);/* FIXME: can't handle right now */
/* First, all the 'source-less' blits */
if (dwFlags & DDBLT_COLORFILL) {
int bpp = ddesc.ddpfPixelFormat.x.dwRGBBitCount / 8;
LPBYTE xline,xpixel;
xline = (LPBYTE) ddesc.y.lpSurface + xdst.top * ddesc.lPitch;
for (i=xdst.top;i<xdst.bottom;i++) {
xpixel = xline+bpp*xdst.left;
for (j=xdst.left;j<xdst.right;j++) {
/* FIXME: this only works on little endian
* architectures, where DWORD starts with low
* byte first!
*/
memcpy(xpixel,&(lpbltfx->b.dwFillColor),bpp);
xpixel += bpp;
}
xline += ddesc.lPitch;
}
dwFlags &= ~(DDBLT_COLORFILL);
}
if (dwFlags & DDBLT_DEPTHFILL) {
#ifdef HAVE_MESAGL
GLboolean ztest;
/* Clears the screen */
TRACE(ddraw, " Filling depth buffer with %ld\n", lpbltfx->b.dwFillDepth);
glClearDepth(lpbltfx->b.dwFillDepth / 65535.0); /* We suppose a 16 bit Z Buffer */
glGetBooleanv(GL_DEPTH_TEST, &ztest);
glDepthMask(GL_TRUE); /* Enables Z writing to be sure to delete also the Z buffer */
glClear(GL_DEPTH_BUFFER_BIT);
glDepthMask(ztest);
dwFlags &= ~(DDBLT_DEPTHFILL);
#endif HAVE_MESAGL
}
if (!src) {
if (dwFlags) {
TRACE(ddraw,"\t(src=NULL):Unsupported flags: "); _dump_DDBLT(dwFlags);
}
this->lpvtbl->fnUnlock(this,ddesc.y.lpSurface);
return DD_OK;
}
/* Now the 'with source' blits */
/* Standard 'full-surface' blit without special effects */
if ( (xsrc.top ==0) && (xsrc.bottom ==ddesc.dwHeight) &&
(xsrc.left==0) && (xsrc.right ==ddesc.dwWidth) &&
(xdst.top ==0) && (xdst.bottom ==ddesc.dwHeight) &&
(xdst.left==0) && (xdst.right ==ddesc.dwWidth) &&
!dwFlags
) {
memcpy(ddesc.y.lpSurface,
sdesc.y.lpSurface,
ddesc.dwHeight * ddesc.lPitch);
} else {
int bpp = ddesc.ddpfPixelFormat.x.dwRGBBitCount / 8;
int srcheight = xsrc.bottom - xsrc.top;
int srcwidth = xsrc.right - xsrc.left;
int dstheight = xdst.bottom - xdst.top;
int dstwidth = xdst.right - xdst.left;
int width = (xsrc.right - xsrc.left) * bpp;
int h;
/* Sanity check for rectangle sizes */
if ((srcheight != dstheight) || (srcwidth != dstwidth)) {
int x, y;
/* I think we should do a Blit with 'stretching' here....
Tomb Raider II uses this to display the background during the menu selection
when the screen resolution is != than 640x480 */
TRACE(ddraw, "Blt with stretching\n");
/* This is a basic stretch implementation. It is painfully slow and quite ugly. */
if (bpp == 1) {
/* In this case, we cannot do any anti-aliasing */
if(dwFlags & DDBLT_KEYSRC) {
for (y = xdst.top; y < xdst.bottom; y++) {
for (x = xdst.left; x < xdst.right; x++) {
double sx, sy;
unsigned char tmp;
unsigned char *dbuf = (unsigned char *) ddesc.y.lpSurface;
unsigned char *sbuf = (unsigned char *) sdesc.y.lpSurface;
sx = (((double) (x - xdst.left) / dstwidth) * srcwidth) + xsrc.left;
sy = (((double) (y - xdst.top) / dstheight) * srcheight) + xsrc.top;
tmp = sbuf[(((int) sy) * sdesc.lPitch) + ((int) sx)];
if ((tmp < src->s.surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue) ||
(tmp > src->s.surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue))
dbuf[(y * ddesc.lPitch) + x] = tmp;
}
}
} else {
for (y = xdst.top; y < xdst.bottom; y++) {
for (x = xdst.left; x < xdst.right; x++) {
double sx, sy;
unsigned char *dbuf = (unsigned char *) ddesc.y.lpSurface;
unsigned char *sbuf = (unsigned char *) sdesc.y.lpSurface;
sx = (((double) (x - xdst.left) / dstwidth) * srcwidth) + xsrc.left;
sy = (((double) (y - xdst.top) / dstheight) * srcheight) + xsrc.top;
dbuf[(y * ddesc.lPitch) + x] = sbuf[(((int) sy) * sdesc.lPitch) + ((int) sx)];
}
}
}
} else {
FIXME(ddraw, "Not done yet for depth != 8\n");
}
} else {
/* Same size => fast blit */
if (dwFlags & DDBLT_KEYSRC) {
switch (bpp) {
case 1: {
unsigned char tmp,*psrc,*pdst;
int h,i;
for (h = 0; h < srcheight; h++) {
psrc=sdesc.y.lpSurface +
((h + xsrc.top) * sdesc.lPitch) + xsrc.left;
pdst=ddesc.y.lpSurface +
((h + xdst.top) * ddesc.lPitch) + xdst.left;
for(i=0;i<srcwidth;i++) {
tmp=*(psrc + i);
if ((tmp < src->s.surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue) ||
(tmp > src->s.surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue))
*(pdst + i)=tmp;
}
}
dwFlags&=~(DDBLT_KEYSRC);
} break;
case 2: {
unsigned short tmp,*psrc,*pdst;
int h,i;
for (h = 0; h < srcheight; h++) {
psrc=sdesc.y.lpSurface +
((h + xsrc.top) * sdesc.lPitch) + xsrc.left;
pdst=ddesc.y.lpSurface +
((h + xdst.top) * ddesc.lPitch) + xdst.left;
for(i=0;i<srcwidth;i++) {
tmp=*(psrc + i);
if ((tmp < src->s.surface_desc.ddckCKSrcBlt.dwColorSpaceLowValue) ||
(tmp > src->s.surface_desc.ddckCKSrcBlt.dwColorSpaceHighValue))
*(pdst + i)=tmp;
}
}
dwFlags&=~(DDBLT_KEYSRC);
} break;
default:
FIXME(ddraw, "Bitblt, KEYSRC: Not done yet for depth > 16\n");
}
} else {
/* Non-stretching Blt without color keying */
for (h = 0; h < srcheight; h++) {
memcpy(ddesc.y.lpSurface + ((h + xdst.top) * ddesc.lPitch) + xdst.left * bpp,
sdesc.y.lpSurface + ((h + xsrc.top) * sdesc.lPitch) + xsrc.left * bpp,
width);
}
}
}
}
if (dwFlags && FIXME_ON(ddraw)) {
FIXME(ddraw,"\tUnsupported flags: ");_dump_DDBLT(dwFlags);
}
this->lpvtbl->fnUnlock(this,ddesc.y.lpSurface);
src ->lpvtbl->fnUnlock(src,sdesc.y.lpSurface);
return DD_OK;
}
static HRESULT WINAPI IDirectDrawSurface4_BltFast(
LPDIRECTDRAWSURFACE4 this,DWORD dstx,DWORD dsty,LPDIRECTDRAWSURFACE4 src,LPRECT rsrc,DWORD trans
) {
int i,bpp,w,h;
DDSURFACEDESC ddesc,sdesc;
if (1 || TRACE_ON(ddraw)) {
FIXME(ddraw,"(%p)->(%ld,%ld,%p,%p,%08lx)\n",
this,dstx,dsty,src,rsrc,trans
);
FIXME(ddraw," trans:");
if (FIXME_ON(ddraw))
_dump_DDBLTFAST(trans);
FIXME(ddraw," srcrect: %dx%d-%dx%d\n",rsrc->left,rsrc->top,rsrc->right,rsrc->bottom);
}
/* We need to lock the surfaces, or we won't get refreshes when done. */
src ->lpvtbl->fnLock(src, NULL,&sdesc,DDLOCK_READONLY, 0);
this->lpvtbl->fnLock(this,NULL,&ddesc,DDLOCK_WRITEONLY,0);
bpp = this->s.surface_desc.ddpfPixelFormat.x.dwRGBBitCount / 8;
h=rsrc->bottom-rsrc->top;
if (h>ddesc.dwHeight-dsty) h=ddesc.dwHeight-dsty;
if (h>sdesc.dwHeight-rsrc->top) h=sdesc.dwHeight-rsrc->top;
if (h<0) h=0;
w=rsrc->right-rsrc->left;
if (w>ddesc.dwWidth-dstx) w=ddesc.dwWidth-dstx;
if (w>sdesc.dwWidth-rsrc->left) w=sdesc.dwWidth-rsrc->left;
if (w<0) w=0;
for (i=0;i<h;i++) {
memcpy( ddesc.y.lpSurface+(dsty +i)*ddesc.lPitch+dstx*bpp,
sdesc.y.lpSurface+(rsrc->top+i)*sdesc.lPitch+rsrc->left*bpp,
w*bpp
);
}
this->lpvtbl->fnUnlock(this,ddesc.y.lpSurface);
src ->lpvtbl->fnUnlock(src,sdesc.y.lpSurface);
return DD_OK;
}
static HRESULT WINAPI IDirectDrawSurface4_BltBatch(
LPDIRECTDRAWSURFACE4 this,LPDDBLTBATCH ddbltbatch,DWORD x,DWORD y
) {
FIXME(ddraw,"(%p)->BltBatch(%p,%08lx,%08lx),stub!\n",
this,ddbltbatch,x,y
);
return DD_OK;
}
static HRESULT WINAPI IDirectDrawSurface4_GetCaps(
LPDIRECTDRAWSURFACE4 this,LPDDSCAPS caps
) {
TRACE(ddraw,"(%p)->GetCaps(%p)\n",this,caps);
caps->dwCaps = DDSCAPS_PALETTE; /* probably more */
return DD_OK;
}
static HRESULT WINAPI IDirectDrawSurface4_GetSurfaceDesc(
LPDIRECTDRAWSURFACE4 this,LPDDSURFACEDESC ddsd
) {
TRACE(ddraw, "(%p)->GetSurfaceDesc(%p)\n",
this,ddsd);
/* Simply copy the surface description stored in the object */
*ddsd = this->s.surface_desc;
if (TRACE_ON(ddraw)) {
DUMP(" flags: ");
_dump_DDSD(ddsd->dwFlags);
if (ddsd->dwFlags & DDSD_CAPS) {
DUMP(" caps: ");
_dump_DDSCAPS(ddsd->ddsCaps.dwCaps);
}
if (ddsd->dwFlags & DDSD_PIXELFORMAT) {
DUMP(" pixel format : \n");
_dump_pixelformat(&(ddsd->ddpfPixelFormat));
}
}
return DD_OK;
}
static ULONG WINAPI IDirectDrawSurface4_AddRef(LPDIRECTDRAWSURFACE4 this) {
TRACE( ddraw, "(%p)->() incrementing from %lu.\n", this, this->ref );
return ++(this->ref);
}
static ULONG WINAPI DGA_IDirectDrawSurface4_Release(LPDIRECTDRAWSURFACE4 this) {
TRACE( ddraw, "(%p)->() decrementing from %lu.\n", this, this->ref );
#ifdef HAVE_LIBXXF86DGA
if (!--(this->ref)) {
this->s.ddraw->lpvtbl->fnRelease(this->s.ddraw);
/* clear out of surface list */
if (this->t.dga.fb_height == -1) {
HeapFree(GetProcessHeap(),0,this->s.surface_desc.y.lpSurface);
} else {
this->s.ddraw->e.dga.vpmask &= ~(1<<(this->t.dga.fb_height/this->s.ddraw->e.dga.fb_height));
}
/* Free the backbuffer */
if (this->s.backbuffer)
this->s.backbuffer->lpvtbl->fnRelease(this->s.backbuffer);
HeapFree(GetProcessHeap(),0,this);
return 0;
}
#endif /* defined(HAVE_LIBXXF86DGA) */
return this->ref;
}
static ULONG WINAPI Xlib_IDirectDrawSurface4_Release(LPDIRECTDRAWSURFACE4 this) {
TRACE( ddraw, "(%p)->() decrementing from %lu.\n", this, this->ref );
if (!--(this->ref)) {
this->s.ddraw->lpvtbl->fnRelease(this->s.ddraw);
if( this->s.backbuffer )
this->s.backbuffer->lpvtbl->fnRelease(this->s.backbuffer);
if (this->t.xlib.image != NULL) {
if (this->s.ddraw->d.pixel_convert != NULL) {
/* In pixel conversion mode, there are two buffers to release... */
HeapFree(GetProcessHeap(),0,this->s.surface_desc.y.lpSurface);
#ifdef HAVE_LIBXXSHM
if (this->s.ddraw->e.xlib.xshm_active) {
TSXShmDetach(display, &(this->t.xlib.shminfo));
TSXDestroyImage(this->t.xlib.image);
shmdt(this->t.xlib.shminfo.shmaddr);
} else {
#endif
HeapFree(GetProcessHeap(),0,this->t.xlib.image->data);
this->t.xlib.image->data = NULL;
TSXDestroyImage(this->t.xlib.image);
#ifdef HAVE_LIBXXSHM
}
#endif
} else {
this->t.xlib.image->data = NULL;
#ifdef HAVE_LIBXXSHM
if (this->s.ddraw->e.xlib.xshm_active) {
TSXShmDetach(display, &(this->t.xlib.shminfo));
TSXDestroyImage(this->t.xlib.image);
shmdt(this->t.xlib.shminfo.shmaddr);
} else {
#endif
HeapFree(GetProcessHeap(),0,this->s.surface_desc.y.lpSurface);
TSXDestroyImage(this->t.xlib.image);
#ifdef HAVE_LIBXXSHM
}
#endif
}
this->t.xlib.image = 0;
} else {
HeapFree(GetProcessHeap(),0,this->s.surface_desc.y.lpSurface);
}
if (this->s.palette)
this->s.palette->lpvtbl->fnRelease(this->s.palette);
HeapFree(GetProcessHeap(),0,this);
return 0;
}
return this->ref;
}
static HRESULT WINAPI IDirectDrawSurface4_GetAttachedSurface(
LPDIRECTDRAWSURFACE4 this,LPDDSCAPS lpddsd,LPDIRECTDRAWSURFACE4 *lpdsf
) {
TRACE(ddraw, "(%p)->GetAttachedSurface(%p,%p)\n",
this, lpddsd, lpdsf);
if (TRACE_ON(ddraw)) {
TRACE(ddraw," caps ");
_dump_DDSCAPS(lpddsd->dwCaps);
}
if (!(lpddsd->dwCaps & DDSCAPS_BACKBUFFER)) {
FIXME(ddraw,"whoops, can only handle backbuffers for now\n");
return E_FAIL;
}
/* FIXME: should handle more than one backbuffer */
*lpdsf = this->s.backbuffer;
if( this->s.backbuffer )
this->s.backbuffer->lpvtbl->fnAddRef( this->s.backbuffer );
return DD_OK;
}
static HRESULT WINAPI IDirectDrawSurface4_Initialize(
LPDIRECTDRAWSURFACE4 this,LPDIRECTDRAW ddraw,LPDDSURFACEDESC lpdsfd
) {
TRACE(ddraw,"(%p)->(%p, %p)\n",this,ddraw,lpdsfd);
return DDERR_ALREADYINITIALIZED;
}
static HRESULT WINAPI IDirectDrawSurface4_GetPixelFormat(
LPDIRECTDRAWSURFACE4 this,LPDDPIXELFORMAT pf
) {
TRACE(ddraw,"(%p)->(%p)\n",this,pf);
*pf = this->s.surface_desc.ddpfPixelFormat;
return DD_OK;
}
static HRESULT WINAPI IDirectDrawSurface4_GetBltStatus(LPDIRECTDRAWSURFACE4 this,DWORD dwFlags) {
FIXME(ddraw,"(%p)->(0x%08lx),stub!\n",this,dwFlags);
return DD_OK;
}
static HRESULT WINAPI IDirectDrawSurface4_GetOverlayPosition(
LPDIRECTDRAWSURFACE4 this,LPLONG x1,LPLONG x2
) {
FIXME(ddraw,"(%p)->(%p,%p),stub!\n",this,x1,x2);
return DD_OK;
}
static HRESULT WINAPI IDirectDrawSurface4_SetClipper(
LPDIRECTDRAWSURFACE4 this,LPDIRECTDRAWCLIPPER clipper
) {
FIXME(ddraw,"(%p)->(%p),stub!\n",this,clipper);
return DD_OK;
}
static HRESULT WINAPI IDirectDrawSurface4_AddAttachedSurface(
LPDIRECTDRAWSURFACE4 this,LPDIRECTDRAWSURFACE4 surf
) {
FIXME(ddraw,"(%p)->(%p),stub!\n",this,surf);
this->lpvtbl->fnAddRef(this);
/* This hack will be enough for the moment */
if (this->s.backbuffer == NULL)
this->s.backbuffer = surf;
return DD_OK;
}
static HRESULT WINAPI IDirectDrawSurface4_GetDC(LPDIRECTDRAWSURFACE4 this,HDC* lphdc) {
FIXME(ddraw,"(%p)->GetDC(%p)\n",this,lphdc);
*lphdc = BeginPaint(this->s.ddraw->d.window,&this->s.ddraw->d.ps);
return DD_OK;
}
static HRESULT WINAPI IDirectDrawSurface4_ReleaseDC(LPDIRECTDRAWSURFACE4 this,HDC hdc) {
DDSURFACEDESC desc;
DWORD x, y;
FIXME(ddraw,"(%p)->(0x%08lx),stub!\n",this,(long)hdc);
EndPaint(this->s.ddraw->d.window,&this->s.ddraw->d.ps);
/* Well, as what the application did paint in this DC is NOT saved in the surface,
I fill it with 'dummy' values to have something on the screen */
this->lpvtbl->fnLock(this,NULL,&desc,0,0);
for (y = 0; y < desc.dwHeight; y++) {
for (x = 0; x < desc.dwWidth; x++) {
((unsigned char *) desc.y.lpSurface)[x + y * desc.dwWidth] = (unsigned int) this + x + y;
}
}
this->lpvtbl->fnUnlock(this,NULL);
return DD_OK;
}
static HRESULT WINAPI IDirectDrawSurface4_QueryInterface(LPDIRECTDRAWSURFACE4 this,REFIID refiid,LPVOID *obj) {
char xrefiid[50];
WINE_StringFromCLSID((LPCLSID)refiid,xrefiid);
TRACE(ddraw,"(%p)->(%s,%p)\n",this,xrefiid,obj);
/* All DirectDrawSurface versions (1, 2, 3 and 4) use
* the same interface. And IUnknown does that too of course.
*/
if ( !memcmp(&IID_IDirectDrawSurface4,refiid,sizeof(IID)) ||
!memcmp(&IID_IDirectDrawSurface3,refiid,sizeof(IID)) ||
!memcmp(&IID_IDirectDrawSurface2,refiid,sizeof(IID)) ||
!memcmp(&IID_IDirectDrawSurface,refiid,sizeof(IID)) ||
!memcmp(&IID_IUnknown,refiid,sizeof(IID))
) {
*obj = this;
this->lpvtbl->fnAddRef(this);
TRACE(ddraw, " Creating IDirectDrawSurface interface (%p)\n", *obj);
return S_OK;
}
else if (!memcmp(&IID_IDirect3DTexture2,refiid,sizeof(IID)))
{
/* Texture interface */
*obj = d3dtexture2_create(this);
this->lpvtbl->fnAddRef(this);
TRACE(ddraw, " Creating IDirect3DTexture2 interface (%p)\n", *obj);
return S_OK;
}
else if (!memcmp(&IID_IDirect3DTexture,refiid,sizeof(IID)))
{
/* Texture interface */
*obj = d3dtexture_create(this);
this->lpvtbl->fnAddRef(this);
TRACE(ddraw, " Creating IDirect3DTexture interface (%p)\n", *obj);
return S_OK;
}
else if (is_OpenGL_dx3(refiid, (LPDIRECTDRAWSURFACE) this, (LPDIRECT3DDEVICE *) obj))
{
/* It is the OpenGL Direct3D Device */
this->lpvtbl->fnAddRef(this);
TRACE(ddraw, " Creating IDirect3DDevice interface (%p)\n", *obj);
return S_OK;
}
FIXME(ddraw,"(%p):interface for IID %s NOT found!\n",this,xrefiid);
return OLE_E_ENUM_NOMORE;
}
static HRESULT WINAPI IDirectDrawSurface4_IsLost(LPDIRECTDRAWSURFACE4 this) {
TRACE(ddraw,"(%p)->(), stub!\n",this);
return DD_OK; /* hmm */
}
static HRESULT WINAPI IDirectDrawSurface4_EnumAttachedSurfaces(LPDIRECTDRAWSURFACE4 this,LPVOID context,LPDDENUMSURFACESCALLBACK esfcb) {
FIXME(ddraw,"(%p)->(%p,%p),stub!\n",this,context,esfcb);
return DD_OK;
}
static HRESULT WINAPI IDirectDrawSurface4_Restore(LPDIRECTDRAWSURFACE4 this) {
FIXME(ddraw,"(%p)->(),stub!\n",this);
return DD_OK;
}
static HRESULT WINAPI IDirectDrawSurface4_SetColorKey(
LPDIRECTDRAWSURFACE4 this, DWORD dwFlags, LPDDCOLORKEY ckey )
{
TRACE(ddraw,"(%p)->(0x%08lx,%p)\n",this,dwFlags,ckey);
if( dwFlags & DDCKEY_SRCBLT )
{
dwFlags &= ~DDCKEY_SRCBLT;
this->s.surface_desc.dwFlags |= DDSD_CKSRCBLT;
memcpy( &(this->s.surface_desc.ddckCKSrcBlt), ckey, sizeof( *ckey ) );
}
if( dwFlags & DDCKEY_DESTBLT )
{
dwFlags &= ~DDCKEY_DESTBLT;
this->s.surface_desc.dwFlags |= DDSD_CKDESTBLT;
memcpy( &(this->s.surface_desc.ddckCKDestBlt), ckey, sizeof( *ckey ) );
}
if( dwFlags & DDCKEY_SRCOVERLAY )
{
dwFlags &= ~DDCKEY_SRCOVERLAY;
this->s.surface_desc.dwFlags |= DDSD_CKSRCOVERLAY;
memcpy( &(this->s.surface_desc.ddckCKSrcOverlay), ckey, sizeof( *ckey ) );
}
if( dwFlags & DDCKEY_DESTOVERLAY )
{
dwFlags &= ~DDCKEY_DESTOVERLAY;
this->s.surface_desc.dwFlags |= DDSD_CKDESTOVERLAY;
memcpy( &(this->s.surface_desc.ddckCKDestOverlay), ckey, sizeof( *ckey ) );
}
if( dwFlags )
{
FIXME( ddraw, "unhandled dwFlags: 0x%08lx\n", dwFlags );
}
return DD_OK;
}
static HRESULT WINAPI IDirectDrawSurface4_AddOverlayDirtyRect(
LPDIRECTDRAWSURFACE4 this,
LPRECT lpRect )
{
FIXME(ddraw,"(%p)->(%p),stub!\n",this,lpRect);
return DD_OK;
}
static HRESULT WINAPI IDirectDrawSurface4_DeleteAttachedSurface(
LPDIRECTDRAWSURFACE4 this,
DWORD dwFlags,
LPDIRECTDRAWSURFACE4 lpDDSAttachedSurface )
{
FIXME(ddraw,"(%p)->(0x%08lx,%p),stub!\n",this,dwFlags,lpDDSAttachedSurface);
return DD_OK;
}
static HRESULT WINAPI IDirectDrawSurface4_EnumOverlayZOrders(
LPDIRECTDRAWSURFACE4 this,
DWORD dwFlags,
LPVOID lpContext,
LPDDENUMSURFACESCALLBACK lpfnCallback )
{
FIXME(ddraw,"(%p)->(0x%08lx,%p,%p),stub!\n", this,dwFlags,
lpContext, lpfnCallback );
return DD_OK;
}
static HRESULT WINAPI IDirectDrawSurface4_GetClipper(
LPDIRECTDRAWSURFACE4 this,
LPDIRECTDRAWCLIPPER* lplpDDClipper )
{
FIXME(ddraw,"(%p)->(%p),stub!\n", this, lplpDDClipper);
return DD_OK;
}
static HRESULT WINAPI IDirectDrawSurface4_GetColorKey(
LPDIRECTDRAWSURFACE4 this,
DWORD dwFlags,
LPDDCOLORKEY lpDDColorKey )
{
TRACE(ddraw,"(%p)->(0x%08lx,%p)\n", this, dwFlags, lpDDColorKey);
if( dwFlags & DDCKEY_SRCBLT ) {
dwFlags &= ~DDCKEY_SRCBLT;
memcpy( lpDDColorKey, &(this->s.surface_desc.ddckCKSrcBlt), sizeof( *lpDDColorKey ) );
}
if( dwFlags & DDCKEY_DESTBLT )
{
dwFlags &= ~DDCKEY_DESTBLT;
memcpy( lpDDColorKey, &(this->s.surface_desc.ddckCKDestBlt), sizeof( *lpDDColorKey ) );
}
if( dwFlags & DDCKEY_SRCOVERLAY )
{
dwFlags &= ~DDCKEY_SRCOVERLAY;
memcpy( lpDDColorKey, &(this->s.surface_desc.ddckCKSrcOverlay), sizeof( *lpDDColorKey ) );
}
if( dwFlags & DDCKEY_DESTOVERLAY )
{
dwFlags &= ~DDCKEY_DESTOVERLAY;
memcpy( lpDDColorKey, &(this->s.surface_desc.ddckCKDestOverlay), sizeof( *lpDDColorKey ) );
}
if( dwFlags )
{
FIXME( ddraw, "unhandled dwFlags: 0x%08lx\n", dwFlags );
}
return DD_OK;
}
static HRESULT WINAPI IDirectDrawSurface4_GetFlipStatus(
LPDIRECTDRAWSURFACE4 this,
DWORD dwFlags )
{
FIXME(ddraw,"(%p)->(0x%08lx),stub!\n", this, dwFlags);
return DD_OK;
}
static HRESULT WINAPI IDirectDrawSurface4_GetPalette(
LPDIRECTDRAWSURFACE4 this,
LPDIRECTDRAWPALETTE* lplpDDPalette )
{
FIXME(ddraw,"(%p)->(%p),stub!\n", this, lplpDDPalette);
return DD_OK;
}
static HRESULT WINAPI IDirectDrawSurface4_SetOverlayPosition(
LPDIRECTDRAWSURFACE4 this,
LONG lX,
LONG lY)
{
FIXME(ddraw,"(%p)->(%ld,%ld),stub!\n", this, lX, lY);
return DD_OK;
}
static HRESULT WINAPI IDirectDrawSurface4_UpdateOverlay(
LPDIRECTDRAWSURFACE4 this,
LPRECT lpSrcRect,
LPDIRECTDRAWSURFACE4 lpDDDestSurface,
LPRECT lpDestRect,
DWORD dwFlags,
LPDDOVERLAYFX lpDDOverlayFx )
{
FIXME(ddraw,"(%p)->(%p,%p,%p,0x%08lx,%p),stub!\n", this,
lpSrcRect, lpDDDestSurface, lpDestRect, dwFlags, lpDDOverlayFx );
return DD_OK;
}
static HRESULT WINAPI IDirectDrawSurface4_UpdateOverlayDisplay(
LPDIRECTDRAWSURFACE4 this,
DWORD dwFlags )
{
FIXME(ddraw,"(%p)->(0x%08lx),stub!\n", this, dwFlags);
return DD_OK;
}
static HRESULT WINAPI IDirectDrawSurface4_UpdateOverlayZOrder(
LPDIRECTDRAWSURFACE4 this,
DWORD dwFlags,
LPDIRECTDRAWSURFACE4 lpDDSReference )
{
FIXME(ddraw,"(%p)->(0x%08lx,%p),stub!\n", this, dwFlags, lpDDSReference);
return DD_OK;
}
static HRESULT WINAPI IDirectDrawSurface4_GetDDInterface(
LPDIRECTDRAWSURFACE4 this,
LPVOID* lplpDD )
{
FIXME(ddraw,"(%p)->(%p),stub!\n", this, lplpDD);
/* Not sure about that... */
*lplpDD = (void *) this->s.ddraw;
return DD_OK;
}
static HRESULT WINAPI IDirectDrawSurface4_PageLock(
LPDIRECTDRAWSURFACE4 this,
DWORD dwFlags )
{
FIXME(ddraw,"(%p)->(0x%08lx),stub!\n", this, dwFlags);
return DD_OK;
}
static HRESULT WINAPI IDirectDrawSurface4_PageUnlock(
LPDIRECTDRAWSURFACE4 this,
DWORD dwFlags )
{
FIXME(ddraw,"(%p)->(0x%08lx),stub!\n", this, dwFlags);
return DD_OK;
}
static HRESULT WINAPI IDirectDrawSurface4_SetSurfaceDesc(
LPDIRECTDRAWSURFACE4 this,
LPDDSURFACEDESC lpDDSD,
DWORD dwFlags )
{
FIXME(ddraw,"(%p)->(%p,0x%08lx),stub!\n", this, lpDDSD, dwFlags);
return DD_OK;
}
static HRESULT WINAPI IDirectDrawSurface4_SetPrivateData(LPDIRECTDRAWSURFACE4 this,
REFGUID guidTag,
LPVOID lpData,
DWORD cbSize,
DWORD dwFlags) {
FIXME(ddraw, "(%p)->(%p,%p,%ld,%08lx\n", this, guidTag, lpData, cbSize, dwFlags);
return DD_OK;
}
static HRESULT WINAPI IDirectDrawSurface4_GetPrivateData(LPDIRECTDRAWSURFACE4 this,
REFGUID guidTag,
LPVOID lpBuffer,
LPDWORD lpcbBufferSize) {
FIXME(ddraw, "(%p)->(%p,%p,%p)\n", this, guidTag, lpBuffer, lpcbBufferSize);
return DD_OK;
}
static HRESULT WINAPI IDirectDrawSurface4_FreePrivateData(LPDIRECTDRAWSURFACE4 this,
REFGUID guidTag) {
FIXME(ddraw, "(%p)->(%p)\n", this, guidTag);
return DD_OK;
}
static HRESULT WINAPI IDirectDrawSurface4_GetUniquenessValue(LPDIRECTDRAWSURFACE4 this,
LPDWORD lpValue) {
FIXME(ddraw, "(%p)->(%p)\n", this, lpValue);
return DD_OK;
}
static HRESULT WINAPI IDirectDrawSurface4_ChangeUniquenessValue(LPDIRECTDRAWSURFACE4 this) {
FIXME(ddraw, "(%p)\n", this);
return DD_OK;
}
static struct IDirectDrawSurface4_VTable dga_dds4vt = {
IDirectDrawSurface4_QueryInterface,
IDirectDrawSurface4_AddRef,
DGA_IDirectDrawSurface4_Release,
IDirectDrawSurface4_AddAttachedSurface,
IDirectDrawSurface4_AddOverlayDirtyRect,
IDirectDrawSurface4_Blt,
IDirectDrawSurface4_BltBatch,
IDirectDrawSurface4_BltFast,
IDirectDrawSurface4_DeleteAttachedSurface,
IDirectDrawSurface4_EnumAttachedSurfaces,
IDirectDrawSurface4_EnumOverlayZOrders,
DGA_IDirectDrawSurface4_Flip,
IDirectDrawSurface4_GetAttachedSurface,
IDirectDrawSurface4_GetBltStatus,
IDirectDrawSurface4_GetCaps,
IDirectDrawSurface4_GetClipper,
IDirectDrawSurface4_GetColorKey,
IDirectDrawSurface4_GetDC,
IDirectDrawSurface4_GetFlipStatus,
IDirectDrawSurface4_GetOverlayPosition,
IDirectDrawSurface4_GetPalette,
IDirectDrawSurface4_GetPixelFormat,
IDirectDrawSurface4_GetSurfaceDesc,
IDirectDrawSurface4_Initialize,
IDirectDrawSurface4_IsLost,
IDirectDrawSurface4_Lock,
IDirectDrawSurface4_ReleaseDC,
IDirectDrawSurface4_Restore,
IDirectDrawSurface4_SetClipper,
IDirectDrawSurface4_SetColorKey,
IDirectDrawSurface4_SetOverlayPosition,
DGA_IDirectDrawSurface4_SetPalette,
DGA_IDirectDrawSurface4_Unlock,
IDirectDrawSurface4_UpdateOverlay,
IDirectDrawSurface4_UpdateOverlayDisplay,
IDirectDrawSurface4_UpdateOverlayZOrder,
IDirectDrawSurface4_GetDDInterface,
IDirectDrawSurface4_PageLock,
IDirectDrawSurface4_PageUnlock,
IDirectDrawSurface4_SetSurfaceDesc,
IDirectDrawSurface4_SetPrivateData,
IDirectDrawSurface4_GetPrivateData,
IDirectDrawSurface4_FreePrivateData,
IDirectDrawSurface4_GetUniquenessValue,
IDirectDrawSurface4_ChangeUniquenessValue
};
static struct IDirectDrawSurface4_VTable xlib_dds4vt = {
IDirectDrawSurface4_QueryInterface,
IDirectDrawSurface4_AddRef,
Xlib_IDirectDrawSurface4_Release,
IDirectDrawSurface4_AddAttachedSurface,
IDirectDrawSurface4_AddOverlayDirtyRect,
IDirectDrawSurface4_Blt,
IDirectDrawSurface4_BltBatch,
IDirectDrawSurface4_BltFast,
IDirectDrawSurface4_DeleteAttachedSurface,
IDirectDrawSurface4_EnumAttachedSurfaces,
IDirectDrawSurface4_EnumOverlayZOrders,
Xlib_IDirectDrawSurface4_Flip,
IDirectDrawSurface4_GetAttachedSurface,
IDirectDrawSurface4_GetBltStatus,
IDirectDrawSurface4_GetCaps,
IDirectDrawSurface4_GetClipper,
IDirectDrawSurface4_GetColorKey,
IDirectDrawSurface4_GetDC,
IDirectDrawSurface4_GetFlipStatus,
IDirectDrawSurface4_GetOverlayPosition,
IDirectDrawSurface4_GetPalette,
IDirectDrawSurface4_GetPixelFormat,
IDirectDrawSurface4_GetSurfaceDesc,
IDirectDrawSurface4_Initialize,
IDirectDrawSurface4_IsLost,
IDirectDrawSurface4_Lock,
IDirectDrawSurface4_ReleaseDC,
IDirectDrawSurface4_Restore,
IDirectDrawSurface4_SetClipper,
IDirectDrawSurface4_SetColorKey,
IDirectDrawSurface4_SetOverlayPosition,
Xlib_IDirectDrawSurface4_SetPalette,
Xlib_IDirectDrawSurface4_Unlock,
IDirectDrawSurface4_UpdateOverlay,
IDirectDrawSurface4_UpdateOverlayDisplay,
IDirectDrawSurface4_UpdateOverlayZOrder,
IDirectDrawSurface4_GetDDInterface,
IDirectDrawSurface4_PageLock,
IDirectDrawSurface4_PageUnlock,
IDirectDrawSurface4_SetSurfaceDesc,
IDirectDrawSurface4_SetPrivateData,
IDirectDrawSurface4_GetPrivateData,
IDirectDrawSurface4_FreePrivateData,
IDirectDrawSurface4_GetUniquenessValue,
IDirectDrawSurface4_ChangeUniquenessValue
};
/******************************************************************************
* DirectDrawCreateClipper (DDRAW.7)
*/
HRESULT WINAPI DirectDrawCreateClipper( DWORD dwFlags,
LPDIRECTDRAWCLIPPER *lplpDDClipper,
LPUNKNOWN pUnkOuter)
{
TRACE(ddraw, "(%08lx,%p,%p)\n", dwFlags, lplpDDClipper, pUnkOuter);
*lplpDDClipper = (LPDIRECTDRAWCLIPPER)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawClipper));
(*lplpDDClipper)->lpvtbl = &ddclipvt;
(*lplpDDClipper)->ref = 1;
return DD_OK;
}
/******************************************************************************
* IDirectDrawClipper
*/
static HRESULT WINAPI IDirectDrawClipper_SetHwnd(
LPDIRECTDRAWCLIPPER this,DWORD x,HWND hwnd
) {
FIXME(ddraw,"(%p)->SetHwnd(0x%08lx,0x%08lx),stub!\n",this,x,(DWORD)hwnd);
return DD_OK;
}
static ULONG WINAPI IDirectDrawClipper_Release(LPDIRECTDRAWCLIPPER this) {
TRACE( ddraw, "(%p)->() decrementing from %lu.\n", this, this->ref );
this->ref--;
if (this->ref)
return this->ref;
HeapFree(GetProcessHeap(),0,this);
return 0;
}
static HRESULT WINAPI IDirectDrawClipper_GetClipList(
LPDIRECTDRAWCLIPPER this,LPRECT rects,LPRGNDATA lprgn,LPDWORD hmm
) {
FIXME(ddraw,"(%p,%p,%p,%p),stub!\n",this,rects,lprgn,hmm);
if (hmm) *hmm=0;
return DD_OK;
}
static HRESULT WINAPI IDirectDrawClipper_SetClipList(
LPDIRECTDRAWCLIPPER this,LPRGNDATA lprgn,DWORD hmm
) {
FIXME(ddraw,"(%p,%p,%ld),stub!\n",this,lprgn,hmm);
return DD_OK;
}
static HRESULT WINAPI IDirectDrawClipper_QueryInterface(
LPDIRECTDRAWCLIPPER this,
REFIID riid,
LPVOID* ppvObj )
{
FIXME(ddraw,"(%p)->(%p,%p),stub!\n",this,riid,ppvObj);
return OLE_E_ENUM_NOMORE;
}
static ULONG WINAPI IDirectDrawClipper_AddRef( LPDIRECTDRAWCLIPPER this )
{
TRACE( ddraw, "(%p)->() incrementing from %lu.\n", this, this->ref );
return ++(this->ref);
}
static HRESULT WINAPI IDirectDrawClipper_GetHWnd(
LPDIRECTDRAWCLIPPER this,
HWND* HWndPtr )
{
FIXME(ddraw,"(%p)->(%p),stub!\n",this,HWndPtr);
return DD_OK;
}
static HRESULT WINAPI IDirectDrawClipper_Initialize(
LPDIRECTDRAWCLIPPER this,
LPDIRECTDRAW lpDD,
DWORD dwFlags )
{
FIXME(ddraw,"(%p)->(%p,0x%08lx),stub!\n",this,lpDD,dwFlags);
return DD_OK;
}
static HRESULT WINAPI IDirectDrawClipper_IsClipListChanged(
LPDIRECTDRAWCLIPPER this,
BOOL* lpbChanged )
{
FIXME(ddraw,"(%p)->(%p),stub!\n",this,lpbChanged);
return DD_OK;
}
static struct IDirectDrawClipper_VTable ddclipvt = {
IDirectDrawClipper_QueryInterface,
IDirectDrawClipper_AddRef,
IDirectDrawClipper_Release,
IDirectDrawClipper_GetClipList,
IDirectDrawClipper_GetHWnd,
IDirectDrawClipper_Initialize,
IDirectDrawClipper_IsClipListChanged,
IDirectDrawClipper_SetClipList,
IDirectDrawClipper_SetHwnd
};
/******************************************************************************
* IDirectDrawPalette
*/
static HRESULT WINAPI IDirectDrawPalette_GetEntries(
LPDIRECTDRAWPALETTE this,DWORD x,DWORD start,DWORD count,LPPALETTEENTRY palent
) {
int i;
TRACE(ddraw,"(%p)->GetEntries(%08lx,%ld,%ld,%p)\n",
this,x,start,count,palent);
if (!this->cm) /* should not happen */ {
FIXME(ddraw,"app tried to read colormap for non-palettized mode\n");
return DDERR_GENERIC;
}
for (i=0;i<count;i++) {
palent[i].peRed = this->palents[start+i].peRed;
palent[i].peBlue = this->palents[start+i].peBlue;
palent[i].peGreen = this->palents[start+i].peGreen;
palent[i].peFlags = this->palents[start+i].peFlags;
}
return DD_OK;
}
static HRESULT WINAPI Xlib_IDirectDrawPalette_SetEntries(
LPDIRECTDRAWPALETTE this,DWORD x,DWORD start,DWORD count,LPPALETTEENTRY palent
) {
XColor xc;
int i;
TRACE(ddraw,"(%p)->SetEntries(%08lx,%ld,%ld,%p)\n",
this,x,start,count,palent
);
for (i=0;i<count;i++) {
xc.red = palent[i].peRed<<8;
xc.blue = palent[i].peBlue<<8;
xc.green = palent[i].peGreen<<8;
xc.flags = DoRed|DoBlue|DoGreen;
xc.pixel = start+i;
if (this->cm)
TSXStoreColor(display,this->cm,&xc);
this->palents[start+i].peRed = palent[i].peRed;
this->palents[start+i].peBlue = palent[i].peBlue;
this->palents[start+i].peGreen = palent[i].peGreen;
this->palents[start+i].peFlags = palent[i].peFlags;
}
/* Now, if we are in 'depth conversion mode', update the screen palette */
if (this->ddraw->d.palette_convert != NULL)
this->ddraw->d.palette_convert(palent, this->screen_palents, start, count);
return DD_OK;
}
static HRESULT WINAPI DGA_IDirectDrawPalette_SetEntries(
LPDIRECTDRAWPALETTE this,DWORD x,DWORD start,DWORD count,LPPALETTEENTRY palent
) {
#ifdef HAVE_LIBXXF86DGA
XColor xc;
Colormap cm;
int i;
TRACE(ddraw,"(%p)->SetEntries(%08lx,%ld,%ld,%p)\n",
this,x,start,count,palent
);
if (!this->cm) /* should not happen */ {
FIXME(ddraw,"app tried to set colormap in non-palettized mode\n");
return DDERR_GENERIC;
}
/* FIXME: free colorcells instead of freeing whole map */
cm = this->cm;
this->cm = TSXCopyColormapAndFree(display,this->cm);
TSXFreeColormap(display,cm);
for (i=0;i<count;i++) {
xc.red = palent[i].peRed<<8;
xc.blue = palent[i].peBlue<<8;
xc.green = palent[i].peGreen<<8;
xc.flags = DoRed|DoBlue|DoGreen;
xc.pixel = i+start;
TSXStoreColor(display,this->cm,&xc);
this->palents[start+i].peRed = palent[i].peRed;
this->palents[start+i].peBlue = palent[i].peBlue;
this->palents[start+i].peGreen = palent[i].peGreen;
this->palents[start+i].peFlags = palent[i].peFlags;
}
TSXF86DGAInstallColormap(display,DefaultScreen(display),this->cm);
return DD_OK;
#else /* defined(HAVE_LIBXXF86DGA) */
return E_UNEXPECTED;
#endif /* defined(HAVE_LIBXXF86DGA) */
}
static ULONG WINAPI IDirectDrawPalette_Release(LPDIRECTDRAWPALETTE this) {
TRACE( ddraw, "(%p)->() decrementing from %lu.\n", this, this->ref );
if (!--(this->ref)) {
if (this->cm) {
TSXFreeColormap(display,this->cm);
this->cm = 0;
}
HeapFree(GetProcessHeap(),0,this);
return 0;
}
return this->ref;
}
static ULONG WINAPI IDirectDrawPalette_AddRef(LPDIRECTDRAWPALETTE this) {
TRACE( ddraw, "(%p)->() incrementing from %lu.\n", this, this->ref );
return ++(this->ref);
}
static HRESULT WINAPI IDirectDrawPalette_Initialize(
LPDIRECTDRAWPALETTE this,LPDIRECTDRAW ddraw,DWORD x,LPPALETTEENTRY palent
) {
TRACE(ddraw,"(%p)->(%p,%ld,%p)\n", this, ddraw, x, palent);
return DDERR_ALREADYINITIALIZED;
}
static HRESULT WINAPI IDirectDrawPalette_GetCaps(
LPDIRECTDRAWPALETTE this, LPDWORD lpdwCaps )
{
FIXME( ddraw, "(%p)->(%p) stub.\n", this, lpdwCaps );
return DD_OK;
}
static HRESULT WINAPI IDirectDrawPalette_QueryInterface(
LPDIRECTDRAWPALETTE this,REFIID refiid,LPVOID *obj )
{
char xrefiid[50];
WINE_StringFromCLSID((LPCLSID)refiid,xrefiid);
FIXME(ddraw,"(%p)->(%s,%p) stub.\n",this,xrefiid,obj);
return S_OK;
}
static struct IDirectDrawPalette_VTable dga_ddpalvt = {
IDirectDrawPalette_QueryInterface,
IDirectDrawPalette_AddRef,
IDirectDrawPalette_Release,
IDirectDrawPalette_GetCaps,
IDirectDrawPalette_GetEntries,
IDirectDrawPalette_Initialize,
DGA_IDirectDrawPalette_SetEntries
};
static struct IDirectDrawPalette_VTable xlib_ddpalvt = {
IDirectDrawPalette_QueryInterface,
IDirectDrawPalette_AddRef,
IDirectDrawPalette_Release,
IDirectDrawPalette_GetCaps,
IDirectDrawPalette_GetEntries,
IDirectDrawPalette_Initialize,
Xlib_IDirectDrawPalette_SetEntries
};
/*******************************************************************************
* IDirect3D
*/
static HRESULT WINAPI IDirect3D_QueryInterface(
LPDIRECT3D this,REFIID refiid,LPVOID *obj
) {
/* FIXME: Not sure if this is correct */
char xrefiid[50];
WINE_StringFromCLSID((LPCLSID)refiid,xrefiid);
TRACE(ddraw,"(%p)->(%s,%p)\n",this,xrefiid,obj);
if (!memcmp(&IID_IUnknown,refiid,sizeof(IID_IUnknown))) {
*obj = this;
this->lpvtbl->fnAddRef(this);
TRACE(ddraw, " Creating IUnknown interface (%p)\n", *obj);
return S_OK;
}
if (!memcmp(&IID_IDirect3D,refiid,sizeof(IID_IDirect3D))) {
LPDIRECT3D d3d;
d3d = HeapAlloc(GetProcessHeap(),0,sizeof(*d3d));
d3d->ref = 1;
d3d->ddraw = (LPDIRECTDRAW)this;
this->lpvtbl->fnAddRef(this);
d3d->lpvtbl = &d3dvt;
*obj = d3d;
TRACE(ddraw, " Creating IDirect3D interface (%p)\n", *obj);
return S_OK;
}
if (!memcmp(&IID_IDirect3D2,refiid,sizeof(IID_IDirect3D2))) {
LPDIRECT3D2 d3d;
d3d = HeapAlloc(GetProcessHeap(),0,sizeof(*d3d));
d3d->ref = 1;
d3d->ddraw = (LPDIRECTDRAW)this;
this->lpvtbl->fnAddRef(this);
d3d->lpvtbl = &d3d2vt;
*obj = d3d;
TRACE(ddraw, " Creating IDirect3D2 interface (%p)\n", *obj);
return S_OK;
}
FIXME(ddraw,"(%p):interface for IID %s NOT found!\n",this,xrefiid);
return OLE_E_ENUM_NOMORE;
}
static ULONG WINAPI IDirect3D_AddRef(LPDIRECT3D this) {
TRACE( ddraw, "(%p)->() incrementing from %lu.\n", this, this->ref );
return ++(this->ref);
}
static ULONG WINAPI IDirect3D_Release(LPDIRECT3D this)
{
TRACE( ddraw, "(%p)->() decrementing from %lu.\n", this, this->ref );
if (!--(this->ref)) {
this->ddraw->lpvtbl->fnRelease(this->ddraw);
HeapFree(GetProcessHeap(),0,this);
return 0;
}
return this->ref;
}
static HRESULT WINAPI IDirect3D_Initialize(
LPDIRECT3D this, REFIID refiid )
{
/* FIXME: Not sure if this is correct */
char xrefiid[50];
WINE_StringFromCLSID((LPCLSID)refiid,xrefiid);
FIXME(ddraw,"(%p)->(%s):stub.\n",this,xrefiid);
return DDERR_ALREADYINITIALIZED;
}
static HRESULT WINAPI IDirect3D_EnumDevices(LPDIRECT3D this,
LPD3DENUMDEVICESCALLBACK cb,
LPVOID context) {
FIXME(ddraw,"(%p)->(%p,%p),stub!\n",this,cb,context);
/* Call functions defined in d3ddevices.c */
if (!d3d_OpenGL_dx3(cb, context))
return DD_OK;
return DD_OK;
}
static HRESULT WINAPI IDirect3D_CreateLight(LPDIRECT3D this,
LPDIRECT3DLIGHT *lplight,
IUnknown *lpunk)
{
TRACE(ddraw, "(%p)->(%p,%p): stub\n", this, lplight, lpunk);
/* Call the creation function that is located in d3dlight.c */
*lplight = d3dlight_create_dx3(this);
return DD_OK;
}
static HRESULT WINAPI IDirect3D_CreateMaterial(LPDIRECT3D this,
LPDIRECT3DMATERIAL *lpmaterial,
IUnknown *lpunk)
{
TRACE(ddraw, "(%p)->(%p,%p): stub\n", this, lpmaterial, lpunk);
/* Call the creation function that is located in d3dviewport.c */
*lpmaterial = d3dmaterial_create(this);
return DD_OK;
}
static HRESULT WINAPI IDirect3D_CreateViewport(LPDIRECT3D this,
LPDIRECT3DVIEWPORT *lpviewport,
IUnknown *lpunk)
{
TRACE(ddraw, "(%p)->(%p,%p): stub\n", this, lpviewport, lpunk);
/* Call the creation function that is located in d3dviewport.c */
*lpviewport = d3dviewport_create(this);
return DD_OK;
}
static HRESULT WINAPI IDirect3D_FindDevice(LPDIRECT3D this,
LPD3DFINDDEVICESEARCH lpfinddevsrc,
LPD3DFINDDEVICERESULT lpfinddevrst)
{
TRACE(ddraw, "(%p)->(%p,%p): stub\n", this, lpfinddevsrc, lpfinddevrst);
return DD_OK;
}
static struct IDirect3D_VTable d3dvt = {
IDirect3D_QueryInterface,
IDirect3D_AddRef,
IDirect3D_Release,
IDirect3D_Initialize,
IDirect3D_EnumDevices,
IDirect3D_CreateLight,
IDirect3D_CreateMaterial,
IDirect3D_CreateViewport,
IDirect3D_FindDevice
};
/*******************************************************************************
* IDirect3D2
*/
static HRESULT WINAPI IDirect3D2_QueryInterface(
LPDIRECT3D2 this,REFIID refiid,LPVOID *obj) {
/* For the moment, we use the same function as in IDirect3D */
TRACE(ddraw, "Calling IDirect3D enumerating function.\n");
return IDirect3D_QueryInterface((LPDIRECT3D) this, refiid, obj);
}
static ULONG WINAPI IDirect3D2_AddRef(LPDIRECT3D2 this) {
TRACE( ddraw, "(%p)->() incrementing from %lu.\n", this, this->ref );
return ++(this->ref);
}
static ULONG WINAPI IDirect3D2_Release(LPDIRECT3D2 this) {
TRACE( ddraw, "(%p)->() decrementing from %lu.\n", this, this->ref );
if (!--(this->ref)) {
this->ddraw->lpvtbl->fnRelease(this->ddraw);
HeapFree(GetProcessHeap(),0,this);
return 0;
}
return this->ref;
}
static HRESULT WINAPI IDirect3D2_EnumDevices(
LPDIRECT3D2 this,LPD3DENUMDEVICESCALLBACK cb, LPVOID context
) {
FIXME(ddraw,"(%p)->(%p,%p),stub!\n",this,cb,context);
/* Call functions defined in d3ddevices.c */
if (!d3d_OpenGL(cb, context))
return DD_OK;
return DD_OK;
}
static HRESULT WINAPI IDirect3D2_CreateLight(LPDIRECT3D2 this,
LPDIRECT3DLIGHT *lplight,
IUnknown *lpunk)
{
TRACE(ddraw, "(%p)->(%p,%p): stub\n", this, lplight, lpunk);
/* Call the creation function that is located in d3dlight.c */
*lplight = d3dlight_create(this);
return DD_OK;
}
static HRESULT WINAPI IDirect3D2_CreateMaterial(LPDIRECT3D2 this,
LPDIRECT3DMATERIAL2 *lpmaterial,
IUnknown *lpunk)
{
TRACE(ddraw, "(%p)->(%p,%p): stub\n", this, lpmaterial, lpunk);
/* Call the creation function that is located in d3dviewport.c */
*lpmaterial = d3dmaterial2_create(this);
return DD_OK;
}
static HRESULT WINAPI IDirect3D2_CreateViewport(LPDIRECT3D2 this,
LPDIRECT3DVIEWPORT2 *lpviewport,
IUnknown *lpunk)
{
TRACE(ddraw, "(%p)->(%p,%p): stub\n", this, lpviewport, lpunk);
/* Call the creation function that is located in d3dviewport.c */
*lpviewport = d3dviewport2_create(this);
return DD_OK;
}
static HRESULT WINAPI IDirect3D2_FindDevice(LPDIRECT3D2 this,
LPD3DFINDDEVICESEARCH lpfinddevsrc,
LPD3DFINDDEVICERESULT lpfinddevrst)
{
TRACE(ddraw, "(%p)->(%p,%p): stub\n", this, lpfinddevsrc, lpfinddevrst);
return DD_OK;
}
static HRESULT WINAPI IDirect3D2_CreateDevice(LPDIRECT3D2 this,
REFCLSID rguid,
LPDIRECTDRAWSURFACE surface,
LPDIRECT3DDEVICE2 *device)
{
char xbuf[50];
WINE_StringFromCLSID(rguid,xbuf);
FIXME(ddraw,"(%p)->(%s,%p,%p): stub\n",this,xbuf,surface,device);
if (is_OpenGL(rguid, surface, device, this)) {
this->lpvtbl->fnAddRef(this);
return DD_OK;
}
return DDERR_INVALIDPARAMS;
}
static struct IDirect3D2_VTable d3d2vt = {
IDirect3D2_QueryInterface,
IDirect3D2_AddRef,
IDirect3D2_Release,
IDirect3D2_EnumDevices,
IDirect3D2_CreateLight,
IDirect3D2_CreateMaterial,
IDirect3D2_CreateViewport,
IDirect3D2_FindDevice,
IDirect3D2_CreateDevice
};
/*******************************************************************************
* IDirectDraw
*/
/* Used in conjunction with cbWndExtra for storage of the this ptr for the window.
* Please adjust allocation in Xlib_DirectDrawCreate if you store more data here.
*/
static INT ddrawXlibThisOffset = 0;
static HRESULT common_off_screen_CreateSurface(LPDIRECTDRAW2 this,
LPDDSURFACEDESC lpddsd,
LPDIRECTDRAWSURFACE lpdsf)
{
int bpp;
/* The surface was already allocated when entering in this function */
TRACE(ddraw,"using system memory for a surface (%p)\n", lpdsf);
if (lpddsd->dwFlags & DDSD_ZBUFFERBITDEPTH) {
/* This is a Z Buffer */
TRACE(ddraw, "Creating Z-Buffer of %ld bit depth\n", lpddsd->x.dwZBufferBitDepth);
bpp = lpddsd->x.dwZBufferBitDepth / 8;
} else {
/* This is a standard image */
if (!(lpddsd->dwFlags & DDSD_PIXELFORMAT)) {
/* No pixel format => use DirectDraw's format */
lpddsd->ddpfPixelFormat = this->d.directdraw_pixelformat;
lpddsd->dwFlags |= DDSD_PIXELFORMAT;
} else {
/* To check what the program wants */
if (TRACE_ON(ddraw)) {
_dump_pixelformat(&(lpddsd->ddpfPixelFormat));
}
}
if (lpddsd->ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
bpp = 1;
} else {
bpp = lpddsd->ddpfPixelFormat.x.dwRGBBitCount / 8;
}
}
/* Copy the surface description */
lpdsf->s.surface_desc = *lpddsd;
lpdsf->s.surface_desc.dwFlags |= DDSD_WIDTH|DDSD_HEIGHT|DDSD_PITCH|DDSD_LPSURFACE;
lpdsf->s.surface_desc.y.lpSurface = (LPBYTE)HeapAlloc(GetProcessHeap(),0,lpddsd->dwWidth * lpddsd->dwHeight * bpp);
lpdsf->s.surface_desc.lPitch = lpddsd->dwWidth * bpp;
return DD_OK;
}
static HRESULT WINAPI DGA_IDirectDraw2_CreateSurface(
LPDIRECTDRAW2 this,LPDDSURFACEDESC lpddsd,LPDIRECTDRAWSURFACE *lpdsf,IUnknown *lpunk
) {
#ifdef HAVE_LIBXXF86DGA
int i;
TRACE(ddraw, "(%p)->(%p,%p,%p)\n",this,lpddsd,lpdsf,lpunk);
if (TRACE_ON(ddraw)) {
DUMP(" w=%ld,h=%ld,flags ",lpddsd->dwWidth,lpddsd->dwHeight);
_dump_DDSD(lpddsd->dwFlags);
DUMP(" caps ");
_dump_DDSCAPS(lpddsd->ddsCaps.dwCaps);
}
*lpdsf = (LPDIRECTDRAWSURFACE)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawSurface));
this->lpvtbl->fnAddRef(this);
(*lpdsf)->ref = 1;
(*lpdsf)->lpvtbl = (LPDIRECTDRAWSURFACE_VTABLE)&dga_dds4vt;
(*lpdsf)->s.ddraw = this;
(*lpdsf)->s.palette = NULL;
(*lpdsf)->t.dga.fb_height = -1; /* This is to have non-on screen surfaces freed */
if (!(lpddsd->dwFlags & DDSD_WIDTH))
lpddsd->dwWidth = this->d.width;
if (!(lpddsd->dwFlags & DDSD_HEIGHT))
lpddsd->dwHeight = this->d.height;
/* Check if this a 'primary surface' or not */
if ((lpddsd->dwFlags & DDSD_CAPS) &&
(lpddsd->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)) {
/* This is THE primary surface => there is DGA-specific code */
/* First, store the surface description */
(*lpdsf)->s.surface_desc = *lpddsd;
/* Find a viewport */
for (i=0;i<32;i++)
if (!(this->e.dga.vpmask & (1<<i)))
break;
TRACE(ddraw,"using viewport %d for a primary surface\n",i);
/* if i == 32 or maximum ... return error */
this->e.dga.vpmask|=(1<<i);
(*lpdsf)->s.surface_desc.y.lpSurface =
this->e.dga.fb_addr+((i*this->e.dga.fb_height)*this->e.dga.fb_width*this->d.directdraw_pixelformat.x.dwRGBBitCount/8);
(*lpdsf)->t.dga.fb_height = i*this->e.dga.fb_height;
(*lpdsf)->s.surface_desc.lPitch = this->e.dga.fb_width*this->d.directdraw_pixelformat.x.dwRGBBitCount/8;
lpddsd->lPitch = (*lpdsf)->s.surface_desc.lPitch;
/* Add flags if there were not present */
(*lpdsf)->s.surface_desc.dwFlags |= DDSD_WIDTH|DDSD_HEIGHT|DDSD_PITCH|DDSD_LPSURFACE|DDSD_PIXELFORMAT;
(*lpdsf)->s.surface_desc.dwWidth = this->d.width;
(*lpdsf)->s.surface_desc.dwHeight = this->d.height;
TRACE(ddraw,"primary surface: dwWidth=%ld, dwHeight=%ld, lPitch=%ld\n",this->d.width,this->d.height,lpddsd->lPitch);
/* We put our surface always in video memory */
(*lpdsf)->s.surface_desc.ddsCaps.dwCaps |= DDSCAPS_VISIBLE|DDSCAPS_VIDEOMEMORY;
(*lpdsf)->s.surface_desc.ddpfPixelFormat = this->d.directdraw_pixelformat;
(*lpdsf)->s.backbuffer = NULL;
if (lpddsd->dwFlags & DDSD_BACKBUFFERCOUNT) {
LPDIRECTDRAWSURFACE4 back;
if (lpddsd->dwBackBufferCount>1)
FIXME(ddraw,"urks, wants to have more than one backbuffer (%ld)!\n",lpddsd->dwBackBufferCount);
(*lpdsf)->s.backbuffer = back =
(LPDIRECTDRAWSURFACE4)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawSurface4));
this->lpvtbl->fnAddRef(this);
back->ref = 1;
back->lpvtbl = (LPDIRECTDRAWSURFACE4_VTABLE)&dga_dds4vt;
for (i=0;i<32;i++)
if (!(this->e.dga.vpmask & (1<<i)))
break;
TRACE(ddraw,"using viewport %d for backbuffer\n",i);
/* if i == 32 or maximum ... return error */
this->e.dga.vpmask|=(1<<i);
back->t.dga.fb_height = i*this->e.dga.fb_height;
/* Copy the surface description from the front buffer */
back->s.surface_desc = (*lpdsf)->s.surface_desc;
/* Change the parameters that are not the same */
back->s.surface_desc.y.lpSurface = this->e.dga.fb_addr+
((i*this->e.dga.fb_height)*this->e.dga.fb_width*this->d.directdraw_pixelformat.x.dwRGBBitCount/8);
back->s.ddraw = this;
back->s.backbuffer = NULL; /* does not have a backbuffer, it is
* one! */
/* Add relevant info to front and back buffers */
(*lpdsf)->s.surface_desc.ddsCaps.dwCaps |= DDSCAPS_FRONTBUFFER;
back->s.surface_desc.ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER;
back->s.surface_desc.dwFlags &= ~DDSD_BACKBUFFERCOUNT;
back->s.surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_VISIBLE;
back->s.surface_desc.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
}
} else {
/* There is no DGA-specific code here...
Go to the common surface creation function */
return common_off_screen_CreateSurface(this, lpddsd, *lpdsf);
}
return DD_OK;
#else /* defined(HAVE_LIBXXF86DGA) */
return E_UNEXPECTED;
#endif /* defined(HAVE_LIBXXF86DGA) */
}
#ifdef HAVE_LIBXXSHM
/* Error handlers for Image creation */
static int XShmErrorHandler(Display *dpy, XErrorEvent *event) {
XShmErrorFlag = 1;
return 0;
}
static XImage *create_xshmimage(LPDIRECTDRAW2 this, LPDIRECTDRAWSURFACE4 lpdsf) {
XImage *img;
int (*WineXHandler)(Display *, XErrorEvent *);
img = TSXShmCreateImage(display,
DefaultVisualOfScreen(X11DRV_GetXScreen()),
this->d.pixmap_depth,
ZPixmap,
NULL,
&(lpdsf->t.xlib.shminfo),
lpdsf->s.surface_desc.dwWidth,
lpdsf->s.surface_desc.dwHeight);
if (img == NULL) {
MSG("Couldn't create XShm image (due to X11 remote display or failure).\nReverting to standard X images !\n");
this->e.xlib.xshm_active = 0;
return NULL;
}
lpdsf->t.xlib.shminfo.shmid = shmget( IPC_PRIVATE, img->bytes_per_line * img->height, IPC_CREAT|0777 );
if (lpdsf->t.xlib.shminfo.shmid < 0) {
MSG("Couldn't create shared memory segment (due to X11 remote display or failure).\nReverting to standard X images !\n");
this->e.xlib.xshm_active = 0;
TSXDestroyImage(img);
return NULL;
}
lpdsf->t.xlib.shminfo.shmaddr = img->data = (char*)shmat(lpdsf->t.xlib.shminfo.shmid, 0, 0);
if (img->data == (char *) -1) {
MSG("Couldn't attach shared memory segment (due to X11 remote display or failure).\nReverting to standard X images !\n");
this->e.xlib.xshm_active = 0;
TSXDestroyImage(img);
shmctl(lpdsf->t.xlib.shminfo.shmid, IPC_RMID, 0);
return NULL;
}
lpdsf->t.xlib.shminfo.readOnly = False;
/* This is where things start to get trickier....
First, we flush the current X connections to be sure to catch all non-XShm related
errors */
TSXSync(display, False);
/* Then we enter in the non-thread safe part of the tests */
EnterCriticalSection( &X11DRV_CritSection );
/* Reset the error flag, sets our new error handler and try to attach the surface */
XShmErrorFlag = 0;
WineXHandler = XSetErrorHandler(XShmErrorHandler);
XShmAttach(display, &(lpdsf->t.xlib.shminfo));
XSync(display, False);
/* Check the error flag */
if (XShmErrorFlag) {
/* An error occured */
XFlush(display);
XShmErrorFlag = 0;
XDestroyImage(img);
shmdt(lpdsf->t.xlib.shminfo.shmaddr);
shmctl(lpdsf->t.xlib.shminfo.shmid, IPC_RMID, 0);
XSetErrorHandler(WineXHandler);
MSG("Couldn't attach shared memory segment to X server (due to X11 remote display or failure).\nReverting to standard X images !\n");
this->e.xlib.xshm_active = 0;
/* Leave the critical section */
LeaveCriticalSection( &X11DRV_CritSection );
return NULL;
}
/* Here, to be REALLY sure, I should do a XShmPutImage to check if this works,
but it may be a bit overkill.... */
XSetErrorHandler(WineXHandler);
LeaveCriticalSection( &X11DRV_CritSection );
shmctl(lpdsf->t.xlib.shminfo.shmid, IPC_RMID, 0);
if (this->d.pixel_convert != NULL) {
lpdsf->s.surface_desc.y.lpSurface = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
lpdsf->s.surface_desc.dwWidth *
lpdsf->s.surface_desc.dwHeight *
(this->d.directdraw_pixelformat.x.dwRGBBitCount));
} else {
lpdsf->s.surface_desc.y.lpSurface = img->data;
}
return img;
}
#endif /* HAVE_LIBXXSHM */
static XImage *create_ximage(LPDIRECTDRAW2 this, LPDIRECTDRAWSURFACE4 lpdsf) {
XImage *img = NULL;
void *img_data;
#ifdef HAVE_LIBXXSHM
if (this->e.xlib.xshm_active) {
img = create_xshmimage(this, lpdsf);
}
if (img == NULL) {
#endif
/* Allocate surface memory */
lpdsf->s.surface_desc.y.lpSurface = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
lpdsf->s.surface_desc.dwWidth *
lpdsf->s.surface_desc.dwHeight *
(this->d.directdraw_pixelformat.x.dwRGBBitCount / 8));
if (this->d.pixel_convert != NULL) {
img_data = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
lpdsf->s.surface_desc.dwWidth *
lpdsf->s.surface_desc.dwHeight *
(this->d.screen_pixelformat.x.dwRGBBitCount / 8));
} else {
img_data = lpdsf->s.surface_desc.y.lpSurface;
}
/* In this case, create an XImage */
img =
TSXCreateImage(display,
DefaultVisualOfScreen(X11DRV_GetXScreen()),
this->d.pixmap_depth,
ZPixmap,
0,
img_data,
lpdsf->s.surface_desc.dwWidth,
lpdsf->s.surface_desc.dwHeight,
32,
lpdsf->s.surface_desc.dwWidth * (this->d.screen_pixelformat.x.dwRGBBitCount / 8)
);
#ifdef HAVE_LIBXXSHM
}
#endif
if (this->d.pixel_convert != NULL) {
lpdsf->s.surface_desc.lPitch = (this->d.directdraw_pixelformat.x.dwRGBBitCount / 8) * lpdsf->s.surface_desc.dwWidth;
} else {
lpdsf->s.surface_desc.lPitch = img->bytes_per_line;
}
return img;
}
static HRESULT WINAPI Xlib_IDirectDraw2_CreateSurface(
LPDIRECTDRAW2 this,LPDDSURFACEDESC lpddsd,LPDIRECTDRAWSURFACE *lpdsf,IUnknown *lpunk
) {
TRACE(ddraw, "(%p)->CreateSurface(%p,%p,%p)\n",
this,lpddsd,lpdsf,lpunk);
if (TRACE_ON(ddraw)) {
DUMP(" w=%ld,h=%ld,flags ",lpddsd->dwWidth,lpddsd->dwHeight);
_dump_DDSD(lpddsd->dwFlags);
DUMP(" caps ");
_dump_DDSCAPS(lpddsd->ddsCaps.dwCaps);
}
*lpdsf = (LPDIRECTDRAWSURFACE)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawSurface));
this->lpvtbl->fnAddRef(this);
(*lpdsf)->s.ddraw = this;
(*lpdsf)->ref = 1;
(*lpdsf)->lpvtbl = (LPDIRECTDRAWSURFACE_VTABLE)&xlib_dds4vt;
(*lpdsf)->s.palette = NULL;
(*lpdsf)->t.xlib.image = NULL; /* This is for off-screen buffers */
if (!(lpddsd->dwFlags & DDSD_WIDTH))
lpddsd->dwWidth = this->d.width;
if (!(lpddsd->dwFlags & DDSD_HEIGHT))
lpddsd->dwHeight = this->d.height;
/* Check if this a 'primary surface' or not */
if ((lpddsd->dwFlags & DDSD_CAPS) &&
(lpddsd->ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)) {
XImage *img;
TRACE(ddraw,"using standard XImage for a primary surface (%p)\n", *lpdsf);
/* First, store the surface description */
(*lpdsf)->s.surface_desc = *lpddsd;
/* Create the XImage */
img = create_ximage(this, (LPDIRECTDRAWSURFACE4) *lpdsf);
if (img == NULL)
return DDERR_OUTOFMEMORY;
(*lpdsf)->t.xlib.image = img;
/* Add flags if there were not present */
(*lpdsf)->s.surface_desc.dwFlags |= DDSD_WIDTH|DDSD_HEIGHT|DDSD_PITCH|DDSD_LPSURFACE|DDSD_PIXELFORMAT;
(*lpdsf)->s.surface_desc.dwWidth = this->d.width;
(*lpdsf)->s.surface_desc.dwHeight = this->d.height;
(*lpdsf)->s.surface_desc.ddsCaps.dwCaps |= DDSCAPS_VISIBLE|DDSCAPS_VIDEOMEMORY;
(*lpdsf)->s.surface_desc.ddpfPixelFormat = this->d.directdraw_pixelformat;
(*lpdsf)->s.backbuffer = NULL;
/* Check for backbuffers */
if (lpddsd->dwFlags & DDSD_BACKBUFFERCOUNT) {
LPDIRECTDRAWSURFACE4 back;
XImage *img;
if (lpddsd->dwBackBufferCount>1)
FIXME(ddraw,"urks, wants to have more than one backbuffer (%ld)!\n",lpddsd->dwBackBufferCount);
(*lpdsf)->s.backbuffer = back =
(LPDIRECTDRAWSURFACE4)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawSurface4));
TRACE(ddraw,"allocated back-buffer (%p)\n", back);
this->lpvtbl->fnAddRef(this);
back->s.ddraw = this;
back->ref = 1;
back->lpvtbl = (LPDIRECTDRAWSURFACE4_VTABLE)&xlib_dds4vt;
/* Copy the surface description from the front buffer */
back->s.surface_desc = (*lpdsf)->s.surface_desc;
/* Create the XImage */
img = create_ximage(this, back);
if (img == NULL)
return DDERR_OUTOFMEMORY;
back->t.xlib.image = img;
back->s.backbuffer = NULL; /* does not have a backbuffer, it is
* one! */
/* Add relevant info to front and back buffers */
(*lpdsf)->s.surface_desc.ddsCaps.dwCaps |= DDSCAPS_FRONTBUFFER;
back->s.surface_desc.ddsCaps.dwCaps |= DDSCAPS_BACKBUFFER;
back->s.surface_desc.dwFlags &= ~DDSD_BACKBUFFERCOUNT;
back->s.surface_desc.ddsCaps.dwCaps &= ~DDSCAPS_VISIBLE;
back->s.surface_desc.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY;
}
} else {
/* There is no Xlib-specific code here...
Go to the common surface creation function */
return common_off_screen_CreateSurface(this, lpddsd, *lpdsf);
}
return DD_OK;
}
static HRESULT WINAPI IDirectDraw2_DuplicateSurface(
LPDIRECTDRAW2 this,LPDIRECTDRAWSURFACE src,LPDIRECTDRAWSURFACE *dst
) {
FIXME(ddraw,"(%p)->(%p,%p) simply copies\n",this,src,dst);
*dst = src; /* FIXME */
return DD_OK;
}
/*
* 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,HWND hwnd,DWORD cooplevel
) {
int i;
const struct {
int mask;
char *name;
} flagmap[] = {
FE(DDSCL_FULLSCREEN)
FE(DDSCL_ALLOWREBOOT)
FE(DDSCL_NOWINDOWCHANGES)
FE(DDSCL_NORMAL)
FE(DDSCL_ALLOWMODEX)
FE(DDSCL_EXCLUSIVE)
FE(DDSCL_SETFOCUSWINDOW)
FE(DDSCL_SETDEVICEWINDOW)
FE(DDSCL_CREATEDEVICEWINDOW)
};
FIXME(ddraw,"(%p)->(%08lx,%08lx)\n",this,(DWORD)hwnd,cooplevel);
if(TRACE_ON(ddraw)){
dbg_decl_str(ddraw, 512);
for (i=0;i<sizeof(flagmap)/sizeof(flagmap[0]);i++)
if (flagmap[i].mask & cooplevel)
dsprintf(ddraw, "%s ", flagmap[i].name);
TRACE(ddraw," cooperative level %s\n", dbg_str(ddraw));
}
this->d.mainWindow = hwnd;
/* This will be overwritten in the case of Full Screen mode.
Windowed games could work with that :-) */
if (hwnd)
this->d.drawable = X11DRV_WND_GetXWindow(WIN_FindWndPtr(hwnd));
return DD_OK;
}
/* 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) {
RECT rect;
/* Do not destroy the application supplied cooperative window */
if (this->d.window && this->d.window != this->d.mainWindow) {
DestroyWindow(this->d.window);
this->d.window = 0;
}
/* Sanity check cooperative window before assigning it to drawing. */
if ( IsWindow(this->d.mainWindow) &&
IsWindowVisible(this->d.mainWindow)
) {
GetWindowRect(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 = CreateWindowExA(
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*/
SetWindowLongA(this->d.window,ddrawXlibThisOffset,(LONG)this);
ShowWindow(this->d.window,TRUE);
UpdateWindow(this->d.window);
}
SetFocus(this->d.window);
}
static int _common_depth_to_pixelformat(DWORD depth, DDPIXELFORMAT *pixelformat, DDPIXELFORMAT *screen_pixelformat, int *pix_depth) {
XVisualInfo *vi;
XPixmapFormatValues *pf;
XVisualInfo vt;
int nvisuals, npixmap, i;
int match = 0;
vi = TSXGetVisualInfo(display, VisualNoMask, &vt, &nvisuals);
pf = XListPixmapFormats(display, &npixmap);
for (i = 0; i < npixmap; i++) {
if (pf[i].bits_per_pixel == depth) {
int j;
for (j = 0; j < nvisuals; j++) {
if (vi[j].depth == pf[i].depth) {
pixelformat->dwSize = sizeof(*pixelformat);
if (depth == 8) {
pixelformat->dwFlags = DDPF_PALETTEINDEXED8;
pixelformat->y.dwRBitMask = 0;
pixelformat->z.dwGBitMask = 0;
pixelformat->xx.dwBBitMask = 0;
} else {
pixelformat->dwFlags = DDPF_RGB;
pixelformat->y.dwRBitMask = vi[j].red_mask;
pixelformat->z.dwGBitMask = vi[j].green_mask;
pixelformat->xx.dwBBitMask = vi[j].blue_mask;
}
pixelformat->dwFourCC = 0;
pixelformat->x.dwRGBBitCount = pf[i].bits_per_pixel;
pixelformat->xy.dwRGBAlphaBitMask= 0;
*screen_pixelformat = *pixelformat;
if (pix_depth != NULL)
*pix_depth = vi[j].depth;
match = 1;
break;
}
}
if (j == nvisuals)
ERR(ddraw, "No visual corresponding to pixmap format !\n");
}
}
if ((match == 0) && (depth == 8)) {
pixelformat->dwSize = sizeof(*pixelformat);
pixelformat->dwFlags = DDPF_PALETTEINDEXED8;
pixelformat->dwFourCC = 0;
pixelformat->x.dwRGBBitCount = 8;
pixelformat->y.dwRBitMask = 0;
pixelformat->z.dwGBitMask = 0;
pixelformat->xx.dwBBitMask = 0;
pixelformat->xy.dwRGBAlphaBitMask= 0;
/* In that case, find a visual to emulate the 8 bpp format */
for (i = 0; i < npixmap; i++) {
if (pf[i].bits_per_pixel >= depth) {
int j;
for (j = 0; j < nvisuals; j++) {
if (vi[j].depth == pf[i].depth) {
screen_pixelformat->dwSize = sizeof(*screen_pixelformat);
screen_pixelformat->dwFlags = DDPF_RGB;
screen_pixelformat->dwFourCC = 0;
screen_pixelformat->x.dwRGBBitCount = pf[i].bits_per_pixel;
screen_pixelformat->y.dwRBitMask = vi[j].red_mask;
screen_pixelformat->z.dwGBitMask = vi[j].green_mask;
screen_pixelformat->xx.dwBBitMask = vi[j].blue_mask;
screen_pixelformat->xy.dwRGBAlphaBitMask= 0;
if (pix_depth != NULL)
*pix_depth = vi[j].depth;
match = 2;
break;
}
}
if (j == nvisuals)
ERR(ddraw, "No visual corresponding to pixmap format !\n");
}
}
}
TSXFree(vi);
TSXFree(pf);
return match;
}
static HRESULT WINAPI DGA_IDirectDraw_SetDisplayMode(
LPDIRECTDRAW this,DWORD width,DWORD height,DWORD depth
) {
#ifdef HAVE_LIBXXF86DGA
int i,mode_count;
TRACE(ddraw, "(%p)->(%ld,%ld,%ld)\n", this, width, height, depth);
/* We hope getting the asked for depth */
if (_common_depth_to_pixelformat(depth, &(this->d.directdraw_pixelformat), &(this->d.screen_pixelformat), NULL) != 1) {
/* I.e. no visual found or emulated */
ERR(ddraw,"(w=%ld,h=%ld,d=%ld), unsupported depth!\n",width,height,depth);
return DDERR_UNSUPPORTEDMODE;
}
if (this->d.width < width) {
ERR(ddraw,"SetDisplayMode(w=%ld,h=%ld,d=%ld), width %ld exceeds framebuffer width %ld\n",width,height,depth,width,this->d.width);
return DDERR_UNSUPPORTEDMODE;
}
this->d.width = width;
this->d.height = height;
/* adjust fb_height, so we don't overlap */
if (this->e.dga.fb_height < height)
this->e.dga.fb_height = height;
_common_IDirectDraw_SetDisplayMode(this);
#ifdef HAVE_LIBXXF86VM
{
XF86VidModeModeInfo **all_modes, *vidmode = NULL;
XF86VidModeModeLine mod_tmp;
/* int dotclock_tmp; */
/* save original video mode and set fullscreen if available*/
orig_mode = (XF86VidModeModeInfo *) malloc (sizeof(XF86VidModeModeInfo));
TSXF86VidModeGetModeLine(display, DefaultScreen(display), &orig_mode->dotclock, &mod_tmp);
orig_mode->hdisplay = mod_tmp.hdisplay;
orig_mode->hsyncstart = mod_tmp.hsyncstart;
orig_mode->hsyncend = mod_tmp.hsyncend;
orig_mode->htotal = mod_tmp.htotal;
orig_mode->vdisplay = mod_tmp.vdisplay;
orig_mode->vsyncstart = mod_tmp.vsyncstart;
orig_mode->vsyncend = mod_tmp.vsyncend;
orig_mode->vtotal = mod_tmp.vtotal;
orig_mode->flags = mod_tmp.flags;
orig_mode->private = mod_tmp.private;
TSXF86VidModeGetAllModeLines(display,DefaultScreen(display),&mode_count,&all_modes);
for (i=0;i<mode_count;i++)
{
if (all_modes[i]->hdisplay == width && all_modes[i]->vdisplay == height)
{
vidmode = (XF86VidModeModeInfo *)malloc(sizeof(XF86VidModeModeInfo));
*vidmode = *(all_modes[i]);
break;
} else
TSXFree(all_modes[i]->private);
}
for (i++;i<mode_count;i++) TSXFree(all_modes[i]->private);
TSXFree(all_modes);
if (!vidmode)
WARN(ddraw, "Fullscreen mode not available!\n");
if (vidmode)
{
TRACE(ddraw,"SwitchToMode(%dx%d)\n",vidmode->hdisplay,vidmode->vdisplay);
TSXF86VidModeSwitchToMode(display, DefaultScreen(display), vidmode);
#if 0 /* This messes up my screen (XF86_Mach64, 3.3.2.3a) for some reason, and should now be unnecessary */
TSXF86VidModeSetViewPort(display, DefaultScreen(display), 0, 0);
#endif
}
}
#endif
/* 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?
*/
TSXF86DGADirectVideo(display,DefaultScreen(display),XF86DGADirectGraphics);
#ifdef DIABLO_HACK
TSXF86DGASetViewPort(display,DefaultScreen(display),0,this->e.dga.fb_height);
#else
TSXF86DGASetViewPort(display,DefaultScreen(display),0,0);
#endif
#ifdef RESTORE_SIGNALS
SIGNAL_InitHandlers();
#endif
return DD_OK;
#else /* defined(HAVE_LIBXXF86DGA) */
return E_UNEXPECTED;
#endif /* defined(HAVE_LIBXXF86DGA) */
}
/* *************************************
16 / 15 bpp to palettized 8 bpp
************************************* */
static void pixel_convert_16_to_8(void *src, void *dst, DWORD width, DWORD height, LONG pitch, LPDIRECTDRAWPALETTE palette) {
unsigned char *c_src = (unsigned char *) src;
unsigned short *c_dst = (unsigned short *) dst;
int x, y;
if (palette != NULL) {
unsigned short *pal = (unsigned short *) palette->screen_palents;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
c_dst[x + y * width] = pal[c_src[x + y * pitch]];
}
}
} else {
WARN(ddraw, "No palette set...\n");
memset(dst, 0, width * height * 2);
}
}
static void palette_convert_16_to_8(LPPALETTEENTRY palent, void *screen_palette, DWORD start, DWORD count) {
int i;
unsigned short *pal = (unsigned short *) screen_palette;
for (i = 0; i < count; i++)
pal[start + i] = (((((unsigned short) palent[i].peRed) & 0xF8) << 8) |
((((unsigned short) palent[i].peBlue) & 0xF8) >> 3) |
((((unsigned short) palent[i].peGreen) & 0xFC) << 3));
}
static void palette_convert_15_to_8(LPPALETTEENTRY palent, void *screen_palette, DWORD start, DWORD count) {
int i;
unsigned short *pal = (unsigned short *) screen_palette;
for (i = 0; i < count; i++)
pal[start + i] = (((((unsigned short) palent[i].peRed) & 0xF8) << 7) |
((((unsigned short) palent[i].peBlue) & 0xF8) >> 3) |
((((unsigned short) palent[i].peGreen) & 0xF8) << 2));
}
/* *************************************
24 / 32 bpp to palettized 8 bpp
************************************* */
static void pixel_convert_32_to_8(void *src, void *dst, DWORD width, DWORD height, LONG pitch, LPDIRECTDRAWPALETTE palette) {
unsigned char *c_src = (unsigned char *) src;
unsigned int *c_dst = (unsigned int *) dst;
int x, y;
if (palette != NULL) {
unsigned int *pal = (unsigned int *) palette->screen_palents;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
c_dst[x + y * width] = pal[c_src[x + y * pitch]];
}
}
} else {
WARN(ddraw, "No palette set...\n");
memset(dst, 0, width * height * 4);
}
}
static void palette_convert_24_to_8(LPPALETTEENTRY palent, void *screen_palette, DWORD start, DWORD count) {
int i;
unsigned int *pal = (unsigned int *) screen_palette;
for (i = 0; i < count; i++)
pal[start + i] = ((((unsigned int) palent[i].peRed) << 16) |
(((unsigned int) palent[i].peGreen) << 8) |
((unsigned int) palent[i].peBlue));
}
static HRESULT WINAPI Xlib_IDirectDraw_SetDisplayMode(
LPDIRECTDRAW this,DWORD width,DWORD height,DWORD depth
) {
char buf[200];
TRACE(ddraw, "(%p)->SetDisplayMode(%ld,%ld,%ld)\n",
this, width, height, depth);
switch (_common_depth_to_pixelformat(depth,
&(this->d.directdraw_pixelformat),
&(this->d.screen_pixelformat),
&(this->d.pixmap_depth))) {
case 0:
sprintf(buf,"SetDisplayMode(w=%ld,h=%ld,d=%ld), unsupported depth!",width,height,depth);
MessageBoxA(0,buf,"WINE DirectDraw",MB_OK|MB_ICONSTOP);
return DDERR_UNSUPPORTEDMODE;
case 1:
/* No convertion */
this->d.pixel_convert = NULL;
this->d.palette_convert = NULL;
break;
case 2: {
int found = 0;
WARN(ddraw, "Warning : running in depth-convertion mode. Should run using a %ld depth for optimal performances.\n", depth);
/* Set the depth convertion routines */
switch (this->d.screen_pixelformat.x.dwRGBBitCount) {
case 16:
if ((this->d.screen_pixelformat.y.dwRBitMask == 0xF800) &&
(this->d.screen_pixelformat.z.dwGBitMask == 0x07E0) &&
(this->d.screen_pixelformat.xx.dwBBitMask == 0x001F)) {
/* 16 bpp */
found = 1;
this->d.pixel_convert = pixel_convert_16_to_8;
this->d.palette_convert = palette_convert_16_to_8;
} else if ((this->d.screen_pixelformat.y.dwRBitMask == 0x7C00) &&
(this->d.screen_pixelformat.z.dwGBitMask == 0x03E0) &&
(this->d.screen_pixelformat.xx.dwBBitMask == 0x001F)) {
/* 15 bpp */
found = 1;
this->d.pixel_convert = pixel_convert_16_to_8;
this->d.palette_convert = palette_convert_15_to_8;
}
break;
case 24:
/* Not handled yet :/ */
found = 0;
break;
case 32:
if ((this->d.screen_pixelformat.y.dwRBitMask == 0xFF0000) &&
(this->d.screen_pixelformat.z.dwGBitMask == 0x00FF00) &&
(this->d.screen_pixelformat.xx.dwBBitMask == 0x0000FF)) {
/* 24 bpp */
found = 1;
this->d.pixel_convert = pixel_convert_32_to_8;
this->d.palette_convert = palette_convert_24_to_8;
}
break;
}
if (!found) {
sprintf(buf,"SetDisplayMode(w=%ld,h=%ld,d=%ld), unsupported depth!",width,height,depth);
MessageBoxA(0,buf,"WINE DirectDraw",MB_OK|MB_ICONSTOP);
return DDERR_UNSUPPORTEDMODE;
}
} break;
}
this->d.width = width;
this->d.height = height;
_common_IDirectDraw_SetDisplayMode(this);
this->d.paintable = 1;
this->d.drawable = ((X11DRV_WND_DATA *) WIN_FindWndPtr(this->d.window)->pDriverData)->window;
/* We don't have a context for this window. Host off the desktop */
if( !this->d.drawable )
this->d.drawable = ((X11DRV_WND_DATA *) WIN_GetDesktop()->pDriverData)->window;
return DD_OK;
}
static HRESULT WINAPI DGA_IDirectDraw2_GetCaps(
LPDIRECTDRAW2 this,LPDDCAPS caps1,LPDDCAPS caps2
) {
#ifdef HAVE_LIBXXF86DGA
TRACE(ddraw,"(%p)->GetCaps(%p,%p)\n",this,caps1,caps2);
caps1->dwVidMemTotal = this->e.dga.fb_memsize;
caps1->dwCaps = 0xffffffff&~(DDCAPS_BANKSWITCHED); /* we can do anything */
caps1->ddsCaps.dwCaps = 0xffffffff; /* we can do anything */
if (caps2) {
caps2->dwVidMemTotal = this->e.dga.fb_memsize;
caps2->dwCaps = 0xffffffff&~(DDCAPS_BANKSWITCHED); /* we can do anything */
caps2->ddsCaps.dwCaps = 0xffffffff; /* we can do anything */
}
return DD_OK;
#else /* defined(HAVE_LIBXXF86DGA) */
return E_UNEXPECTED;
#endif /* defined(HAVE_LIBXXF86DGA) */
}
static void fill_caps(LPDDCAPS caps) {
/* This function tries to fill the capabilities of Wine's DDraw implementation.
Need to be fixed, though.. */
if (caps == NULL)
return;
caps->dwSize = sizeof(*caps);
caps->dwCaps = DDCAPS_ALPHA | DDCAPS_BLT | DDCAPS_BLTSTRETCH | DDCAPS_BLTCOLORFILL | DDCAPS_BLTDEPTHFILL |
DDCAPS_CANBLTSYSMEM | DDCAPS_COLORKEY | DDCAPS_PALETTE;
caps->dwCaps2 = DDCAPS2_CERTIFIED | DDCAPS2_NOPAGELOCKREQUIRED | DDCAPS2_WIDESURFACES;
caps->dwCKeyCaps = 0xFFFFFFFF; /* Should put real caps here one day... */
caps->dwFXCaps = 0;
caps->dwFXAlphaCaps = 0;
caps->dwPalCaps = DDPCAPS_8BIT | DDPCAPS_ALLOW256;
caps->dwSVCaps = 0;
caps->dwZBufferBitDepths = DDBD_16;
/* I put here 8 Mo so that D3D applications will believe they have enough memory
to put textures in video memory.
BTW, is this only frame buffer memory or also texture memory (for Voodoo boards
for example) ? */
caps->dwVidMemTotal = 8192 * 1024;
caps->dwVidMemFree = 8192 * 1024;
/* These are all the supported capabilities of the surfaces */
caps->ddsCaps.dwCaps = DDSCAPS_ALPHA | DDSCAPS_BACKBUFFER | DDSCAPS_COMPLEX | DDSCAPS_FLIP |
DDSCAPS_FRONTBUFFER | DDSCAPS_LOCALVIDMEM | DDSCAPS_NONLOCALVIDMEM | DDSCAPS_OFFSCREENPLAIN |
DDSCAPS_OVERLAY | DDSCAPS_PALETTE | DDSCAPS_PRIMARYSURFACE | DDSCAPS_SYSTEMMEMORY |
DDSCAPS_VIDEOMEMORY | DDSCAPS_VISIBLE;
#ifdef HAVE_MESAGL
caps->dwCaps |= DDCAPS_3D | DDCAPS_ZBLTS;
caps->dwCaps2 |= DDCAPS2_NO2DDURING3DSCENE;
caps->ddsCaps.dwCaps |= DDSCAPS_3DDEVICE | DDSCAPS_MIPMAP | DDSCAPS_TEXTURE | DDSCAPS_ZBUFFER;
#endif
}
static HRESULT WINAPI Xlib_IDirectDraw2_GetCaps(
LPDIRECTDRAW2 this,LPDDCAPS caps1,LPDDCAPS caps2
) {
TRACE(ddraw,"(%p)->GetCaps(%p,%p)\n",this,caps1,caps2);
/* Put the same caps for the two capabilities */
fill_caps(caps1);
fill_caps(caps2);
return DD_OK;
}
static HRESULT WINAPI IDirectDraw2_CreateClipper(
LPDIRECTDRAW2 this,DWORD x,LPDIRECTDRAWCLIPPER *lpddclip,LPUNKNOWN lpunk
) {
FIXME(ddraw,"(%p)->(%08lx,%p,%p),stub!\n",
this,x,lpddclip,lpunk
);
*lpddclip = (LPDIRECTDRAWCLIPPER)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawClipper));
(*lpddclip)->ref = 1;
(*lpddclip)->lpvtbl = &ddclipvt;
return DD_OK;
}
static HRESULT WINAPI common_IDirectDraw2_CreatePalette(
LPDIRECTDRAW2 this,DWORD dwFlags,LPPALETTEENTRY palent,LPDIRECTDRAWPALETTE *lpddpal,LPUNKNOWN lpunk,int *psize
) {
int size = 0;
if (TRACE_ON(ddraw))
_dump_paletteformat(dwFlags);
*lpddpal = (LPDIRECTDRAWPALETTE)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawPalette));
if (*lpddpal == NULL) return E_OUTOFMEMORY;
(*lpddpal)->ref = 1;
(*lpddpal)->ddraw = (LPDIRECTDRAW)this;
(*lpddpal)->installed = 0;
if (dwFlags & DDPCAPS_1BIT)
size = 2;
else if (dwFlags & DDPCAPS_2BIT)
size = 4;
else if (dwFlags & DDPCAPS_4BIT)
size = 16;
else if (dwFlags & DDPCAPS_8BIT)
size = 256;
else
ERR(ddraw, "unhandled palette format\n");
*psize = size;
if (palent)
{
/* Now, if we are in 'depth conversion mode', create the screen palette */
if (this->d.palette_convert != NULL)
this->d.palette_convert(palent, (*lpddpal)->screen_palents, 0, size);
memcpy((*lpddpal)->palents, palent, size * sizeof(PALETTEENTRY));
} else if (this->d.palette_convert != NULL) {
/* In that case, put all 0xFF */
memset((*lpddpal)->screen_palents, 0xFF, 256 * sizeof(int));
}
return DD_OK;
}
static HRESULT WINAPI DGA_IDirectDraw2_CreatePalette(
LPDIRECTDRAW2 this,DWORD dwFlags,LPPALETTEENTRY palent,LPDIRECTDRAWPALETTE *lpddpal,LPUNKNOWN lpunk
) {
HRESULT res;
int xsize = 0,i;
TRACE(ddraw,"(%p)->(%08lx,%p,%p,%p)\n",this,dwFlags,palent,lpddpal,lpunk);
res = common_IDirectDraw2_CreatePalette(this,dwFlags,palent,lpddpal,lpunk,&xsize);
if (res != 0) return res;
(*lpddpal)->lpvtbl = &dga_ddpalvt;
if (this->d.directdraw_pixelformat.x.dwRGBBitCount<=8) {
(*lpddpal)->cm = TSXCreateColormap(display,DefaultRootWindow(display),DefaultVisualOfScreen(X11DRV_GetXScreen()),AllocAll);
} else {
FIXME(ddraw,"why are we doing CreatePalette in hi/truecolor?\n");
(*lpddpal)->cm = 0;
}
if (((*lpddpal)->cm)&&xsize) {
for (i=0;i<xsize;i++) {
XColor xc;
xc.red = (*lpddpal)->palents[i].peRed<<8;
xc.blue = (*lpddpal)->palents[i].peBlue<<8;
xc.green = (*lpddpal)->palents[i].peGreen<<8;
xc.flags = DoRed|DoBlue|DoGreen;
xc.pixel = i;
TSXStoreColor(display,(*lpddpal)->cm,&xc);
}
}
return DD_OK;
}
static HRESULT WINAPI Xlib_IDirectDraw2_CreatePalette(
LPDIRECTDRAW2 this,DWORD dwFlags,LPPALETTEENTRY palent,LPDIRECTDRAWPALETTE *lpddpal,LPUNKNOWN lpunk
) {
int xsize;
HRESULT res;
TRACE(ddraw,"(%p)->(%08lx,%p,%p,%p)\n",this,dwFlags,palent,lpddpal,lpunk);
res = common_IDirectDraw2_CreatePalette(this,dwFlags,palent,lpddpal,lpunk,&xsize);
if (res != 0) return res;
(*lpddpal)->lpvtbl = &xlib_ddpalvt;
return DD_OK;
}
static HRESULT WINAPI DGA_IDirectDraw2_RestoreDisplayMode(LPDIRECTDRAW2 this) {
#ifdef HAVE_LIBXXF86DGA
TRACE(ddraw, "(%p)->()\n",this);
Sleep(1000);
TSXF86DGADirectVideo(display,DefaultScreen(display),0);
#ifdef RESTORE_SIGNALS
SIGNAL_InitHandlers();
#endif
return DD_OK;
#else /* defined(HAVE_LIBXXF86DGA) */
return E_UNEXPECTED;
#endif
}
static HRESULT WINAPI Xlib_IDirectDraw2_RestoreDisplayMode(LPDIRECTDRAW2 this) {
TRACE(ddraw, "(%p)->RestoreDisplayMode()\n", this);
Sleep(1000);
return DD_OK;
}
static HRESULT WINAPI IDirectDraw2_WaitForVerticalBlank(
LPDIRECTDRAW2 this,DWORD x,HANDLE h
) {
TRACE(ddraw,"(%p)->(0x%08lx,0x%08x)\n",this,x,h);
return DD_OK;
}
static ULONG WINAPI IDirectDraw2_AddRef(LPDIRECTDRAW2 this) {
TRACE( ddraw, "(%p)->() incrementing from %lu.\n", this, this->ref );
return ++(this->ref);
}
static ULONG WINAPI DGA_IDirectDraw2_Release(LPDIRECTDRAW2 this) {
TRACE( ddraw, "(%p)->() decrementing from %lu.\n", this, this->ref );
#ifdef HAVE_LIBXXF86DGA
if (!--(this->ref)) {
TSXF86DGADirectVideo(display,DefaultScreen(display),0);
if (this->d.window && (this->d.mainWindow != this->d.window))
DestroyWindow(this->d.window);
#ifdef HAVE_LIBXXF86VM
if (orig_mode) {
TSXF86VidModeSwitchToMode(
display,
DefaultScreen(display),
orig_mode);
if (orig_mode->privsize)
TSXFree(orig_mode->private);
free(orig_mode);
orig_mode = NULL;
}
#endif
#ifdef RESTORE_SIGNALS
SIGNAL_InitHandlers();
#endif
HeapFree(GetProcessHeap(),0,this);
return 0;
}
#endif /* defined(HAVE_LIBXXF86DGA) */
return this->ref;
}
static ULONG WINAPI Xlib_IDirectDraw2_Release(LPDIRECTDRAW2 this) {
TRACE( ddraw, "(%p)->() decrementing from %lu.\n", this, this->ref );
if (!--(this->ref)) {
if (this->d.window && (this->d.mainWindow != this->d.window))
DestroyWindow(this->d.window);
HeapFree(GetProcessHeap(),0,this);
return 0;
}
/* FIXME: destroy window ... */
return this->ref;
}
static HRESULT WINAPI DGA_IDirectDraw2_QueryInterface(
LPDIRECTDRAW2 this,REFIID refiid,LPVOID *obj
) {
char xrefiid[50];
WINE_StringFromCLSID((LPCLSID)refiid,xrefiid);
TRACE(ddraw,"(%p)->(%s,%p)\n",this,xrefiid,obj);
if (!memcmp(&IID_IUnknown,refiid,sizeof(IID_IUnknown))) {
*obj = this;
this->lpvtbl->fnAddRef(this);
TRACE(ddraw, " Creating IUnknown interface (%p)\n", *obj);
return S_OK;
}
if (!memcmp(&IID_IDirectDraw,refiid,sizeof(IID_IDirectDraw))) {
this->lpvtbl = (LPDIRECTDRAW2_VTABLE)&dga_ddvt;
this->lpvtbl->fnAddRef(this);
*obj = this;
TRACE(ddraw, " Creating IDirectDraw interface (%p)\n", *obj);
return S_OK;
}
if (!memcmp(&IID_IDirectDraw2,refiid,sizeof(IID_IDirectDraw2))) {
this->lpvtbl = (LPDIRECTDRAW2_VTABLE)&dga_dd2vt;
this->lpvtbl->fnAddRef(this);
*obj = this;
TRACE(ddraw, " Creating IDirectDraw2 interface (%p)\n", *obj);
return S_OK;
}
if (!memcmp(&IID_IDirectDraw4,refiid,sizeof(IID_IDirectDraw4))) {
this->lpvtbl = (LPDIRECTDRAW2_VTABLE)&dga_dd4vt;
this->lpvtbl->fnAddRef(this);
*obj = this;
TRACE(ddraw, " Creating IDirectDraw4 interface (%p)\n", *obj);
return S_OK;
}
if (!memcmp(&IID_IDirect3D,refiid,sizeof(IID_IDirect3D))) {
LPDIRECT3D d3d;
d3d = HeapAlloc(GetProcessHeap(),0,sizeof(*d3d));
d3d->ref = 1;
d3d->ddraw = (LPDIRECTDRAW)this;
this->lpvtbl->fnAddRef(this);
d3d->lpvtbl = &d3dvt;
*obj = d3d;
TRACE(ddraw, " Creating IDirect3D interface (%p)\n", *obj);
return S_OK;
}
if (!memcmp(&IID_IDirect3D2,refiid,sizeof(IID_IDirect3D2))) {
LPDIRECT3D2 d3d;
d3d = HeapAlloc(GetProcessHeap(),0,sizeof(*d3d));
d3d->ref = 1;
d3d->ddraw = (LPDIRECTDRAW)this;
this->lpvtbl->fnAddRef(this);
d3d->lpvtbl = &d3d2vt;
*obj = d3d;
TRACE(ddraw, " Creating IDirect3D2 interface (%p)\n", *obj);
return S_OK;
}
WARN(ddraw,"(%p):interface for IID %s _NOT_ found!\n",this,xrefiid);
return OLE_E_ENUM_NOMORE;
}
static HRESULT WINAPI Xlib_IDirectDraw2_QueryInterface(
LPDIRECTDRAW2 this,REFIID refiid,LPVOID *obj
) {
char xrefiid[50];
WINE_StringFromCLSID((LPCLSID)refiid,xrefiid);
TRACE(ddraw,"(%p)->(%s,%p)\n",this,xrefiid,obj);
if (!memcmp(&IID_IUnknown,refiid,sizeof(IID_IUnknown))) {
*obj = this;
this->lpvtbl->fnAddRef(this);
TRACE(ddraw, " Creating IUnknown interface (%p)\n", *obj);
return S_OK;
}
if (!memcmp(&IID_IDirectDraw,refiid,sizeof(IID_IDirectDraw))) {
this->lpvtbl = (LPDIRECTDRAW2_VTABLE)&xlib_ddvt;
this->lpvtbl->fnAddRef(this);
*obj = this;
TRACE(ddraw, " Creating IDirectDraw interface (%p)\n", *obj);
return S_OK;
}
if (!memcmp(&IID_IDirectDraw2,refiid,sizeof(IID_IDirectDraw2))) {
this->lpvtbl = (LPDIRECTDRAW2_VTABLE)&xlib_dd2vt;
this->lpvtbl->fnAddRef(this);
*obj = this;
TRACE(ddraw, " Creating IDirectDraw2 interface (%p)\n", *obj);
return S_OK;
}
if (!memcmp(&IID_IDirectDraw4,refiid,sizeof(IID_IDirectDraw4))) {
this->lpvtbl = (LPDIRECTDRAW2_VTABLE)&xlib_dd4vt;
this->lpvtbl->fnAddRef(this);
*obj = this;
TRACE(ddraw, " Creating IDirectDraw4 interface (%p)\n", *obj);
return S_OK;
}
if (!memcmp(&IID_IDirect3D,refiid,sizeof(IID_IDirect3D))) {
LPDIRECT3D d3d;
d3d = HeapAlloc(GetProcessHeap(),0,sizeof(*d3d));
d3d->ref = 1;
d3d->ddraw = (LPDIRECTDRAW)this;
this->lpvtbl->fnAddRef(this);
d3d->lpvtbl = &d3dvt;
*obj = d3d;
TRACE(ddraw, " Creating IDirect3D interface (%p)\n", *obj);
return S_OK;
}
if (!memcmp(&IID_IDirect3D2,refiid,sizeof(IID_IDirect3D))) {
LPDIRECT3D2 d3d;
d3d = HeapAlloc(GetProcessHeap(),0,sizeof(*d3d));
d3d->ref = 1;
d3d->ddraw = (LPDIRECTDRAW)this;
this->lpvtbl->fnAddRef(this);
d3d->lpvtbl = &d3d2vt;
*obj = d3d;
TRACE(ddraw, " Creating IDirect3D2 interface (%p)\n", *obj);
return S_OK;
}
WARN(ddraw,"(%p):interface for IID %s _NOT_ found!\n",this,xrefiid);
return OLE_E_ENUM_NOMORE;
}
static HRESULT WINAPI IDirectDraw2_GetVerticalBlankStatus(
LPDIRECTDRAW2 this,BOOL *status
) {
TRACE(ddraw,"(%p)->(%p)\n",this,status);
*status = TRUE;
return DD_OK;
}
static HRESULT WINAPI DGA_IDirectDraw2_EnumDisplayModes(
LPDIRECTDRAW2 this,DWORD dwFlags,LPDDSURFACEDESC lpddsfd,LPVOID context,LPDDENUMMODESCALLBACK modescb
) {
DDSURFACEDESC ddsfd;
static struct {
int w,h;
} modes[5] = { /* some of the usual modes */
{512,384},
{640,400},
{640,480},
{800,600},
{1024,768},
};
static int depths[4] = {8,16,24,32};
int i,j;
TRACE(ddraw,"(%p)->(0x%08lx,%p,%p,%p)\n",this,dwFlags,lpddsfd,context,modescb);
ddsfd.dwSize = sizeof(ddsfd);
ddsfd.dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_BACKBUFFERCOUNT|DDSD_PIXELFORMAT|DDSD_CAPS;
if (dwFlags & DDEDM_REFRESHRATES) {
ddsfd.dwFlags |= DDSD_REFRESHRATE;
ddsfd.x.dwRefreshRate = 60;
}
for (i=0;i<sizeof(depths)/sizeof(depths[0]);i++) {
ddsfd.dwBackBufferCount = 1;
ddsfd.ddpfPixelFormat.dwFourCC = 0;
ddsfd.ddpfPixelFormat.dwFlags = DDPF_RGB;
ddsfd.ddpfPixelFormat.x.dwRGBBitCount = depths[i];
/* FIXME: those masks would have to be set in depth > 8 */
if (depths[i]==8) {
ddsfd.ddpfPixelFormat.y.dwRBitMask = 0;
ddsfd.ddpfPixelFormat.z.dwGBitMask = 0;
ddsfd.ddpfPixelFormat.xx.dwBBitMask = 0;
ddsfd.ddpfPixelFormat.xy.dwRGBAlphaBitMask= 0;
ddsfd.ddsCaps.dwCaps=DDSCAPS_PALETTE;
ddsfd.ddpfPixelFormat.dwFlags|=DDPF_PALETTEINDEXED8;
} else {
ddsfd.ddpfPixelFormat.xy.dwRGBAlphaBitMask= 0;
/* FIXME: We should query those from X itself */
switch (depths[i]) {
case 16:
ddsfd.ddpfPixelFormat.y.dwRBitMask = 0xF800;
ddsfd.ddpfPixelFormat.z.dwGBitMask = 0x07E0;
ddsfd.ddpfPixelFormat.xx.dwBBitMask= 0x001F;
break;
case 24:
ddsfd.ddpfPixelFormat.y.dwRBitMask = 0x00FF0000;
ddsfd.ddpfPixelFormat.z.dwGBitMask = 0x0000FF00;
ddsfd.ddpfPixelFormat.xx.dwBBitMask= 0x000000FF;
break;
case 32:
ddsfd.ddpfPixelFormat.y.dwRBitMask = 0x00FF0000;
ddsfd.ddpfPixelFormat.z.dwGBitMask = 0x0000FF00;
ddsfd.ddpfPixelFormat.xx.dwBBitMask= 0x000000FF;
break;
}
}
ddsfd.dwWidth = MONITOR_GetWidth(&MONITOR_PrimaryMonitor);
ddsfd.dwHeight = MONITOR_GetHeight(&MONITOR_PrimaryMonitor);
TRACE(ddraw," enumerating (%ldx%ldx%d)\n",ddsfd.dwWidth,ddsfd.dwHeight,depths[i]);
if (!modescb(&ddsfd,context)) return DD_OK;
for (j=0;j<sizeof(modes)/sizeof(modes[0]);j++) {
ddsfd.dwWidth = modes[j].w;
ddsfd.dwHeight = modes[j].h;
TRACE(ddraw," enumerating (%ldx%ldx%d)\n",ddsfd.dwWidth,ddsfd.dwHeight,depths[i]);
if (!modescb(&ddsfd,context)) return DD_OK;
}
if (!(dwFlags & DDEDM_STANDARDVGAMODES)) {
/* modeX is not standard VGA */
ddsfd.dwHeight = 200;
ddsfd.dwWidth = 320;
TRACE(ddraw," enumerating (320x200x%d)\n",depths[i]);
if (!modescb(&ddsfd,context)) return DD_OK;
}
}
return DD_OK;
}
static HRESULT WINAPI Xlib_IDirectDraw2_EnumDisplayModes(
LPDIRECTDRAW2 this,DWORD dwFlags,LPDDSURFACEDESC lpddsfd,LPVOID context,LPDDENUMMODESCALLBACK modescb
) {
XVisualInfo *vi;
XPixmapFormatValues *pf;
XVisualInfo vt;
int nvisuals, npixmap, i;
int send_mode;
int has_8bpp = 0;
DDSURFACEDESC ddsfd;
static struct {
int w,h;
} modes[] = { /* some of the usual modes */
{512,384},
{640,400},
{640,480},
{800,600},
{1024,768},
{1280,1024}
};
DWORD maxWidth, maxHeight;
TRACE(ddraw,"(%p)->(0x%08lx,%p,%p,%p)\n",this,dwFlags,lpddsfd,context,modescb);
ddsfd.dwSize = sizeof(ddsfd);
ddsfd.dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT|DDSD_CAPS;
if (dwFlags & DDEDM_REFRESHRATES) {
ddsfd.dwFlags |= DDSD_REFRESHRATE;
ddsfd.x.dwRefreshRate = 60;
}
maxWidth = MONITOR_GetWidth(&MONITOR_PrimaryMonitor);
maxHeight = MONITOR_GetHeight(&MONITOR_PrimaryMonitor);
vi = TSXGetVisualInfo(display, VisualNoMask, &vt, &nvisuals);
pf = XListPixmapFormats(display, &npixmap);
i = 0;
send_mode = 0;
while (i < npixmap) {
if ((has_8bpp == 0) && (pf[i].depth == 8)) {
/* Special case of a 8bpp depth */
has_8bpp = 1;
send_mode = 1;
ddsfd.ddsCaps.dwCaps = DDSCAPS_PALETTE;
ddsfd.ddpfPixelFormat.dwSize = sizeof(ddsfd.ddpfPixelFormat);
ddsfd.ddpfPixelFormat.dwFlags = DDPF_PALETTEINDEXED8;
ddsfd.ddpfPixelFormat.dwFourCC = 0;
ddsfd.ddpfPixelFormat.x.dwRGBBitCount = 8;
ddsfd.ddpfPixelFormat.y.dwRBitMask = 0;
ddsfd.ddpfPixelFormat.z.dwGBitMask = 0;
ddsfd.ddpfPixelFormat.xx.dwBBitMask = 0;
ddsfd.ddpfPixelFormat.xy.dwRGBAlphaBitMask= 0;
} else if (pf[i].depth > 8) {
int j;
/* All the 'true color' depths (15, 16 and 24)
First, find the corresponding visual to extract the bit masks */
for (j = 0; j < nvisuals; j++) {
if (vi[j].depth == pf[i].depth) {
ddsfd.ddsCaps.dwCaps = 0;
ddsfd.ddpfPixelFormat.dwSize = sizeof(ddsfd.ddpfPixelFormat);
ddsfd.ddpfPixelFormat.dwFlags = DDPF_RGB;
ddsfd.ddpfPixelFormat.dwFourCC = 0;
ddsfd.ddpfPixelFormat.x.dwRGBBitCount = pf[i].bits_per_pixel;
ddsfd.ddpfPixelFormat.y.dwRBitMask = vi[j].red_mask;
ddsfd.ddpfPixelFormat.z.dwGBitMask = vi[j].green_mask;
ddsfd.ddpfPixelFormat.xx.dwBBitMask = vi[j].blue_mask;
ddsfd.ddpfPixelFormat.xy.dwRGBAlphaBitMask= 0;
send_mode = 1;
break;
}
}
if (j == nvisuals)
ERR(ddraw, "Did not find visual corresponding the the pixmap format !\n");
} else {
send_mode = 0;
}
if (send_mode) {
int mode;
if (TRACE_ON(ddraw)) {
TRACE(ddraw, "Enumerating with pixel format : \n");
_dump_pixelformat(&(ddsfd.ddpfPixelFormat));
}
for (mode = 0; mode < sizeof(modes)/sizeof(modes[0]); mode++) {
/* Do not enumerate modes we cannot handle anyway */
if ((modes[mode].w > maxWidth) || (modes[mode].h > maxHeight))
break;
ddsfd.dwWidth = modes[mode].w;
ddsfd.dwHeight = modes[mode].h;
/* Now, send the mode description to the application */
TRACE(ddraw, " - mode %4ld - %4ld\n", ddsfd.dwWidth, ddsfd.dwHeight);
if (!modescb(&ddsfd, context))
goto exit_enum;
}
if (!(dwFlags & DDEDM_STANDARDVGAMODES)) {
/* modeX is not standard VGA */
ddsfd.dwWidth = 320;
ddsfd.dwHeight = 200;
if (!modescb(&ddsfd, context))
goto exit_enum;
}
}
/* Hack to always enumerate a 8bpp depth */
i++;
if ((i == npixmap) && (has_8bpp == 0)) {
i--;
pf[i].depth = 8;
}
}
exit_enum:
TSXFree(vi);
TSXFree(pf);
return DD_OK;
}
static HRESULT WINAPI DGA_IDirectDraw2_GetDisplayMode(
LPDIRECTDRAW2 this,LPDDSURFACEDESC lpddsfd
) {
#ifdef HAVE_LIBXXF86DGA
TRACE(ddraw,"(%p)->(%p)\n",this,lpddsfd);
lpddsfd->dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PITCH|DDSD_BACKBUFFERCOUNT|DDSD_PIXELFORMAT|DDSD_CAPS;
lpddsfd->dwHeight = MONITOR_GetHeight(&MONITOR_PrimaryMonitor);
lpddsfd->dwWidth = MONITOR_GetWidth(&MONITOR_PrimaryMonitor);
lpddsfd->lPitch = this->e.dga.fb_width*this->d.directdraw_pixelformat.x.dwRGBBitCount/8;
lpddsfd->dwBackBufferCount = 1;
lpddsfd->x.dwRefreshRate = 60;
lpddsfd->ddsCaps.dwCaps = DDSCAPS_PALETTE;
lpddsfd->ddpfPixelFormat = this->d.directdraw_pixelformat;
return DD_OK;
#else /* defined(HAVE_LIBXXF86DGA) */
return E_UNEXPECTED;
#endif /* defined(HAVE_LIBXXF86DGA) */
}
static HRESULT WINAPI Xlib_IDirectDraw2_GetDisplayMode(
LPDIRECTDRAW2 this,LPDDSURFACEDESC lpddsfd
) {
TRACE(ddraw,"(%p)->GetDisplayMode(%p)\n",this,lpddsfd);
lpddsfd->dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PITCH|DDSD_BACKBUFFERCOUNT|DDSD_PIXELFORMAT|DDSD_CAPS;
lpddsfd->dwHeight = MONITOR_GetHeight(&MONITOR_PrimaryMonitor);
lpddsfd->dwWidth = MONITOR_GetWidth(&MONITOR_PrimaryMonitor);
lpddsfd->lPitch = lpddsfd->dwWidth * this->d.directdraw_pixelformat.x.dwRGBBitCount/8;
lpddsfd->dwBackBufferCount = 1;
lpddsfd->x.dwRefreshRate = 60;
lpddsfd->ddsCaps.dwCaps = DDSCAPS_PALETTE;
lpddsfd->ddpfPixelFormat = this->d.directdraw_pixelformat;
return DD_OK;
}
static HRESULT WINAPI IDirectDraw2_FlipToGDISurface(LPDIRECTDRAW2 this) {
TRACE(ddraw,"(%p)->()\n",this);
return DD_OK;
}
static HRESULT WINAPI IDirectDraw2_GetMonitorFrequency(
LPDIRECTDRAW2 this,LPDWORD freq
) {
FIXME(ddraw,"(%p)->(%p) returns 60 Hz always\n",this,freq);
*freq = 60*100; /* 60 Hz */
return DD_OK;
}
/* what can we directly decompress? */
static HRESULT WINAPI IDirectDraw2_GetFourCCCodes(
LPDIRECTDRAW2 this,LPDWORD x,LPDWORD y
) {
FIXME(ddraw,"(%p,%p,%p), stub\n",this,x,y);
return DD_OK;
}
static HRESULT WINAPI IDirectDraw2_EnumSurfaces(
LPDIRECTDRAW2 this,DWORD x,LPDDSURFACEDESC ddsfd,LPVOID context,LPDDENUMSURFACESCALLBACK ddsfcb
) {
FIXME(ddraw,"(%p)->(0x%08lx,%p,%p,%p),stub!\n",this,x,ddsfd,context,ddsfcb);
return DD_OK;
}
static HRESULT WINAPI IDirectDraw2_Compact(
LPDIRECTDRAW2 this )
{
FIXME(ddraw,"(%p)->()\n", this );
return DD_OK;
}
static HRESULT WINAPI IDirectDraw2_GetGDISurface(LPDIRECTDRAW2 this,
LPDIRECTDRAWSURFACE *lplpGDIDDSSurface) {
FIXME(ddraw,"(%p)->(%p)\n", this, lplpGDIDDSSurface);
return DD_OK;
}
static HRESULT WINAPI IDirectDraw2_GetScanLine(LPDIRECTDRAW2 this,
LPDWORD lpdwScanLine) {
FIXME(ddraw,"(%p)->(%p)\n", this, lpdwScanLine);
return DD_OK;
}
static HRESULT WINAPI IDirectDraw2_Initialize(LPDIRECTDRAW2 this,
GUID *lpGUID) {
FIXME(ddraw,"(%p)->(%p)\n", this, lpGUID);
return DD_OK;
}
/* Note: Hack so we can reuse the old functions without compiler warnings */
#ifdef __GNUC__
# define XCAST(fun) (typeof(dga_ddvt.fn##fun))
#else
# define XCAST(fun) (void*)
#endif
static struct IDirectDraw_VTable dga_ddvt = {
XCAST(QueryInterface)DGA_IDirectDraw2_QueryInterface,
XCAST(AddRef)IDirectDraw2_AddRef,
XCAST(Release)DGA_IDirectDraw2_Release,
XCAST(Compact)IDirectDraw2_Compact,
XCAST(CreateClipper)IDirectDraw2_CreateClipper,
XCAST(CreatePalette)DGA_IDirectDraw2_CreatePalette,
XCAST(CreateSurface)DGA_IDirectDraw2_CreateSurface,
XCAST(DuplicateSurface)IDirectDraw2_DuplicateSurface,
XCAST(EnumDisplayModes)DGA_IDirectDraw2_EnumDisplayModes,
XCAST(EnumSurfaces)IDirectDraw2_EnumSurfaces,
XCAST(FlipToGDISurface)IDirectDraw2_FlipToGDISurface,
XCAST(GetCaps)DGA_IDirectDraw2_GetCaps,
XCAST(GetDisplayMode)DGA_IDirectDraw2_GetDisplayMode,
XCAST(GetFourCCCodes)IDirectDraw2_GetFourCCCodes,
XCAST(GetGDISurface)IDirectDraw2_GetGDISurface,
XCAST(GetMonitorFrequency)IDirectDraw2_GetMonitorFrequency,
XCAST(GetScanLine)IDirectDraw2_GetScanLine,
XCAST(GetVerticalBlankStatus)IDirectDraw2_GetVerticalBlankStatus,
XCAST(Initialize)IDirectDraw2_Initialize,
XCAST(RestoreDisplayMode)DGA_IDirectDraw2_RestoreDisplayMode,
XCAST(SetCooperativeLevel)IDirectDraw2_SetCooperativeLevel,
DGA_IDirectDraw_SetDisplayMode,
XCAST(WaitForVerticalBlank)IDirectDraw2_WaitForVerticalBlank,
};
static struct IDirectDraw_VTable xlib_ddvt = {
XCAST(QueryInterface)Xlib_IDirectDraw2_QueryInterface,
XCAST(AddRef)IDirectDraw2_AddRef,
XCAST(Release)Xlib_IDirectDraw2_Release,
XCAST(Compact)IDirectDraw2_Compact,
XCAST(CreateClipper)IDirectDraw2_CreateClipper,
XCAST(CreatePalette)Xlib_IDirectDraw2_CreatePalette,
XCAST(CreateSurface)Xlib_IDirectDraw2_CreateSurface,
XCAST(DuplicateSurface)IDirectDraw2_DuplicateSurface,
XCAST(EnumDisplayModes)Xlib_IDirectDraw2_EnumDisplayModes,
XCAST(EnumSurfaces)IDirectDraw2_EnumSurfaces,
XCAST(FlipToGDISurface)IDirectDraw2_FlipToGDISurface,
XCAST(GetCaps)Xlib_IDirectDraw2_GetCaps,
XCAST(GetDisplayMode)Xlib_IDirectDraw2_GetDisplayMode,
XCAST(GetFourCCCodes)IDirectDraw2_GetFourCCCodes,
XCAST(GetGDISurface)IDirectDraw2_GetGDISurface,
XCAST(GetMonitorFrequency)IDirectDraw2_GetMonitorFrequency,
XCAST(GetScanLine)IDirectDraw2_GetScanLine,
XCAST(GetVerticalBlankStatus)IDirectDraw2_GetVerticalBlankStatus,
XCAST(Initialize)IDirectDraw2_Initialize,
XCAST(RestoreDisplayMode)Xlib_IDirectDraw2_RestoreDisplayMode,
XCAST(SetCooperativeLevel)IDirectDraw2_SetCooperativeLevel,
Xlib_IDirectDraw_SetDisplayMode,
XCAST(WaitForVerticalBlank)IDirectDraw2_WaitForVerticalBlank,
};
#undef XCAST
/*****************************************************************************
* IDirectDraw2
*
*/
static HRESULT WINAPI DGA_IDirectDraw2_SetDisplayMode(
LPDIRECTDRAW2 this,DWORD width,DWORD height,DWORD depth,DWORD xx,DWORD yy
) {
return DGA_IDirectDraw_SetDisplayMode((LPDIRECTDRAW)this,width,height,depth);
}
static HRESULT WINAPI Xlib_IDirectDraw2_SetDisplayMode(
LPDIRECTDRAW2 this,DWORD width,DWORD height,DWORD depth,DWORD xx,DWORD yy
) {
return Xlib_IDirectDraw_SetDisplayMode((LPDIRECTDRAW)this,width,height,depth);
}
static HRESULT WINAPI DGA_IDirectDraw2_GetAvailableVidMem(
LPDIRECTDRAW2 this,LPDDSCAPS ddscaps,LPDWORD total,LPDWORD free
) {
TRACE(ddraw,"(%p)->(%p,%p,%p)\n",
this,ddscaps,total,free
);
if (total) *total = this->e.dga.fb_memsize * 1024;
if (free) *free = this->e.dga.fb_memsize * 1024;
return DD_OK;
}
static HRESULT WINAPI Xlib_IDirectDraw2_GetAvailableVidMem(
LPDIRECTDRAW2 this,LPDDSCAPS ddscaps,LPDWORD total,LPDWORD free
) {
TRACE(ddraw,"(%p)->(%p,%p,%p)\n",
this,ddscaps,total,free
);
if (total) *total = 2048 * 1024;
if (free) *free = 2048 * 1024;
return DD_OK;
}
static IDirectDraw2_VTable dga_dd2vt = {
DGA_IDirectDraw2_QueryInterface,
IDirectDraw2_AddRef,
DGA_IDirectDraw2_Release,
IDirectDraw2_Compact,
IDirectDraw2_CreateClipper,
DGA_IDirectDraw2_CreatePalette,
DGA_IDirectDraw2_CreateSurface,
IDirectDraw2_DuplicateSurface,
DGA_IDirectDraw2_EnumDisplayModes,
IDirectDraw2_EnumSurfaces,
IDirectDraw2_FlipToGDISurface,
DGA_IDirectDraw2_GetCaps,
DGA_IDirectDraw2_GetDisplayMode,
IDirectDraw2_GetFourCCCodes,
IDirectDraw2_GetGDISurface,
IDirectDraw2_GetMonitorFrequency,
IDirectDraw2_GetScanLine,
IDirectDraw2_GetVerticalBlankStatus,
IDirectDraw2_Initialize,
DGA_IDirectDraw2_RestoreDisplayMode,
IDirectDraw2_SetCooperativeLevel,
DGA_IDirectDraw2_SetDisplayMode,
IDirectDraw2_WaitForVerticalBlank,
DGA_IDirectDraw2_GetAvailableVidMem
};
static struct IDirectDraw2_VTable xlib_dd2vt = {
Xlib_IDirectDraw2_QueryInterface,
IDirectDraw2_AddRef,
Xlib_IDirectDraw2_Release,
IDirectDraw2_Compact,
IDirectDraw2_CreateClipper,
Xlib_IDirectDraw2_CreatePalette,
Xlib_IDirectDraw2_CreateSurface,
IDirectDraw2_DuplicateSurface,
Xlib_IDirectDraw2_EnumDisplayModes,
IDirectDraw2_EnumSurfaces,
IDirectDraw2_FlipToGDISurface,
Xlib_IDirectDraw2_GetCaps,
Xlib_IDirectDraw2_GetDisplayMode,
IDirectDraw2_GetFourCCCodes,
IDirectDraw2_GetGDISurface,
IDirectDraw2_GetMonitorFrequency,
IDirectDraw2_GetScanLine,
IDirectDraw2_GetVerticalBlankStatus,
IDirectDraw2_Initialize,
Xlib_IDirectDraw2_RestoreDisplayMode,
IDirectDraw2_SetCooperativeLevel,
Xlib_IDirectDraw2_SetDisplayMode,
IDirectDraw2_WaitForVerticalBlank,
Xlib_IDirectDraw2_GetAvailableVidMem
};
/*****************************************************************************
* IDirectDraw4
*
*/
static HRESULT WINAPI IDirectDraw4_GetSurfaceFromDC(LPDIRECTDRAW4 this,
HDC hdc,
LPDIRECTDRAWSURFACE *lpDDS) {
FIXME(ddraw, "(%p)->(%08ld,%p)\n", this, (DWORD) hdc, lpDDS);
return DD_OK;
}
static HRESULT WINAPI IDirectDraw4_RestoreAllSurfaces(LPDIRECTDRAW4 this) {
FIXME(ddraw, "(%p)->()\n", this);
return DD_OK;
}
static HRESULT WINAPI IDirectDraw4_TestCooperativeLevel(LPDIRECTDRAW4 this) {
FIXME(ddraw, "(%p)->()\n", this);
return DD_OK;
}
static HRESULT WINAPI IDirectDraw4_GetDeviceIdentifier(LPDIRECTDRAW4 this,
LPDDDEVICEIDENTIFIER lpdddi,
DWORD dwFlags) {
FIXME(ddraw, "(%p)->(%p,%08lx)\n", this, lpdddi, dwFlags);
return DD_OK;
}
#ifdef __GNUC__
# define XCAST(fun) (typeof(dga_dd4vt.fn##fun))
#else
# define XCAST(fun) (void*)
#endif
static struct IDirectDraw4_VTable dga_dd4vt = {
XCAST(QueryInterface)DGA_IDirectDraw2_QueryInterface,
XCAST(AddRef)IDirectDraw2_AddRef,
XCAST(Release)DGA_IDirectDraw2_Release,
XCAST(Compact)IDirectDraw2_Compact,
XCAST(CreateClipper)IDirectDraw2_CreateClipper,
XCAST(CreatePalette)DGA_IDirectDraw2_CreatePalette,
XCAST(CreateSurface)DGA_IDirectDraw2_CreateSurface,
XCAST(DuplicateSurface)IDirectDraw2_DuplicateSurface,
XCAST(EnumDisplayModes)DGA_IDirectDraw2_EnumDisplayModes,
XCAST(EnumSurfaces)IDirectDraw2_EnumSurfaces,
XCAST(FlipToGDISurface)IDirectDraw2_FlipToGDISurface,
XCAST(GetCaps)DGA_IDirectDraw2_GetCaps,
XCAST(GetDisplayMode)DGA_IDirectDraw2_GetDisplayMode,
XCAST(GetFourCCCodes)IDirectDraw2_GetFourCCCodes,
XCAST(GetGDISurface)IDirectDraw2_GetGDISurface,
XCAST(GetMonitorFrequency)IDirectDraw2_GetMonitorFrequency,
XCAST(GetScanLine)IDirectDraw2_GetScanLine,
XCAST(GetVerticalBlankStatus)IDirectDraw2_GetVerticalBlankStatus,
XCAST(Initialize)IDirectDraw2_Initialize,
XCAST(RestoreDisplayMode)DGA_IDirectDraw2_RestoreDisplayMode,
XCAST(SetCooperativeLevel)IDirectDraw2_SetCooperativeLevel,
XCAST(SetDisplayMode)DGA_IDirectDraw_SetDisplayMode,
XCAST(WaitForVerticalBlank)IDirectDraw2_WaitForVerticalBlank,
XCAST(GetAvailableVidMem)DGA_IDirectDraw2_GetAvailableVidMem,
IDirectDraw4_GetSurfaceFromDC,
IDirectDraw4_RestoreAllSurfaces,
IDirectDraw4_TestCooperativeLevel,
IDirectDraw4_GetDeviceIdentifier
};
static struct IDirectDraw4_VTable xlib_dd4vt = {
XCAST(QueryInterface)Xlib_IDirectDraw2_QueryInterface,
XCAST(AddRef)IDirectDraw2_AddRef,
XCAST(Release)Xlib_IDirectDraw2_Release,
XCAST(Compact)IDirectDraw2_Compact,
XCAST(CreateClipper)IDirectDraw2_CreateClipper,
XCAST(CreatePalette)Xlib_IDirectDraw2_CreatePalette,
XCAST(CreateSurface)Xlib_IDirectDraw2_CreateSurface,
XCAST(DuplicateSurface)IDirectDraw2_DuplicateSurface,
XCAST(EnumDisplayModes)Xlib_IDirectDraw2_EnumDisplayModes,
XCAST(EnumSurfaces)IDirectDraw2_EnumSurfaces,
XCAST(FlipToGDISurface)IDirectDraw2_FlipToGDISurface,
XCAST(GetCaps)Xlib_IDirectDraw2_GetCaps,
XCAST(GetDisplayMode)Xlib_IDirectDraw2_GetDisplayMode,
XCAST(GetFourCCCodes)IDirectDraw2_GetFourCCCodes,
XCAST(GetGDISurface)IDirectDraw2_GetGDISurface,
XCAST(GetMonitorFrequency)IDirectDraw2_GetMonitorFrequency,
XCAST(GetScanLine)IDirectDraw2_GetScanLine,
XCAST(GetVerticalBlankStatus)IDirectDraw2_GetVerticalBlankStatus,
XCAST(Initialize)IDirectDraw2_Initialize,
XCAST(RestoreDisplayMode)Xlib_IDirectDraw2_RestoreDisplayMode,
XCAST(SetCooperativeLevel)IDirectDraw2_SetCooperativeLevel,
XCAST(SetDisplayMode)Xlib_IDirectDraw_SetDisplayMode,
XCAST(WaitForVerticalBlank)IDirectDraw2_WaitForVerticalBlank,
XCAST(GetAvailableVidMem)Xlib_IDirectDraw2_GetAvailableVidMem,
IDirectDraw4_GetSurfaceFromDC,
IDirectDraw4_RestoreAllSurfaces,
IDirectDraw4_TestCooperativeLevel,
IDirectDraw4_GetDeviceIdentifier
};
#undef XCAST
/******************************************************************************
* DirectDrawCreate
*/
LRESULT WINAPI Xlib_DDWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
LRESULT ret;
LPDIRECTDRAW ddraw = NULL;
DWORD lastError;
/* FIXME(ddraw,"(0x%04x,%s,0x%08lx,0x%08lx),stub!\n",(int)hwnd,SPY_GetMsgName(msg),(long)wParam,(long)lParam); */
SetLastError( ERROR_SUCCESS );
ddraw = (LPDIRECTDRAW)GetWindowLongA( hwnd, ddrawXlibThisOffset );
if( (!ddraw) &&
( ( lastError = GetLastError() ) != ERROR_SUCCESS )
)
{
ERR( ddraw, "Unable to retrieve this ptr from window. Error %08lx\n", lastError );
}
if( ddraw )
{
/* Perform any special direct draw functions */
if (msg==WM_PAINT)
ddraw->d.paintable = 1;
/* Now let the application deal with the rest of this */
if( ddraw->d.mainWindow )
{
/* Don't think that we actually need to call this but...
might as well be on the safe side of things... */
/* I changed hwnd to ddraw->d.mainWindow as I did not see why
it should be the procedures of our fake window that gets called
instead of those of the window provided by the application.
And with this patch, mouse clicks work with Monkey Island III
- Lionel */
ret = DefWindowProcA( ddraw->d.mainWindow, msg, wParam, lParam );
if( !ret )
{
/* We didn't handle the message - give it to the application */
if (ddraw && ddraw->d.mainWindow && WIN_FindWndPtr(ddraw->d.mainWindow)) {
ret = CallWindowProcA( WIN_FindWndPtr( ddraw->d.mainWindow )->winproc,
ddraw->d.mainWindow, msg, wParam, lParam );
}
}
} else {
ret = DefWindowProcA(hwnd, msg, wParam, lParam );
}
}
else
{
ret = DefWindowProcA(hwnd,msg,wParam,lParam);
}
return ret;
}
HRESULT WINAPI DGA_DirectDrawCreate( LPDIRECTDRAW *lplpDD, LPUNKNOWN pUnkOuter) {
#ifdef HAVE_LIBXXF86DGA
int memsize,banksize,width,major,minor,flags,height;
char *addr;
int fd;
int depth;
/* Must be able to access /dev/mem for DGA extensions to work, root is not neccessary. --stephenc */
if ((fd = open("/dev/mem", O_RDWR)) != -1)
close(fd);
if (fd == -1) {
MSG("Must be able to access /dev/mem to use XF86DGA!\n");
MessageBoxA(0,"Using the XF86DGA extension requires access to /dev/mem.","WINE DirectDraw",MB_OK|MB_ICONSTOP);
return E_UNEXPECTED;
}
if (!DDRAW_DGA_Available()) {
TRACE(ddraw,"No XF86DGA detected.\n");
return DDERR_GENERIC;
}
*lplpDD = (LPDIRECTDRAW)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDraw));
(*lplpDD)->lpvtbl = &dga_ddvt;
(*lplpDD)->ref = 1;
TSXF86DGAQueryVersion(display,&major,&minor);
TRACE(ddraw,"XF86DGA is version %d.%d\n",major,minor);
TSXF86DGAQueryDirectVideo(display,DefaultScreen(display),&flags);
if (!(flags & XF86DGADirectPresent))
MSG("direct video is NOT PRESENT.\n");
TSXF86DGAGetVideo(display,DefaultScreen(display),&addr,&width,&banksize,&memsize);
TRACE(ddraw,"video framebuffer: begin %p, width %d,banksize %d,memsize %d\n",
addr,width,banksize,memsize
);
(*lplpDD)->e.dga.fb_width = width;
(*lplpDD)->d.width = width;
(*lplpDD)->e.dga.fb_addr = addr;
(*lplpDD)->e.dga.fb_memsize = memsize;
(*lplpDD)->e.dga.fb_banksize = banksize;
TSXF86DGAGetViewPortSize(display,DefaultScreen(display),&width,&height);
TSXF86DGASetViewPort(display,DefaultScreen(display),0,0);
(*lplpDD)->e.dga.fb_height = MONITOR_GetHeight(&MONITOR_PrimaryMonitor);
#ifdef DIABLO_HACK
(*lplpDD)->e.dga.vpmask = 1;
#else
(*lplpDD)->e.dga.vpmask = 0;
#endif
/* just assume the default depth is the DGA depth too */
depth = DefaultDepthOfScreen(X11DRV_GetXScreen());
_common_depth_to_pixelformat(depth, &((*lplpDD)->d.directdraw_pixelformat), &((*lplpDD)->d.screen_pixelformat), NULL);
#ifdef RESTORE_SIGNALS
SIGNAL_InitHandlers();
#endif
return DD_OK;
#else /* defined(HAVE_LIBXXF86DGA) */
return DDERR_INVALIDDIRECTDRAWGUID;
#endif /* defined(HAVE_LIBXXF86DGA) */
}
BOOL
DDRAW_XSHM_Available(void)
{
#ifdef HAVE_LIBXXSHM
if (TSXShmQueryExtension(display))
{
int major, minor;
Bool shpix;
if (TSXShmQueryVersion(display, &major, &minor, &shpix))
return 1;
else
return 0;
}
else
return 0;
#else
return 0;
#endif
}
HRESULT WINAPI Xlib_DirectDrawCreate( LPDIRECTDRAW *lplpDD, LPUNKNOWN pUnkOuter) {
int depth;
*lplpDD = (LPDIRECTDRAW)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDraw));
(*lplpDD)->lpvtbl = &xlib_ddvt;
(*lplpDD)->ref = 1;
(*lplpDD)->d.drawable = 0; /* in SetDisplayMode */
/* At DirectDraw creation, the depth is the default depth */
depth = DefaultDepthOfScreen(X11DRV_GetXScreen());
_common_depth_to_pixelformat(depth, &((*lplpDD)->d.directdraw_pixelformat), &((*lplpDD)->d.screen_pixelformat), NULL);
(*lplpDD)->d.height = MONITOR_GetHeight(&MONITOR_PrimaryMonitor);
(*lplpDD)->d.width = MONITOR_GetWidth(&MONITOR_PrimaryMonitor);
#ifdef HAVE_LIBXXSHM
/* Test if XShm is available. */
if (((*lplpDD)->e.xlib.xshm_active = DDRAW_XSHM_Available()))
TRACE(ddraw, "Using XShm extension.\n");
#endif
return DD_OK;
}
HRESULT WINAPI DirectDrawCreate( LPGUID lpGUID, LPDIRECTDRAW *lplpDD, LPUNKNOWN pUnkOuter ) {
char xclsid[50];
WNDCLASSA wc;
WND* pParentWindow;
HRESULT ret;
if (HIWORD(lpGUID))
WINE_StringFromCLSID(lpGUID,xclsid);
else {
sprintf(xclsid,"<guid-0x%08x>",(int)lpGUID);
lpGUID = NULL;
}
TRACE(ddraw,"(%s,%p,%p)\n",xclsid,lplpDD,pUnkOuter);
if (!lpGUID) {
/* if they didn't request a particular interface, use the best
* supported one */
if (DDRAW_DGA_Available())
lpGUID = &DGA_DirectDraw_GUID;
else
lpGUID = &XLIB_DirectDraw_GUID;
}
wc.style = CS_GLOBALCLASS;
wc.lpfnWndProc = Xlib_DDWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = /* Defines extra mem for window. This is used for storing this */
sizeof( LPDIRECTDRAW ); /* ddrawXlibThisOffset */
/* We can be a child of the desktop since we're really important */
pParentWindow = WIN_GetDesktop();
wc.hInstance = pParentWindow ? pParentWindow->hwndSelf : 0;
wc.hInstance = 0;
wc.hIcon = 0;
wc.hCursor = (HCURSOR)IDC_ARROWA;
wc.hbrBackground= NULL_BRUSH;
wc.lpszMenuName = 0;
wc.lpszClassName= "WINE_DirectDraw";
RegisterClassA(&wc);
if (!memcmp(lpGUID, &DGA_DirectDraw_GUID, sizeof(GUID)))
ret = DGA_DirectDrawCreate(lplpDD, pUnkOuter);
else if (!memcmp(lpGUID, &XLIB_DirectDraw_GUID, sizeof(GUID)))
ret = Xlib_DirectDrawCreate(lplpDD, pUnkOuter);
else
goto err;
(*lplpDD)->d.winclass = RegisterClassA(&wc);
return ret;
err:
ERR(ddraw, "DirectDrawCreate(%s,%p,%p): did not recognize requested GUID\n",xclsid,lplpDD,pUnkOuter);
return DDERR_INVALIDDIRECTDRAWGUID;
}