xref: /OK3568_Linux_fs/external/xserver/hw/xwin/winscrinit.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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