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