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 #ifdef XWIN_MULTIWINDOWEXTWM
42 static RootlessFrameProcsRec winMWExtWMProcs = {
43 winMWExtWMCreateFrame,
44 winMWExtWMDestroyFrame,
45
46 winMWExtWMMoveFrame,
47 winMWExtWMResizeFrame,
48 winMWExtWMRestackFrame,
49 winMWExtWMReshapeFrame,
50 winMWExtWMUnmapFrame,
51
52 winMWExtWMStartDrawing,
53 winMWExtWMStopDrawing,
54 winMWExtWMUpdateRegion,
55 winMWExtWMDamageRects,
56 winMWExtWMRootlessSwitchWindow,
57 NULL, //winMWExtWMDoReorderWindow,
58 NULL, //winMWExtWMHideWindow,
59 NULL, //winMWExtWMUpdateColorMap,
60
61 NULL, //winMWExtWMCopyBytes,
62 winMWExtWMCopyWindow
63 };
64 #endif
65
66 /*
67 * Prototypes
68 */
69
70 /*
71 * Local functions
72 */
73
74 static Bool
75 winSaveScreen(ScreenPtr pScreen, int on);
76
77 /*
78 * Determine what type of screen we are initializing
79 * and call the appropriate procedure to intiailize
80 * that type of screen.
81 */
82
83 Bool
winScreenInit(ScreenPtr pScreen,int argc,char ** argv)84 winScreenInit(ScreenPtr pScreen, int argc, char **argv)
85 {
86 winScreenInfoPtr pScreenInfo = &g_ScreenInfo[pScreen->myNum];
87 winPrivScreenPtr pScreenPriv;
88 HDC hdc;
89 DWORD dwInitialBPP;
90
91 #if CYGDEBUG || YES
92 winDebug("winScreenInit - dwWidth: %u dwHeight: %u\n",
93 (unsigned int)pScreenInfo->dwWidth, (unsigned int)pScreenInfo->dwHeight);
94 #endif
95
96 /* Allocate privates for this screen */
97 if (!winAllocatePrivates(pScreen)) {
98 ErrorF("winScreenInit - Couldn't allocate screen privates\n");
99 return FALSE;
100 }
101
102 /* Get a pointer to the privates structure that was allocated */
103 pScreenPriv = winGetScreenPriv(pScreen);
104
105 /* Save a pointer to this screen in the screen info structure */
106 pScreenInfo->pScreen = pScreen;
107
108 /* Save a pointer to the screen info in the screen privates structure */
109 /* This allows us to get back to the screen info from a screen pointer */
110 pScreenPriv->pScreenInfo = pScreenInfo;
111
112 /*
113 * Determine which engine to use.
114 *
115 * NOTE: This is done once per screen because each screen possibly has
116 * a preferred engine specified on the command line.
117 */
118 if (!winSetEngine(pScreen)) {
119 ErrorF("winScreenInit - winSetEngine () failed\n");
120 return FALSE;
121 }
122
123 /* Horribly misnamed function: Allow engine to adjust BPP for screen */
124 dwInitialBPP = pScreenInfo->dwBPP;
125
126 if (!(*pScreenPriv->pwinAdjustVideoMode) (pScreen)) {
127 ErrorF("winScreenInit - winAdjustVideoMode () failed\n");
128 return FALSE;
129 }
130
131 if (dwInitialBPP == WIN_DEFAULT_BPP) {
132 /* No -depth parameter was passed, let the user know the depth being used */
133 ErrorF
134 ("winScreenInit - Using Windows display depth of %d bits per pixel\n",
135 (int) pScreenInfo->dwBPP);
136 }
137 else if (dwInitialBPP != pScreenInfo->dwBPP) {
138 /* Warn user if engine forced a depth different to -depth parameter */
139 ErrorF
140 ("winScreenInit - Command line depth of %d bpp overidden by engine, using %d bpp\n",
141 (int) dwInitialBPP, (int) pScreenInfo->dwBPP);
142 }
143 else {
144 ErrorF("winScreenInit - Using command line depth of %d bpp\n",
145 (int) pScreenInfo->dwBPP);
146 }
147
148 /* Check for supported display depth */
149 if (!(WIN_SUPPORTED_BPPS & (1 << (pScreenInfo->dwBPP - 1)))) {
150 ErrorF("winScreenInit - Unsupported display depth: %d\n"
151 "Change your Windows display depth to 15, 16, 24, or 32 bits "
152 "per pixel.\n", (int) pScreenInfo->dwBPP);
153 ErrorF("winScreenInit - Supported depths: %08x\n", WIN_SUPPORTED_BPPS);
154 #if WIN_CHECK_DEPTH
155 return FALSE;
156 #endif
157 }
158
159 /*
160 * Check that all monitors have the same display depth if we are using
161 * multiple monitors
162 */
163 if (pScreenInfo->fMultipleMonitors
164 && !GetSystemMetrics(SM_SAMEDISPLAYFORMAT)) {
165 ErrorF("winScreenInit - Monitors do not all have same pixel format / "
166 "display depth.\n");
167 if (pScreenInfo->dwEngine == WIN_SERVER_SHADOW_GDI) {
168 ErrorF
169 ("winScreenInit - Performance may suffer off primary display.\n");
170 }
171 else {
172 ErrorF("winScreenInit - Using primary display only.\n");
173 pScreenInfo->fMultipleMonitors = FALSE;
174 }
175 }
176
177 /* Create display window */
178 if (!(*pScreenPriv->pwinCreateBoundingWindow) (pScreen)) {
179 ErrorF("winScreenInit - pwinCreateBoundingWindow () " "failed\n");
180 return FALSE;
181 }
182
183 /* Get a device context */
184 hdc = GetDC(pScreenPriv->hwndScreen);
185
186 /* Are we using multiple monitors? */
187 if (pScreenInfo->fMultipleMonitors) {
188 /*
189 * In this case, some of the defaults set in
190 * winInitializeScreenDefaults() are not correct ...
191 */
192 if (!pScreenInfo->fUserGaveHeightAndWidth) {
193 pScreenInfo->dwWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN);
194 pScreenInfo->dwHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN);
195 }
196 }
197
198 /* Release the device context */
199 ReleaseDC(pScreenPriv->hwndScreen, hdc);
200
201 /* Clear the visuals list */
202 miClearVisualTypes();
203
204 /* Call the engine dependent screen initialization procedure */
205 if (!((*pScreenPriv->pwinFinishScreenInit) (pScreen->myNum, pScreen, argc, argv))) {
206 ErrorF("winScreenInit - winFinishScreenInit () failed\n");
207
208 /* call the engine dependent screen close procedure to clean up from a failure */
209 pScreenPriv->pwinCloseScreen(pScreen);
210
211 return FALSE;
212 }
213
214 if (!g_fSoftwareCursor)
215 winInitCursor(pScreen);
216 else
217 winErrorFVerb(2, "winScreenInit - Using software cursor\n");
218
219 if (!noPanoramiXExtension) {
220 /*
221 Note the screen origin in a normalized coordinate space where (0,0) is at the top left
222 of the native virtual desktop area
223 */
224 pScreen->x =
225 pScreenInfo->dwInitialX - GetSystemMetrics(SM_XVIRTUALSCREEN);
226 pScreen->y =
227 pScreenInfo->dwInitialY - GetSystemMetrics(SM_YVIRTUALSCREEN);
228
229 ErrorF("Screen %d added at virtual desktop coordinate (%d,%d).\n",
230 pScreen->myNum, pScreen->x, pScreen->y);
231 }
232
233 #if CYGDEBUG || YES
234 winDebug("winScreenInit - returning\n");
235 #endif
236
237 return TRUE;
238 }
239
240 static Bool
winCreateScreenResources(ScreenPtr pScreen)241 winCreateScreenResources(ScreenPtr pScreen)
242 {
243 winScreenPriv(pScreen);
244 Bool result;
245
246 result = pScreenPriv->pwinCreateScreenResources(pScreen);
247
248 /* Now the screen bitmap has been wrapped in a pixmap,
249 add that to the Shadow framebuffer */
250 if (!shadowAdd(pScreen, pScreen->devPrivate,
251 pScreenPriv->pwinShadowUpdate, NULL, 0, 0)) {
252 ErrorF("winCreateScreenResources - shadowAdd () failed\n");
253 return FALSE;
254 }
255
256 return result;
257 }
258
259 /* See Porting Layer Definition - p. 20 */
260 Bool
winFinishScreenInitFB(int i,ScreenPtr pScreen,int argc,char ** argv)261 winFinishScreenInitFB(int i, ScreenPtr pScreen, int argc, char **argv)
262 {
263 winScreenPriv(pScreen);
264 winScreenInfo *pScreenInfo = pScreenPriv->pScreenInfo;
265 VisualPtr pVisual = NULL;
266
267 int iReturn;
268
269 /* Create framebuffer */
270 if (!(*pScreenPriv->pwinInitScreen) (pScreen)) {
271 ErrorF("winFinishScreenInitFB - Could not allocate framebuffer\n");
272 return FALSE;
273 }
274
275 /*
276 * Calculate the number of bits that are used to represent color in each pixel,
277 * the color depth for the screen
278 */
279 if (pScreenInfo->dwBPP == 8)
280 pScreenInfo->dwDepth = 8;
281 else
282 pScreenInfo->dwDepth = winCountBits(pScreenPriv->dwRedMask)
283 + winCountBits(pScreenPriv->dwGreenMask)
284 + winCountBits(pScreenPriv->dwBlueMask);
285
286 winErrorFVerb(2, "winFinishScreenInitFB - Masks: %08x %08x %08x\n",
287 (unsigned int) pScreenPriv->dwRedMask,
288 (unsigned int) pScreenPriv->dwGreenMask,
289 (unsigned int) pScreenPriv->dwBlueMask);
290
291 /* Init visuals */
292 if (!(*pScreenPriv->pwinInitVisuals) (pScreen)) {
293 ErrorF("winFinishScreenInitFB - winInitVisuals failed\n");
294 return FALSE;
295 }
296
297 /* Apparently we need this for the render extension */
298 miSetPixmapDepths();
299
300 /* Start fb initialization */
301 if (!fbSetupScreen(pScreen,
302 pScreenInfo->pfb,
303 pScreenInfo->dwWidth, pScreenInfo->dwHeight,
304 monitorResolution, monitorResolution,
305 pScreenInfo->dwStride, pScreenInfo->dwBPP)) {
306 ErrorF("winFinishScreenInitFB - fbSetupScreen failed\n");
307 return FALSE;
308 }
309
310 /* Override default colormap routines if visual class is dynamic */
311 if (pScreenInfo->dwDepth == 8
312 && (pScreenInfo->dwEngine == WIN_SERVER_SHADOW_GDI
313 || (pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DDNL
314 && pScreenInfo->fFullScreen))) {
315 winSetColormapFunctions(pScreen);
316
317 /*
318 * NOTE: Setting whitePixel to 255 causes Magic 7.1 to allocate its
319 * own colormap, as it cannot allocate 7 planes in the default
320 * colormap. Setting whitePixel to 1 allows Magic to get 7
321 * planes in the default colormap, so it doesn't create its
322 * own colormap. This latter situation is highly desireable,
323 * as it keeps the Magic window viewable when switching to
324 * other X clients that use the default colormap.
325 */
326 pScreen->blackPixel = 0;
327 pScreen->whitePixel = 1;
328 }
329
330 /* Place our save screen function */
331 pScreen->SaveScreen = winSaveScreen;
332
333 /* Finish fb initialization */
334 if (!fbFinishScreenInit(pScreen,
335 pScreenInfo->pfb,
336 pScreenInfo->dwWidth, pScreenInfo->dwHeight,
337 monitorResolution, monitorResolution,
338 pScreenInfo->dwStride, pScreenInfo->dwBPP)) {
339 ErrorF("winFinishScreenInitFB - fbFinishScreenInit failed\n");
340 return FALSE;
341 }
342
343 /* Save a pointer to the root visual */
344 for (pVisual = pScreen->visuals;
345 pVisual->vid != pScreen->rootVisual; pVisual++);
346 pScreenPriv->pRootVisual = pVisual;
347
348 /*
349 * Setup points to the block and wakeup handlers. Pass a pointer
350 * to the current screen as pWakeupdata.
351 */
352 pScreen->BlockHandler = winBlockHandler;
353 pScreen->WakeupHandler = winWakeupHandler;
354
355 /* Render extension initialization, calls miPictureInit */
356 if (!fbPictureInit(pScreen, NULL, 0)) {
357 ErrorF("winFinishScreenInitFB - fbPictureInit () failed\n");
358 return FALSE;
359 }
360
361 #ifdef RANDR
362 /* Initialize resize and rotate support */
363 if (!winRandRInit(pScreen)) {
364 ErrorF("winFinishScreenInitFB - winRandRInit () failed\n");
365 return FALSE;
366 }
367 #endif
368
369 /* Setup the cursor routines */
370 #if CYGDEBUG
371 winDebug("winFinishScreenInitFB - Calling miDCInitialize ()\n");
372 #endif
373 miDCInitialize(pScreen, &g_winPointerCursorFuncs);
374
375 /* KDrive does winCreateDefColormap right after miDCInitialize */
376 /* Create a default colormap */
377 #if CYGDEBUG
378 winDebug("winFinishScreenInitFB - Calling winCreateDefColormap ()\n");
379 #endif
380 if (!winCreateDefColormap(pScreen)) {
381 ErrorF("winFinishScreenInitFB - Could not create colormap\n");
382 return FALSE;
383 }
384
385 /* Initialize the shadow framebuffer layer */
386 if ((pScreenInfo->dwEngine == WIN_SERVER_SHADOW_GDI
387 || pScreenInfo->dwEngine == WIN_SERVER_SHADOW_DDNL)
388 #ifdef XWIN_MULTIWINDOWEXTWM
389 && !pScreenInfo->fMWExtWM
390 #endif
391 ) {
392 #if CYGDEBUG
393 winDebug("winFinishScreenInitFB - Calling shadowSetup ()\n");
394 #endif
395 if (!shadowSetup(pScreen)) {
396 ErrorF("winFinishScreenInitFB - shadowSetup () failed\n");
397 return FALSE;
398 }
399
400 /* Wrap CreateScreenResources so we can add the screen pixmap
401 to the Shadow framebuffer after it's been created */
402 pScreenPriv->pwinCreateScreenResources = pScreen->CreateScreenResources;
403 pScreen->CreateScreenResources = winCreateScreenResources;
404 }
405
406 #ifdef XWIN_MULTIWINDOWEXTWM
407 /* Handle multi-window external window manager mode */
408 if (pScreenInfo->fMWExtWM) {
409 winDebug("winScreenInit - MultiWindowExtWM - Calling RootlessInit\n");
410
411 RootlessInit(pScreen, &winMWExtWMProcs);
412
413 winDebug("winScreenInit - MultiWindowExtWM - RootlessInit returned\n");
414
415 rootless_CopyBytes_threshold = 0;
416 /* FIXME: How many? Profiling needed? */
417 rootless_CopyWindow_threshold = 1;
418
419 winWindowsWMExtensionInit();
420 }
421 #endif
422
423 /* Handle rootless mode */
424 if (pScreenInfo->fRootless) {
425 /* Define the WRAP macro temporarily for local use */
426 #define WRAP(a) \
427 if (pScreen->a) { \
428 pScreenPriv->a = pScreen->a; \
429 } else { \
430 winDebug("winScreenInit - null screen fn " #a "\n"); \
431 pScreenPriv->a = NULL; \
432 }
433
434 /* Save a pointer to each lower-level window procedure */
435 WRAP(CreateWindow);
436 WRAP(DestroyWindow);
437 WRAP(RealizeWindow);
438 WRAP(UnrealizeWindow);
439 WRAP(PositionWindow);
440 WRAP(ChangeWindowAttributes);
441 WRAP(SetShape);
442
443 /* Assign rootless window procedures to be top level procedures */
444 pScreen->CreateWindow = winCreateWindowRootless;
445 pScreen->DestroyWindow = winDestroyWindowRootless;
446 pScreen->PositionWindow = winPositionWindowRootless;
447 /*pScreen->ChangeWindowAttributes = winChangeWindowAttributesRootless; */
448 pScreen->RealizeWindow = winMapWindowRootless;
449 pScreen->UnrealizeWindow = winUnmapWindowRootless;
450 pScreen->SetShape = winSetShapeRootless;
451
452 /* Undefine the WRAP macro, as it is not needed elsewhere */
453 #undef WRAP
454 }
455
456 /* Handle multi window mode */
457 else if (pScreenInfo->fMultiWindow) {
458 /* Define the WRAP macro temporarily for local use */
459 #define WRAP(a) \
460 if (pScreen->a) { \
461 pScreenPriv->a = pScreen->a; \
462 } else { \
463 winDebug("null screen fn " #a "\n"); \
464 pScreenPriv->a = NULL; \
465 }
466
467 /* Save a pointer to each lower-level window procedure */
468 WRAP(CreateWindow);
469 WRAP(DestroyWindow);
470 WRAP(RealizeWindow);
471 WRAP(UnrealizeWindow);
472 WRAP(PositionWindow);
473 WRAP(ChangeWindowAttributes);
474 WRAP(ReparentWindow);
475 WRAP(RestackWindow);
476 WRAP(ResizeWindow);
477 WRAP(MoveWindow);
478 WRAP(CopyWindow);
479 WRAP(SetShape);
480
481 /* Assign multi-window window procedures to be top level procedures */
482 pScreen->CreateWindow = winCreateWindowMultiWindow;
483 pScreen->DestroyWindow = winDestroyWindowMultiWindow;
484 pScreen->PositionWindow = winPositionWindowMultiWindow;
485 /*pScreen->ChangeWindowAttributes = winChangeWindowAttributesMultiWindow; */
486 pScreen->RealizeWindow = winMapWindowMultiWindow;
487 pScreen->UnrealizeWindow = winUnmapWindowMultiWindow;
488 pScreen->ReparentWindow = winReparentWindowMultiWindow;
489 pScreen->RestackWindow = winRestackWindowMultiWindow;
490 pScreen->ResizeWindow = winResizeWindowMultiWindow;
491 pScreen->MoveWindow = winMoveWindowMultiWindow;
492 pScreen->CopyWindow = winCopyWindowMultiWindow;
493 pScreen->SetShape = winSetShapeMultiWindow;
494
495 /* Undefine the WRAP macro, as it is not needed elsewhere */
496 #undef WRAP
497 }
498
499 /* Wrap either fb's or shadow's CloseScreen with our CloseScreen */
500 pScreenPriv->CloseScreen = pScreen->CloseScreen;
501 pScreen->CloseScreen = pScreenPriv->pwinCloseScreen;
502
503 /* Create a mutex for modules in separate threads to wait for */
504 iReturn = pthread_mutex_init(&pScreenPriv->pmServerStarted, NULL);
505 if (iReturn != 0) {
506 ErrorF("winFinishScreenInitFB - pthread_mutex_init () failed: %d\n",
507 iReturn);
508 return FALSE;
509 }
510
511 /* Own the mutex for modules in separate threads */
512 iReturn = pthread_mutex_lock(&pScreenPriv->pmServerStarted);
513 if (iReturn != 0) {
514 ErrorF("winFinishScreenInitFB - pthread_mutex_lock () failed: %d\n",
515 iReturn);
516 return FALSE;
517 }
518
519 /* Set the ServerStarted flag to false */
520 pScreenPriv->fServerStarted = FALSE;
521
522 #ifdef XWIN_MULTIWINDOWEXTWM
523 pScreenPriv->fRestacking = FALSE;
524 #endif
525
526 if (pScreenInfo->fMultiWindow) {
527 #if CYGDEBUG || YES
528 winDebug("winFinishScreenInitFB - Calling winInitWM.\n");
529 #endif
530
531 /* Initialize multi window mode */
532 if (!winInitWM(&pScreenPriv->pWMInfo,
533 &pScreenPriv->ptWMProc,
534 &pScreenPriv->ptXMsgProc,
535 &pScreenPriv->pmServerStarted,
536 pScreenInfo->dwScreen,
537 (HWND) &pScreenPriv->hwndScreen)) {
538 ErrorF("winFinishScreenInitFB - winInitWM () failed.\n");
539 return FALSE;
540 }
541 }
542
543 /* Tell the server that we are enabled */
544 pScreenPriv->fEnabled = TRUE;
545
546 /* Tell the server that we have a valid depth */
547 pScreenPriv->fBadDepth = FALSE;
548
549 #if CYGDEBUG || YES
550 winDebug("winFinishScreenInitFB - returning\n");
551 #endif
552
553 return TRUE;
554 }
555
556 /* See Porting Layer Definition - p. 33 */
557 static Bool
winSaveScreen(ScreenPtr pScreen,int on)558 winSaveScreen(ScreenPtr pScreen, int on)
559 {
560 return TRUE;
561 }
562