Do not support DGA when DirectVideo not present.
[wine] / dlls / ddraw / dga.c
1 /*              DirectDraw using DGA
2  *
3  * Copyright 1997-2000 Marcus Meissner
4  * Copyright 1998-2000 Lionel Ulmer (most of Direct3D stuff)
5  */
6 /* XF86DGA:
7  * When DirectVideo mode is enabled you can no longer use 'normal' X 
8  * applications nor can you switch to a virtual console. Also, enabling
9  * only works, if you have switched to the screen where the application
10  * is running.
11  * Some ways to debug this stuff are:
12  * - A terminal connected to the serial port. Can be bought used for cheap.
13  *   (This is the method I am using.)
14  * - Another machine connected over some kind of network.
15  */
16
17 #include "config.h"
18 #include "winerror.h"
19
20 #include <unistd.h>
21 #include <assert.h>
22 #ifdef HAVE_SYS_SIGNAL_H
23 # include <sys/signal.h>
24 #endif
25 #include <fcntl.h>
26 #include <string.h>
27 #include <stdio.h>
28
29 #include "heap.h"
30 #include "wine/exception.h"
31 #include "ddraw.h"
32 #include "d3d.h"
33 #include "debugtools.h"
34 #include "options.h"
35
36 #include "dga_private.h"
37
38 #define RESTORE__SIGNALS
39
40 DEFAULT_DEBUG_CHANNEL(ddraw);
41
42 #ifdef HAVE_LIBXXF86VM
43 XF86VidModeModeInfo *orig_mode = NULL;
44 #endif
45
46 static inline BOOL get_option( const char *name, BOOL def ) {
47     return PROFILE_GetWineIniBool( "x11drv", name, def );
48 }
49
50 static BYTE
51 DDRAW_DGA_Available(void)
52 {
53     int fd, evbase, evret, majver, minver;
54     static BYTE return_value = 0xFF;
55
56     /* This prevents from probing X times for DGA */
57     if (return_value != 0xFF)
58         return return_value;
59
60     if (!get_option( "UseDGA", 1 )) {
61         TRACE("UseDGA disabled.\n");
62         return_value = 0;
63         return 0;
64     }
65
66     /* First, query the extenstion and its version */
67     if (!TSXF86DGAQueryExtension(display,&evbase,&evret)) {
68         TRACE("DGA extension not detected.\n");
69         return_value = 0;
70         return 0;
71     }
72
73     if (!TSXF86DGAQueryVersion(display,&majver,&minver)) {
74         TRACE("DGA version not detected.\n");
75         return_value = 0;
76         return 0;
77     }
78
79     /* You don't have to be root to use DGA extensions. Simply having access
80      * to /dev/mem will do the trick
81      * This can be achieved by adding the user to the "kmem" group on
82      * Debian 2.x systems, don't know about 
83      * others. --stephenc
84      */
85     if ((fd = open("/dev/mem", O_RDWR)) != -1)
86         close(fd);
87
88     if (fd != -1)
89         return_value = 1;
90     else {
91         TRACE("You have no access to /dev/mem\n");
92         return_value = 0;
93     }
94     return return_value;
95 }
96
97 HRESULT 
98 DGA_Create( LPDIRECTDRAW *lplpDD ) {
99     IDirectDrawImpl*            ddraw;
100     dga_dd_private*     dgpriv;
101     int  memsize,banksize,major,minor,flags;
102     char *addr;
103     int  depth;
104     int  dga_version;
105     int  width, height;
106       
107     /* Get DGA availability / version */
108     dga_version = DDRAW_DGA_Available();
109     if (dga_version == 0)
110         return DDERR_GENERIC;
111
112     /* If we were just testing ... return OK */
113     if (lplpDD == NULL)
114         return DD_OK;
115
116     ddraw = (IDirectDrawImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawImpl));
117     *lplpDD = (LPDIRECTDRAW)ddraw;
118     ddraw->ref = 1;
119     ICOM_VTBL(ddraw) = &dga_ddvt;
120     ddraw->d = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*(ddraw->d)));
121     ddraw->d->ref = 1;
122     ddraw->d->private = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(dga_dd_private));
123     dgpriv = (dga_dd_private*)ddraw->d->private;
124
125     TSXF86DGAQueryVersion(display,&major,&minor);
126     TRACE("XF86DGA is version %d.%d\n",major,minor);
127     
128     TSXF86DGAQueryDirectVideo(display,DefaultScreen(display),&flags);
129     if (!(flags & XF86DGADirectPresent)) {
130       /* On some boards, DGA extension is present but does not support DirectVideo */
131       MESSAGE("direct video is NOT PRESENT.\n");
132       return DDERR_GENERIC;
133     }
134     TSXF86DGAGetVideo(display,DefaultScreen(display),&addr,&width,&banksize,&memsize);
135     dgpriv->fb_width = width;
136     TSXF86DGAGetViewPortSize(display,DefaultScreen(display),&width,&height);
137     TSXF86DGASetViewPort(display,DefaultScreen(display),0,0);
138     dgpriv->fb_height = height;
139     TRACE("video framebuffer: begin %p, width %d,banksize %d,memsize %d\n",
140           addr,width,banksize,memsize
141           );
142     TRACE("viewport height: %d\n",height);
143     /* Get the screen dimensions as seen by Wine.
144      * In that case, it may be better to ignore the -desktop mode and
145      * return the real screen size => print a warning
146      */
147     ddraw->d->height = GetSystemMetrics(SM_CYSCREEN);
148     ddraw->d->width = GetSystemMetrics(SM_CXSCREEN);
149     if ((ddraw->d->height != height) || (ddraw->d->width  != width))
150       WARN("You seem to be running in -desktop mode. This may prove dangerous in DGA mode...\n");
151     dgpriv->fb_addr             = addr;
152     dgpriv->fb_memsize  = memsize;
153     dgpriv->vpmask              = 0;
154
155     /* Register frame buffer with the kernel, it is a potential DIB section */
156     VirtualAlloc(dgpriv->fb_addr, dgpriv->fb_memsize, MEM_RESERVE|MEM_SYSTEM, PAGE_READWRITE);
157
158     /* The cast is because DGA2's install colormap does not return a value whereas
159        DGA1 version does */
160     dgpriv->InstallColormap = (void (*)(Display *, int, Colormap)) TSXF86DGAInstallColormap;
161     
162     /* just assume the default depth is the DGA depth too */
163     depth = DefaultDepthOfScreen(X11DRV_GetXScreen());
164     
165     _common_depth_to_pixelformat(depth, (IDirectDraw*) ddraw);
166     
167 #ifdef RESTORE_SIGNALS
168     SIGNAL_Init();
169 #endif
170
171     return DD_OK;
172 }
173
174 /* Where do these GUIDs come from?  mkuuid.
175  * They exist solely to distinguish between the targets Wine support,
176  * and should be different than any other GUIDs in existence.
177  */
178 static GUID DGA_DirectDraw_GUID = { /* e2dcb020-dc60-11d1-8407-9714f5d50802 */
179     0xe2dcb020,
180     0xdc60,
181     0x11d1,
182     {0x84, 0x07, 0x97, 0x14, 0xf5, 0xd5, 0x08, 0x02}
183 };
184
185 ddraw_driver dga_driver = {
186     &DGA_DirectDraw_GUID,
187     "display",
188     "WINE XF86DGA DirectDraw Driver",
189     100,
190     DGA_Create
191 }; 
192
193 DECL_GLOBAL_CONSTRUCTOR(DGA_register) { ddraw_register_driver(&dga_driver); }