winscrinit.c revision ed6184df
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
47Bool
48winScreenInit(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
204static Bool
205winCreateScreenResources(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 */
224Bool
225winFinishScreenInitFB(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