forked from Mirrors/wine-wine
722 lines
24 KiB
C
722 lines
24 KiB
C
/* DirectDraw IDirectDraw XF86DGA interface
|
|
*
|
|
* Copyright 1997-2000 Marcus Meissner
|
|
* Copyright 1998-2000 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.
|
|
*/
|
|
|
|
/*
|
|
* This file contains the XF86 DGA specific interface functions.
|
|
* We are 'allowed' to call X11 specific IDirectDraw functions.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <assert.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "winerror.h"
|
|
#include "wine/exception.h"
|
|
#include "ddraw.h"
|
|
#include "d3d.h"
|
|
#include "debugtools.h"
|
|
#include "message.h"
|
|
#include "options.h"
|
|
#include "monitor.h"
|
|
|
|
#define RESTORE_SIGNALS
|
|
|
|
DEFAULT_DEBUG_CHANNEL(ddraw);
|
|
|
|
#include "dga_private.h"
|
|
|
|
struct ICOM_VTABLE(IDirectDraw) dga_ddvt;
|
|
struct ICOM_VTABLE(IDirectDraw2) dga_dd2vt;
|
|
struct ICOM_VTABLE(IDirectDraw4) dga_dd4vt;
|
|
|
|
#ifdef HAVE_LIBXXF86VM
|
|
static XF86VidModeModeInfo *orig_mode = NULL;
|
|
#endif
|
|
|
|
#define DDPRIVATE(x) dga_dd_private *ddpriv = ((dga_dd_private*)(x)->private)
|
|
#define DPPRIVATE(x) dga_dp_private *dppriv = ((dga_dp_private*)(x)->private)
|
|
|
|
/*******************************************************************************
|
|
* IDirectDraw
|
|
*/
|
|
|
|
/* This function is used both by DGA and DGA2 drivers, thus the virtual function table
|
|
is not set here, but in the calling function */
|
|
HRESULT WINAPI DGA_IDirectDraw2Impl_CreateSurface_no_VT(
|
|
LPDIRECTDRAW2 iface,LPDDSURFACEDESC lpddsd,LPDIRECTDRAWSURFACE *lpdsf,
|
|
IUnknown *lpunk
|
|
) {
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
IDirectDrawSurfaceImpl* dsurf;
|
|
DDPRIVATE(This);
|
|
dga_ds_private *dspriv;
|
|
int i, fbheight = ddpriv->fb_height;
|
|
|
|
TRACE("(%p)->(%p,%p,%p)\n",This,lpddsd,lpdsf,lpunk);
|
|
if (TRACE_ON(ddraw)) _dump_surface_desc(lpddsd);
|
|
|
|
*lpdsf = (LPDIRECTDRAWSURFACE)HeapAlloc(
|
|
GetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
sizeof(IDirectDrawSurfaceImpl)
|
|
);
|
|
dsurf = *(IDirectDrawSurfaceImpl**)lpdsf;
|
|
dsurf->private = (dga_ds_private*)HeapAlloc(
|
|
GetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
sizeof(dga_ds_private)
|
|
);
|
|
dspriv = (dga_ds_private*)dsurf->private;
|
|
IDirectDraw2_AddRef(iface);
|
|
|
|
dsurf->ref = 1;
|
|
dsurf->s.ddraw = This;
|
|
dsurf->s.palette = NULL;
|
|
dspriv->fb_height = -1; /* This is to have non-on screen surfaces freed */
|
|
dsurf->s.lpClipper = NULL;
|
|
|
|
/* Copy the surface description */
|
|
dsurf->s.surface_desc = *lpddsd;
|
|
|
|
if (!(lpddsd->dwFlags & DDSD_WIDTH))
|
|
dsurf->s.surface_desc.dwWidth = This->d.width;
|
|
if (!(lpddsd->dwFlags & DDSD_HEIGHT))
|
|
dsurf->s.surface_desc.dwHeight = This->d.height;
|
|
|
|
dsurf->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 */
|
|
|
|
/* Find a viewport */
|
|
for (i=0;i<32;i++)
|
|
if (!(ddpriv->vpmask & (1<<i)))
|
|
break;
|
|
TRACE("using viewport %d for a primary surface\n",i);
|
|
/* if i == 32 or maximum ... return error */
|
|
ddpriv->vpmask|=(1<<i);
|
|
lpddsd->lPitch = dsurf->s.surface_desc.lPitch =
|
|
ddpriv->fb_width*PFGET_BPP(This->d.directdraw_pixelformat);
|
|
|
|
dsurf->s.surface_desc.u1.lpSurface =
|
|
ddpriv->fb_addr + i*fbheight*lpddsd->lPitch;
|
|
|
|
dspriv->fb_height = i*fbheight;
|
|
|
|
/* Add flags if there were not present */
|
|
dsurf->s.surface_desc.dwFlags |= DDSD_WIDTH|DDSD_HEIGHT|DDSD_PITCH|DDSD_LPSURFACE|DDSD_PIXELFORMAT;
|
|
dsurf->s.surface_desc.dwWidth = This->d.width;
|
|
dsurf->s.surface_desc.dwHeight = This->d.height;
|
|
TRACE("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 */
|
|
SDDSCAPS(dsurf) |= DDSCAPS_VISIBLE|DDSCAPS_VIDEOMEMORY;
|
|
dsurf->s.surface_desc.ddpfPixelFormat = This->d.directdraw_pixelformat;
|
|
dsurf->s.chain = NULL;
|
|
|
|
if (lpddsd->dwFlags & DDSD_BACKBUFFERCOUNT) {
|
|
IDirectDrawSurface4Impl* back;
|
|
dga_ds_private *bspriv;
|
|
int bbc;
|
|
|
|
for (bbc=lpddsd->dwBackBufferCount;bbc--;) {
|
|
int i;
|
|
|
|
back = (IDirectDrawSurface4Impl*)HeapAlloc(
|
|
GetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
sizeof(IDirectDrawSurface4Impl)
|
|
);
|
|
IDirectDraw2_AddRef(iface);
|
|
back->ref = 1;
|
|
ICOM_VTBL(back) = (ICOM_VTABLE(IDirectDrawSurface4)*)&dga_dds4vt;
|
|
back->private = HeapAlloc(
|
|
GetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
sizeof(dga_ds_private)
|
|
);
|
|
bspriv = (dga_ds_private*)back->private;
|
|
|
|
for (i=0;i<32;i++)
|
|
if (!(ddpriv->vpmask & (1<<i)))
|
|
break;
|
|
TRACE("using viewport %d for backbuffer %d\n",i, bbc);
|
|
/* if i == 32 or maximum ... return error */
|
|
ddpriv->vpmask|=(1<<i);
|
|
|
|
bspriv->fb_height = i*fbheight;
|
|
/* Copy the surface description from the front buffer */
|
|
back->s.surface_desc = dsurf->s.surface_desc;
|
|
/* Change the parameters that are not the same */
|
|
back->s.surface_desc.u1.lpSurface =
|
|
ddpriv->fb_addr + i*fbheight*lpddsd->lPitch;
|
|
|
|
back->s.ddraw = This;
|
|
/* Add relevant info to front and back buffers */
|
|
/* FIXME: backbuffer/frontbuffer handling broken here, but
|
|
* will be fixed up in _Flip().
|
|
*/
|
|
SDDSCAPS(dsurf) |= DDSCAPS_FRONTBUFFER;
|
|
SDDSCAPS(back) |= DDSCAPS_FLIP|DDSCAPS_BACKBUFFER|DDSCAPS_VIDEOMEMORY;
|
|
back->s.surface_desc.dwFlags &= ~DDSD_BACKBUFFERCOUNT;
|
|
SDDSCAPS(back) &= ~DDSCAPS_VISIBLE;
|
|
IDirectDrawSurface4_AddAttachedSurface((LPDIRECTDRAWSURFACE4)(*lpdsf),(LPDIRECTDRAWSURFACE4)back);
|
|
}
|
|
}
|
|
} else {
|
|
/* There is no DGA-specific code here...
|
|
* Go to the common surface creation function
|
|
*/
|
|
return common_off_screen_CreateSurface(This, dsurf);
|
|
}
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI DGA_IDirectDraw2Impl_CreateSurface(
|
|
LPDIRECTDRAW2 iface,LPDDSURFACEDESC lpddsd,LPDIRECTDRAWSURFACE *lpdsf,
|
|
IUnknown *lpunk
|
|
) {
|
|
HRESULT ret;
|
|
IDirectDrawSurfaceImpl* dsurf;
|
|
|
|
ret = DGA_IDirectDraw2Impl_CreateSurface_no_VT(iface, lpddsd, lpdsf, lpunk);
|
|
|
|
dsurf = *(IDirectDrawSurfaceImpl**)lpdsf;
|
|
ICOM_VTBL(dsurf) = (ICOM_VTABLE(IDirectDrawSurface)*)&dga_dds4vt;
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
static HRESULT WINAPI DGA_IDirectDrawImpl_SetDisplayMode(
|
|
LPDIRECTDRAW iface,DWORD width,DWORD height,DWORD depth
|
|
) {
|
|
ICOM_THIS(IDirectDrawImpl,iface);
|
|
DDPRIVATE(This);
|
|
int i,mode_count;
|
|
|
|
TRACE("(%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("(w=%ld,h=%ld,d=%ld), unsupported depth!\n",width,height,depth);
|
|
return DDERR_UNSUPPORTEDMODE;
|
|
}
|
|
|
|
if (This->d.width < width) {
|
|
ERR("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 (ddpriv->fb_height < height)
|
|
ddpriv->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("Fullscreen mode not available!\n");
|
|
|
|
if (vidmode) {
|
|
TRACE("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_Init();
|
|
#endif
|
|
return DD_OK;
|
|
}
|
|
|
|
HRESULT WINAPI DGA_IDirectDraw2Impl_GetCaps(
|
|
LPDIRECTDRAW2 iface,LPDDCAPS caps1,LPDDCAPS caps2
|
|
) {
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
DDPRIVATE(This);
|
|
|
|
TRACE("(%p)->GetCaps(%p,%p)\n",This,caps1,caps2);
|
|
if (!caps1 && !caps2)
|
|
return DDERR_INVALIDPARAMS;
|
|
if (caps1) {
|
|
caps1->dwVidMemTotal = ddpriv->fb_memsize;
|
|
caps1->dwCaps = 0xffffffff&~(DDCAPS_BANKSWITCHED); /* we can do anything */
|
|
caps1->ddsCaps.dwCaps = 0xffffffff; /* we can do anything */
|
|
}
|
|
if (caps2) {
|
|
caps2->dwVidMemTotal = ddpriv->fb_memsize;
|
|
caps2->dwCaps = 0xffffffff&~(DDCAPS_BANKSWITCHED); /* we can do anything */
|
|
caps2->ddsCaps.dwCaps = 0xffffffff; /* we can do anything */
|
|
}
|
|
return DD_OK;
|
|
}
|
|
|
|
#if 0 /* Not used as of now.... */
|
|
static void fill_caps(LPDDCAPS caps) {
|
|
/* This function tries to fill the capabilities of Wine's DDraw
|
|
* implementation. Needs 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 /*| DDCAPS_NOHARDWARE*/;
|
|
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_OPENGL
|
|
caps->dwCaps |= DDCAPS_3D | DDCAPS_ZBLTS;
|
|
caps->dwCaps2 |= DDCAPS2_NO2DDURING3DSCENE;
|
|
caps->ddsCaps.dwCaps |= DDSCAPS_3DDEVICE | DDSCAPS_MIPMAP | DDSCAPS_TEXTURE | DDSCAPS_ZBUFFER;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
static HRESULT WINAPI DGA_IDirectDraw2Impl_CreatePalette(
|
|
LPDIRECTDRAW2 iface,DWORD dwFlags,LPPALETTEENTRY palent,LPDIRECTDRAWPALETTE *lpddpal,LPUNKNOWN lpunk
|
|
) {
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
IDirectDrawPaletteImpl* ddpal;
|
|
dga_dp_private *dppriv;
|
|
HRESULT res;
|
|
int xsize = 0,i;
|
|
|
|
TRACE("(%p)->(%08lx,%p,%p,%p)\n",This,dwFlags,palent,lpddpal,lpunk);
|
|
res = common_IDirectDraw2Impl_CreatePalette(This,dwFlags,palent,(IDirectDrawPaletteImpl**)lpddpal,lpunk,&xsize);
|
|
if (res != 0)
|
|
return res;
|
|
ddpal = *(IDirectDrawPaletteImpl**)lpddpal;
|
|
ddpal->private = HeapAlloc(
|
|
GetProcessHeap(),
|
|
HEAP_ZERO_MEMORY,
|
|
sizeof(dga_dp_private)
|
|
);
|
|
dppriv = (dga_dp_private*)ddpal->private;
|
|
|
|
ICOM_VTBL(ddpal)= &dga_ddpalvt;
|
|
if (This->d.directdraw_pixelformat.u.dwRGBBitCount<=8) {
|
|
dppriv->cm = TSXCreateColormap(display,DefaultRootWindow(display),DefaultVisualOfScreen(X11DRV_GetXScreen()),AllocAll);
|
|
} else {
|
|
ERR("why are we doing CreatePalette in hi/truecolor?\n");
|
|
dppriv->cm = 0;
|
|
}
|
|
if (dppriv->cm && xsize) {
|
|
for (i=0;i<xsize;i++) {
|
|
XColor xc;
|
|
|
|
xc.red = ddpal->palents[i].peRed<<8;
|
|
xc.blue = ddpal->palents[i].peBlue<<8;
|
|
xc.green = ddpal->palents[i].peGreen<<8;
|
|
xc.flags = DoRed|DoBlue|DoGreen;
|
|
xc.pixel = i;
|
|
TSXStoreColor(display,dppriv->cm,&xc);
|
|
}
|
|
}
|
|
return DD_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI DGA_IDirectDraw2Impl_RestoreDisplayMode(LPDIRECTDRAW2 iface) {
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
TRACE("(%p)->()\n",This);
|
|
Sleep(1000);
|
|
TSXF86DGADirectVideo(display,DefaultScreen(display),0);
|
|
#ifdef RESTORE_SIGNALS
|
|
SIGNAL_Init();
|
|
#endif
|
|
return DD_OK;
|
|
}
|
|
|
|
static ULONG WINAPI DGA_IDirectDraw2Impl_Release(LPDIRECTDRAW2 iface) {
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
TRACE("(%p)->() decrementing from %lu.\n", This, This->ref );
|
|
|
|
if (!--(This->ref)) {
|
|
TSXF86DGADirectVideo(display,DefaultScreen(display),0);
|
|
if (This->d.window && GetPropA(This->d.window,ddProp))
|
|
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_Init();
|
|
#endif
|
|
HeapFree(GetProcessHeap(),0,This);
|
|
return S_OK;
|
|
}
|
|
return This->ref;
|
|
}
|
|
|
|
HRESULT WINAPI DGA_IDirectDraw2Impl_QueryInterface(
|
|
LPDIRECTDRAW2 iface,REFIID refiid,LPVOID *obj
|
|
) {
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
|
|
TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(refiid),obj);
|
|
if ( IsEqualGUID( &IID_IUnknown, refiid ) ) {
|
|
*obj = This;
|
|
IDirectDraw2_AddRef(iface);
|
|
|
|
TRACE(" Creating IUnknown interface (%p)\n", *obj);
|
|
|
|
return S_OK;
|
|
}
|
|
if ( IsEqualGUID( &IID_IDirectDraw, refiid ) ) {
|
|
ICOM_VTBL(This) = (ICOM_VTABLE(IDirectDraw2)*)&dga_ddvt;
|
|
IDirectDraw2_AddRef(iface);
|
|
*obj = This;
|
|
|
|
TRACE(" Creating IDirectDraw interface (%p)\n", *obj);
|
|
|
|
return S_OK;
|
|
}
|
|
if ( IsEqualGUID( &IID_IDirectDraw2, refiid ) ) {
|
|
ICOM_VTBL(This) = (ICOM_VTABLE(IDirectDraw2)*)&dga_dd2vt;
|
|
IDirectDraw2_AddRef(iface);
|
|
*obj = This;
|
|
|
|
TRACE(" Creating IDirectDraw2 interface (%p)\n", *obj);
|
|
|
|
return S_OK;
|
|
}
|
|
if ( IsEqualGUID( &IID_IDirectDraw4, refiid ) ) {
|
|
ICOM_VTBL(This) = (ICOM_VTABLE(IDirectDraw2)*)&dga_dd4vt;
|
|
IDirectDraw2_AddRef(iface);
|
|
*obj = This;
|
|
|
|
TRACE(" Creating IDirectDraw4 interface (%p)\n", *obj);
|
|
|
|
return S_OK;
|
|
}
|
|
FIXME("(%p):interface for IID %s _NOT_ found!\n",This,debugstr_guid(refiid));
|
|
return OLE_E_ENUM_NOMORE;
|
|
}
|
|
|
|
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 usual modes */
|
|
{512,384},
|
|
{640,400},
|
|
{640,480},
|
|
{800,600},
|
|
{1024,768},
|
|
};
|
|
static int depths[4] = {8,16,24,32};
|
|
int i,j;
|
|
|
|
TRACE("(%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.u.dwRefreshRate = 60;
|
|
}
|
|
ddsfd.ddsCaps.dwCaps = 0;
|
|
ddsfd.dwBackBufferCount = 1;
|
|
|
|
for (i=0;i<sizeof(depths)/sizeof(depths[0]);i++) {
|
|
ddsfd.dwBackBufferCount = 1;
|
|
ddsfd.ddpfPixelFormat.dwFourCC = 0;
|
|
ddsfd.ddpfPixelFormat.dwFlags = DDPF_RGB;
|
|
ddsfd.ddpfPixelFormat.u.dwRGBBitCount = depths[i];
|
|
/* FIXME: those masks would have to be set in depth > 8 */
|
|
if (depths[i]==8) {
|
|
ddsfd.ddpfPixelFormat.u1.dwRBitMask = 0;
|
|
ddsfd.ddpfPixelFormat.u2.dwGBitMask = 0;
|
|
ddsfd.ddpfPixelFormat.u3.dwBBitMask = 0;
|
|
ddsfd.ddpfPixelFormat.u4.dwRGBAlphaBitMask= 0;
|
|
ddsfd.ddsCaps.dwCaps=DDSCAPS_PALETTE;
|
|
ddsfd.ddpfPixelFormat.dwFlags|=DDPF_PALETTEINDEXED8;
|
|
} else {
|
|
ddsfd.ddpfPixelFormat.u4.dwRGBAlphaBitMask= 0;
|
|
|
|
/* FIXME: We should query those from X itself */
|
|
switch (depths[i]) {
|
|
case 16:
|
|
ddsfd.ddpfPixelFormat.u1.dwRBitMask = 0xF800;
|
|
ddsfd.ddpfPixelFormat.u2.dwGBitMask = 0x07E0;
|
|
ddsfd.ddpfPixelFormat.u3.dwBBitMask= 0x001F;
|
|
break;
|
|
case 24:
|
|
ddsfd.ddpfPixelFormat.u1.dwRBitMask = 0x00FF0000;
|
|
ddsfd.ddpfPixelFormat.u2.dwGBitMask = 0x0000FF00;
|
|
ddsfd.ddpfPixelFormat.u3.dwBBitMask= 0x000000FF;
|
|
break;
|
|
case 32:
|
|
ddsfd.ddpfPixelFormat.u1.dwRBitMask = 0x00FF0000;
|
|
ddsfd.ddpfPixelFormat.u2.dwGBitMask = 0x0000FF00;
|
|
ddsfd.ddpfPixelFormat.u3.dwBBitMask= 0x000000FF;
|
|
break;
|
|
}
|
|
}
|
|
|
|
ddsfd.dwWidth = MONITOR_GetWidth(&MONITOR_PrimaryMonitor);
|
|
ddsfd.dwHeight = MONITOR_GetHeight(&MONITOR_PrimaryMonitor);
|
|
TRACE(" 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(" 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(" enumerating (320x200x%d)\n",depths[i]);
|
|
if (!modescb(&ddsfd,context)) return DD_OK;
|
|
}
|
|
}
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
HRESULT WINAPI DGA_IDirectDraw2Impl_GetDisplayMode(
|
|
LPDIRECTDRAW2 iface,LPDDSURFACEDESC lpddsfd
|
|
) {
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
DDPRIVATE(This);
|
|
|
|
TRACE("(%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 = ddpriv->fb_width*PFGET_BPP(This->d.directdraw_pixelformat);
|
|
lpddsfd->dwBackBufferCount = 2;
|
|
lpddsfd->u.dwRefreshRate = 60;
|
|
lpddsfd->ddsCaps.dwCaps = DDSCAPS_PALETTE;
|
|
lpddsfd->ddpfPixelFormat = This->d.directdraw_pixelformat;
|
|
if (TRACE_ON(ddraw))
|
|
_dump_surface_desc(lpddsfd);
|
|
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
|
|
|
|
struct 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,
|
|
};
|
|
#undef XCAST
|
|
|
|
/*****************************************************************************
|
|
* IDirectDraw2
|
|
*
|
|
*/
|
|
|
|
static HRESULT WINAPI DGA_IDirectDraw2Impl_SetDisplayMode(
|
|
LPDIRECTDRAW2 iface,DWORD width,DWORD height,DWORD depth,DWORD dwRefreshRate, DWORD dwFlags
|
|
) {
|
|
FIXME( "Ignored parameters (0x%08lx,0x%08lx)\n", dwRefreshRate, dwFlags );
|
|
return DGA_IDirectDrawImpl_SetDisplayMode((LPDIRECTDRAW)iface,width,height,depth);
|
|
}
|
|
|
|
HRESULT WINAPI DGA_IDirectDraw2Impl_GetAvailableVidMem(
|
|
LPDIRECTDRAW2 iface,LPDDSCAPS ddscaps,LPDWORD total,LPDWORD free
|
|
) {
|
|
ICOM_THIS(IDirectDraw2Impl,iface);
|
|
DDPRIVATE(This);
|
|
|
|
TRACE("(%p)->(%p,%p,%p)\n",This,ddscaps,total,free);
|
|
if (total) *total = ddpriv->fb_memsize * 1024;
|
|
if (free) *free = ddpriv->fb_memsize * 1024;
|
|
return DD_OK;
|
|
}
|
|
|
|
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
|
|
};
|
|
|
|
#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
|
|
# define XCAST(fun) (typeof(dga_dd4vt.fn##fun))
|
|
#else
|
|
# define XCAST(fun) (void*)
|
|
#endif
|
|
|
|
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
|
|
};
|
|
#undef XCAST
|