wine-wine/dlls/ddraw/dga.c

194 lines
5.7 KiB
C

/* DirectDraw using DGA
*
* 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.
*/
#include "config.h"
#include "winerror.h"
#include <unistd.h>
#include <assert.h>
#ifdef HAVE_SYS_SIGNAL_H
# include <sys/signal.h>
#endif
#include <fcntl.h>
#include <string.h>
#include <stdio.h>
#include "heap.h"
#include "wine/exception.h"
#include "ddraw.h"
#include "d3d.h"
#include "debugtools.h"
#include "options.h"
#include "dga_private.h"
#define RESTORE__SIGNALS
DEFAULT_DEBUG_CHANNEL(ddraw);
#ifdef HAVE_LIBXXF86VM
XF86VidModeModeInfo *orig_mode = NULL;
#endif
static inline BOOL get_option( const char *name, BOOL def ) {
return PROFILE_GetWineIniBool( "x11drv", name, def );
}
static BYTE
DDRAW_DGA_Available(void)
{
int fd, evbase, evret, majver, minver;
static BYTE return_value = 0xFF;
/* This prevents from probing X times for DGA */
if (return_value != 0xFF)
return return_value;
if (!get_option( "UseDGA", 1 )) {
TRACE("UseDGA disabled.\n");
return_value = 0;
return 0;
}
/* First, query the extenstion and its version */
if (!TSXF86DGAQueryExtension(display,&evbase,&evret)) {
TRACE("DGA extension not detected.\n");
return_value = 0;
return 0;
}
if (!TSXF86DGAQueryVersion(display,&majver,&minver)) {
TRACE("DGA version not detected.\n");
return_value = 0;
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);
if (fd != -1)
return_value = 1;
else {
TRACE("You have no access to /dev/mem\n");
return_value = 0;
}
return return_value;
}
HRESULT
DGA_Create( LPDIRECTDRAW *lplpDD ) {
IDirectDrawImpl* ddraw;
dga_dd_private* dgpriv;
int memsize,banksize,major,minor,flags;
char *addr;
int depth;
int dga_version;
int width, height;
/* Get DGA availability / version */
dga_version = DDRAW_DGA_Available();
if (dga_version == 0)
return DDERR_GENERIC;
/* If we were just testing ... return OK */
if (lplpDD == NULL)
return DD_OK;
ddraw = (IDirectDrawImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawImpl));
*lplpDD = (LPDIRECTDRAW)ddraw;
ddraw->ref = 1;
ICOM_VTBL(ddraw) = &dga_ddvt;
ddraw->d = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*(ddraw->d)));
ddraw->d->ref = 1;
ddraw->d->private = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(dga_dd_private));
dgpriv = (dga_dd_private*)ddraw->d->private;
TSXF86DGAQueryVersion(display,&major,&minor);
TRACE("XF86DGA is version %d.%d\n",major,minor);
TSXF86DGAQueryDirectVideo(display,DefaultScreen(display),&flags);
if (!(flags & XF86DGADirectPresent)) {
/* On some boards, DGA extension is present but does not support DirectVideo */
MESSAGE("direct video is NOT PRESENT.\n");
return DDERR_GENERIC;
}
TSXF86DGAGetVideo(display,DefaultScreen(display),&addr,&width,&banksize,&memsize);
dgpriv->fb_width = width;
TSXF86DGAGetViewPortSize(display,DefaultScreen(display),&width,&height);
TSXF86DGASetViewPort(display,DefaultScreen(display),0,0);
dgpriv->fb_height = height;
TRACE("video framebuffer: begin %p, width %d,banksize %d,memsize %d\n",
addr,width,banksize,memsize
);
TRACE("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
*/
ddraw->d->height = GetSystemMetrics(SM_CYSCREEN);
ddraw->d->width = GetSystemMetrics(SM_CXSCREEN);
if ((ddraw->d->height != height) || (ddraw->d->width != width))
WARN("You seem to be running in -desktop mode. This may prove dangerous in DGA mode...\n");
dgpriv->fb_addr = addr;
dgpriv->fb_memsize = memsize;
dgpriv->vpmask = 0;
/* Register frame buffer with the kernel, it is a potential DIB section */
VirtualAlloc(dgpriv->fb_addr, dgpriv->fb_memsize, MEM_RESERVE|MEM_SYSTEM, PAGE_READWRITE);
/* The cast is because DGA2's install colormap does not return a value whereas
DGA1 version does */
dgpriv->InstallColormap = (void (*)(Display *, int, Colormap)) TSXF86DGAInstallColormap;
/* just assume the default depth is the DGA depth too */
depth = DefaultDepthOfScreen(X11DRV_GetXScreen());
_common_depth_to_pixelformat(depth, (IDirectDraw*) ddraw);
#ifdef RESTORE_SIGNALS
SIGNAL_Init();
#endif
return DD_OK;
}
/* 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}
};
ddraw_driver dga_driver = {
&DGA_DirectDraw_GUID,
"display",
"WINE XF86DGA DirectDraw Driver",
100,
DGA_Create
};
DECL_GLOBAL_CONSTRUCTOR(DGA_register) { ddraw_register_driver(&dga_driver); }