/* 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 #include #ifdef HAVE_SYS_SIGNAL_H # include #endif #include #include #include #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); }