5076 lines
153 KiB
C
5076 lines
153 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"
|
|
|
|
#ifndef X_DISPLAY_MISSING
|
|
|
|
#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 "ddraw_private.h"
|
|
#include "d3d_private.h"
|
|
|
|
DEFAULT_DEBUG_CHANNEL(ddraw)
|
|
|
|
/* Restore signal handlers overwritten by XF86DGA
|
|
*/
|
|
#define RESTORE_SIGNALS
|
|
|
|
/* Get the number of bytes per pixel for a given surface */
|
|
#define GET_BPP(desc) (desc.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8 ? \
|
|
1 : \
|
|
desc.ddpfPixelFormat.x.dwRGBBitCount / 8)
|
|
|
|
/* 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 ICOM_VTABLE(IDirectDrawSurface4) dga_dds4vt, xlib_dds4vt;
|
|
static struct ICOM_VTABLE(IDirectDraw) dga_ddvt, xlib_ddvt;
|
|
static struct ICOM_VTABLE(IDirectDraw2) dga_dd2vt, xlib_dd2vt;
|
|
static struct ICOM_VTABLE(IDirectDraw4) dga_dd4vt, xlib_dd4vt;
|
|
static struct ICOM_VTABLE(IDirectDrawClipper) ddclipvt;
|
|
static struct ICOM_VTABLE(IDirectDrawPalette) dga_ddpalvt, xlib_ddpalvt;
|
|
static struct ICOM_VTABLE(IDirect3D) d3dvt;
|
|
static struct ICOM_VTABLE(IDirect3D2) 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) */
|
|
}
|
|
|
|
/**********************************************************************/
|
|
|
|
typedef struct {
|
|
LPVOID lpCallback;
|
|
LPVOID lpContext;
|
|
} DirectDrawEnumerateProcData;
|
|
|
|
/***********************************************************************
|
|
* DirectDrawEnumerateExA (DDRAW.*)
|
|
*/
|
|
HRESULT WINAPI DirectDrawEnumerateExA(
|
|
LPDDENUMCALLBACKEXA lpCallback, LPVOID lpContext, DWORD dwFlags)
|
|
{
|
|
TRACE(ddraw, "(%p,%p, %08lx)\n", lpCallback, lpContext, 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 (!lpCallback(&DGA_DirectDraw_GUID, "WINE with XFree86 DGA", "display", lpContext, 0))
|
|
return DD_OK;
|
|
}
|
|
|
|
TRACE(ddraw, "Enumerating Xlib interface\n");
|
|
if (!lpCallback(&XLIB_DirectDraw_GUID, "WINE with Xlib", "display", lpContext, 0))
|
|
return DD_OK;
|
|
|
|
TRACE(ddraw, "Enumerating Default interface\n");
|
|
if (!lpCallback(NULL,"WINE (default)", "display", lpContext, 0))
|
|
return DD_OK;
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
/***********************************************************************
|
|
* DirectDrawEnumerateExW (DDRAW.*)
|
|
*/
|
|
|
|
static BOOL CALLBACK DirectDrawEnumerateExProcW(
|
|
GUID *lpGUID, LPSTR lpDriverDescription, LPSTR lpDriverName,
|
|
LPVOID lpContext, HMONITOR hm)
|
|
{
|
|
DirectDrawEnumerateProcData *pEPD =
|
|
(DirectDrawEnumerateProcData *) lpContext;
|
|
LPWSTR lpDriverDescriptionW =
|
|
HEAP_strdupAtoW(GetProcessHeap(), 0, lpDriverDescription);
|
|
LPWSTR lpDriverNameW =
|
|
HEAP_strdupAtoW(GetProcessHeap(), 0, lpDriverName);
|
|
|
|
BOOL bResult = (*(LPDDENUMCALLBACKEXW *) pEPD->lpCallback)(
|
|
lpGUID, lpDriverDescriptionW, lpDriverNameW, pEPD->lpContext, hm);
|
|
|
|
HeapFree(GetProcessHeap(), 0, lpDriverDescriptionW);
|
|
HeapFree(GetProcessHeap(), 0, lpDriverNameW);
|
|
|
|
return bResult;
|
|
}
|
|
|
|
/**********************************************************************/
|
|
|
|
HRESULT WINAPI DirectDrawEnumerateExW(
|
|
LPDDENUMCALLBACKEXW lpCallback, LPVOID lpContext, DWORD dwFlags)
|
|
{
|
|
DirectDrawEnumerateProcData epd;
|
|
epd.lpCallback = (LPVOID) lpCallback;
|
|
epd.lpContext = lpContext;
|
|
|
|
return DirectDrawEnumerateExA(DirectDrawEnumerateExProcW,
|
|
(LPVOID) &epd, 0);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* DirectDrawEnumerateA (DDRAW.*)
|
|
*/
|
|
|
|
static BOOL CALLBACK DirectDrawEnumerateProcA(
|
|
GUID *lpGUID, LPSTR lpDriverDescription, LPSTR lpDriverName,
|
|
LPVOID lpContext, HMONITOR hm)
|
|
{
|
|
DirectDrawEnumerateProcData *pEPD =
|
|
(DirectDrawEnumerateProcData *) lpContext;
|
|
|
|
return ((LPDDENUMCALLBACKA) pEPD->lpCallback)(
|
|
lpGUID, lpDriverDescription, lpDriverName, pEPD->lpContext);
|
|
}
|
|
|
|
/**********************************************************************/
|
|
|
|
HRESULT WINAPI DirectDrawEnumerateA(
|
|
LPDDENUMCALLBACKA lpCallback, LPVOID lpContext)
|
|
{
|
|
DirectDrawEnumerateProcData epd;
|
|
epd.lpCallback = (LPVOID) lpCallback;
|
|
epd.lpContext = lpContext;
|
|
|
|
return DirectDrawEnumerateExA(DirectDrawEnumerateProcA,
|
|
(LPVOID) &epd, 0);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* DirectDrawEnumerateW (DDRAW.*)
|
|
*/
|
|
|
|
static BOOL WINAPI DirectDrawEnumerateProcW(
|
|
GUID *lpGUID, LPWSTR lpDriverDescription, LPWSTR lpDriverName,
|
|
LPVOID lpContext, HMONITOR hm)
|
|
{
|
|
DirectDrawEnumerateProcData *pEPD =
|
|
(DirectDrawEnumerateProcData *) lpContext;
|
|
|
|
return ((LPDDENUMCALLBACKW) pEPD->lpCallback)(
|
|
lpGUID, lpDriverDescription, lpDriverName,
|
|
pEPD->lpContext);
|
|
}
|
|
|
|
/**********************************************************************/
|
|
|
|
HRESULT WINAPI DirectDrawEnumerateW(
|
|
LPDDENUMCALLBACKW lpCallback, LPVOID lpContext)
|
|
{
|
|
DirectDrawEnumerateProcData epd;
|
|
epd.lpCallback = (LPVOID) lpCallback;
|
|
epd.lpContext = lpContext;
|
|
|
|
return DirectDrawEnumerateExW(DirectDrawEnumerateProcW,
|
|
(LPVOID) &epd, 0);
|
|
}
|
|
|
|
/***********************************************************************
|
|
* DSoundHelp (DDRAW.?)
|
|
*/
|
|
|
|
/* 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)
|
|
#undef FE
|
|
};
|
|
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)
|
|
#undef FE
|
|
};
|
|
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)
|
|
#undef FE
|
|
};
|
|
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(void *in) {
|
|
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)
|
|
#undef FE
|
|
};
|
|
DWORD flagmask = *((DWORD *) in);
|
|
for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
|
|
if (flags[i].mask & flagmask)
|
|
DUMP("%s ",flags[i].name);
|
|
}
|
|
|
|
static void _dump_pixelformat_flag(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)
|
|
#undef FE
|
|
};
|
|
for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
|
|
if (flags[i].mask & flagmask)
|
|
DUMP("%s ",flags[i].name);
|
|
}
|
|
|
|
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)
|
|
#undef FE
|
|
};
|
|
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(void *in) {
|
|
LPDDPIXELFORMAT pf = (LPDDPIXELFORMAT) in;
|
|
char *cmd;
|
|
|
|
DUMP("( ");
|
|
_dump_pixelformat_flag(pf->dwFlags);
|
|
if (pf->dwFlags & DDPF_FOURCC) {
|
|
DUMP(", dwFourCC : %ld", pf->dwFourCC);
|
|
}
|
|
if (pf->dwFlags & DDPF_RGB) {
|
|
DUMP(", RGB bits: %ld, ", pf->x.dwRGBBitCount);
|
|
switch (pf->x.dwRGBBitCount) {
|
|
case 4:
|
|
cmd = "%1lx";
|
|
break;
|
|
case 8:
|
|
cmd = "%02lx";
|
|
break;
|
|
case 16:
|
|
cmd = "%04lx";
|
|
break;
|
|
case 24:
|
|
cmd = "%06lx";
|
|
break;
|
|
case 32:
|
|
cmd = "%08lx";
|
|
break;
|
|
default:
|
|
ERR(ddraw, "Unexpected bit depth !\n");
|
|
cmd = "%d";
|
|
}
|
|
DUMP(" R "); DUMP(cmd, pf->y.dwRBitMask);
|
|
DUMP(" G "); DUMP(cmd, pf->z.dwGBitMask);
|
|
DUMP(" B "); DUMP(cmd, pf->xx.dwBBitMask);
|
|
if (pf->dwFlags & DDPF_ALPHAPIXELS) {
|
|
DUMP(" A "); DUMP(cmd, pf->xy.dwRGBAlphaBitMask);
|
|
}
|
|
if (pf->dwFlags & DDPF_ZPIXELS) {
|
|
DUMP(" Z "); DUMP(cmd, pf->xy.dwRGBZBitMask);
|
|
}
|
|
}
|
|
if (pf->dwFlags & DDPF_ZBUFFER) {
|
|
DUMP(", Z bits : %ld", pf->x.dwZBufferBitDepth);
|
|
}
|
|
if (pf->dwFlags & DDPF_ALPHA) {
|
|
DUMP(", Alpha bits : %ld", pf->x.dwAlphaBitDepth);
|
|
}
|
|
DUMP(")");
|
|
}
|
|
|
|
static void _dump_colorkeyflag(DWORD ck) {
|
|
int i;
|
|
const struct {
|
|
DWORD mask;
|
|
char *name;
|
|
} flags[] = {
|
|
#define FE(x) { x, #x},
|
|
FE(DDCKEY_COLORSPACE)
|
|
FE(DDCKEY_DESTBLT)
|
|
FE(DDCKEY_DESTOVERLAY)
|
|
FE(DDCKEY_SRCBLT)
|
|
FE(DDCKEY_SRCOVERLAY)
|
|
#undef FE
|
|
};
|
|
for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
|
|
if (flags[i].mask & ck)
|
|
DUMP("%s ",flags[i].name);
|
|
}
|
|
|
|
static void _dump_DWORD(void *in) {
|
|
DUMP("%ld", *((DWORD *) in));
|
|
}
|
|
static void _dump_PTR(void *in) {
|
|
DUMP("%p", *((void **) in));
|
|
}
|
|
static void _dump_DDCOLORKEY(void *in) {
|
|
DDCOLORKEY *ddck = (DDCOLORKEY *) in;
|
|
|
|
DUMP(" Low : %ld - High : %ld", ddck->dwColorSpaceLowValue, ddck->dwColorSpaceHighValue);
|
|
}
|
|
|
|
static void _dump_surface_desc(DDSURFACEDESC *lpddsd) {
|
|
int i;
|
|
const struct {
|
|
DWORD mask;
|
|
char *name;
|
|
void (*func)(void *);
|
|
void *elt;
|
|
} flags[] = {
|
|
#define FE(x,func,elt) { x, #x, func, (void *) &(lpddsd->elt)}
|
|
FE(DDSD_CAPS, _dump_DDSCAPS, ddsCaps),
|
|
FE(DDSD_HEIGHT, _dump_DWORD, dwHeight),
|
|
FE(DDSD_WIDTH, _dump_DWORD, dwWidth),
|
|
FE(DDSD_PITCH, _dump_DWORD, lPitch),
|
|
FE(DDSD_BACKBUFFERCOUNT, _dump_DWORD, dwBackBufferCount),
|
|
FE(DDSD_ZBUFFERBITDEPTH, _dump_DWORD, x.dwZBufferBitDepth),
|
|
FE(DDSD_ALPHABITDEPTH, _dump_DWORD, dwAlphaBitDepth),
|
|
FE(DDSD_PIXELFORMAT, _dump_pixelformat, ddpfPixelFormat),
|
|
FE(DDSD_CKDESTOVERLAY, _dump_DDCOLORKEY, ddckCKDestOverlay),
|
|
FE(DDSD_CKDESTBLT, _dump_DDCOLORKEY, ddckCKDestBlt),
|
|
FE(DDSD_CKSRCOVERLAY, _dump_DDCOLORKEY, ddckCKSrcOverlay),
|
|
FE(DDSD_CKSRCBLT, _dump_DDCOLORKEY, ddckCKSrcBlt),
|
|
FE(DDSD_MIPMAPCOUNT, _dump_DWORD, x.dwMipMapCount),
|
|
FE(DDSD_REFRESHRATE, _dump_DWORD, x.dwRefreshRate),
|
|
FE(DDSD_LINEARSIZE, _dump_DWORD, y.dwLinearSize),
|
|
FE(DDSD_LPSURFACE, _dump_PTR, y.lpSurface)
|
|
#undef FE
|
|
};
|
|
for (i=0;i<sizeof(flags)/sizeof(flags[0]);i++)
|
|
if (flags[i].mask & lpddsd->dwFlags) {
|
|
DUMP(" - %s : ",flags[i].name);
|
|
flags[i].func(flags[i].elt);
|
|
DUMP("\n");
|
|
}
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
* 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 IDirectDrawSurface4Impl_Lock(
|
|
LPDIRECTDRAWSURFACE4 iface,LPRECT lprect,LPDDSURFACEDESC lpddsd,DWORD flags, HANDLE hnd
|
|
) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
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 = (LPVOID) ((char *) 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_IDirectDrawSurface4Impl_Unlock(
|
|
LPDIRECTDRAWSURFACE4 iface,LPVOID surface
|
|
) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
TRACE(ddraw,"(%p)->Unlock(%p)\n",This,surface);
|
|
return DD_OK;
|
|
}
|
|
|
|
static void Xlib_copy_surface_on_screen(IDirectDrawSurface4Impl* 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_IDirectDrawSurface4Impl_Unlock(
|
|
LPDIRECTDRAWSURFACE4 iface,LPVOID surface)
|
|
{
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
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_IDirectDrawSurface4Impl_Flip(
|
|
LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAWSURFACE4 flipto,DWORD dwFlags
|
|
) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
IDirectDrawSurface4Impl* iflipto=(IDirectDrawSurface4Impl*)flipto;
|
|
#ifdef HAVE_LIBXXF86DGA
|
|
TRACE(ddraw,"(%p)->Flip(%p,%08lx)\n",This,iflipto,dwFlags);
|
|
if (!iflipto) {
|
|
if (This->s.backbuffer)
|
|
iflipto = This->s.backbuffer;
|
|
else
|
|
iflipto = This;
|
|
}
|
|
TSXF86DGASetViewPort(display,DefaultScreen(display),0,iflipto->t.dga.fb_height);
|
|
|
|
if (iflipto->s.palette && iflipto->s.palette->cm) {
|
|
TSXF86DGAInstallColormap(display,DefaultScreen(display),iflipto->s.palette->cm);
|
|
}
|
|
while (!TSXF86DGAViewPortChanged(display,DefaultScreen(display),2)) {
|
|
}
|
|
if (iflipto!=This) {
|
|
int tmp;
|
|
LPVOID ptmp;
|
|
|
|
tmp = This->t.dga.fb_height;
|
|
This->t.dga.fb_height = iflipto->t.dga.fb_height;
|
|
iflipto->t.dga.fb_height = tmp;
|
|
|
|
ptmp = This->s.surface_desc.y.lpSurface;
|
|
This->s.surface_desc.y.lpSurface = iflipto->s.surface_desc.y.lpSurface;
|
|
iflipto->s.surface_desc.y.lpSurface = ptmp;
|
|
}
|
|
return DD_OK;
|
|
#else /* defined(HAVE_LIBXXF86DGA) */
|
|
return E_UNEXPECTED;
|
|
#endif /* defined(HAVE_LIBXXF86DGA) */
|
|
}
|
|
|
|
static HRESULT WINAPI Xlib_IDirectDrawSurface4Impl_Flip(
|
|
LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAWSURFACE4 flipto,DWORD dwFlags
|
|
) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
IDirectDrawSurface4Impl* iflipto=(IDirectDrawSurface4Impl*)flipto;
|
|
TRACE(ddraw,"(%p)->Flip(%p,%08lx)\n",This,iflipto,dwFlags);
|
|
|
|
#ifdef HAVE_MESAGL
|
|
if ((This->s.d3d_device != NULL) ||
|
|
((This->s.backbuffer != NULL) && (This->s.backbuffer->s.d3d_device != NULL))) {
|
|
TRACE(ddraw," - OpenGL flip\n");
|
|
ENTER_GL();
|
|
glXSwapBuffers(display,
|
|
This->s.ddraw->d.drawable);
|
|
LEAVE_GL();
|
|
|
|
return DD_OK;
|
|
}
|
|
#endif /* defined(HAVE_MESAGL) */
|
|
|
|
if (!This->s.ddraw->d.paintable)
|
|
return DD_OK;
|
|
|
|
if (!iflipto) {
|
|
if (This->s.backbuffer)
|
|
iflipto = This->s.backbuffer;
|
|
else
|
|
iflipto = This;
|
|
}
|
|
|
|
Xlib_copy_surface_on_screen(iflipto);
|
|
|
|
if (iflipto->s.palette && iflipto->s.palette->cm) {
|
|
TSXSetWindowColormap(display,This->s.ddraw->d.drawable,iflipto->s.palette->cm);
|
|
}
|
|
if (iflipto!=This) {
|
|
XImage *tmp;
|
|
LPVOID *surf;
|
|
tmp = This->t.xlib.image;
|
|
This->t.xlib.image = iflipto->t.xlib.image;
|
|
iflipto->t.xlib.image = tmp;
|
|
surf = This->s.surface_desc.y.lpSurface;
|
|
This->s.surface_desc.y.lpSurface = iflipto->s.surface_desc.y.lpSurface;
|
|
iflipto->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_IDirectDrawSurface4Impl_SetPalette(
|
|
LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAWPALETTE pal
|
|
) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
IDirectDrawPaletteImpl* ipal=(IDirectDrawPaletteImpl*)pal;
|
|
int i;
|
|
TRACE(ddraw,"(%p)->(%p)\n",This,ipal);
|
|
|
|
if (ipal == NULL) {
|
|
if( This->s.palette != NULL )
|
|
IDirectDrawPalette_Release((IDirectDrawPalette*)This->s.palette);
|
|
This->s.palette = ipal;
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
if( !(ipal->cm) && (This->s.ddraw->d.screen_pixelformat.x.dwRGBBitCount<=8))
|
|
{
|
|
ipal->cm = TSXCreateColormap(display,This->s.ddraw->d.drawable,
|
|
DefaultVisualOfScreen(X11DRV_GetXScreen()),AllocAll);
|
|
|
|
if (!Options.managed)
|
|
TSXInstallColormap(display,ipal->cm);
|
|
|
|
for (i=0;i<256;i++) {
|
|
XColor xc;
|
|
|
|
xc.red = ipal->palents[i].peRed<<8;
|
|
xc.blue = ipal->palents[i].peBlue<<8;
|
|
xc.green = ipal->palents[i].peGreen<<8;
|
|
xc.flags = DoRed|DoBlue|DoGreen;
|
|
xc.pixel = i;
|
|
TSXStoreColor(display,ipal->cm,&xc);
|
|
}
|
|
TSXInstallColormap(display,ipal->cm);
|
|
}
|
|
|
|
/* According to spec, we are only supposed to
|
|
* AddRef if this is not the same palette.
|
|
*/
|
|
if( This->s.palette != ipal )
|
|
{
|
|
if( ipal != NULL )
|
|
IDirectDrawPalette_AddRef( (IDirectDrawPalette*)ipal );
|
|
if( This->s.palette != NULL )
|
|
IDirectDrawPalette_Release( (IDirectDrawPalette*)This->s.palette );
|
|
This->s.palette = ipal;
|
|
|
|
/* I think that we need to attach it to all backbuffers...*/
|
|
if( This->s.backbuffer ) {
|
|
if( This->s.backbuffer->s.palette )
|
|
IDirectDrawPalette_Release( (IDirectDrawPalette*)This->s.backbuffer->s.palette );
|
|
This->s.backbuffer->s.palette = ipal;
|
|
if( ipal )
|
|
IDirectDrawPalette_AddRef( (IDirectDrawPalette*)ipal );
|
|
}
|
|
/* Perform the refresh */
|
|
TSXSetWindowColormap(display,This->s.ddraw->d.drawable,This->s.palette->cm);
|
|
}
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI DGA_IDirectDrawSurface4Impl_SetPalette(
|
|
LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAWPALETTE pal
|
|
) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
IDirectDrawPaletteImpl* ipal=(IDirectDrawPaletteImpl*)pal;
|
|
TRACE(ddraw,"(%p)->(%p)\n",This,ipal);
|
|
#ifdef HAVE_LIBXXF86DGA
|
|
/* According to spec, we are only supposed to
|
|
* AddRef if this is not the same palette.
|
|
*/
|
|
if( This->s.palette != ipal )
|
|
{
|
|
if( ipal != NULL )
|
|
IDirectDrawPalette_AddRef( (IDirectDrawPalette*)ipal );
|
|
if( This->s.palette != NULL )
|
|
IDirectDrawPalette_Release( (IDirectDrawPalette*)This->s.palette );
|
|
This->s.palette = ipal;
|
|
|
|
/* I think that we need to attach it to all backbuffers...*/
|
|
if( This->s.backbuffer ) {
|
|
if( This->s.backbuffer->s.palette )
|
|
IDirectDrawPalette_Release( (IDirectDrawPalette*)This->s.backbuffer->s.palette );
|
|
This->s.backbuffer->s.palette = ipal;
|
|
if ( ipal )
|
|
IDirectDrawPalette_AddRef( (IDirectDrawPalette*)ipal );
|
|
}
|
|
TSXF86DGAInstallColormap(display,DefaultScreen(display),This->s.palette->cm);
|
|
}
|
|
return DD_OK;
|
|
#else /* defined(HAVE_LIBXXF86DGA) */
|
|
return E_UNEXPECTED;
|
|
#endif /* defined(HAVE_LIBXXF86DGA) */
|
|
|
|
|
|
}
|
|
|
|
static HRESULT _Blt_ColorFill(LPBYTE buf, int width, int height, int bpp, LONG lPitch, DWORD color)
|
|
{
|
|
int x, y;
|
|
LPBYTE first;
|
|
|
|
/* Do first row */
|
|
|
|
#define COLORFILL_ROW(type) { \
|
|
type *d = (type *) buf; \
|
|
for (x = 0; x < width; x++) \
|
|
d[x] = (type) color; \
|
|
break; \
|
|
}
|
|
|
|
switch(bpp) {
|
|
case 1: COLORFILL_ROW(BYTE)
|
|
case 2: COLORFILL_ROW(WORD)
|
|
case 4: COLORFILL_ROW(DWORD)
|
|
default:
|
|
FIXME(ddraw, "Stretched blit not implemented for bpp %d!\n", bpp*8);
|
|
return DDERR_UNSUPPORTED;
|
|
}
|
|
|
|
#undef COLORFILL_ROW
|
|
|
|
/* Now copy first row */
|
|
first = buf;
|
|
for (y = 1; y < height; y++) {
|
|
buf += lPitch;
|
|
memcpy(buf, first, width * bpp);
|
|
}
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawSurface4Impl_Blt(
|
|
LPDIRECTDRAWSURFACE4 iface,LPRECT rdst,LPDIRECTDRAWSURFACE4 src,LPRECT rsrc,DWORD dwFlags,LPDDBLTFX lpbltfx
|
|
) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
RECT xdst,xsrc;
|
|
DDSURFACEDESC ddesc,sdesc;
|
|
HRESULT ret = DD_OK;
|
|
int bpp, srcheight, srcwidth, dstheight, dstwidth, width;
|
|
int x, y;
|
|
LPBYTE dbuf, sbuf;
|
|
|
|
TRACE(ddraw,"(%p)->(%p,%p,%p,%08lx,%p)\n", This,rdst,src,rsrc,dwFlags,lpbltfx);
|
|
|
|
if (src) IDirectDrawSurface4_Lock(src, NULL, &sdesc, 0, 0);
|
|
IDirectDrawSurface4_Lock(iface,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));
|
|
}
|
|
}
|
|
|
|
bpp = GET_BPP(ddesc);
|
|
srcheight = xsrc.bottom - xsrc.top;
|
|
srcwidth = xsrc.right - xsrc.left;
|
|
dstheight = xdst.bottom - xdst.top;
|
|
dstwidth = xdst.right - xdst.left;
|
|
width = (xdst.right - xdst.left) * bpp;
|
|
dbuf = (BYTE *) ddesc.y.lpSurface + (xdst.top * ddesc.lPitch) + (xdst.left * bpp);
|
|
|
|
dwFlags &= ~(DDBLT_WAIT|DDBLT_ASYNC);/* FIXME: can't handle right now */
|
|
|
|
/* First, all the 'source-less' blits */
|
|
if (dwFlags & DDBLT_COLORFILL) {
|
|
ret = _Blt_ColorFill(dbuf, dstwidth, dstheight, bpp,
|
|
ddesc.lPitch, lpbltfx->b.dwFillColor);
|
|
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 /* defined(HAVE_MESAGL) */
|
|
}
|
|
|
|
if (dwFlags & DDBLT_ROP) {
|
|
/* Catch some degenerate cases here */
|
|
switch(lpbltfx->dwROP) {
|
|
case BLACKNESS:
|
|
ret = _Blt_ColorFill(dbuf, dstwidth, dstheight, bpp, ddesc.lPitch, 0);
|
|
break;
|
|
case 0xAA0029: /* No-op */
|
|
break;
|
|
case WHITENESS:
|
|
ret = _Blt_ColorFill(dbuf, dstwidth, dstheight, bpp, ddesc.lPitch, ~0);
|
|
break;
|
|
default:
|
|
FIXME(ddraw, "Unsupported raster op: %08lx Pattern: %p\n", lpbltfx->dwROP, lpbltfx->b.lpDDSPattern);
|
|
goto error;
|
|
}
|
|
dwFlags &= ~DDBLT_ROP;
|
|
}
|
|
|
|
if (dwFlags & DDBLT_DDROPS) {
|
|
FIXME(ddraw, "\tDdraw Raster Ops: %08lx Pattern: %p\n", lpbltfx->dwDDROP, lpbltfx->b.lpDDSPattern);
|
|
}
|
|
|
|
/* Now the 'with source' blits */
|
|
if (src) {
|
|
LPBYTE sbase;
|
|
int sx, xinc, sy, yinc;
|
|
|
|
sbase = (BYTE *) sdesc.y.lpSurface + (xsrc.top * sdesc.lPitch) + xsrc.left * bpp;
|
|
xinc = (srcwidth << 16) / dstwidth;
|
|
yinc = (srcheight << 16) / dstheight;
|
|
|
|
if (!dwFlags) {
|
|
|
|
/* No effects, we can cheat here */
|
|
if (dstwidth == srcwidth) {
|
|
if (dstheight == srcheight) {
|
|
/* No stretching in either direction. This needs to be as fast as possible */
|
|
sbuf = sbase;
|
|
for (y = 0; y < dstheight; y++) {
|
|
memcpy(dbuf, sbuf, width);
|
|
sbuf += sdesc.lPitch;
|
|
dbuf += ddesc.lPitch;
|
|
}
|
|
} else {
|
|
/* Stretching in Y direction only */
|
|
for (y = sy = 0; y < dstheight; y++, sy += yinc) {
|
|
sbuf = sbase + (sy >> 16) * sdesc.lPitch;
|
|
memcpy(dbuf, sbuf, width);
|
|
dbuf += ddesc.lPitch;
|
|
}
|
|
}
|
|
} else {
|
|
/* Stretching in X direction */
|
|
int last_sy = -1;
|
|
for (y = sy = 0; y < dstheight; y++, sy += yinc) {
|
|
sbuf = sbase + (sy >> 16) * sdesc.lPitch;
|
|
|
|
if ((sy >> 16) == (last_sy >> 16)) {
|
|
/* Same as last row - copy already stretched row */
|
|
memcpy(dbuf, dbuf - ddesc.lPitch, width);
|
|
} else {
|
|
|
|
#define STRETCH_ROW(type) { \
|
|
type *s = (type *) sbuf, *d = (type *) dbuf; \
|
|
for (x = sx = 0; x < dstwidth; x++, sx += xinc) \
|
|
d[x] = s[sx >> 16]; \
|
|
break; \
|
|
}
|
|
|
|
switch(bpp) {
|
|
case 1: STRETCH_ROW(BYTE)
|
|
case 2: STRETCH_ROW(WORD)
|
|
case 4: STRETCH_ROW(DWORD)
|
|
default:
|
|
FIXME(ddraw, "Stretched blit not implemented for bpp %d!\n", bpp*8);
|
|
ret = DDERR_UNSUPPORTED;
|
|
goto error;
|
|
}
|
|
|
|
#undef STRETCH_ROW
|
|
|
|
}
|
|
last_sy = sy;
|
|
dbuf += ddesc.lPitch;
|
|
}
|
|
}
|
|
} else if (dwFlags & (DDBLT_KEYSRC | DDBLT_KEYDEST)) {
|
|
DWORD keylow, keyhigh;
|
|
|
|
if (dwFlags & DDBLT_KEYSRC) {
|
|
keylow = sdesc.ddckCKSrcBlt.dwColorSpaceLowValue;
|
|
keyhigh = sdesc.ddckCKSrcBlt.dwColorSpaceHighValue;
|
|
} else {
|
|
/* I'm not sure if this is correct */
|
|
FIXME(ddraw, "DDBLT_KEYDEST not fully supported yet.\n");
|
|
keylow = ddesc.ddckCKDestBlt.dwColorSpaceLowValue;
|
|
keyhigh = ddesc.ddckCKDestBlt.dwColorSpaceHighValue;
|
|
}
|
|
|
|
#define COPYROW_COLORKEY(type) { \
|
|
type *s = (type *) sbuf, *d = (type *) dbuf, tmp; \
|
|
for (x = sx = 0; x < dstwidth; x++, sx += xinc) { \
|
|
tmp = s[sx >> 16]; \
|
|
if (tmp < keylow || tmp > keyhigh) d[x] = tmp; \
|
|
} \
|
|
break; \
|
|
}
|
|
|
|
for (y = sy = 0; y < dstheight; y++, sy += yinc) {
|
|
sbuf = sbase + (sy >> 16) * sdesc.lPitch;
|
|
|
|
switch (bpp) {
|
|
case 1: COPYROW_COLORKEY(BYTE)
|
|
case 2: COPYROW_COLORKEY(WORD)
|
|
case 4: COPYROW_COLORKEY(DWORD)
|
|
default:
|
|
FIXME(ddraw, "%s color-keyed blit not implemented for bpp %d!\n",
|
|
(dwFlags & DDBLT_KEYSRC) ? "Source" : "Destination", bpp*8);
|
|
ret = DDERR_UNSUPPORTED;
|
|
goto error;
|
|
}
|
|
dbuf += ddesc.lPitch;
|
|
}
|
|
|
|
#undef COPYROW_COLORKEY
|
|
|
|
dwFlags &= ~(DDBLT_KEYSRC | DDBLT_KEYDEST);
|
|
|
|
}
|
|
}
|
|
|
|
error:
|
|
|
|
if (dwFlags && FIXME_ON(ddraw)) {
|
|
FIXME(ddraw,"\tUnsupported flags: ");
|
|
_dump_DDBLT(dwFlags);
|
|
}
|
|
|
|
IDirectDrawSurface4_Unlock(iface,ddesc.y.lpSurface);
|
|
if (src) IDirectDrawSurface4_Unlock(src,sdesc.y.lpSurface);
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawSurface4Impl_BltFast(
|
|
LPDIRECTDRAWSURFACE4 iface,DWORD dstx,DWORD dsty,LPDIRECTDRAWSURFACE4 src,LPRECT rsrc,DWORD trans
|
|
) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
int bpp, w, h, x, y;
|
|
DDSURFACEDESC ddesc,sdesc;
|
|
HRESULT ret = DD_OK;
|
|
LPBYTE sbuf, dbuf;
|
|
|
|
|
|
if (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. */
|
|
IDirectDrawSurface4_Lock(src, NULL,&sdesc,DDLOCK_READONLY, 0);
|
|
IDirectDrawSurface4_Lock(iface,NULL,&ddesc,DDLOCK_WRITEONLY,0);
|
|
|
|
bpp = GET_BPP(This->s.surface_desc);
|
|
sbuf = (BYTE *) sdesc.y.lpSurface + (rsrc->top * sdesc.lPitch) + rsrc->left * bpp;
|
|
dbuf = (BYTE *) ddesc.y.lpSurface + (dsty * ddesc.lPitch) + dstx * bpp;
|
|
|
|
|
|
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;
|
|
|
|
if (trans & (DDBLTFAST_SRCCOLORKEY | DDBLTFAST_DESTCOLORKEY)) {
|
|
DWORD keylow, keyhigh;
|
|
if (trans & DDBLTFAST_SRCCOLORKEY) {
|
|
keylow = sdesc.ddckCKSrcBlt.dwColorSpaceLowValue;
|
|
keyhigh = sdesc.ddckCKSrcBlt.dwColorSpaceHighValue;
|
|
} else {
|
|
/* I'm not sure if this is correct */
|
|
FIXME(ddraw, "DDBLTFAST_DESTCOLORKEY not fully supported yet.\n");
|
|
keylow = ddesc.ddckCKDestBlt.dwColorSpaceLowValue;
|
|
keyhigh = ddesc.ddckCKDestBlt.dwColorSpaceHighValue;
|
|
}
|
|
|
|
#define COPYBOX_COLORKEY(type) { \
|
|
type *d = (type *)dbuf, *s = (type *)sbuf, tmp; \
|
|
s = (type *) ((BYTE *) sdesc.y.lpSurface + (rsrc->top * sdesc.lPitch) + rsrc->left * bpp); \
|
|
d = (type *) ((BYTE *) ddesc.y.lpSurface + (dsty * ddesc.lPitch) + dstx * bpp); \
|
|
for (y = 0; y < h; y++) { \
|
|
for (x = 0; x < w; x++) { \
|
|
tmp = s[x]; \
|
|
if (tmp < keylow || tmp > keyhigh) d[x] = tmp; \
|
|
} \
|
|
(LPBYTE)s += sdesc.lPitch; \
|
|
(LPBYTE)d += ddesc.lPitch; \
|
|
} \
|
|
break; \
|
|
}
|
|
|
|
switch (bpp) {
|
|
case 1: COPYBOX_COLORKEY(BYTE)
|
|
case 2: COPYBOX_COLORKEY(WORD)
|
|
case 4: COPYBOX_COLORKEY(DWORD)
|
|
default:
|
|
FIXME(ddraw, "Source color key blitting not supported for bpp %d\n", bpp*8);
|
|
ret = DDERR_UNSUPPORTED;
|
|
goto error;
|
|
}
|
|
|
|
#undef COPYBOX_COLORKEY
|
|
|
|
} else {
|
|
int width = w * bpp;
|
|
|
|
for (y = 0; y < h; y++) {
|
|
memcpy(dbuf, sbuf, width);
|
|
sbuf += sdesc.lPitch;
|
|
dbuf += ddesc.lPitch;
|
|
}
|
|
}
|
|
|
|
error:
|
|
|
|
IDirectDrawSurface4_Unlock(iface,ddesc.y.lpSurface);
|
|
IDirectDrawSurface4_Unlock(src,sdesc.y.lpSurface);
|
|
return ret;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawSurface4Impl_BltBatch(
|
|
LPDIRECTDRAWSURFACE4 iface,LPDDBLTBATCH ddbltbatch,DWORD x,DWORD y
|
|
) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
FIXME(ddraw,"(%p)->BltBatch(%p,%08lx,%08lx),stub!\n",
|
|
This,ddbltbatch,x,y
|
|
);
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawSurface4Impl_GetCaps(
|
|
LPDIRECTDRAWSURFACE4 iface,LPDDSCAPS caps
|
|
) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
TRACE(ddraw,"(%p)->GetCaps(%p)\n",This,caps);
|
|
caps->dwCaps = DDSCAPS_PALETTE; /* probably more */
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawSurface4Impl_GetSurfaceDesc(
|
|
LPDIRECTDRAWSURFACE4 iface,LPDDSURFACEDESC ddsd
|
|
) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
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_surface_desc(ddsd);
|
|
}
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
static ULONG WINAPI IDirectDrawSurface4Impl_AddRef(LPDIRECTDRAWSURFACE4 iface) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
TRACE( ddraw, "(%p)->() incrementing from %lu.\n", This, This->ref );
|
|
|
|
return ++(This->ref);
|
|
}
|
|
|
|
static ULONG WINAPI DGA_IDirectDrawSurface4Impl_Release(LPDIRECTDRAWSURFACE4 iface) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
TRACE( ddraw, "(%p)->() decrementing from %lu.\n", This, This->ref );
|
|
|
|
#ifdef HAVE_LIBXXF86DGA
|
|
if (!--(This->ref)) {
|
|
IDirectDraw2_Release((IDirectDraw2*)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)
|
|
IDirectDrawSurface4_Release((IDirectDrawSurface4*)This->s.backbuffer);
|
|
|
|
/* Free the DIBSection (if any) */
|
|
if (This->s.hdc != 0) {
|
|
SelectObject(This->s.hdc, This->s.holdbitmap);
|
|
DeleteDC(This->s.hdc);
|
|
DeleteObject(This->s.DIBsection);
|
|
}
|
|
|
|
HeapFree(GetProcessHeap(),0,This);
|
|
return 0;
|
|
}
|
|
#endif /* defined(HAVE_LIBXXF86DGA) */
|
|
return This->ref;
|
|
}
|
|
|
|
static ULONG WINAPI Xlib_IDirectDrawSurface4Impl_Release(LPDIRECTDRAWSURFACE4 iface) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
TRACE( ddraw, "(%p)->() decrementing from %lu.\n", This, This->ref );
|
|
|
|
if (!--(This->ref)) {
|
|
IDirectDraw2_Release((IDirectDraw2*)This->s.ddraw);
|
|
|
|
if( This->s.backbuffer )
|
|
IDirectDrawSurface4_Release((IDirectDrawSurface4*)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)
|
|
IDirectDrawPalette_Release((IDirectDrawPalette*)This->s.palette);
|
|
|
|
/* Free the DIBSection (if any) */
|
|
if (This->s.hdc != 0) {
|
|
SelectObject(This->s.hdc, This->s.holdbitmap);
|
|
DeleteDC(This->s.hdc);
|
|
DeleteObject(This->s.DIBsection);
|
|
}
|
|
|
|
HeapFree(GetProcessHeap(),0,This);
|
|
return 0;
|
|
}
|
|
|
|
return This->ref;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawSurface4Impl_GetAttachedSurface(
|
|
LPDIRECTDRAWSURFACE4 iface,LPDDSCAPS lpddsd,LPDIRECTDRAWSURFACE4 *lpdsf
|
|
) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
TRACE(ddraw, "(%p)->GetAttachedSurface(%p,%p)\n",
|
|
This, lpddsd, lpdsf);
|
|
|
|
if (TRACE_ON(ddraw)) {
|
|
TRACE(ddraw," caps ");
|
|
_dump_DDSCAPS((void *) &(lpddsd->dwCaps));
|
|
DUMP("\n");
|
|
}
|
|
|
|
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 = (LPDIRECTDRAWSURFACE4)This->s.backbuffer;
|
|
|
|
if( This->s.backbuffer )
|
|
IDirectDrawSurface4_AddRef( (IDirectDrawSurface4*)This->s.backbuffer );
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawSurface4Impl_Initialize(
|
|
LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAW ddraw,LPDDSURFACEDESC lpdsfd
|
|
) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
TRACE(ddraw,"(%p)->(%p, %p)\n",This,ddraw,lpdsfd);
|
|
|
|
return DDERR_ALREADYINITIALIZED;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawSurface4Impl_GetPixelFormat(
|
|
LPDIRECTDRAWSURFACE4 iface,LPDDPIXELFORMAT pf
|
|
) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
TRACE(ddraw,"(%p)->(%p)\n",This,pf);
|
|
|
|
*pf = This->s.surface_desc.ddpfPixelFormat;
|
|
|
|
if (TRACE_ON(ddraw)) {
|
|
_dump_pixelformat(pf);
|
|
DUMP("\n");
|
|
}
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawSurface4Impl_GetBltStatus(LPDIRECTDRAWSURFACE4 iface,DWORD dwFlags) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
FIXME(ddraw,"(%p)->(0x%08lx),stub!\n",This,dwFlags);
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawSurface4Impl_GetOverlayPosition(
|
|
LPDIRECTDRAWSURFACE4 iface,LPLONG x1,LPLONG x2
|
|
) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
FIXME(ddraw,"(%p)->(%p,%p),stub!\n",This,x1,x2);
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawSurface4Impl_SetClipper(
|
|
LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAWCLIPPER clipper
|
|
) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
FIXME(ddraw,"(%p)->(%p),stub!\n",This,clipper);
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawSurface4Impl_AddAttachedSurface(
|
|
LPDIRECTDRAWSURFACE4 iface,LPDIRECTDRAWSURFACE4 surf
|
|
) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
FIXME(ddraw,"(%p)->(%p),stub!\n",This,surf);
|
|
|
|
IDirectDrawSurface4_AddRef(iface);
|
|
|
|
/* This hack will be enough for the moment */
|
|
if (This->s.backbuffer == NULL)
|
|
This->s.backbuffer = (IDirectDrawSurface4Impl*)surf;
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawSurface4Impl_GetDC(LPDIRECTDRAWSURFACE4 iface,HDC* lphdc) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
DDSURFACEDESC desc;
|
|
BITMAPINFO *b_info;
|
|
UINT usage;
|
|
|
|
FIXME(ddraw,"(%p)->GetDC(%p)\n",This,lphdc);
|
|
|
|
/* Creates a DIB Section of the same size / format as the surface */
|
|
IDirectDrawSurface4_Lock(iface,NULL,&desc,0,0);
|
|
|
|
if (This->s.hdc == 0) {
|
|
switch (desc.ddpfPixelFormat.x.dwRGBBitCount) {
|
|
case 16:
|
|
case 32:
|
|
#if 0 /* This should be filled if Wine's DIBSection did understand BI_BITFIELDS */
|
|
b_info = (BITMAPINFO *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 3 * sizeof(DWORD));
|
|
break;
|
|
#endif
|
|
|
|
case 24:
|
|
b_info = (BITMAPINFO *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER));
|
|
break;
|
|
|
|
default:
|
|
b_info = (BITMAPINFO *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
|
|
sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * (2 << desc.ddpfPixelFormat.x.dwRGBBitCount));
|
|
break;
|
|
}
|
|
|
|
b_info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
|
b_info->bmiHeader.biWidth = desc.dwWidth;
|
|
b_info->bmiHeader.biHeight = desc.dwHeight;
|
|
b_info->bmiHeader.biPlanes = 1;
|
|
b_info->bmiHeader.biBitCount = desc.ddpfPixelFormat.x.dwRGBBitCount;
|
|
#if 0
|
|
if ((desc.ddpfPixelFormat.x.dwRGBBitCount != 16) &&
|
|
(desc.ddpfPixelFormat.x.dwRGBBitCount != 32))
|
|
#endif
|
|
b_info->bmiHeader.biCompression = BI_RGB;
|
|
#if 0
|
|
else
|
|
b_info->bmiHeader.biCompression = BI_BITFIELDS;
|
|
#endif
|
|
b_info->bmiHeader.biSizeImage = (desc.ddpfPixelFormat.x.dwRGBBitCount / 8) * desc.dwWidth * desc.dwHeight;
|
|
b_info->bmiHeader.biXPelsPerMeter = 0;
|
|
b_info->bmiHeader.biYPelsPerMeter = 0;
|
|
b_info->bmiHeader.biClrUsed = 0;
|
|
b_info->bmiHeader.biClrImportant = 0;
|
|
|
|
switch (desc.ddpfPixelFormat.x.dwRGBBitCount) {
|
|
case 16:
|
|
case 32:
|
|
#if 0
|
|
{
|
|
DWORD *masks = (DWORD *) &(b_info->bmiColors);
|
|
|
|
usage = 0;
|
|
masks[0] = desc.ddpfPixelFormat.y.dwRBitMask;
|
|
masks[1] = desc.ddpfPixelFormat.z.dwGBitMask;
|
|
masks[2] = desc.ddpfPixelFormat.xx.dwBBitMask;
|
|
} break;
|
|
#endif
|
|
|
|
case 24:
|
|
/* Nothing to do */
|
|
usage = DIB_RGB_COLORS;
|
|
break;
|
|
|
|
default: {
|
|
int i;
|
|
|
|
/* Fill the palette */
|
|
usage = DIB_RGB_COLORS;
|
|
|
|
if (This->s.palette == NULL) {
|
|
ERR(ddraw, "Bad palette !!!\n");
|
|
} else {
|
|
RGBQUAD *rgb = (RGBQUAD *) &(b_info->bmiColors);
|
|
PALETTEENTRY *pent = (PALETTEENTRY *) &(This->s.palette->palents);
|
|
|
|
for (i = 0; i < (2 << desc.ddpfPixelFormat.x.dwRGBBitCount); i++) {
|
|
rgb[i].rgbBlue = pent[i].peBlue;
|
|
rgb[i].rgbRed = pent[i].peRed;
|
|
rgb[i].rgbGreen = pent[i].peGreen;
|
|
}
|
|
}
|
|
} break;
|
|
}
|
|
|
|
This->s.DIBsection = CreateDIBSection(BeginPaint(This->s.ddraw->d.mainWindow,&This->s.ddraw->d.ps),
|
|
b_info,
|
|
usage,
|
|
&(This->s.bitmap_data),
|
|
NULL,
|
|
0);
|
|
EndPaint(This->s.ddraw->d.mainWindow,&This->s.ddraw->d.ps);
|
|
TRACE(ddraw, "DIBSection at : %p\n", This->s.bitmap_data);
|
|
|
|
/* b_info is not useful anymore */
|
|
HeapFree(GetProcessHeap(), 0, b_info);
|
|
|
|
/* Create the DC */
|
|
This->s.hdc = CreateCompatibleDC(0);
|
|
This->s.holdbitmap = SelectObject(This->s.hdc, This->s.DIBsection);
|
|
}
|
|
|
|
/* Copy our surface in the DIB section */
|
|
if ((GET_BPP(desc) * desc.dwWidth) == desc.lPitch) {
|
|
memcpy(This->s.bitmap_data, desc.y.lpSurface, desc.lPitch * desc.dwHeight);
|
|
} else {
|
|
/* TODO */
|
|
FIXME(ddraw, "This case has to be done :/\n");
|
|
}
|
|
|
|
TRACE(ddraw, "HDC : %08lx\n", (DWORD) This->s.hdc);
|
|
*lphdc = This->s.hdc;
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawSurface4Impl_ReleaseDC(LPDIRECTDRAWSURFACE4 iface,HDC hdc) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
|
|
FIXME(ddraw,"(%p)->(0x%08lx),stub!\n",This,(long)hdc);
|
|
|
|
TRACE(ddraw, "Copying DIBSection at : %p\n", This->s.bitmap_data);
|
|
|
|
/* Copy the DIB section to our surface */
|
|
if ((GET_BPP(This->s.surface_desc) * This->s.surface_desc.dwWidth) == This->s.surface_desc.lPitch) {
|
|
memcpy(This->s.surface_desc.y.lpSurface, This->s.bitmap_data, This->s.surface_desc.lPitch * This->s.surface_desc.dwHeight);
|
|
} else {
|
|
/* TODO */
|
|
FIXME(ddraw, "This case has to be done :/\n");
|
|
}
|
|
|
|
/* Unlock the surface */
|
|
IDirectDrawSurface4_Unlock(iface,This->s.surface_desc.y.lpSurface);
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawSurface4Impl_QueryInterface(LPDIRECTDRAWSURFACE4 iface,REFIID refiid,LPVOID *obj) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
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;
|
|
IDirectDrawSurface4_AddRef(iface);
|
|
|
|
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);
|
|
IDirectDrawSurface4_AddRef(iface);
|
|
|
|
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);
|
|
IDirectDrawSurface4_AddRef(iface);
|
|
|
|
TRACE(ddraw, " Creating IDirect3DTexture interface (%p)\n", *obj);
|
|
|
|
return S_OK;
|
|
}
|
|
else if (is_OpenGL_dx3(refiid, (IDirectDrawSurfaceImpl*)This, (IDirect3DDeviceImpl**) obj))
|
|
{
|
|
/* It is the OpenGL Direct3D Device */
|
|
IDirectDrawSurface4_AddRef(iface);
|
|
|
|
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 IDirectDrawSurface4Impl_IsLost(LPDIRECTDRAWSURFACE4 iface) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
TRACE(ddraw,"(%p)->(), stub!\n",This);
|
|
return DD_OK; /* hmm */
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawSurface4Impl_EnumAttachedSurfaces(LPDIRECTDRAWSURFACE4 iface,LPVOID context,LPDDENUMSURFACESCALLBACK esfcb) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
FIXME(ddraw,"(%p)->(%p,%p),stub!\n",This,context,esfcb);
|
|
|
|
/* For the moment, only enumerating the back buffer */
|
|
if (This->s.backbuffer != NULL) {
|
|
TRACE(ddraw, "Enumerating back-buffer (%p)\n", This->s.backbuffer);
|
|
if (esfcb((LPDIRECTDRAWSURFACE) This->s.backbuffer, &(This->s.backbuffer->s.surface_desc), context) == DDENUMRET_CANCEL)
|
|
return DD_OK;
|
|
}
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawSurface4Impl_Restore(LPDIRECTDRAWSURFACE4 iface) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
FIXME(ddraw,"(%p)->(),stub!\n",This);
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawSurface4Impl_SetColorKey(
|
|
LPDIRECTDRAWSURFACE4 iface, DWORD dwFlags, LPDDCOLORKEY ckey )
|
|
{
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
TRACE(ddraw,"(%p)->(0x%08lx,%p)\n",This,dwFlags,ckey);
|
|
if (TRACE_ON(ddraw)) {
|
|
_dump_colorkeyflag(dwFlags);
|
|
DUMP(" : ");
|
|
_dump_DDCOLORKEY((void *) ckey);
|
|
DUMP("\n");
|
|
}
|
|
|
|
/* If this surface was loaded as a texture, call also the texture
|
|
SetColorKey callback */
|
|
if (This->s.texture) {
|
|
This->s.SetColorKey_cb(This->s.texture, 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 IDirectDrawSurface4Impl_AddOverlayDirtyRect(
|
|
LPDIRECTDRAWSURFACE4 iface,
|
|
LPRECT lpRect )
|
|
{
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
FIXME(ddraw,"(%p)->(%p),stub!\n",This,lpRect);
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawSurface4Impl_DeleteAttachedSurface(
|
|
LPDIRECTDRAWSURFACE4 iface,
|
|
DWORD dwFlags,
|
|
LPDIRECTDRAWSURFACE4 lpDDSAttachedSurface )
|
|
{
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
FIXME(ddraw,"(%p)->(0x%08lx,%p),stub!\n",This,dwFlags,lpDDSAttachedSurface);
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawSurface4Impl_EnumOverlayZOrders(
|
|
LPDIRECTDRAWSURFACE4 iface,
|
|
DWORD dwFlags,
|
|
LPVOID lpContext,
|
|
LPDDENUMSURFACESCALLBACK lpfnCallback )
|
|
{
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
FIXME(ddraw,"(%p)->(0x%08lx,%p,%p),stub!\n", This,dwFlags,
|
|
lpContext, lpfnCallback );
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawSurface4Impl_GetClipper(
|
|
LPDIRECTDRAWSURFACE4 iface,
|
|
LPDIRECTDRAWCLIPPER* lplpDDClipper )
|
|
{
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
FIXME(ddraw,"(%p)->(%p),stub!\n", This, lplpDDClipper);
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawSurface4Impl_GetColorKey(
|
|
LPDIRECTDRAWSURFACE4 iface,
|
|
DWORD dwFlags,
|
|
LPDDCOLORKEY lpDDColorKey )
|
|
{
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
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 IDirectDrawSurface4Impl_GetFlipStatus(
|
|
LPDIRECTDRAWSURFACE4 iface,
|
|
DWORD dwFlags )
|
|
{
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
FIXME(ddraw,"(%p)->(0x%08lx),stub!\n", This, dwFlags);
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawSurface4Impl_GetPalette(
|
|
LPDIRECTDRAWSURFACE4 iface,
|
|
LPDIRECTDRAWPALETTE* lplpDDPalette )
|
|
{
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
FIXME(ddraw,"(%p)->(%p),stub!\n", This, lplpDDPalette);
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawSurface4Impl_SetOverlayPosition(
|
|
LPDIRECTDRAWSURFACE4 iface,
|
|
LONG lX,
|
|
LONG lY)
|
|
{
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
FIXME(ddraw,"(%p)->(%ld,%ld),stub!\n", This, lX, lY);
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawSurface4Impl_UpdateOverlay(
|
|
LPDIRECTDRAWSURFACE4 iface,
|
|
LPRECT lpSrcRect,
|
|
LPDIRECTDRAWSURFACE4 lpDDDestSurface,
|
|
LPRECT lpDestRect,
|
|
DWORD dwFlags,
|
|
LPDDOVERLAYFX lpDDOverlayFx )
|
|
{
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
FIXME(ddraw,"(%p)->(%p,%p,%p,0x%08lx,%p),stub!\n", This,
|
|
lpSrcRect, lpDDDestSurface, lpDestRect, dwFlags, lpDDOverlayFx );
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawSurface4Impl_UpdateOverlayDisplay(
|
|
LPDIRECTDRAWSURFACE4 iface,
|
|
DWORD dwFlags )
|
|
{
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
FIXME(ddraw,"(%p)->(0x%08lx),stub!\n", This, dwFlags);
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawSurface4Impl_UpdateOverlayZOrder(
|
|
LPDIRECTDRAWSURFACE4 iface,
|
|
DWORD dwFlags,
|
|
LPDIRECTDRAWSURFACE4 lpDDSReference )
|
|
{
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
FIXME(ddraw,"(%p)->(0x%08lx,%p),stub!\n", This, dwFlags, lpDDSReference);
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawSurface4Impl_GetDDInterface(
|
|
LPDIRECTDRAWSURFACE4 iface,
|
|
LPVOID* lplpDD )
|
|
{
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
FIXME(ddraw,"(%p)->(%p),stub!\n", This, lplpDD);
|
|
|
|
/* Not sure about that... */
|
|
*lplpDD = (void *) This->s.ddraw;
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawSurface4Impl_PageLock(
|
|
LPDIRECTDRAWSURFACE4 iface,
|
|
DWORD dwFlags )
|
|
{
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
FIXME(ddraw,"(%p)->(0x%08lx),stub!\n", This, dwFlags);
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawSurface4Impl_PageUnlock(
|
|
LPDIRECTDRAWSURFACE4 iface,
|
|
DWORD dwFlags )
|
|
{
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
FIXME(ddraw,"(%p)->(0x%08lx),stub!\n", This, dwFlags);
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawSurface4Impl_SetSurfaceDesc(
|
|
LPDIRECTDRAWSURFACE4 iface,
|
|
LPDDSURFACEDESC lpDDSD,
|
|
DWORD dwFlags )
|
|
{
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
FIXME(ddraw,"(%p)->(%p,0x%08lx),stub!\n", This, lpDDSD, dwFlags);
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawSurface4Impl_SetPrivateData(LPDIRECTDRAWSURFACE4 iface,
|
|
REFGUID guidTag,
|
|
LPVOID lpData,
|
|
DWORD cbSize,
|
|
DWORD dwFlags) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
FIXME(ddraw, "(%p)->(%p,%p,%ld,%08lx\n", This, guidTag, lpData, cbSize, dwFlags);
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawSurface4Impl_GetPrivateData(LPDIRECTDRAWSURFACE4 iface,
|
|
REFGUID guidTag,
|
|
LPVOID lpBuffer,
|
|
LPDWORD lpcbBufferSize) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
FIXME(ddraw, "(%p)->(%p,%p,%p)\n", This, guidTag, lpBuffer, lpcbBufferSize);
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawSurface4Impl_FreePrivateData(LPDIRECTDRAWSURFACE4 iface,
|
|
REFGUID guidTag) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
FIXME(ddraw, "(%p)->(%p)\n", This, guidTag);
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawSurface4Impl_GetUniquenessValue(LPDIRECTDRAWSURFACE4 iface,
|
|
LPDWORD lpValue) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
FIXME(ddraw, "(%p)->(%p)\n", This, lpValue);
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawSurface4Impl_ChangeUniquenessValue(LPDIRECTDRAWSURFACE4 iface) {
|
|
ICOM_THIS(IDirectDrawSurface4Impl,iface);
|
|
FIXME(ddraw, "(%p)\n", This);
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
static ICOM_VTABLE(IDirectDrawSurface4) dga_dds4vt =
|
|
{
|
|
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
|
|
IDirectDrawSurface4Impl_QueryInterface,
|
|
IDirectDrawSurface4Impl_AddRef,
|
|
DGA_IDirectDrawSurface4Impl_Release,
|
|
IDirectDrawSurface4Impl_AddAttachedSurface,
|
|
IDirectDrawSurface4Impl_AddOverlayDirtyRect,
|
|
IDirectDrawSurface4Impl_Blt,
|
|
IDirectDrawSurface4Impl_BltBatch,
|
|
IDirectDrawSurface4Impl_BltFast,
|
|
IDirectDrawSurface4Impl_DeleteAttachedSurface,
|
|
IDirectDrawSurface4Impl_EnumAttachedSurfaces,
|
|
IDirectDrawSurface4Impl_EnumOverlayZOrders,
|
|
DGA_IDirectDrawSurface4Impl_Flip,
|
|
IDirectDrawSurface4Impl_GetAttachedSurface,
|
|
IDirectDrawSurface4Impl_GetBltStatus,
|
|
IDirectDrawSurface4Impl_GetCaps,
|
|
IDirectDrawSurface4Impl_GetClipper,
|
|
IDirectDrawSurface4Impl_GetColorKey,
|
|
IDirectDrawSurface4Impl_GetDC,
|
|
IDirectDrawSurface4Impl_GetFlipStatus,
|
|
IDirectDrawSurface4Impl_GetOverlayPosition,
|
|
IDirectDrawSurface4Impl_GetPalette,
|
|
IDirectDrawSurface4Impl_GetPixelFormat,
|
|
IDirectDrawSurface4Impl_GetSurfaceDesc,
|
|
IDirectDrawSurface4Impl_Initialize,
|
|
IDirectDrawSurface4Impl_IsLost,
|
|
IDirectDrawSurface4Impl_Lock,
|
|
IDirectDrawSurface4Impl_ReleaseDC,
|
|
IDirectDrawSurface4Impl_Restore,
|
|
IDirectDrawSurface4Impl_SetClipper,
|
|
IDirectDrawSurface4Impl_SetColorKey,
|
|
IDirectDrawSurface4Impl_SetOverlayPosition,
|
|
DGA_IDirectDrawSurface4Impl_SetPalette,
|
|
DGA_IDirectDrawSurface4Impl_Unlock,
|
|
IDirectDrawSurface4Impl_UpdateOverlay,
|
|
IDirectDrawSurface4Impl_UpdateOverlayDisplay,
|
|
IDirectDrawSurface4Impl_UpdateOverlayZOrder,
|
|
IDirectDrawSurface4Impl_GetDDInterface,
|
|
IDirectDrawSurface4Impl_PageLock,
|
|
IDirectDrawSurface4Impl_PageUnlock,
|
|
IDirectDrawSurface4Impl_SetSurfaceDesc,
|
|
IDirectDrawSurface4Impl_SetPrivateData,
|
|
IDirectDrawSurface4Impl_GetPrivateData,
|
|
IDirectDrawSurface4Impl_FreePrivateData,
|
|
IDirectDrawSurface4Impl_GetUniquenessValue,
|
|
IDirectDrawSurface4Impl_ChangeUniquenessValue
|
|
};
|
|
|
|
static ICOM_VTABLE(IDirectDrawSurface4) xlib_dds4vt =
|
|
{
|
|
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
|
|
IDirectDrawSurface4Impl_QueryInterface,
|
|
IDirectDrawSurface4Impl_AddRef,
|
|
Xlib_IDirectDrawSurface4Impl_Release,
|
|
IDirectDrawSurface4Impl_AddAttachedSurface,
|
|
IDirectDrawSurface4Impl_AddOverlayDirtyRect,
|
|
IDirectDrawSurface4Impl_Blt,
|
|
IDirectDrawSurface4Impl_BltBatch,
|
|
IDirectDrawSurface4Impl_BltFast,
|
|
IDirectDrawSurface4Impl_DeleteAttachedSurface,
|
|
IDirectDrawSurface4Impl_EnumAttachedSurfaces,
|
|
IDirectDrawSurface4Impl_EnumOverlayZOrders,
|
|
Xlib_IDirectDrawSurface4Impl_Flip,
|
|
IDirectDrawSurface4Impl_GetAttachedSurface,
|
|
IDirectDrawSurface4Impl_GetBltStatus,
|
|
IDirectDrawSurface4Impl_GetCaps,
|
|
IDirectDrawSurface4Impl_GetClipper,
|
|
IDirectDrawSurface4Impl_GetColorKey,
|
|
IDirectDrawSurface4Impl_GetDC,
|
|
IDirectDrawSurface4Impl_GetFlipStatus,
|
|
IDirectDrawSurface4Impl_GetOverlayPosition,
|
|
IDirectDrawSurface4Impl_GetPalette,
|
|
IDirectDrawSurface4Impl_GetPixelFormat,
|
|
IDirectDrawSurface4Impl_GetSurfaceDesc,
|
|
IDirectDrawSurface4Impl_Initialize,
|
|
IDirectDrawSurface4Impl_IsLost,
|
|
IDirectDrawSurface4Impl_Lock,
|
|
IDirectDrawSurface4Impl_ReleaseDC,
|
|
IDirectDrawSurface4Impl_Restore,
|
|
IDirectDrawSurface4Impl_SetClipper,
|
|
IDirectDrawSurface4Impl_SetColorKey,
|
|
IDirectDrawSurface4Impl_SetOverlayPosition,
|
|
Xlib_IDirectDrawSurface4Impl_SetPalette,
|
|
Xlib_IDirectDrawSurface4Impl_Unlock,
|
|
IDirectDrawSurface4Impl_UpdateOverlay,
|
|
IDirectDrawSurface4Impl_UpdateOverlayDisplay,
|
|
IDirectDrawSurface4Impl_UpdateOverlayZOrder,
|
|
IDirectDrawSurface4Impl_GetDDInterface,
|
|
IDirectDrawSurface4Impl_PageLock,
|
|
IDirectDrawSurface4Impl_PageUnlock,
|
|
IDirectDrawSurface4Impl_SetSurfaceDesc,
|
|
IDirectDrawSurface4Impl_SetPrivateData,
|
|
IDirectDrawSurface4Impl_GetPrivateData,
|
|
IDirectDrawSurface4Impl_FreePrivateData,
|
|
IDirectDrawSurface4Impl_GetUniquenessValue,
|
|
IDirectDrawSurface4Impl_ChangeUniquenessValue
|
|
};
|
|
|
|
/******************************************************************************
|
|
* DirectDrawCreateClipper (DDRAW.7)
|
|
*/
|
|
HRESULT WINAPI DirectDrawCreateClipper( DWORD dwFlags,
|
|
LPDIRECTDRAWCLIPPER *lplpDDClipper,
|
|
LPUNKNOWN pUnkOuter)
|
|
{
|
|
IDirectDrawClipperImpl** ilplpDDClipper=(IDirectDrawClipperImpl**)lplpDDClipper;
|
|
TRACE(ddraw, "(%08lx,%p,%p)\n", dwFlags, ilplpDDClipper, pUnkOuter);
|
|
|
|
*ilplpDDClipper = (IDirectDrawClipperImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawClipperImpl));
|
|
(*ilplpDDClipper)->lpvtbl = &ddclipvt;
|
|
(*ilplpDDClipper)->ref = 1;
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* IDirectDrawClipper
|
|
*/
|
|
static HRESULT WINAPI IDirectDrawClipperImpl_SetHwnd(
|
|
LPDIRECTDRAWCLIPPER iface,DWORD x,HWND hwnd
|
|
) {
|
|
ICOM_THIS(IDirectDrawClipperImpl,iface);
|
|
FIXME(ddraw,"(%p)->SetHwnd(0x%08lx,0x%08lx),stub!\n",This,x,(DWORD)hwnd);
|
|
return DD_OK;
|
|
}
|
|
|
|
static ULONG WINAPI IDirectDrawClipperImpl_Release(LPDIRECTDRAWCLIPPER iface) {
|
|
ICOM_THIS(IDirectDrawClipperImpl,iface);
|
|
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 IDirectDrawClipperImpl_GetClipList(
|
|
LPDIRECTDRAWCLIPPER iface,LPRECT rects,LPRGNDATA lprgn,LPDWORD hmm
|
|
) {
|
|
ICOM_THIS(IDirectDrawClipperImpl,iface);
|
|
FIXME(ddraw,"(%p,%p,%p,%p),stub!\n",This,rects,lprgn,hmm);
|
|
if (hmm) *hmm=0;
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawClipperImpl_SetClipList(
|
|
LPDIRECTDRAWCLIPPER iface,LPRGNDATA lprgn,DWORD hmm
|
|
) {
|
|
ICOM_THIS(IDirectDrawClipperImpl,iface);
|
|
FIXME(ddraw,"(%p,%p,%ld),stub!\n",This,lprgn,hmm);
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawClipperImpl_QueryInterface(
|
|
LPDIRECTDRAWCLIPPER iface,
|
|
REFIID riid,
|
|
LPVOID* ppvObj )
|
|
{
|
|
ICOM_THIS(IDirectDrawClipperImpl,iface);
|
|
FIXME(ddraw,"(%p)->(%p,%p),stub!\n",This,riid,ppvObj);
|
|
return OLE_E_ENUM_NOMORE;
|
|
}
|
|
|
|
static ULONG WINAPI IDirectDrawClipperImpl_AddRef( LPDIRECTDRAWCLIPPER iface )
|
|
{
|
|
ICOM_THIS(IDirectDrawClipperImpl,iface);
|
|
TRACE( ddraw, "(%p)->() incrementing from %lu.\n", This, This->ref );
|
|
return ++(This->ref);
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawClipperImpl_GetHWnd(
|
|
LPDIRECTDRAWCLIPPER iface,
|
|
HWND* HWndPtr )
|
|
{
|
|
ICOM_THIS(IDirectDrawClipperImpl,iface);
|
|
FIXME(ddraw,"(%p)->(%p),stub!\n",This,HWndPtr);
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawClipperImpl_Initialize(
|
|
LPDIRECTDRAWCLIPPER iface,
|
|
LPDIRECTDRAW lpDD,
|
|
DWORD dwFlags )
|
|
{
|
|
ICOM_THIS(IDirectDrawClipperImpl,iface);
|
|
FIXME(ddraw,"(%p)->(%p,0x%08lx),stub!\n",This,lpDD,dwFlags);
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawClipperImpl_IsClipListChanged(
|
|
LPDIRECTDRAWCLIPPER iface,
|
|
BOOL* lpbChanged )
|
|
{
|
|
ICOM_THIS(IDirectDrawClipperImpl,iface);
|
|
FIXME(ddraw,"(%p)->(%p),stub!\n",This,lpbChanged);
|
|
return DD_OK;
|
|
}
|
|
|
|
static ICOM_VTABLE(IDirectDrawClipper) ddclipvt =
|
|
{
|
|
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
|
|
IDirectDrawClipperImpl_QueryInterface,
|
|
IDirectDrawClipperImpl_AddRef,
|
|
IDirectDrawClipperImpl_Release,
|
|
IDirectDrawClipperImpl_GetClipList,
|
|
IDirectDrawClipperImpl_GetHWnd,
|
|
IDirectDrawClipperImpl_Initialize,
|
|
IDirectDrawClipperImpl_IsClipListChanged,
|
|
IDirectDrawClipperImpl_SetClipList,
|
|
IDirectDrawClipperImpl_SetHwnd
|
|
};
|
|
|
|
|
|
/******************************************************************************
|
|
* IDirectDrawPalette
|
|
*/
|
|
static HRESULT WINAPI IDirectDrawPaletteImpl_GetEntries(
|
|
LPDIRECTDRAWPALETTE iface,DWORD x,DWORD start,DWORD count,LPPALETTEENTRY palent
|
|
) {
|
|
ICOM_THIS(IDirectDrawPaletteImpl,iface);
|
|
int i;
|
|
|
|
TRACE(ddraw,"(%p)->GetEntries(%08lx,%ld,%ld,%p)\n",
|
|
This,x,start,count,palent);
|
|
|
|
/* No palette created and not in depth-convertion mode -> BUG ! */
|
|
if ((This->cm == None) &&
|
|
(This->ddraw->d.palette_convert == NULL))
|
|
{
|
|
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_IDirectDrawPaletteImpl_SetEntries(
|
|
LPDIRECTDRAWPALETTE iface,DWORD x,DWORD start,DWORD count,LPPALETTEENTRY palent
|
|
) {
|
|
ICOM_THIS(IDirectDrawPaletteImpl,iface);
|
|
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 */
|
|
/* FIXME: we need to update the image or we won't get palette fading. */
|
|
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_IDirectDrawPaletteImpl_SetEntries(
|
|
LPDIRECTDRAWPALETTE iface,DWORD x,DWORD start,DWORD count,LPPALETTEENTRY palent
|
|
) {
|
|
#ifdef HAVE_LIBXXF86DGA
|
|
ICOM_THIS(IDirectDrawPaletteImpl,iface);
|
|
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 IDirectDrawPaletteImpl_Release(LPDIRECTDRAWPALETTE iface) {
|
|
ICOM_THIS(IDirectDrawPaletteImpl,iface);
|
|
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 IDirectDrawPaletteImpl_AddRef(LPDIRECTDRAWPALETTE iface) {
|
|
ICOM_THIS(IDirectDrawPaletteImpl,iface);
|
|
|
|
TRACE( ddraw, "(%p)->() incrementing from %lu.\n", This, This->ref );
|
|
return ++(This->ref);
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawPaletteImpl_Initialize(
|
|
LPDIRECTDRAWPALETTE iface,LPDIRECTDRAW ddraw,DWORD x,LPPALETTEENTRY palent
|
|
) {
|
|
ICOM_THIS(IDirectDrawPaletteImpl,iface);
|
|
TRACE(ddraw,"(%p)->(%p,%ld,%p)\n", This, ddraw, x, palent);
|
|
|
|
return DDERR_ALREADYINITIALIZED;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawPaletteImpl_GetCaps(
|
|
LPDIRECTDRAWPALETTE iface, LPDWORD lpdwCaps )
|
|
{
|
|
ICOM_THIS(IDirectDrawPaletteImpl,iface);
|
|
FIXME( ddraw, "(%p)->(%p) stub.\n", This, lpdwCaps );
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDrawPaletteImpl_QueryInterface(
|
|
LPDIRECTDRAWPALETTE iface,REFIID refiid,LPVOID *obj )
|
|
{
|
|
ICOM_THIS(IDirectDrawPaletteImpl,iface);
|
|
char xrefiid[50];
|
|
|
|
WINE_StringFromCLSID((LPCLSID)refiid,xrefiid);
|
|
FIXME(ddraw,"(%p)->(%s,%p) stub.\n",This,xrefiid,obj);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static ICOM_VTABLE(IDirectDrawPalette) dga_ddpalvt =
|
|
{
|
|
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
|
|
IDirectDrawPaletteImpl_QueryInterface,
|
|
IDirectDrawPaletteImpl_AddRef,
|
|
IDirectDrawPaletteImpl_Release,
|
|
IDirectDrawPaletteImpl_GetCaps,
|
|
IDirectDrawPaletteImpl_GetEntries,
|
|
IDirectDrawPaletteImpl_Initialize,
|
|
DGA_IDirectDrawPaletteImpl_SetEntries
|
|
};
|
|
|
|
static ICOM_VTABLE(IDirectDrawPalette) xlib_ddpalvt =
|
|
{
|
|
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
|
|
IDirectDrawPaletteImpl_QueryInterface,
|
|
IDirectDrawPaletteImpl_AddRef,
|
|
IDirectDrawPaletteImpl_Release,
|
|
IDirectDrawPaletteImpl_GetCaps,
|
|
IDirectDrawPaletteImpl_GetEntries,
|
|
IDirectDrawPaletteImpl_Initialize,
|
|
Xlib_IDirectDrawPaletteImpl_SetEntries
|
|
};
|
|
|
|
/*******************************************************************************
|
|
* IDirect3D
|
|
*/
|
|
static HRESULT WINAPI IDirect3DImpl_QueryInterface(
|
|
LPDIRECT3D iface,REFIID refiid,LPVOID *obj
|
|
) {
|
|
ICOM_THIS(IDirect3DImpl,iface);
|
|
/* 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_IDirectDraw,refiid,sizeof(IID_IDirectDraw))) ||
|
|
(!memcmp(&IID_IDirectDraw2,refiid,sizeof(IID_IDirectDraw2))) ||
|
|
(!memcmp(&IID_IDirectDraw4,refiid,sizeof(IID_IDirectDraw4)))) {
|
|
*obj = This->ddraw;
|
|
IDirect3D_AddRef(iface);
|
|
|
|
TRACE(ddraw, " Creating IDirectDrawX interface (%p)\n", *obj);
|
|
|
|
return S_OK;
|
|
}
|
|
if ((!memcmp(&IID_IDirect3D,refiid,sizeof(IID_IDirect3D))) ||
|
|
(!memcmp(&IID_IUnknown,refiid,sizeof(IID_IUnknown)))) {
|
|
*obj = This;
|
|
IDirect3D_AddRef(iface);
|
|
|
|
TRACE(ddraw, " Creating IDirect3D interface (%p)\n", *obj);
|
|
|
|
return S_OK;
|
|
}
|
|
if (!memcmp(&IID_IDirect3D2,refiid,sizeof(IID_IDirect3D2))) {
|
|
IDirect3D2Impl* d3d;
|
|
|
|
d3d = HeapAlloc(GetProcessHeap(),0,sizeof(*d3d));
|
|
d3d->ref = 1;
|
|
d3d->ddraw = This->ddraw;
|
|
IDirect3D_AddRef(iface);
|
|
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 IDirect3DImpl_AddRef(LPDIRECT3D iface) {
|
|
ICOM_THIS(IDirect3DImpl,iface);
|
|
TRACE( ddraw, "(%p)->() incrementing from %lu.\n", This, This->ref );
|
|
|
|
return ++(This->ref);
|
|
}
|
|
|
|
static ULONG WINAPI IDirect3DImpl_Release(LPDIRECT3D iface)
|
|
{
|
|
ICOM_THIS(IDirect3DImpl,iface);
|
|
TRACE( ddraw, "(%p)->() decrementing from %lu.\n", This, This->ref );
|
|
|
|
if (!--(This->ref)) {
|
|
IDirectDraw2_Release((IDirectDraw2*)This->ddraw);
|
|
HeapFree(GetProcessHeap(),0,This);
|
|
return 0;
|
|
}
|
|
return This->ref;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirect3DImpl_Initialize(
|
|
LPDIRECT3D iface, REFIID refiid )
|
|
{
|
|
ICOM_THIS(IDirect3DImpl,iface);
|
|
/* 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 IDirect3DImpl_EnumDevices(LPDIRECT3D iface,
|
|
LPD3DENUMDEVICESCALLBACK cb,
|
|
LPVOID context) {
|
|
ICOM_THIS(IDirect3DImpl,iface);
|
|
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 IDirect3DImpl_CreateLight(LPDIRECT3D iface,
|
|
LPDIRECT3DLIGHT *lplight,
|
|
IUnknown *lpunk)
|
|
{
|
|
ICOM_THIS(IDirect3DImpl,iface);
|
|
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 IDirect3DImpl_CreateMaterial(LPDIRECT3D iface,
|
|
LPDIRECT3DMATERIAL *lpmaterial,
|
|
IUnknown *lpunk)
|
|
{
|
|
ICOM_THIS(IDirect3DImpl,iface);
|
|
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 IDirect3DImpl_CreateViewport(LPDIRECT3D iface,
|
|
LPDIRECT3DVIEWPORT *lpviewport,
|
|
IUnknown *lpunk)
|
|
{
|
|
ICOM_THIS(IDirect3DImpl,iface);
|
|
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 IDirect3DImpl_FindDevice(LPDIRECT3D iface,
|
|
LPD3DFINDDEVICESEARCH lpfinddevsrc,
|
|
LPD3DFINDDEVICERESULT lpfinddevrst)
|
|
{
|
|
ICOM_THIS(IDirect3DImpl,iface);
|
|
TRACE(ddraw, "(%p)->(%p,%p): stub\n", This, lpfinddevsrc, lpfinddevrst);
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
static ICOM_VTABLE(IDirect3D) d3dvt =
|
|
{
|
|
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
|
|
IDirect3DImpl_QueryInterface,
|
|
IDirect3DImpl_AddRef,
|
|
IDirect3DImpl_Release,
|
|
IDirect3DImpl_Initialize,
|
|
IDirect3DImpl_EnumDevices,
|
|
IDirect3DImpl_CreateLight,
|
|
IDirect3DImpl_CreateMaterial,
|
|
IDirect3DImpl_CreateViewport,
|
|
IDirect3DImpl_FindDevice
|
|
};
|
|
|
|
/*******************************************************************************
|
|
* IDirect3D2
|
|
*/
|
|
static HRESULT WINAPI IDirect3D2Impl_QueryInterface(
|
|
LPDIRECT3D2 iface,REFIID refiid,LPVOID *obj) {
|
|
ICOM_THIS(IDirect3D2Impl,iface);
|
|
|
|
/* 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_IDirectDraw,refiid,sizeof(IID_IDirectDraw))) ||
|
|
(!memcmp(&IID_IDirectDraw2,refiid,sizeof(IID_IDirectDraw2))) ||
|
|
(!memcmp(&IID_IDirectDraw4,refiid,sizeof(IID_IDirectDraw4)))) {
|
|
*obj = This->ddraw;
|
|
IDirect3D2_AddRef(iface);
|
|
|
|
TRACE(ddraw, " Creating IDirectDrawX interface (%p)\n", *obj);
|
|
|
|
return S_OK;
|
|
}
|
|
if ((!memcmp(&IID_IDirect3D2,refiid,sizeof(IID_IDirect3D2))) ||
|
|
(!memcmp(&IID_IUnknown,refiid,sizeof(IID_IUnknown)))) {
|
|
*obj = This;
|
|
IDirect3D2_AddRef(iface);
|
|
|
|
TRACE(ddraw, " Creating IDirect3D2 interface (%p)\n", *obj);
|
|
|
|
return S_OK;
|
|
}
|
|
if (!memcmp(&IID_IDirect3D,refiid,sizeof(IID_IDirect3D))) {
|
|
IDirect3DImpl* d3d;
|
|
|
|
d3d = HeapAlloc(GetProcessHeap(),0,sizeof(*d3d));
|
|
d3d->ref = 1;
|
|
d3d->ddraw = This->ddraw;
|
|
IDirect3D2_AddRef(iface);
|
|
d3d->lpvtbl = &d3dvt;
|
|
*obj = d3d;
|
|
|
|
TRACE(ddraw, " Creating IDirect3D 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 IDirect3D2Impl_AddRef(LPDIRECT3D2 iface) {
|
|
ICOM_THIS(IDirect3D2Impl,iface);
|
|
TRACE( ddraw, "(%p)->() incrementing from %lu.\n", This, This->ref );
|
|
|
|
return ++(This->ref);
|
|
}
|
|
|
|
static ULONG WINAPI IDirect3D2Impl_Release(LPDIRECT3D2 iface) {
|
|
ICOM_THIS(IDirect3D2Impl,iface);
|
|
TRACE( ddraw, "(%p)->() decrementing from %lu.\n", This, This->ref );
|
|
|
|
if (!--(This->ref)) {
|
|
IDirectDraw2_Release((IDirectDraw2*)This->ddraw);
|
|
HeapFree(GetProcessHeap(),0,This);
|
|
return 0;
|
|
}
|
|
return This->ref;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirect3D2Impl_EnumDevices(
|
|
LPDIRECT3D2 iface,LPD3DENUMDEVICESCALLBACK cb, LPVOID context
|
|
) {
|
|
ICOM_THIS(IDirect3D2Impl,iface);
|
|
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 IDirect3D2Impl_CreateLight(LPDIRECT3D2 iface,
|
|
LPDIRECT3DLIGHT *lplight,
|
|
IUnknown *lpunk)
|
|
{
|
|
ICOM_THIS(IDirect3D2Impl,iface);
|
|
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 IDirect3D2Impl_CreateMaterial(LPDIRECT3D2 iface,
|
|
LPDIRECT3DMATERIAL2 *lpmaterial,
|
|
IUnknown *lpunk)
|
|
{
|
|
ICOM_THIS(IDirect3D2Impl,iface);
|
|
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 IDirect3D2Impl_CreateViewport(LPDIRECT3D2 iface,
|
|
LPDIRECT3DVIEWPORT2 *lpviewport,
|
|
IUnknown *lpunk)
|
|
{
|
|
ICOM_THIS(IDirect3D2Impl,iface);
|
|
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 IDirect3D2Impl_FindDevice(LPDIRECT3D2 iface,
|
|
LPD3DFINDDEVICESEARCH lpfinddevsrc,
|
|
LPD3DFINDDEVICERESULT lpfinddevrst)
|
|
{
|
|
ICOM_THIS(IDirect3D2Impl,iface);
|
|
TRACE(ddraw, "(%p)->(%p,%p): stub\n", This, lpfinddevsrc, lpfinddevrst);
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirect3D2Impl_CreateDevice(LPDIRECT3D2 iface,
|
|
REFCLSID rguid,
|
|
LPDIRECTDRAWSURFACE surface,
|
|
LPDIRECT3DDEVICE2 *device)
|
|
{
|
|
ICOM_THIS(IDirect3D2Impl,iface);
|
|
char xbuf[50];
|
|
|
|
WINE_StringFromCLSID(rguid,xbuf);
|
|
FIXME(ddraw,"(%p)->(%s,%p,%p): stub\n",This,xbuf,surface,device);
|
|
|
|
if (is_OpenGL(rguid, (IDirectDrawSurfaceImpl*)surface, (IDirect3DDevice2Impl**)device, This)) {
|
|
IDirect3D2_AddRef(iface);
|
|
return DD_OK;
|
|
}
|
|
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
|
|
static ICOM_VTABLE(IDirect3D2) d3d2vt =
|
|
{
|
|
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
|
|
IDirect3D2Impl_QueryInterface,
|
|
IDirect3D2Impl_AddRef,
|
|
IDirect3D2Impl_Release,
|
|
IDirect3D2Impl_EnumDevices,
|
|
IDirect3D2Impl_CreateLight,
|
|
IDirect3D2Impl_CreateMaterial,
|
|
IDirect3D2Impl_CreateViewport,
|
|
IDirect3D2Impl_FindDevice,
|
|
IDirect3D2Impl_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(IDirectDraw2Impl* This,
|
|
IDirectDrawSurfaceImpl* 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 (lpdsf->s.surface_desc.dwFlags & DDSD_ZBUFFERBITDEPTH) {
|
|
/* This is a Z Buffer */
|
|
TRACE(ddraw, "Creating Z-Buffer of %ld bit depth\n", lpdsf->s.surface_desc.x.dwZBufferBitDepth);
|
|
bpp = lpdsf->s.surface_desc.x.dwZBufferBitDepth / 8;
|
|
} else {
|
|
/* This is a standard image */
|
|
if (!(lpdsf->s.surface_desc.dwFlags & DDSD_PIXELFORMAT)) {
|
|
/* No pixel format => use DirectDraw's format */
|
|
lpdsf->s.surface_desc.ddpfPixelFormat = This->d.directdraw_pixelformat;
|
|
lpdsf->s.surface_desc.dwFlags |= DDSD_PIXELFORMAT;
|
|
}
|
|
|
|
bpp = GET_BPP(lpdsf->s.surface_desc);
|
|
}
|
|
|
|
if (lpdsf->s.surface_desc.dwFlags & DDSD_LPSURFACE) {
|
|
/* The surface was preallocated : seems that we have nothing to do :-) */
|
|
WARN(ddraw, "Creates a surface that is already allocated : assuming this is an application bug !\n");
|
|
}
|
|
|
|
lpdsf->s.surface_desc.dwFlags |= DDSD_PITCH|DDSD_LPSURFACE;
|
|
lpdsf->s.surface_desc.y.lpSurface =
|
|
(LPBYTE)HeapAlloc(GetProcessHeap(),0,lpdsf->s.surface_desc.dwWidth * lpdsf->s.surface_desc.dwHeight * bpp);
|
|
lpdsf->s.surface_desc.lPitch = lpdsf->s.surface_desc.dwWidth * bpp;
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI DGA_IDirectDraw2Impl_CreateSurface(
|
|
LPDIRECTDRAW2 iface,LPDDSURFACEDESC lpddsd,LPDIRECTDRAWSURFACE *lpdsf,IUnknown *lpunk
|
|
) {
|
|
#ifdef HAVE_LIBXXF86DGA
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
IDirectDrawSurfaceImpl** ilpdsf=(IDirectDrawSurfaceImpl**)lpdsf;
|
|
int i;
|
|
|
|
TRACE(ddraw, "(%p)->(%p,%p,%p)\n",This,lpddsd,ilpdsf,lpunk);
|
|
if (TRACE_ON(ddraw)) {
|
|
_dump_surface_desc(lpddsd);
|
|
}
|
|
|
|
*ilpdsf = (IDirectDrawSurfaceImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawSurfaceImpl));
|
|
IDirectDraw2_AddRef(iface);
|
|
|
|
(*ilpdsf)->ref = 1;
|
|
(*ilpdsf)->lpvtbl = (ICOM_VTABLE(IDirectDrawSurface)*)&dga_dds4vt;
|
|
(*ilpdsf)->s.ddraw = This;
|
|
(*ilpdsf)->s.palette = NULL;
|
|
(*ilpdsf)->t.dga.fb_height = -1; /* This is to have non-on screen surfaces freed */
|
|
|
|
/* Copy the surface description */
|
|
(*ilpdsf)->s.surface_desc = *lpddsd;
|
|
|
|
if (!(lpddsd->dwFlags & DDSD_WIDTH))
|
|
(*ilpdsf)->s.surface_desc.dwWidth = This->d.width;
|
|
if (!(lpddsd->dwFlags & DDSD_HEIGHT))
|
|
(*ilpdsf)->s.surface_desc.dwHeight = This->d.height;
|
|
(*ilpdsf)->s.surface_desc.dwFlags |= DDSD_WIDTH|DDSD_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 */
|
|
(*ilpdsf)->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);
|
|
(*ilpdsf)->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);
|
|
(*ilpdsf)->t.dga.fb_height = i*This->e.dga.fb_height;
|
|
(*ilpdsf)->s.surface_desc.lPitch = This->e.dga.fb_width*This->d.directdraw_pixelformat.x.dwRGBBitCount/8;
|
|
lpddsd->lPitch = (*ilpdsf)->s.surface_desc.lPitch;
|
|
|
|
/* Add flags if there were not present */
|
|
(*ilpdsf)->s.surface_desc.dwFlags |= DDSD_WIDTH|DDSD_HEIGHT|DDSD_PITCH|DDSD_LPSURFACE|DDSD_PIXELFORMAT;
|
|
(*ilpdsf)->s.surface_desc.dwWidth = This->d.width;
|
|
(*ilpdsf)->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 */
|
|
(*ilpdsf)->s.surface_desc.ddsCaps.dwCaps |= DDSCAPS_VISIBLE|DDSCAPS_VIDEOMEMORY;
|
|
(*ilpdsf)->s.surface_desc.ddpfPixelFormat = This->d.directdraw_pixelformat;
|
|
(*ilpdsf)->s.backbuffer = NULL;
|
|
|
|
if (lpddsd->dwFlags & DDSD_BACKBUFFERCOUNT) {
|
|
IDirectDrawSurface4Impl* back;
|
|
|
|
if (lpddsd->dwBackBufferCount>1)
|
|
FIXME(ddraw,"urks, wants to have more than one backbuffer (%ld)!\n",lpddsd->dwBackBufferCount);
|
|
|
|
(*ilpdsf)->s.backbuffer = back =
|
|
(IDirectDrawSurface4Impl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawSurface4Impl));
|
|
IDirectDraw2_AddRef(iface);
|
|
back->ref = 1;
|
|
back->lpvtbl = (ICOM_VTABLE(IDirectDrawSurface4)*)&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 = (*ilpdsf)->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 */
|
|
(*ilpdsf)->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, *ilpdsf);
|
|
}
|
|
|
|
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(IDirectDraw2Impl* This, IDirectDrawSurface4Impl* 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(IDirectDraw2Impl* This, IDirectDrawSurface4Impl* 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_IDirectDraw2Impl_CreateSurface(
|
|
LPDIRECTDRAW2 iface,LPDDSURFACEDESC lpddsd,LPDIRECTDRAWSURFACE *lpdsf,IUnknown *lpunk
|
|
) {
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
IDirectDrawSurfaceImpl** ilpdsf=(IDirectDrawSurfaceImpl**)lpdsf;
|
|
TRACE(ddraw, "(%p)->CreateSurface(%p,%p,%p)\n",
|
|
This,lpddsd,ilpdsf,lpunk);
|
|
|
|
if (TRACE_ON(ddraw)) {
|
|
_dump_surface_desc(lpddsd);
|
|
}
|
|
|
|
*ilpdsf = (IDirectDrawSurfaceImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawSurfaceImpl));
|
|
|
|
IDirectDraw2_AddRef(iface);
|
|
(*ilpdsf)->s.ddraw = This;
|
|
(*ilpdsf)->ref = 1;
|
|
(*ilpdsf)->lpvtbl = (ICOM_VTABLE(IDirectDrawSurface)*)&xlib_dds4vt;
|
|
(*ilpdsf)->s.palette = NULL;
|
|
(*ilpdsf)->t.xlib.image = NULL; /* This is for off-screen buffers */
|
|
|
|
/* Copy the surface description */
|
|
(*ilpdsf)->s.surface_desc = *lpddsd;
|
|
|
|
if (!(lpddsd->dwFlags & DDSD_WIDTH))
|
|
(*ilpdsf)->s.surface_desc.dwWidth = This->d.width;
|
|
if (!(lpddsd->dwFlags & DDSD_HEIGHT))
|
|
(*ilpdsf)->s.surface_desc.dwHeight = This->d.height;
|
|
(*ilpdsf)->s.surface_desc.dwFlags |= DDSD_WIDTH|DDSD_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", *ilpdsf);
|
|
|
|
/* Create the XImage */
|
|
img = create_ximage(This, (IDirectDrawSurface4Impl*) *ilpdsf);
|
|
if (img == NULL)
|
|
return DDERR_OUTOFMEMORY;
|
|
(*ilpdsf)->t.xlib.image = img;
|
|
|
|
/* Add flags if there were not present */
|
|
(*ilpdsf)->s.surface_desc.dwFlags |= DDSD_WIDTH|DDSD_HEIGHT|DDSD_PITCH|DDSD_LPSURFACE|DDSD_PIXELFORMAT;
|
|
(*ilpdsf)->s.surface_desc.dwWidth = This->d.width;
|
|
(*ilpdsf)->s.surface_desc.dwHeight = This->d.height;
|
|
(*ilpdsf)->s.surface_desc.ddsCaps.dwCaps |= DDSCAPS_VISIBLE|DDSCAPS_VIDEOMEMORY;
|
|
(*ilpdsf)->s.surface_desc.ddpfPixelFormat = This->d.directdraw_pixelformat;
|
|
(*ilpdsf)->s.backbuffer = NULL;
|
|
|
|
/* Check for backbuffers */
|
|
if (lpddsd->dwFlags & DDSD_BACKBUFFERCOUNT) {
|
|
IDirectDrawSurface4Impl* back;
|
|
XImage *img;
|
|
|
|
if (lpddsd->dwBackBufferCount>1)
|
|
FIXME(ddraw,"urks, wants to have more than one backbuffer (%ld)!\n",lpddsd->dwBackBufferCount);
|
|
|
|
(*ilpdsf)->s.backbuffer = back =
|
|
(IDirectDrawSurface4Impl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawSurface4Impl));
|
|
|
|
TRACE(ddraw,"allocated back-buffer (%p)\n", back);
|
|
|
|
IDirectDraw2_AddRef(iface);
|
|
back->s.ddraw = This;
|
|
|
|
back->ref = 1;
|
|
back->lpvtbl = (ICOM_VTABLE(IDirectDrawSurface4)*)&xlib_dds4vt;
|
|
/* Copy the surface description from the front buffer */
|
|
back->s.surface_desc = (*ilpdsf)->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 */
|
|
(*ilpdsf)->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, *ilpdsf);
|
|
}
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDraw2Impl_DuplicateSurface(
|
|
LPDIRECTDRAW2 iface,LPDIRECTDRAWSURFACE src,LPDIRECTDRAWSURFACE *dst
|
|
) {
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
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 IDirectDraw2Impl_SetCooperativeLevel(
|
|
LPDIRECTDRAW2 iface,HWND hwnd,DWORD cooplevel
|
|
) {
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
int i;
|
|
const struct {
|
|
int mask;
|
|
char *name;
|
|
} flagmap[] = {
|
|
#define FE(x) { x, #x},
|
|
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)
|
|
#undef FE
|
|
};
|
|
|
|
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)
|
|
{
|
|
WND *tmpWnd = WIN_FindWndPtr(hwnd);
|
|
This->d.drawable = X11DRV_WND_GetXWindow(tmpWnd);
|
|
WIN_ReleaseWndPtr(tmpWnd);
|
|
|
|
if( !This->d.drawable ) {
|
|
This->d.drawable = ((X11DRV_WND_DATA *) WIN_GetDesktop()->pDriverData)->window;
|
|
WIN_ReleaseDesktop();
|
|
}
|
|
TRACE(ddraw, "Setting drawable to %ld\n", This->d.drawable);
|
|
}
|
|
|
|
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_IDirectDrawImpl_SetDisplayMode(IDirectDrawImpl* 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_IDirectDrawImpl_SetDisplayMode(
|
|
LPDIRECTDRAW iface,DWORD width,DWORD height,DWORD depth
|
|
) {
|
|
#ifdef HAVE_LIBXXF86DGA
|
|
ICOM_THIS(IDirectDrawImpl,iface);
|
|
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_IDirectDrawImpl_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);
|
|
TSXF86DGASetViewPort(display,DefaultScreen(display),0,0);
|
|
|
|
#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, IDirectDrawPaletteImpl* palette) {
|
|
unsigned char *c_src = (unsigned char *) src;
|
|
unsigned short *c_dst = (unsigned short *) dst;
|
|
int y;
|
|
|
|
if (palette != NULL) {
|
|
const unsigned short * pal = (unsigned short *) palette->screen_palents;
|
|
|
|
for (y = height; y--; ) {
|
|
#ifdef __i386__
|
|
/* gcc generates slightly inefficient code for the the copy / lookup,
|
|
* it generates one excess memory access (to pal) per pixel. Since
|
|
* we know that pal is not modified by the memory write we can
|
|
* put it into a register and reduce the number of memory accesses
|
|
* from 4 to 3 pp. There are two xor eax,eax to avoid pipeline stalls.
|
|
* (This is not guaranteed to be the fastest method.)
|
|
*/
|
|
__asm__ __volatile__(
|
|
"xor %%eax,%%eax\n"
|
|
"1:\n"
|
|
" lodsb\n"
|
|
" movw (%%edx,%%eax,2),%%ax\n"
|
|
" stosw\n"
|
|
" xor %%eax,%%eax\n"
|
|
" loop 1b\n"
|
|
: "=S" (c_src), "=D" (c_dst)
|
|
: "S" (c_src), "D" (c_dst) , "c" (width), "d" (pal)
|
|
: "eax", "cc", "memory"
|
|
);
|
|
c_src+=(pitch-width);
|
|
#else
|
|
unsigned char * srclineend = c_src+width;
|
|
while (c_src < srclineend)
|
|
*c_dst++ = pal[*c_src++];
|
|
c_src+=(pitch-width);
|
|
#endif
|
|
}
|
|
} 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 to palettized 8 bpp
|
|
************************************* */
|
|
static void pixel_convert_24_to_8(void *src, void *dst, DWORD width, DWORD height, LONG pitch, IDirectDrawPaletteImpl* palette) {
|
|
unsigned char *c_src = (unsigned char *) src;
|
|
unsigned char *c_dst = (unsigned char *) dst;
|
|
int y;
|
|
|
|
if (palette != NULL) {
|
|
const unsigned int *pal = (unsigned int *) palette->screen_palents;
|
|
|
|
for (y = height; y--; ) {
|
|
unsigned char * srclineend = c_src+width;
|
|
while (c_src < srclineend ) {
|
|
register long pixel = pal[*c_src++];
|
|
*c_dst++ = pixel;
|
|
*c_dst++ = pixel>>8;
|
|
*c_dst++ = pixel>>16;
|
|
}
|
|
c_src+=(pitch-width);
|
|
}
|
|
} else {
|
|
WARN(ddraw, "No palette set...\n");
|
|
memset(dst, 0, width * height * 4);
|
|
}
|
|
}
|
|
/* *************************************
|
|
32 bpp to palettized 8 bpp
|
|
************************************* */
|
|
static void pixel_convert_32_to_8(void *src, void *dst, DWORD width, DWORD height, LONG pitch, IDirectDrawPaletteImpl* palette) {
|
|
unsigned char *c_src = (unsigned char *) src;
|
|
unsigned int *c_dst = (unsigned int *) dst;
|
|
int y;
|
|
|
|
if (palette != NULL) {
|
|
const unsigned int *pal = (unsigned int *) palette->screen_palents;
|
|
|
|
for (y = height; y--; ) {
|
|
#ifdef __i386__
|
|
/* See comment in pixel_convert_16_to_8 */
|
|
__asm__ __volatile__(
|
|
"xor %%eax,%%eax\n"
|
|
"1:\n"
|
|
" lodsb\n"
|
|
" movl (%%edx,%%eax,4),%%eax\n"
|
|
" stosl\n"
|
|
" xor %%eax,%%eax\n"
|
|
" loop 1b\n"
|
|
: "=S" (c_src), "=D" (c_dst)
|
|
: "S" (c_src), "D" (c_dst) , "c" (width), "d" (pal)
|
|
: "eax", "cc", "memory"
|
|
);
|
|
c_src+=(pitch-width);
|
|
#else
|
|
unsigned char * srclineend = c_src+width;
|
|
while (c_src < srclineend )
|
|
*c_dst++ = pal[*c_src++];
|
|
c_src+=(pitch-width);
|
|
#endif
|
|
}
|
|
} 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_IDirectDrawImpl_SetDisplayMode(
|
|
LPDIRECTDRAW iface,DWORD width,DWORD height,DWORD depth
|
|
) {
|
|
ICOM_THIS(IDirectDrawImpl,iface);
|
|
char buf[200];
|
|
WND *tmpWnd;
|
|
|
|
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:
|
|
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_24_to_8;
|
|
This->d.palette_convert = palette_convert_24_to_8;
|
|
}
|
|
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_IDirectDrawImpl_SetDisplayMode(This);
|
|
|
|
tmpWnd = WIN_FindWndPtr(This->d.window);
|
|
This->d.paintable = 1;
|
|
This->d.drawable = ((X11DRV_WND_DATA *) tmpWnd->pDriverData)->window;
|
|
WIN_ReleaseWndPtr(tmpWnd);
|
|
|
|
/* 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;
|
|
WIN_ReleaseDesktop();
|
|
}
|
|
TRACE(ddraw, "Setting drawable to %ld\n", This->d.drawable);
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI DGA_IDirectDraw2Impl_GetCaps(
|
|
LPDIRECTDRAW2 iface,LPDDCAPS caps1,LPDDCAPS caps2
|
|
) {
|
|
#ifdef HAVE_LIBXXF86DGA
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
TRACE(ddraw,"(%p)->GetCaps(%p,%p)\n",This,caps1,caps2);
|
|
if (caps1) {
|
|
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_IDirectDraw2Impl_GetCaps(
|
|
LPDIRECTDRAW2 iface,LPDDCAPS caps1,LPDDCAPS caps2
|
|
) {
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
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 IDirectDraw2Impl_CreateClipper(
|
|
LPDIRECTDRAW2 iface,DWORD x,LPDIRECTDRAWCLIPPER *lpddclip,LPUNKNOWN lpunk
|
|
) {
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
IDirectDrawClipperImpl** ilpddclip=(IDirectDrawClipperImpl**)lpddclip;
|
|
FIXME(ddraw,"(%p)->(%08lx,%p,%p),stub!\n",
|
|
This,x,ilpddclip,lpunk
|
|
);
|
|
*ilpddclip = (IDirectDrawClipperImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawClipperImpl));
|
|
(*ilpddclip)->ref = 1;
|
|
(*ilpddclip)->lpvtbl = &ddclipvt;
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI common_IDirectDraw2Impl_CreatePalette(
|
|
IDirectDraw2Impl* This,DWORD dwFlags,LPPALETTEENTRY palent,IDirectDrawPaletteImpl **lpddpal,LPUNKNOWN lpunk,int *psize
|
|
) {
|
|
int size = 0;
|
|
|
|
if (TRACE_ON(ddraw))
|
|
_dump_paletteformat(dwFlags);
|
|
|
|
*lpddpal = (IDirectDrawPaletteImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawPaletteImpl));
|
|
if (*lpddpal == NULL) return E_OUTOFMEMORY;
|
|
(*lpddpal)->ref = 1;
|
|
(*lpddpal)->ddraw = (IDirectDrawImpl*)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_IDirectDraw2Impl_CreatePalette(
|
|
LPDIRECTDRAW2 iface,DWORD dwFlags,LPPALETTEENTRY palent,LPDIRECTDRAWPALETTE *lpddpal,LPUNKNOWN lpunk
|
|
) {
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
IDirectDrawPaletteImpl** ilpddpal=(IDirectDrawPaletteImpl**)lpddpal;
|
|
HRESULT res;
|
|
int xsize = 0,i;
|
|
|
|
TRACE(ddraw,"(%p)->(%08lx,%p,%p,%p)\n",This,dwFlags,palent,ilpddpal,lpunk);
|
|
res = common_IDirectDraw2Impl_CreatePalette(This,dwFlags,palent,ilpddpal,lpunk,&xsize);
|
|
if (res != 0) return res;
|
|
(*ilpddpal)->lpvtbl = &dga_ddpalvt;
|
|
if (This->d.directdraw_pixelformat.x.dwRGBBitCount<=8) {
|
|
(*ilpddpal)->cm = TSXCreateColormap(display,DefaultRootWindow(display),DefaultVisualOfScreen(X11DRV_GetXScreen()),AllocAll);
|
|
} else {
|
|
FIXME(ddraw,"why are we doing CreatePalette in hi/truecolor?\n");
|
|
(*ilpddpal)->cm = 0;
|
|
}
|
|
if (((*ilpddpal)->cm)&&xsize) {
|
|
for (i=0;i<xsize;i++) {
|
|
XColor xc;
|
|
|
|
xc.red = (*ilpddpal)->palents[i].peRed<<8;
|
|
xc.blue = (*ilpddpal)->palents[i].peBlue<<8;
|
|
xc.green = (*ilpddpal)->palents[i].peGreen<<8;
|
|
xc.flags = DoRed|DoBlue|DoGreen;
|
|
xc.pixel = i;
|
|
TSXStoreColor(display,(*ilpddpal)->cm,&xc);
|
|
}
|
|
}
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI Xlib_IDirectDraw2Impl_CreatePalette(
|
|
LPDIRECTDRAW2 iface,DWORD dwFlags,LPPALETTEENTRY palent,LPDIRECTDRAWPALETTE *lpddpal,LPUNKNOWN lpunk
|
|
) {
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
IDirectDrawPaletteImpl** ilpddpal=(IDirectDrawPaletteImpl**)lpddpal;
|
|
int xsize;
|
|
HRESULT res;
|
|
|
|
TRACE(ddraw,"(%p)->(%08lx,%p,%p,%p)\n",This,dwFlags,palent,ilpddpal,lpunk);
|
|
res = common_IDirectDraw2Impl_CreatePalette(This,dwFlags,palent,ilpddpal,lpunk,&xsize);
|
|
if (res != 0) return res;
|
|
(*ilpddpal)->lpvtbl = &xlib_ddpalvt;
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI DGA_IDirectDraw2Impl_RestoreDisplayMode(LPDIRECTDRAW2 iface) {
|
|
#ifdef HAVE_LIBXXF86DGA
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
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_IDirectDraw2Impl_RestoreDisplayMode(LPDIRECTDRAW2 iface) {
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
TRACE(ddraw, "(%p)->RestoreDisplayMode()\n", This);
|
|
Sleep(1000);
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDraw2Impl_WaitForVerticalBlank(
|
|
LPDIRECTDRAW2 iface,DWORD x,HANDLE h
|
|
) {
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
TRACE(ddraw,"(%p)->(0x%08lx,0x%08x)\n",This,x,h);
|
|
return DD_OK;
|
|
}
|
|
|
|
static ULONG WINAPI IDirectDraw2Impl_AddRef(LPDIRECTDRAW2 iface) {
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
TRACE( ddraw, "(%p)->() incrementing from %lu.\n", This, This->ref );
|
|
|
|
return ++(This->ref);
|
|
}
|
|
|
|
static ULONG WINAPI DGA_IDirectDraw2Impl_Release(LPDIRECTDRAW2 iface) {
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
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_IDirectDraw2Impl_Release(LPDIRECTDRAW2 iface) {
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
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_IDirectDraw2Impl_QueryInterface(
|
|
LPDIRECTDRAW2 iface,REFIID refiid,LPVOID *obj
|
|
) {
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
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;
|
|
IDirectDraw2_AddRef(iface);
|
|
|
|
TRACE(ddraw, " Creating IUnknown interface (%p)\n", *obj);
|
|
|
|
return S_OK;
|
|
}
|
|
if (!memcmp(&IID_IDirectDraw,refiid,sizeof(IID_IDirectDraw))) {
|
|
This->lpvtbl = (ICOM_VTABLE(IDirectDraw2)*)&dga_ddvt;
|
|
IDirectDraw2_AddRef(iface);
|
|
*obj = This;
|
|
|
|
TRACE(ddraw, " Creating IDirectDraw interface (%p)\n", *obj);
|
|
|
|
return S_OK;
|
|
}
|
|
if (!memcmp(&IID_IDirectDraw2,refiid,sizeof(IID_IDirectDraw2))) {
|
|
This->lpvtbl = (ICOM_VTABLE(IDirectDraw2)*)&dga_dd2vt;
|
|
IDirectDraw2_AddRef(iface);
|
|
*obj = This;
|
|
|
|
TRACE(ddraw, " Creating IDirectDraw2 interface (%p)\n", *obj);
|
|
|
|
return S_OK;
|
|
}
|
|
if (!memcmp(&IID_IDirectDraw4,refiid,sizeof(IID_IDirectDraw4))) {
|
|
This->lpvtbl = (ICOM_VTABLE(IDirectDraw2)*)&dga_dd4vt;
|
|
IDirectDraw2_AddRef(iface);
|
|
*obj = This;
|
|
|
|
TRACE(ddraw, " Creating IDirectDraw4 interface (%p)\n", *obj);
|
|
|
|
return S_OK;
|
|
}
|
|
if (!memcmp(&IID_IDirect3D,refiid,sizeof(IID_IDirect3D))) {
|
|
IDirect3DImpl* d3d;
|
|
|
|
d3d = HeapAlloc(GetProcessHeap(),0,sizeof(*d3d));
|
|
d3d->ref = 1;
|
|
d3d->ddraw = (IDirectDrawImpl*)This;
|
|
IDirectDraw2_AddRef(iface);
|
|
d3d->lpvtbl = &d3dvt;
|
|
*obj = d3d;
|
|
|
|
TRACE(ddraw, " Creating IDirect3D interface (%p)\n", *obj);
|
|
|
|
return S_OK;
|
|
}
|
|
if (!memcmp(&IID_IDirect3D2,refiid,sizeof(IID_IDirect3D2))) {
|
|
IDirect3D2Impl* d3d;
|
|
|
|
d3d = HeapAlloc(GetProcessHeap(),0,sizeof(*d3d));
|
|
d3d->ref = 1;
|
|
d3d->ddraw = (IDirectDrawImpl*)This;
|
|
IDirectDraw2_AddRef(iface);
|
|
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_IDirectDraw2Impl_QueryInterface(
|
|
LPDIRECTDRAW2 iface,REFIID refiid,LPVOID *obj
|
|
) {
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
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;
|
|
IDirectDraw2_AddRef(iface);
|
|
|
|
TRACE(ddraw, " Creating IUnknown interface (%p)\n", *obj);
|
|
|
|
return S_OK;
|
|
}
|
|
if (!memcmp(&IID_IDirectDraw,refiid,sizeof(IID_IDirectDraw))) {
|
|
This->lpvtbl = (ICOM_VTABLE(IDirectDraw2)*)&xlib_ddvt;
|
|
IDirectDraw2_AddRef(iface);
|
|
*obj = This;
|
|
|
|
TRACE(ddraw, " Creating IDirectDraw interface (%p)\n", *obj);
|
|
|
|
return S_OK;
|
|
}
|
|
if (!memcmp(&IID_IDirectDraw2,refiid,sizeof(IID_IDirectDraw2))) {
|
|
This->lpvtbl = (ICOM_VTABLE(IDirectDraw2)*)&xlib_dd2vt;
|
|
IDirectDraw2_AddRef(iface);
|
|
*obj = This;
|
|
|
|
TRACE(ddraw, " Creating IDirectDraw2 interface (%p)\n", *obj);
|
|
|
|
return S_OK;
|
|
}
|
|
if (!memcmp(&IID_IDirectDraw4,refiid,sizeof(IID_IDirectDraw4))) {
|
|
This->lpvtbl = (ICOM_VTABLE(IDirectDraw2)*)&xlib_dd4vt;
|
|
IDirectDraw2_AddRef(iface);
|
|
*obj = This;
|
|
|
|
TRACE(ddraw, " Creating IDirectDraw4 interface (%p)\n", *obj);
|
|
|
|
return S_OK;
|
|
}
|
|
if (!memcmp(&IID_IDirect3D,refiid,sizeof(IID_IDirect3D))) {
|
|
IDirect3DImpl* d3d;
|
|
|
|
d3d = HeapAlloc(GetProcessHeap(),0,sizeof(*d3d));
|
|
d3d->ref = 1;
|
|
d3d->ddraw = (IDirectDrawImpl*)This;
|
|
IDirectDraw2_AddRef(iface);
|
|
d3d->lpvtbl = &d3dvt;
|
|
*obj = d3d;
|
|
|
|
TRACE(ddraw, " Creating IDirect3D interface (%p)\n", *obj);
|
|
|
|
return S_OK;
|
|
}
|
|
if (!memcmp(&IID_IDirect3D2,refiid,sizeof(IID_IDirect3D))) {
|
|
IDirect3D2Impl* d3d;
|
|
|
|
d3d = HeapAlloc(GetProcessHeap(),0,sizeof(*d3d));
|
|
d3d->ref = 1;
|
|
d3d->ddraw = (IDirectDrawImpl*)This;
|
|
IDirectDraw2_AddRef(iface);
|
|
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 IDirectDraw2Impl_GetVerticalBlankStatus(
|
|
LPDIRECTDRAW2 iface,BOOL *status
|
|
) {
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
TRACE(ddraw,"(%p)->(%p)\n",This,status);
|
|
*status = TRUE;
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI DGA_IDirectDraw2Impl_EnumDisplayModes(
|
|
LPDIRECTDRAW2 iface,DWORD dwFlags,LPDDSURFACEDESC lpddsfd,LPVOID context,LPDDENUMMODESCALLBACK modescb
|
|
) {
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
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_IDirectDraw2Impl_EnumDisplayModes(
|
|
LPDIRECTDRAW2 iface,DWORD dwFlags,LPDDSURFACEDESC lpddsfd,LPVOID context,LPDDENUMMODESCALLBACK modescb
|
|
) {
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
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));
|
|
DUMP("\n");
|
|
}
|
|
|
|
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_IDirectDraw2Impl_GetDisplayMode(
|
|
LPDIRECTDRAW2 iface,LPDDSURFACEDESC lpddsfd
|
|
) {
|
|
#ifdef HAVE_LIBXXF86DGA
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
TRACE(ddraw,"(%p)->(%p)\n",This,lpddsfd);
|
|
lpddsfd->dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PITCH|DDSD_BACKBUFFERCOUNT|DDSD_PIXELFORMAT|DDSD_CAPS;
|
|
lpddsfd->dwHeight = This->d.height;
|
|
lpddsfd->dwWidth = This->d.width;
|
|
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_IDirectDraw2Impl_GetDisplayMode(
|
|
LPDIRECTDRAW2 iface,LPDDSURFACEDESC lpddsfd
|
|
) {
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
TRACE(ddraw,"(%p)->GetDisplayMode(%p)\n",This,lpddsfd);
|
|
lpddsfd->dwFlags = DDSD_HEIGHT|DDSD_WIDTH|DDSD_PITCH|DDSD_BACKBUFFERCOUNT|DDSD_PIXELFORMAT|DDSD_CAPS;
|
|
lpddsfd->dwHeight = This->d.height;
|
|
lpddsfd->dwWidth = This->d.width;
|
|
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 IDirectDraw2Impl_FlipToGDISurface(LPDIRECTDRAW2 iface) {
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
TRACE(ddraw,"(%p)->()\n",This);
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDraw2Impl_GetMonitorFrequency(
|
|
LPDIRECTDRAW2 iface,LPDWORD freq
|
|
) {
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
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 IDirectDraw2Impl_GetFourCCCodes(
|
|
LPDIRECTDRAW2 iface,LPDWORD x,LPDWORD y
|
|
) {
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
FIXME(ddraw,"(%p,%p,%p), stub\n",This,x,y);
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDraw2Impl_EnumSurfaces(
|
|
LPDIRECTDRAW2 iface,DWORD x,LPDDSURFACEDESC ddsfd,LPVOID context,LPDDENUMSURFACESCALLBACK ddsfcb
|
|
) {
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
FIXME(ddraw,"(%p)->(0x%08lx,%p,%p,%p),stub!\n",This,x,ddsfd,context,ddsfcb);
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDraw2Impl_Compact(
|
|
LPDIRECTDRAW2 iface )
|
|
{
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
FIXME(ddraw,"(%p)->()\n", This );
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDraw2Impl_GetGDISurface(LPDIRECTDRAW2 iface,
|
|
LPDIRECTDRAWSURFACE *lplpGDIDDSSurface) {
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
FIXME(ddraw,"(%p)->(%p)\n", This, lplpGDIDDSSurface);
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDraw2Impl_GetScanLine(LPDIRECTDRAW2 iface,
|
|
LPDWORD lpdwScanLine) {
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
FIXME(ddraw,"(%p)->(%p)\n", This, lpdwScanLine);
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDraw2Impl_Initialize(LPDIRECTDRAW2 iface,
|
|
GUID *lpGUID) {
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
FIXME(ddraw,"(%p)->(%p)\n", This, lpGUID);
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
/* Note: Hack so we can reuse the old functions without compiler warnings */
|
|
#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
|
|
# define XCAST(fun) (typeof(dga_ddvt.fn##fun))
|
|
#else
|
|
# define XCAST(fun) (void *)
|
|
#endif
|
|
|
|
static ICOM_VTABLE(IDirectDraw) dga_ddvt =
|
|
{
|
|
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
|
|
XCAST(QueryInterface)DGA_IDirectDraw2Impl_QueryInterface,
|
|
XCAST(AddRef)IDirectDraw2Impl_AddRef,
|
|
XCAST(Release)DGA_IDirectDraw2Impl_Release,
|
|
XCAST(Compact)IDirectDraw2Impl_Compact,
|
|
XCAST(CreateClipper)IDirectDraw2Impl_CreateClipper,
|
|
XCAST(CreatePalette)DGA_IDirectDraw2Impl_CreatePalette,
|
|
XCAST(CreateSurface)DGA_IDirectDraw2Impl_CreateSurface,
|
|
XCAST(DuplicateSurface)IDirectDraw2Impl_DuplicateSurface,
|
|
XCAST(EnumDisplayModes)DGA_IDirectDraw2Impl_EnumDisplayModes,
|
|
XCAST(EnumSurfaces)IDirectDraw2Impl_EnumSurfaces,
|
|
XCAST(FlipToGDISurface)IDirectDraw2Impl_FlipToGDISurface,
|
|
XCAST(GetCaps)DGA_IDirectDraw2Impl_GetCaps,
|
|
XCAST(GetDisplayMode)DGA_IDirectDraw2Impl_GetDisplayMode,
|
|
XCAST(GetFourCCCodes)IDirectDraw2Impl_GetFourCCCodes,
|
|
XCAST(GetGDISurface)IDirectDraw2Impl_GetGDISurface,
|
|
XCAST(GetMonitorFrequency)IDirectDraw2Impl_GetMonitorFrequency,
|
|
XCAST(GetScanLine)IDirectDraw2Impl_GetScanLine,
|
|
XCAST(GetVerticalBlankStatus)IDirectDraw2Impl_GetVerticalBlankStatus,
|
|
XCAST(Initialize)IDirectDraw2Impl_Initialize,
|
|
XCAST(RestoreDisplayMode)DGA_IDirectDraw2Impl_RestoreDisplayMode,
|
|
XCAST(SetCooperativeLevel)IDirectDraw2Impl_SetCooperativeLevel,
|
|
DGA_IDirectDrawImpl_SetDisplayMode,
|
|
XCAST(WaitForVerticalBlank)IDirectDraw2Impl_WaitForVerticalBlank,
|
|
};
|
|
|
|
static ICOM_VTABLE(IDirectDraw) xlib_ddvt =
|
|
{
|
|
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
|
|
XCAST(QueryInterface)Xlib_IDirectDraw2Impl_QueryInterface,
|
|
XCAST(AddRef)IDirectDraw2Impl_AddRef,
|
|
XCAST(Release)Xlib_IDirectDraw2Impl_Release,
|
|
XCAST(Compact)IDirectDraw2Impl_Compact,
|
|
XCAST(CreateClipper)IDirectDraw2Impl_CreateClipper,
|
|
XCAST(CreatePalette)Xlib_IDirectDraw2Impl_CreatePalette,
|
|
XCAST(CreateSurface)Xlib_IDirectDraw2Impl_CreateSurface,
|
|
XCAST(DuplicateSurface)IDirectDraw2Impl_DuplicateSurface,
|
|
XCAST(EnumDisplayModes)Xlib_IDirectDraw2Impl_EnumDisplayModes,
|
|
XCAST(EnumSurfaces)IDirectDraw2Impl_EnumSurfaces,
|
|
XCAST(FlipToGDISurface)IDirectDraw2Impl_FlipToGDISurface,
|
|
XCAST(GetCaps)Xlib_IDirectDraw2Impl_GetCaps,
|
|
XCAST(GetDisplayMode)Xlib_IDirectDraw2Impl_GetDisplayMode,
|
|
XCAST(GetFourCCCodes)IDirectDraw2Impl_GetFourCCCodes,
|
|
XCAST(GetGDISurface)IDirectDraw2Impl_GetGDISurface,
|
|
XCAST(GetMonitorFrequency)IDirectDraw2Impl_GetMonitorFrequency,
|
|
XCAST(GetScanLine)IDirectDraw2Impl_GetScanLine,
|
|
XCAST(GetVerticalBlankStatus)IDirectDraw2Impl_GetVerticalBlankStatus,
|
|
XCAST(Initialize)IDirectDraw2Impl_Initialize,
|
|
XCAST(RestoreDisplayMode)Xlib_IDirectDraw2Impl_RestoreDisplayMode,
|
|
XCAST(SetCooperativeLevel)IDirectDraw2Impl_SetCooperativeLevel,
|
|
Xlib_IDirectDrawImpl_SetDisplayMode,
|
|
XCAST(WaitForVerticalBlank)IDirectDraw2Impl_WaitForVerticalBlank,
|
|
};
|
|
|
|
#undef XCAST
|
|
|
|
/*****************************************************************************
|
|
* IDirectDraw2
|
|
*
|
|
*/
|
|
|
|
|
|
static HRESULT WINAPI DGA_IDirectDraw2Impl_SetDisplayMode(
|
|
LPDIRECTDRAW2 iface,DWORD width,DWORD height,DWORD depth,DWORD xx,DWORD yy
|
|
) {
|
|
return DGA_IDirectDrawImpl_SetDisplayMode((LPDIRECTDRAW)iface,width,height,depth);
|
|
}
|
|
|
|
static HRESULT WINAPI Xlib_IDirectDraw2Impl_SetDisplayMode(
|
|
LPDIRECTDRAW2 iface,DWORD width,DWORD height,DWORD depth,DWORD xx,DWORD yy
|
|
) {
|
|
return Xlib_IDirectDrawImpl_SetDisplayMode((LPDIRECTDRAW)iface,width,height,depth);
|
|
}
|
|
|
|
static HRESULT WINAPI DGA_IDirectDraw2Impl_GetAvailableVidMem(
|
|
LPDIRECTDRAW2 iface,LPDDSCAPS ddscaps,LPDWORD total,LPDWORD free
|
|
) {
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
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_IDirectDraw2Impl_GetAvailableVidMem(
|
|
LPDIRECTDRAW2 iface,LPDDSCAPS ddscaps,LPDWORD total,LPDWORD free
|
|
) {
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
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 ICOM_VTABLE(IDirectDraw2) dga_dd2vt =
|
|
{
|
|
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
|
|
DGA_IDirectDraw2Impl_QueryInterface,
|
|
IDirectDraw2Impl_AddRef,
|
|
DGA_IDirectDraw2Impl_Release,
|
|
IDirectDraw2Impl_Compact,
|
|
IDirectDraw2Impl_CreateClipper,
|
|
DGA_IDirectDraw2Impl_CreatePalette,
|
|
DGA_IDirectDraw2Impl_CreateSurface,
|
|
IDirectDraw2Impl_DuplicateSurface,
|
|
DGA_IDirectDraw2Impl_EnumDisplayModes,
|
|
IDirectDraw2Impl_EnumSurfaces,
|
|
IDirectDraw2Impl_FlipToGDISurface,
|
|
DGA_IDirectDraw2Impl_GetCaps,
|
|
DGA_IDirectDraw2Impl_GetDisplayMode,
|
|
IDirectDraw2Impl_GetFourCCCodes,
|
|
IDirectDraw2Impl_GetGDISurface,
|
|
IDirectDraw2Impl_GetMonitorFrequency,
|
|
IDirectDraw2Impl_GetScanLine,
|
|
IDirectDraw2Impl_GetVerticalBlankStatus,
|
|
IDirectDraw2Impl_Initialize,
|
|
DGA_IDirectDraw2Impl_RestoreDisplayMode,
|
|
IDirectDraw2Impl_SetCooperativeLevel,
|
|
DGA_IDirectDraw2Impl_SetDisplayMode,
|
|
IDirectDraw2Impl_WaitForVerticalBlank,
|
|
DGA_IDirectDraw2Impl_GetAvailableVidMem
|
|
};
|
|
|
|
static ICOM_VTABLE(IDirectDraw2) xlib_dd2vt =
|
|
{
|
|
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
|
|
Xlib_IDirectDraw2Impl_QueryInterface,
|
|
IDirectDraw2Impl_AddRef,
|
|
Xlib_IDirectDraw2Impl_Release,
|
|
IDirectDraw2Impl_Compact,
|
|
IDirectDraw2Impl_CreateClipper,
|
|
Xlib_IDirectDraw2Impl_CreatePalette,
|
|
Xlib_IDirectDraw2Impl_CreateSurface,
|
|
IDirectDraw2Impl_DuplicateSurface,
|
|
Xlib_IDirectDraw2Impl_EnumDisplayModes,
|
|
IDirectDraw2Impl_EnumSurfaces,
|
|
IDirectDraw2Impl_FlipToGDISurface,
|
|
Xlib_IDirectDraw2Impl_GetCaps,
|
|
Xlib_IDirectDraw2Impl_GetDisplayMode,
|
|
IDirectDraw2Impl_GetFourCCCodes,
|
|
IDirectDraw2Impl_GetGDISurface,
|
|
IDirectDraw2Impl_GetMonitorFrequency,
|
|
IDirectDraw2Impl_GetScanLine,
|
|
IDirectDraw2Impl_GetVerticalBlankStatus,
|
|
IDirectDraw2Impl_Initialize,
|
|
Xlib_IDirectDraw2Impl_RestoreDisplayMode,
|
|
IDirectDraw2Impl_SetCooperativeLevel,
|
|
Xlib_IDirectDraw2Impl_SetDisplayMode,
|
|
IDirectDraw2Impl_WaitForVerticalBlank,
|
|
Xlib_IDirectDraw2Impl_GetAvailableVidMem
|
|
};
|
|
|
|
/*****************************************************************************
|
|
* IDirectDraw4
|
|
*
|
|
*/
|
|
|
|
static HRESULT WINAPI IDirectDraw4Impl_GetSurfaceFromDC(LPDIRECTDRAW4 iface,
|
|
HDC hdc,
|
|
LPDIRECTDRAWSURFACE *lpDDS) {
|
|
ICOM_THIS(IDirectDraw4Impl,iface);
|
|
FIXME(ddraw, "(%p)->(%08ld,%p)\n", This, (DWORD) hdc, lpDDS);
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDraw4Impl_RestoreAllSurfaces(LPDIRECTDRAW4 iface) {
|
|
ICOM_THIS(IDirectDraw4Impl,iface);
|
|
FIXME(ddraw, "(%p)->()\n", This);
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDraw4Impl_TestCooperativeLevel(LPDIRECTDRAW4 iface) {
|
|
ICOM_THIS(IDirectDraw4Impl,iface);
|
|
FIXME(ddraw, "(%p)->()\n", This);
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IDirectDraw4Impl_GetDeviceIdentifier(LPDIRECTDRAW4 iface,
|
|
LPDDDEVICEIDENTIFIER lpdddi,
|
|
DWORD dwFlags) {
|
|
ICOM_THIS(IDirectDraw4Impl,iface);
|
|
FIXME(ddraw, "(%p)->(%p,%08lx)\n", This, lpdddi, dwFlags);
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
|
|
# define XCAST(fun) (typeof(dga_dd4vt.fn##fun))
|
|
#else
|
|
# define XCAST(fun) (void*)
|
|
#endif
|
|
|
|
|
|
static ICOM_VTABLE(IDirectDraw4) dga_dd4vt =
|
|
{
|
|
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
|
|
XCAST(QueryInterface)DGA_IDirectDraw2Impl_QueryInterface,
|
|
XCAST(AddRef)IDirectDraw2Impl_AddRef,
|
|
XCAST(Release)DGA_IDirectDraw2Impl_Release,
|
|
XCAST(Compact)IDirectDraw2Impl_Compact,
|
|
XCAST(CreateClipper)IDirectDraw2Impl_CreateClipper,
|
|
XCAST(CreatePalette)DGA_IDirectDraw2Impl_CreatePalette,
|
|
XCAST(CreateSurface)DGA_IDirectDraw2Impl_CreateSurface,
|
|
XCAST(DuplicateSurface)IDirectDraw2Impl_DuplicateSurface,
|
|
XCAST(EnumDisplayModes)DGA_IDirectDraw2Impl_EnumDisplayModes,
|
|
XCAST(EnumSurfaces)IDirectDraw2Impl_EnumSurfaces,
|
|
XCAST(FlipToGDISurface)IDirectDraw2Impl_FlipToGDISurface,
|
|
XCAST(GetCaps)DGA_IDirectDraw2Impl_GetCaps,
|
|
XCAST(GetDisplayMode)DGA_IDirectDraw2Impl_GetDisplayMode,
|
|
XCAST(GetFourCCCodes)IDirectDraw2Impl_GetFourCCCodes,
|
|
XCAST(GetGDISurface)IDirectDraw2Impl_GetGDISurface,
|
|
XCAST(GetMonitorFrequency)IDirectDraw2Impl_GetMonitorFrequency,
|
|
XCAST(GetScanLine)IDirectDraw2Impl_GetScanLine,
|
|
XCAST(GetVerticalBlankStatus)IDirectDraw2Impl_GetVerticalBlankStatus,
|
|
XCAST(Initialize)IDirectDraw2Impl_Initialize,
|
|
XCAST(RestoreDisplayMode)DGA_IDirectDraw2Impl_RestoreDisplayMode,
|
|
XCAST(SetCooperativeLevel)IDirectDraw2Impl_SetCooperativeLevel,
|
|
XCAST(SetDisplayMode)DGA_IDirectDrawImpl_SetDisplayMode,
|
|
XCAST(WaitForVerticalBlank)IDirectDraw2Impl_WaitForVerticalBlank,
|
|
XCAST(GetAvailableVidMem)DGA_IDirectDraw2Impl_GetAvailableVidMem,
|
|
IDirectDraw4Impl_GetSurfaceFromDC,
|
|
IDirectDraw4Impl_RestoreAllSurfaces,
|
|
IDirectDraw4Impl_TestCooperativeLevel,
|
|
IDirectDraw4Impl_GetDeviceIdentifier
|
|
};
|
|
|
|
static ICOM_VTABLE(IDirectDraw4) xlib_dd4vt =
|
|
{
|
|
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
|
|
XCAST(QueryInterface)Xlib_IDirectDraw2Impl_QueryInterface,
|
|
XCAST(AddRef)IDirectDraw2Impl_AddRef,
|
|
XCAST(Release)Xlib_IDirectDraw2Impl_Release,
|
|
XCAST(Compact)IDirectDraw2Impl_Compact,
|
|
XCAST(CreateClipper)IDirectDraw2Impl_CreateClipper,
|
|
XCAST(CreatePalette)Xlib_IDirectDraw2Impl_CreatePalette,
|
|
XCAST(CreateSurface)Xlib_IDirectDraw2Impl_CreateSurface,
|
|
XCAST(DuplicateSurface)IDirectDraw2Impl_DuplicateSurface,
|
|
XCAST(EnumDisplayModes)Xlib_IDirectDraw2Impl_EnumDisplayModes,
|
|
XCAST(EnumSurfaces)IDirectDraw2Impl_EnumSurfaces,
|
|
XCAST(FlipToGDISurface)IDirectDraw2Impl_FlipToGDISurface,
|
|
XCAST(GetCaps)Xlib_IDirectDraw2Impl_GetCaps,
|
|
XCAST(GetDisplayMode)Xlib_IDirectDraw2Impl_GetDisplayMode,
|
|
XCAST(GetFourCCCodes)IDirectDraw2Impl_GetFourCCCodes,
|
|
XCAST(GetGDISurface)IDirectDraw2Impl_GetGDISurface,
|
|
XCAST(GetMonitorFrequency)IDirectDraw2Impl_GetMonitorFrequency,
|
|
XCAST(GetScanLine)IDirectDraw2Impl_GetScanLine,
|
|
XCAST(GetVerticalBlankStatus)IDirectDraw2Impl_GetVerticalBlankStatus,
|
|
XCAST(Initialize)IDirectDraw2Impl_Initialize,
|
|
XCAST(RestoreDisplayMode)Xlib_IDirectDraw2Impl_RestoreDisplayMode,
|
|
XCAST(SetCooperativeLevel)IDirectDraw2Impl_SetCooperativeLevel,
|
|
XCAST(SetDisplayMode)Xlib_IDirectDrawImpl_SetDisplayMode,
|
|
XCAST(WaitForVerticalBlank)IDirectDraw2Impl_WaitForVerticalBlank,
|
|
XCAST(GetAvailableVidMem)Xlib_IDirectDraw2Impl_GetAvailableVidMem,
|
|
IDirectDraw4Impl_GetSurfaceFromDC,
|
|
IDirectDraw4Impl_RestoreAllSurfaces,
|
|
IDirectDraw4Impl_TestCooperativeLevel,
|
|
IDirectDraw4Impl_GetDeviceIdentifier
|
|
};
|
|
|
|
#undef XCAST
|
|
|
|
/******************************************************************************
|
|
* DirectDrawCreate
|
|
*/
|
|
|
|
LRESULT WINAPI Xlib_DDWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
|
|
{
|
|
LRESULT ret;
|
|
IDirectDrawImpl* 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 = (IDirectDrawImpl*)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 )
|
|
{
|
|
WND *tmpWnd =WIN_FindWndPtr(ddraw->d.mainWindow);
|
|
/* We didn't handle the message - give it to the application */
|
|
if (ddraw && ddraw->d.mainWindow && tmpWnd)
|
|
{
|
|
ret = CallWindowProcA(tmpWnd->winproc,
|
|
ddraw->d.mainWindow, msg, wParam, lParam );
|
|
}
|
|
WIN_ReleaseWndPtr(tmpWnd);
|
|
|
|
}
|
|
|
|
} 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
|
|
IDirectDrawImpl** ilplpDD=(IDirectDrawImpl**)lplpDD;
|
|
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;
|
|
}
|
|
*ilplpDD = (IDirectDrawImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawImpl));
|
|
(*ilplpDD)->lpvtbl = &dga_ddvt;
|
|
(*ilplpDD)->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);
|
|
(*ilplpDD)->e.dga.fb_width = width;
|
|
TSXF86DGAGetViewPortSize(display,DefaultScreen(display),&width,&height);
|
|
TSXF86DGASetViewPort(display,DefaultScreen(display),0,0);
|
|
(*ilplpDD)->e.dga.fb_height = height;
|
|
TRACE(ddraw,"video framebuffer: begin %p, width %d,banksize %d,memsize %d\n",
|
|
addr,width,banksize,memsize
|
|
);
|
|
TRACE(ddraw,"viewport height: %d\n",height);
|
|
|
|
/* Get the screen dimensions as seen by Wine.
|
|
In that case, it may be better to ignore the -desktop mode and return the
|
|
real screen size => print a warning */
|
|
(*ilplpDD)->d.height = MONITOR_GetHeight(&MONITOR_PrimaryMonitor);
|
|
(*ilplpDD)->d.width = MONITOR_GetWidth(&MONITOR_PrimaryMonitor);
|
|
if (((*ilplpDD)->d.height != height) ||
|
|
((*ilplpDD)->d.width != width))
|
|
WARN(ddraw, "You seem to be runnin in -desktop mode. This may prove dangerous in DGA mode...\n");
|
|
(*ilplpDD)->e.dga.fb_addr = addr;
|
|
(*ilplpDD)->e.dga.fb_memsize = memsize;
|
|
(*ilplpDD)->e.dga.fb_banksize = banksize;
|
|
(*ilplpDD)->e.dga.vpmask = 0;
|
|
|
|
/* just assume the default depth is the DGA depth too */
|
|
depth = DefaultDepthOfScreen(X11DRV_GetXScreen());
|
|
_common_depth_to_pixelformat(depth, &((*ilplpDD)->d.directdraw_pixelformat), &((*ilplpDD)->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) {
|
|
IDirectDrawImpl** ilplpDD=(IDirectDrawImpl**)lplpDD;
|
|
int depth;
|
|
|
|
*ilplpDD = (IDirectDrawImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawImpl));
|
|
(*ilplpDD)->lpvtbl = &xlib_ddvt;
|
|
(*ilplpDD)->ref = 1;
|
|
(*ilplpDD)->d.drawable = 0; /* in SetDisplayMode */
|
|
|
|
/* At DirectDraw creation, the depth is the default depth */
|
|
depth = DefaultDepthOfScreen(X11DRV_GetXScreen());
|
|
_common_depth_to_pixelformat(depth,
|
|
&((*ilplpDD)->d.directdraw_pixelformat),
|
|
&((*ilplpDD)->d.screen_pixelformat),
|
|
&((*ilplpDD)->d.pixmap_depth));
|
|
(*ilplpDD)->d.height = MONITOR_GetHeight(&MONITOR_PrimaryMonitor);
|
|
(*ilplpDD)->d.width = MONITOR_GetWidth(&MONITOR_PrimaryMonitor);
|
|
|
|
#ifdef HAVE_LIBXXSHM
|
|
/* Test if XShm is available. */
|
|
if (((*ilplpDD)->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 ) {
|
|
IDirectDrawImpl** ilplpDD=(IDirectDrawImpl**)lplpDD;
|
|
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,ilplpDD,pUnkOuter);
|
|
|
|
if ((!lpGUID) ||
|
|
(!memcmp(lpGUID,&IID_IDirectDraw ,sizeof(IID_IDirectDraw ))) ||
|
|
(!memcmp(lpGUID,&IID_IDirectDraw2,sizeof(IID_IDirectDraw2))) ||
|
|
(!memcmp(lpGUID,&IID_IDirectDraw4,sizeof(IID_IDirectDraw4)))) {
|
|
/* 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 */
|
|
/*
|
|
This code is not useful since hInstance is forced to 0 afterward
|
|
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;
|
|
|
|
|
|
(*ilplpDD)->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;
|
|
}
|
|
|
|
|
|
#else /* !defined(X_DISPLAY_MISSING) */
|
|
|
|
#include "windef.h"
|
|
|
|
#define DD_OK 0
|
|
|
|
typedef void *LPGUID;
|
|
typedef void *LPUNKNOWN;
|
|
typedef void *LPDIRECTDRAW;
|
|
typedef void *LPDIRECTDRAWCLIPPER;
|
|
typedef void *LPDDENUMCALLBACKA;
|
|
typedef void *LPDDENUMCALLBACKEXA;
|
|
typedef void *LPDDENUMCALLBACKEXW;
|
|
typedef void *LPDDENUMCALLBACKW;
|
|
|
|
HRESULT WINAPI DSoundHelp(DWORD x, DWORD y, DWORD z)
|
|
{
|
|
return DD_OK;
|
|
}
|
|
|
|
HRESULT WINAPI DirectDrawCreate(
|
|
LPGUID lpGUID, LPDIRECTDRAW *lplpDD, LPUNKNOWN pUnkOuter)
|
|
{
|
|
return DD_OK;
|
|
}
|
|
|
|
HRESULT WINAPI DirectDrawCreateClipper(
|
|
DWORD dwFlags, LPDIRECTDRAWCLIPPER *lplpDDClipper, LPUNKNOWN pUnkOuter)
|
|
{
|
|
return DD_OK;
|
|
}
|
|
|
|
HRESULT WINAPI DirectDrawEnumerateA(
|
|
LPDDENUMCALLBACKA lpCallback, LPVOID lpContext)
|
|
{
|
|
return DD_OK;
|
|
}
|
|
|
|
HRESULT WINAPI DirectDrawEnumerateExA(
|
|
LPDDENUMCALLBACKEXA lpCallback, LPVOID lpContext, DWORD dwFlags)
|
|
{
|
|
return DD_OK;
|
|
}
|
|
|
|
HRESULT WINAPI DirectDrawEnumerateExW(
|
|
LPDDENUMCALLBACKEXW lpCallback, LPVOID lpContext, DWORD dwFlags)
|
|
{
|
|
return DD_OK;
|
|
}
|
|
|
|
HRESULT WINAPI DirectDrawEnumerateW(
|
|
LPDDENUMCALLBACKW lpCallback, LPVOID lpContext)
|
|
{
|
|
return DD_OK;
|
|
}
|
|
|
|
#endif /* !defined(X_DISPLAY_MISSING) */
|
|
|
|
|
|
/*******************************************************************************
|
|
* DirectDraw ClassFactory
|
|
*
|
|
* Heavily inspired (well, can you say completely copied :-) ) from DirectSound
|
|
*
|
|
*/
|
|
typedef struct
|
|
{
|
|
/* IUnknown fields */
|
|
ICOM_VTABLE(IClassFactory)* lpvtbl;
|
|
DWORD ref;
|
|
} IClassFactoryImpl;
|
|
|
|
static HRESULT WINAPI
|
|
DDCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) {
|
|
ICOM_THIS(IClassFactoryImpl,iface);
|
|
char buf[80];
|
|
|
|
if (HIWORD(riid))
|
|
WINE_StringFromCLSID(riid,buf);
|
|
else
|
|
sprintf(buf,"<guid-0x%04x>",LOWORD(riid));
|
|
FIXME(ddraw,"(%p)->(%s,%p),stub!\n",This,buf,ppobj);
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
static ULONG WINAPI
|
|
DDCF_AddRef(LPCLASSFACTORY iface) {
|
|
ICOM_THIS(IClassFactoryImpl,iface);
|
|
return ++(This->ref);
|
|
}
|
|
|
|
static ULONG WINAPI DDCF_Release(LPCLASSFACTORY iface) {
|
|
ICOM_THIS(IClassFactoryImpl,iface);
|
|
/* static class, won't be freed */
|
|
return --(This->ref);
|
|
}
|
|
|
|
static HRESULT WINAPI DDCF_CreateInstance(
|
|
LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj
|
|
) {
|
|
ICOM_THIS(IClassFactoryImpl,iface);
|
|
char buf[80];
|
|
|
|
WINE_StringFromCLSID(riid,buf);
|
|
TRACE(ddraw,"(%p)->(%p,%s,%p)\n",This,pOuter,buf,ppobj);
|
|
if ((!memcmp(riid,&IID_IDirectDraw ,sizeof(IID_IDirectDraw ))) ||
|
|
(!memcmp(riid,&IID_IDirectDraw2,sizeof(IID_IDirectDraw2))) ||
|
|
(!memcmp(riid,&IID_IDirectDraw4,sizeof(IID_IDirectDraw4)))) {
|
|
/* FIXME: reuse already created DirectDraw if present? */
|
|
return DirectDrawCreate((LPGUID) riid,(LPDIRECTDRAW*)ppobj,pOuter);
|
|
}
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
static HRESULT WINAPI DDCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) {
|
|
ICOM_THIS(IClassFactoryImpl,iface);
|
|
FIXME(ddraw,"(%p)->(%d),stub!\n",This,dolock);
|
|
return S_OK;
|
|
}
|
|
|
|
static ICOM_VTABLE(IClassFactory) DDCF_Vtbl =
|
|
{
|
|
ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
|
|
DDCF_QueryInterface,
|
|
DDCF_AddRef,
|
|
DDCF_Release,
|
|
DDCF_CreateInstance,
|
|
DDCF_LockServer
|
|
};
|
|
static IClassFactoryImpl DDRAW_CF = {&DDCF_Vtbl, 1 };
|
|
|
|
/*******************************************************************************
|
|
* DllGetClassObject [DDRAW.13]
|
|
* Retrieves class object from a DLL object
|
|
*
|
|
* NOTES
|
|
* Docs say returns STDAPI
|
|
*
|
|
* PARAMS
|
|
* rclsid [I] CLSID for the class object
|
|
* riid [I] Reference to identifier of interface for class object
|
|
* ppv [O] Address of variable to receive interface pointer for riid
|
|
*
|
|
* RETURNS
|
|
* Success: S_OK
|
|
* Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG,
|
|
* E_UNEXPECTED
|
|
*/
|
|
DWORD WINAPI DDRAW_DllGetClassObject(REFCLSID rclsid,REFIID riid,LPVOID *ppv)
|
|
{
|
|
char buf[80],xbuf[80];
|
|
|
|
if (HIWORD(rclsid))
|
|
WINE_StringFromCLSID(rclsid,xbuf);
|
|
else
|
|
sprintf(xbuf,"<guid-0x%04x>",LOWORD(rclsid));
|
|
if (HIWORD(riid))
|
|
WINE_StringFromCLSID(riid,buf);
|
|
else
|
|
sprintf(buf,"<guid-0x%04x>",LOWORD(riid));
|
|
WINE_StringFromCLSID(riid,xbuf);
|
|
TRACE(ddraw, "(%p,%p,%p)\n", xbuf, buf, ppv);
|
|
if (!memcmp(riid,&IID_IClassFactory,sizeof(IID_IClassFactory))) {
|
|
*ppv = (LPVOID)&DDRAW_CF;
|
|
IClassFactory_AddRef((IClassFactory*)*ppv);
|
|
return S_OK;
|
|
}
|
|
FIXME(ddraw, "(%p,%p,%p): no interface found.\n", xbuf, buf, ppv);
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
|
|
/*******************************************************************************
|
|
* DllCanUnloadNow [DDRAW.12] Determines whether the DLL is in use.
|
|
*
|
|
* RETURNS
|
|
* Success: S_OK
|
|
* Failure: S_FALSE
|
|
*/
|
|
DWORD WINAPI DDRAW_DllCanUnloadNow(void)
|
|
{
|
|
FIXME(ddraw, "(void): stub\n");
|
|
return S_FALSE;
|
|
}
|