1 /*
2 *Copyright (C) 1994-2000 The XFree86 Project, Inc. All Rights Reserved.
3 *
4 *Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 *"Software"), to deal in the Software without restriction, including
7 *without limitation the rights to use, copy, modify, merge, publish,
8 *distribute, sublicense, and/or sell copies of the Software, and to
9 *permit persons to whom the Software is furnished to do so, subject to
10 *the following conditions:
11 *
12 *The above copyright notice and this permission notice shall be
13 *included in all copies or substantial portions of the Software.
14 *
15 *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 *MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 *NONINFRINGEMENT. IN NO EVENT SHALL THE XFREE86 PROJECT BE LIABLE FOR
19 *ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
20 *CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 *WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 *
23 *Except as contained in this notice, the name of the XFree86 Project
24 *shall not be used in advertising or otherwise to promote the sale, use
25 *or other dealings in this Software without prior written authorization
26 *from the XFree86 Project.
27 *
28 * Authors: Dakshinamurthy Karra
29 * Suhaib M Siddiqi
30 * Peter Busch
31 * Harold L Hunt II
32 * Kensuke Matsuzaki
33 */
34
35 #ifdef HAVE_XWIN_CONFIG_H
36 #include <xwin-config.h>
37 #endif
38 #include "win.h"
39 #include "winmsg.h"
40
41 /*
42 * Determine what type of screen we are initializing
43 * and call the appropriate procedure to initialize
44 * that type of screen.
45 */
46
47 Bool
winScreenInit(ScreenPtr pScreen,int argc,char ** argv)48 winScreenInit(ScreenPtr pScreen, int argc, char **argv)
49 {
50 winScreenInfoPtr pScreenInfo = &g_ScreenInfo[pScreen->myNum];
51 winPrivScreenPtr pScreenPriv;
52 HDC hdc;
53 DWORD dwInitialBPP;
54
55 #if CYGDEBUG || YES
56 winDebug("winScreenInit - dwWidth: %u dwHeight: %u\n",
57 (unsigned int)pScreenInfo->dwWidth, (unsigned int)pScreenInfo->dwHeight);
58 #endif
59
60 /* Allocate privates for this screen */
61 if (!winAllocatePrivates(pScreen)) {
62 ErrorF("winScreenInit - Couldn't allocate screen privates\n");
63 return FALSE;
64 }
65
66 /* Get a pointer to the privates structure that was allocated */
67 pScreenPriv = winGetScreenPriv(pScreen);
68
69 /* Save a pointer to this screen in the screen info structure */
70 pScreenInfo->pScreen = pScreen;
71
72 /* Save a pointer to the screen info in the screen privates structure */
73 /* This allows us to get back to the screen info from a screen pointer */
74 pScreenPriv->pScreenInfo = pScreenInfo;
75
76 /*
77 * Determine which engine to use.
78 *
79 * NOTE: This is done once per screen because each screen possibly has
80 * a preferred engine specified on the command line.
81 */
82 if (!winSetEngine(pScreen)) {
83 ErrorF("winScreenInit - winSetEngine () failed\n");
84 return FALSE;
85 }
86
87 /* Horribly misnamed function: Allow engine to adjust BPP for screen */
88 dwInitialBPP = pScreenInfo->dwBPP;
89
90 if (!(*pScreenPriv->pwinAdjustVideoMode) (pScreen)) {
91 ErrorF("winScreenInit - winAdjustVideoMode () failed\n");
92 return FALSE;
93 }
94
95 if (dwInitialBPP == WIN_DEFAULT_BPP) {
96 /* No -depth parameter was passed, let the user know the depth being used */
97 ErrorF
98 ("winScreenInit - Using Windows display depth of %d bits per pixel\n",
99 (int) pScreenInfo->dwBPP);
100 }
101 else if (dwInitialBPP != pScreenInfo->dwBPP) {
102 /* Warn user if engine forced a depth different to -depth parameter */
103 ErrorF
104 ("winScreenInit - Command line depth of %d bpp overridden by engine, using %d bpp\n",
105 (int) dwInitialBPP, (int) pScreenInfo->dwBPP);
106 }
107 else {
108 ErrorF("winScreenInit - Using command line depth of %d bpp\n",
109 (int) pScreenInfo->dwBPP);
110 }
111
112 /* Check for supported display depth */
113 if (!(WIN_SUPPORTED_BPPS & (1 << (pScreenInfo->dwBPP - 1)))) {
114 ErrorF("winScreenInit - Unsupported display depth: %d\n"
115 "Change your Windows display depth to 15, 16, 24, or 32 bits "
116 "per pixel.\n", (int) pScreenInfo->dwBPP);
117 ErrorF("winScreenInit - Supported depths: %08x\n", WIN_SUPPORTED_BPPS);
118 #if WIN_CHECK_DEPTH
119 return FALSE;
120 #endif
121 }
122
123 /*
124 * Check that all monitors have the same display depth if we are using
125 * multiple monitors
126 */
127 if (pScreenInfo->fMultipleMonitors
128 && !GetSystemMetrics(SM_SAMEDISPLAYFORMAT)) {
129 ErrorF("winScreenInit - Monitors do not all have same pixel format / "
130 "display depth.\n");
131 if (pScreenInfo->dwEngine == WIN_SERVER_SHADOW_GDI) {
132 ErrorF
133 ("winScreenInit - Performance may suffer off primary display.\n");
134 }
135 else {
136 ErrorF("winScreenInit - Using primary display only.\n");
137 pScreenInfo->fMultipleMonitors = FALSE;
138 }
139 }
140
141 /* Create display window */
142 if (!(*pScreenPriv->pwinCreateBoundingWindow) (pScreen)) {
143 ErrorF("winScreenInit - pwinCreateBoundingWindow () " "failed\n");
144 return FALSE;
145 }
146
147 /* Get a device context */
148 hdc = GetDC(pScreenPriv->hwndScreen);
149
150 /* Are we using multiple monitors? */
151 if (pScreenInfo->fMultipleMonitors) {
152 /*
153 * In this case, some of the defaults set in
154 * winInitializeScreenDefaults() are not correct ...
155 */
156 if (!pScreenInfo->fUserGaveHeightAndWidth) {
157 pScreenInfo->dwWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN);
158 pScreenInfo->dwHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN);
159 }
160 }
161
162 /* Release the device context */
163 ReleaseDC(pScreenPriv->hwndScreen, hdc);
164
165 /* Clear the visuals list */
166 miClearVisualTypes();
167
168 /* Call the engine dependent screen initialization procedure */
169 if (!((*pScreenPriv->pwinFinishScreenInit) (pScreen->myNum, pScreen, argc, argv))) {
170 ErrorF("winScreenInit - winFinishScreenInit () failed\n");
171
172 /* call the engine dependent screen close procedure to clean up from a failure */
173 pScreenPriv->pwinCloseScreen(pScreen);
174
175 return FALSE;
176 }
177
178 if (!g_fSoftwareCursor)
179 winInitCursor(pScreen);
180 else
181 winErrorFVerb(2, "winScreenInit - Using software cursor\n");
182
183 if (!noPanoramiXExtension) {
184 /*
185 Note the screen origin in a normalized coordinate space where (0,0) is at the top left
186 of the native virtual desktop area
187 */
188 pScreen->x =
189 pScreenInfo->dwInitialX - GetSystemMetrics(SM_XVIRTUALSCREEN);
190 pScreen->y =
191 pScreenInfo->dwInitialY - GetSystemMetrics(SM_YVIRTUALSCREEN);
192
193 ErrorF("Screen %d added at virtual desktop coordinate (%d,%d).\n",
194 pScreen->myNum, pScreen->x, pScreen->y);
195 }
196
197 #if CYGDEBUG || YES
198 winDebug("winScreenInit - returning\n");
199 #endif
200
201 return TRUE;
202 }
203
204 static Bool
winCreateScreenResources(ScreenPtr pScreen)205 winCreateScreenResources(ScreenPtr pScreen)
206 {
207 winScreenPriv(pScreen);
208 Bool result;
209
210 result = pScreenPriv->pwinCreateScreenResources(pScreen);
211
212 /* Now the screen bitmap has been wrapped in a pixmap,
213 add that to the Shadow framebuffer */
214 if (!shadowAdd(pScreen, pScreen->devPrivate,
215 pScreenPriv->pwinShadowUpdate, NULL, 0, 0)) {
216 ErrorF("winCreateScreenResources - shadowAdd () failed\n");
217 return FALSE;
218 }
219
220 return result;
221 }
222
223 /* See Porting Layer Definition - p. 20 */
224 Bool
winFinishScreenInitFB(int i,ScreenPtr pScreen,int argc,char ** argv)225 winFinishScreenInitFB(int i, ScreenPtr pScreen, int argc, char **argv)
226 {
227 winScreenPriv(pScreen);
228 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
229 VisualPtr pVisual = NULL;
230
231 int iReturn;
232
233 /* Create framebuffer */
234 if (!(*pScreenPriv->pwinInitScreen) (pScreen)) {
235 ErrorF("winFinishScreenInitFB - Could not allocate framebuffer\n");
236 return FALSE;
237 }
238
239 /*
240 * Calculate the number of bits that are used to represent color in each pixel,
241 * the color depth for the screen
242 */
243 if (pScreenInfo->dwBPP == 8)
244 pScreenInfo->dwDepth = 8;
245 else
246 pScreenInfo->dwDepth = winCountBits(pScreenPriv->dwRedMask)
247 + winCountBits(pScreenPriv->dwGreenMask)
248 + winCountBits(pScreenPriv->dwBlueMask);
249
250 winErrorFVerb(2, "winFinishScreenInitFB - Masks: %08x %08x %08x\n",
251 (unsigned int) pScreenPriv->dwRedMask,
252 (unsigned int) pScreenPriv->dwGreenMask,
253 (unsigned int) pScreenPriv->dwBlueMask);
254
255 /* Init visuals */
256 if (!(*pScreenPriv->pwinInitVisuals) (pScreen)) {
257 ErrorF("winFinishScreenInitFB - winInitVisuals failed\n");
258 return FALSE;
259 }
260
261 if ((pScreenInfo->dwBPP == 8) && (pScreenInfo->fCompositeWM)) {
262 ErrorF("-compositewm disabled due to 8bpp depth\n");
263 pScreenInfo->fCompositeWM = FALSE;
264 }
265
266 /* Apparently we need this for the render extension */
267 miSetPixmapDepths();
268
269 /* Start fb initialization */
270 if (!fbSetupScreen(pScreen,
271 pScreenInfo->pfb,
272 pScreenInfo->dwWidth, pScreenInfo->dwHeight,
273 monitorResolution, monitorResolution,
274 pScreenInfo->dwStride, pScreenInfo->dwBPP)) {
275 ErrorF("winFinishScreenInitFB - fbSetupScreen failed\n");
276 return FALSE;
277 }
278
279 /* Override default colormap routines if visual class is dynamic */
280 if (pScreenInfo->dwDepth == 8
281 && (pScreenInfo->dwEngine == WIN_SERVER_SHADOW_GDI
282 || (pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DDNL
283 && pScreenInfo->fFullScreen))) {
284 winSetColormapFunctions(pScreen);
285
286 /*
287 * NOTE: Setting whitePixel to 255 causes Magic 7.1 to allocate its
288 * own colormap, as it cannot allocate 7 planes in the default
289 * colormap. Setting whitePixel to 1 allows Magic to get 7
290 * planes in the default colormap, so it doesn't create its
291 * own colormap. This latter situation is highly desirable,
292 * as it keeps the Magic window viewable when switching to
293 * other X clients that use the default colormap.
294 */
295 pScreen->blackPixel = 0;
296 pScreen->whitePixel = 1;
297 }
298
299 /* Finish fb initialization */
300 if (!fbFinishScreenInit(pScreen,
301 pScreenInfo->pfb,
302 pScreenInfo->dwWidth, pScreenInfo->dwHeight,
303 monitorResolution, monitorResolution,
304 pScreenInfo->dwStride, pScreenInfo->dwBPP)) {
305 ErrorF("winFinishScreenInitFB - fbFinishScreenInit failed\n");
306 return FALSE;
307 }
308
309 /* Save a pointer to the root visual */
310 for (pVisual = pScreen->visuals;
311 pVisual->vid != pScreen->rootVisual; pVisual++);
312 pScreenPriv->pRootVisual = pVisual;
313
314 /*
315 * Setup points to the block and wakeup handlers. Pass a pointer
316 * to the current screen as pWakeupdata.
317 */
318 pScreen->BlockHandler = winBlockHandler;
319 pScreen->WakeupHandler = winWakeupHandler;
320
321 /* Render extension initialization, calls miPictureInit */
322 if (!fbPictureInit(pScreen, NULL, 0)) {
323 ErrorF("winFinishScreenInitFB - fbPictureInit () failed\n");
324 return FALSE;
325 }
326
327 #ifdef RANDR
328 /* Initialize resize and rotate support */
329 if (!winRandRInit(pScreen)) {
330 ErrorF("winFinishScreenInitFB - winRandRInit () failed\n");
331 return FALSE;
332 }
333 #endif
334
335 /* Setup the cursor routines */
336 #if CYGDEBUG
337 winDebug("winFinishScreenInitFB - Calling miDCInitialize ()\n");
338 #endif
339 miDCInitialize(pScreen, &g_winPointerCursorFuncs);
340
341 /* KDrive does winCreateDefColormap right after miDCInitialize */
342 /* Create a default colormap */
343 #if CYGDEBUG
344 winDebug("winFinishScreenInitFB - Calling winCreateDefColormap ()\n");
345 #endif
346 if (!winCreateDefColormap(pScreen)) {
347 ErrorF("winFinishScreenInitFB - Could not create colormap\n");
348 return FALSE;
349 }
350
351 /* Initialize the shadow framebuffer layer */
352 if ((pScreenInfo->dwEngine == WIN_SERVER_SHADOW_GDI
353 || pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DDNL)) {
354 #if CYGDEBUG
355 winDebug("winFinishScreenInitFB - Calling shadowSetup ()\n");
356 #endif
357 if (!shadowSetup(pScreen)) {
358 ErrorF("winFinishScreenInitFB - shadowSetup () failed\n");
359 return FALSE;
360 }
361
362 /* Wrap CreateScreenResources so we can add the screen pixmap
363 to the Shadow framebuffer after it's been created */
364 pScreenPriv->pwinCreateScreenResources = pScreen->CreateScreenResources;
365 pScreen->CreateScreenResources = winCreateScreenResources;
366 }
367
368 /* Handle rootless mode */
369 if (pScreenInfo->fRootless) {
370 /* Define the WRAP macro temporarily for local use */
371 #define WRAP(a) \
372 if (pScreen->a) { \
373 pScreenPriv->a = pScreen->a; \
374 } else { \
375 winDebug("winScreenInit - null screen fn " #a "\n"); \
376 pScreenPriv->a = NULL; \
377 }
378
379 /* Save a pointer to each lower-level window procedure */
380 WRAP(CreateWindow);
381 WRAP(DestroyWindow);
382 WRAP(RealizeWindow);
383 WRAP(UnrealizeWindow);
384 WRAP(PositionWindow);
385 WRAP(ChangeWindowAttributes);
386 WRAP(SetShape);
387
388 /* Assign rootless window procedures to be top level procedures */
389 pScreen->CreateWindow = winCreateWindowRootless;
390 pScreen->DestroyWindow = winDestroyWindowRootless;
391 pScreen->PositionWindow = winPositionWindowRootless;
392 /*pScreen->ChangeWindowAttributes = winChangeWindowAttributesRootless; */
393 pScreen->RealizeWindow = winMapWindowRootless;
394 pScreen->UnrealizeWindow = winUnmapWindowRootless;
395 pScreen->SetShape = winSetShapeRootless;
396
397 /* Undefine the WRAP macro, as it is not needed elsewhere */
398 #undef WRAP
399 }
400
401 /* Handle multi window mode */
402 else if (pScreenInfo->fMultiWindow) {
403 /* Define the WRAP macro temporarily for local use */
404 #define WRAP(a) \
405 if (pScreen->a) { \
406 pScreenPriv->a = pScreen->a; \
407 } else { \
408 winDebug("null screen fn " #a "\n"); \
409 pScreenPriv->a = NULL; \
410 }
411
412 /* Save a pointer to each lower-level window procedure */
413 WRAP(CreateWindow);
414 WRAP(DestroyWindow);
415 WRAP(RealizeWindow);
416 WRAP(UnrealizeWindow);
417 WRAP(PositionWindow);
418 WRAP(ChangeWindowAttributes);
419 WRAP(ReparentWindow);
420 WRAP(RestackWindow);
421 WRAP(ResizeWindow);
422 WRAP(MoveWindow);
423 WRAP(CopyWindow);
424 WRAP(SetShape);
425 WRAP(ModifyPixmapHeader);
426
427 /* Assign multi-window window procedures to be top level procedures */
428 pScreen->CreateWindow = winCreateWindowMultiWindow;
429 pScreen->DestroyWindow = winDestroyWindowMultiWindow;
430 pScreen->PositionWindow = winPositionWindowMultiWindow;
431 /*pScreen->ChangeWindowAttributes = winChangeWindowAttributesMultiWindow; */
432 pScreen->RealizeWindow = winMapWindowMultiWindow;
433 pScreen->UnrealizeWindow = winUnmapWindowMultiWindow;
434 pScreen->ReparentWindow = winReparentWindowMultiWindow;
435 pScreen->RestackWindow = winRestackWindowMultiWindow;
436 pScreen->ResizeWindow = winResizeWindowMultiWindow;
437 pScreen->MoveWindow = winMoveWindowMultiWindow;
438 pScreen->CopyWindow = winCopyWindowMultiWindow;
439 pScreen->SetShape = winSetShapeMultiWindow;
440
441 if (pScreenInfo->fCompositeWM) {
442 pScreen->CreatePixmap = winCreatePixmapMultiwindow;
443 pScreen->DestroyPixmap = winDestroyPixmapMultiwindow;
444 pScreen->ModifyPixmapHeader = winModifyPixmapHeaderMultiwindow;
445 }
446
447 /* Undefine the WRAP macro, as it is not needed elsewhere */
448 #undef WRAP
449 }
450
451 /* Wrap either fb's or shadow's CloseScreen with our CloseScreen */
452 pScreenPriv->CloseScreen = pScreen->CloseScreen;
453 pScreen->CloseScreen = pScreenPriv->pwinCloseScreen;
454
455 /* Create a mutex for modules in separate threads to wait for */
456 iReturn = pthread_mutex_init(&pScreenPriv->pmServerStarted, NULL);
457 if (iReturn != 0) {
458 ErrorF("winFinishScreenInitFB - pthread_mutex_init () failed: %d\n",
459 iReturn);
460 return FALSE;
461 }
462
463 /* Own the mutex for modules in separate threads */
464 iReturn = pthread_mutex_lock(&pScreenPriv->pmServerStarted);
465 if (iReturn != 0) {
466 ErrorF("winFinishScreenInitFB - pthread_mutex_lock () failed: %d\n",
467 iReturn);
468 return FALSE;
469 }
470
471 /* Set the ServerStarted flag to false */
472 pScreenPriv->fServerStarted = FALSE;
473
474
475 if (pScreenInfo->fMultiWindow) {
476 #if CYGDEBUG || YES
477 winDebug("winFinishScreenInitFB - Calling winInitWM.\n");
478 #endif
479
480 /* Initialize multi window mode */
481 if (!winInitWM(&pScreenPriv->pWMInfo,
482 &pScreenPriv->ptWMProc,
483 &pScreenPriv->ptXMsgProc,
484 &pScreenPriv->pmServerStarted,
485 pScreenInfo->dwScreen,
486 (HWND) &pScreenPriv->hwndScreen,
487 pScreenInfo->fCompositeWM)) {
488 ErrorF("winFinishScreenInitFB - winInitWM () failed.\n");
489 return FALSE;
490 }
491 }
492
493 /* Tell the server that we are enabled */
494 pScreenPriv->fEnabled = TRUE;
495
496 /* Tell the server that we have a valid depth */
497 pScreenPriv->fBadDepth = FALSE;
498
499 #if CYGDEBUG || YES
500 winDebug("winFinishScreenInitFB - returning\n");
501 #endif
502
503 return TRUE;
504 }
505