winscrinit.c revision 1b5d61b8
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
42static 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
74static 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
83Bool
84winScreenInit(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
240static Bool
241winCreateScreenResources(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 */
260Bool
261winFinishScreenInitFB(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 */
557static Bool
558winSaveScreen(ScreenPtr pScreen, int on)
559{
560    return TRUE;
561}
562