Removed a few inter-dll dependencies.
[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 "gdi.h"
30 #include "heap.h"
31 #include "dc.h"
32 #include "win.h"
33 #include "wine/exception.h"
34 #include "ddraw.h"
35 #include "d3d.h"
36 #include "debugtools.h"
37 #include "spy.h"
38 #include "message.h"
39 #include "options.h"
40 #include "monitor.h"
41
42 #include "dga_private.h"
43
44 #define RESTORE__SIGNALS
45
46 DEFAULT_DEBUG_CHANNEL(ddraw);
47
48 #ifdef HAVE_LIBXXF86VM
49 XF86VidModeModeInfo *orig_mode = NULL;
50 #endif
51
52 static inline BOOL get_option( const char *name, BOOL def ) {
53     return PROFILE_GetWineIniBool( "x11drv", name, def );
54 }
55
56 static BYTE
57 DDRAW_DGA_Available(void)
58 {
59     int fd, evbase, evret, majver, minver;
60     static BYTE return_value = 0xFF;
61
62     /* This prevents from probing X times for DGA */
63     if (return_value != 0xFF)
64         return return_value;
65
66     if (!get_option( "UseDGA", 1 )) {
67         TRACE("UseDGA disabled.\n");
68         return_value = 0;
69         return 0;
70     }
71
72     /* First, query the extenstion and its version */
73     if (!TSXF86DGAQueryExtension(display,&evbase,&evret)) {
74         TRACE("DGA extension not detected.\n");
75         return_value = 0;
76         return 0;
77     }
78
79     if (!TSXF86DGAQueryVersion(display,&majver,&minver)) {
80         TRACE("DGA version not detected.\n");
81         return_value = 0;
82         return 0;
83     }
84
85 #ifdef HAVE_LIBXXF86DGA2
86     if (majver >= 2) {
87         /* We have DGA 2.0 available ! */
88         if (TSXDGAOpenFramebuffer(display, DefaultScreen(display))) {
89             TSXDGACloseFramebuffer(display, DefaultScreen(display));
90             return_value = 2;
91         } else
92             return_value = 0;
93         return return_value;
94     }
95 #endif /* defined(HAVE_LIBXXF86DGA2) */
96
97     /* You don't have to be root to use DGA extensions. Simply having access
98      * to /dev/mem will do the trick
99      * This can be achieved by adding the user to the "kmem" group on
100      * Debian 2.x systems, don't know about 
101      * others. --stephenc
102      */
103     if ((fd = open("/dev/mem", O_RDWR)) != -1)
104         close(fd);
105
106     if (fd != -1)
107         return_value = 1;
108     else {
109         TRACE("You have no access to /dev/mem\n");
110         return_value = 0;
111     }
112     return return_value;
113 }
114
115 HRESULT 
116 DGA_Create( LPDIRECTDRAW *lplpDD ) {
117     IDirectDrawImpl*            ddraw;
118     dga_dd_private*     dgpriv;
119     int  memsize,banksize,major,minor,flags;
120     char *addr;
121     int  depth;
122     int  dga_version;
123     int  width, height;
124       
125     /* Get DGA availability / version */
126     dga_version = DDRAW_DGA_Available();
127     if (dga_version == 0)
128         return DDERR_GENERIC;
129
130     /* If we were just testing ... return OK */
131     if (lplpDD == NULL)
132         return DD_OK;
133
134     ddraw = (IDirectDrawImpl*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectDrawImpl));
135     *lplpDD = (LPDIRECTDRAW)ddraw;
136     ddraw->ref = 1;
137     ICOM_VTBL(ddraw) = &dga_ddvt;
138     
139     ddraw->private = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(dga_dd_private));
140
141     dgpriv = (dga_dd_private*)ddraw->private;
142 #ifdef HAVE_LIBXXF86DGA2
143     if (dga_version == 1) {
144         dgpriv->version = 1;
145 #endif /* defined(HAVE_LIBXXF86DGA2) */
146         TSXF86DGAQueryVersion(display,&major,&minor);
147         TRACE("XF86DGA is version %d.%d\n",major,minor);
148
149         TSXF86DGAQueryDirectVideo(display,DefaultScreen(display),&flags);
150         if (!(flags & XF86DGADirectPresent))
151             MESSAGE("direct video is NOT PRESENT.\n");
152         TSXF86DGAGetVideo(display,DefaultScreen(display),&addr,&width,&banksize,&memsize);
153         dgpriv->fb_width = width;
154         TSXF86DGAGetViewPortSize(display,DefaultScreen(display),&width,&height);
155         TSXF86DGASetViewPort(display,DefaultScreen(display),0,0);
156         dgpriv->fb_height = height;
157         TRACE("video framebuffer: begin %p, width %d,banksize %d,memsize %d\n",
158             addr,width,banksize,memsize
159         );
160         TRACE("viewport height: %d\n",height);
161         /* Get the screen dimensions as seen by Wine.
162          * In that case, it may be better to ignore the -desktop mode and
163          * return the real screen size => print a warning
164          */
165         ddraw->d.height = MONITOR_GetHeight(&MONITOR_PrimaryMonitor);
166         ddraw->d.width = MONITOR_GetWidth(&MONITOR_PrimaryMonitor);
167         if ((ddraw->d.height != height) || (ddraw->d.width  != width))
168                 WARN("You seem to be running in -desktop mode. This may prove dangerous in DGA mode...\n");
169         dgpriv->fb_addr         = addr;
170         dgpriv->fb_memsize      = memsize;
171         dgpriv->vpmask          = 0;
172
173         /* just assume the default depth is the DGA depth too */
174         depth = DefaultDepthOfScreen(X11DRV_GetXScreen());
175
176         _common_depth_to_pixelformat(depth, &(ddraw->d.directdraw_pixelformat), &(ddraw->d.screen_pixelformat), NULL);
177
178 #ifdef RESTORE_SIGNALS
179         SIGNAL_Init();
180 #endif
181 #ifdef HAVE_LIBXXF86DGA2
182     } else {
183         XDGAMode *modes;
184         int i, num_modes;
185         int mode_to_use = 0;
186
187         dgpriv->version = 2;
188
189         TSXDGAQueryVersion(display,&major,&minor);
190         TRACE("XDGA is version %d.%d\n",major,minor);
191
192         TRACE("Opening the frame buffer.\n");
193         if (!TSXDGAOpenFramebuffer(display, DefaultScreen(display))) {
194             ERR("Error opening the frame buffer !!!\n");
195             return DDERR_GENERIC;
196         }
197
198         /* List all available modes */
199         modes = TSXDGAQueryModes(display, DefaultScreen(display), &num_modes);
200         dgpriv->modes           = modes;
201         dgpriv->num_modes       = num_modes;
202
203         TRACE("Available modes :\n");
204         for (i = 0; i < num_modes; i++) {
205             if (TRACE_ON(ddraw)) {
206                 DPRINTF("   %d) - %s (FB: %dx%d / VP: %dx%d) - depth %d -",
207                     modes[i].num,
208                     modes[i].name, modes[i].imageWidth, modes[i].imageHeight,
209                     modes[i].viewportWidth, modes[i].viewportHeight,
210                     modes[i].depth
211                 );
212 #define XX(x) if (modes[i].flags & x) DPRINTF(" "#x" ");
213                 XX(XDGAConcurrentAccess);
214                 XX(XDGASolidFillRect);
215                 XX(XDGABlitRect);
216                 XX(XDGABlitTransRect);
217                 XX(XDGAPixmap);
218 #undef XX
219                 DPRINTF("\n");
220             }
221             if ((MONITOR_GetHeight(&MONITOR_PrimaryMonitor) == modes[i].viewportHeight) &&
222                 (MONITOR_GetWidth(&MONITOR_PrimaryMonitor) == modes[i].viewportWidth) &&
223                 (MONITOR_GetDepth(&MONITOR_PrimaryMonitor) == modes[i].depth)
224             ) {
225                 mode_to_use = modes[i].num;
226             }
227         }
228         if (mode_to_use == 0) {
229             ERR("Could not find mode !\n");
230             mode_to_use = 1;
231         } else {
232             DPRINTF("Using mode number %d\n", mode_to_use);
233         }
234
235         /* Initialize the frame buffer */
236         _DGA_Initialize_FrameBuffer(*lplpDD, mode_to_use);
237         /* Set the input handling for relative mouse movements */
238         X11DRV_EVENT_SetInputMethod(X11DRV_INPUT_RELATIVE);
239     }
240 #endif /* defined(HAVE_LIBXXF86DGA2) */
241     return DD_OK;
242 }
243
244 /* Where do these GUIDs come from?  mkuuid.
245  * They exist solely to distinguish between the targets Wine support,
246  * and should be different than any other GUIDs in existence.
247  */
248 static GUID DGA_DirectDraw_GUID = { /* e2dcb020-dc60-11d1-8407-9714f5d50802 */
249     0xe2dcb020,
250     0xdc60,
251     0x11d1,
252     {0x84, 0x07, 0x97, 0x14, 0xf5, 0xd5, 0x08, 0x02}
253 };
254
255 ddraw_driver dga_driver = {
256     &DGA_DirectDraw_GUID,
257     "display",
258     "WINE XF86DGA DirectDraw Driver",
259     100,
260     DGA_Create
261 }; 
262
263 #ifdef __GNUC__
264 static void DGA_register(void) __attribute__((constructor));
265 #else /* defined(__GNUC__) */
266 static void __asm__dummy_dll_init(void) {
267     asm("\t.section .init ,\"ax\"\n"
268                 "\tcall DGA_register\n"
269                     "\t.previous\n");
270 }
271 #endif /* defined(__GNUC__) */
272 static void DGA_register(void) { ddraw_register_driver(&dga_driver); }