1706f2543Smrg/*
2706f2543Smrg * Copyright © 1999 Keith Packard
3706f2543Smrg *
4706f2543Smrg * Permission to use, copy, modify, distribute, and sell this software and its
5706f2543Smrg * documentation for any purpose is hereby granted without fee, provided that
6706f2543Smrg * the above copyright notice appear in all copies and that both that
7706f2543Smrg * copyright notice and this permission notice appear in supporting
8706f2543Smrg * documentation, and that the name of Keith Packard not be used in
9706f2543Smrg * advertising or publicity pertaining to distribution of the software without
10706f2543Smrg * specific, written prior permission.  Keith Packard makes no
11706f2543Smrg * representations about the suitability of this software for any purpose.  It
12706f2543Smrg * is provided "as is" without express or implied warranty.
13706f2543Smrg *
14706f2543Smrg * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15706f2543Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16706f2543Smrg * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17706f2543Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18706f2543Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19706f2543Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20706f2543Smrg * PERFORMANCE OF THIS SOFTWARE.
21706f2543Smrg */
22706f2543Smrg
23706f2543Smrg#ifdef HAVE_CONFIG_H
24706f2543Smrg#include <kdrive-config.h>
25706f2543Smrg#endif
26706f2543Smrg#include "kdrive.h"
27706f2543Smrg#include <mivalidate.h>
28706f2543Smrg#include <dixstruct.h>
29706f2543Smrg#include "privates.h"
30706f2543Smrg#ifdef RANDR
31706f2543Smrg#include <randrstr.h>
32706f2543Smrg#endif
33706f2543Smrg
34706f2543Smrg#ifdef XV
35706f2543Smrg#include "kxv.h"
36706f2543Smrg#endif
37706f2543Smrg
38706f2543Smrg#ifdef DPMSExtension
39706f2543Smrg#include "dpmsproc.h"
40706f2543Smrg#endif
41706f2543Smrg
42706f2543Smrg#ifdef HAVE_EXECINFO_H
43706f2543Smrg#include <execinfo.h>
44706f2543Smrg#endif
45706f2543Smrg
46706f2543Smrg#include <signal.h>
47706f2543Smrg
48706f2543Smrgtypedef struct _kdDepths {
49706f2543Smrg    CARD8   depth;
50706f2543Smrg    CARD8   bpp;
51706f2543Smrg} KdDepths;
52706f2543Smrg
53706f2543SmrgKdDepths    kdDepths[] = {
54706f2543Smrg    { 1, 1 },
55706f2543Smrg    { 4, 4 },
56706f2543Smrg    { 8, 8 },
57706f2543Smrg    { 15, 16 },
58706f2543Smrg    { 16, 16 },
59706f2543Smrg    { 24, 32 },
60706f2543Smrg    { 32, 32 }
61706f2543Smrg};
62706f2543Smrg
63706f2543Smrg#define NUM_KD_DEPTHS (sizeof (kdDepths) / sizeof (kdDepths[0]))
64706f2543Smrg
65706f2543Smrg#define KD_DEFAULT_BUTTONS 5
66706f2543Smrg
67706f2543SmrgDevPrivateKeyRec    kdScreenPrivateKeyRec;
68706f2543Smrgunsigned long	    kdGeneration;
69706f2543Smrg
70706f2543SmrgBool                kdVideoTest;
71706f2543Smrgunsigned long       kdVideoTestTime;
72706f2543SmrgBool		    kdEmulateMiddleButton;
73706f2543SmrgBool		    kdRawPointerCoordinates;
74706f2543SmrgBool		    kdDisableZaphod;
75706f2543SmrgBool                kdAllowZap;
76706f2543SmrgBool		    kdEnabled;
77706f2543Smrgint		    kdSubpixelOrder;
78706f2543Smrgint		    kdVirtualTerminal = -1;
79706f2543SmrgBool		    kdSwitchPending;
80706f2543Smrgchar		    *kdSwitchCmd;
81706f2543SmrgDDXPointRec	    kdOrigin;
82706f2543SmrgBool		    kdHasPointer = FALSE;
83706f2543SmrgBool		    kdHasKbd = FALSE;
84706f2543Smrg
85706f2543Smrgstatic Bool         kdCaughtSignal = FALSE;
86706f2543Smrg
87706f2543Smrg/*
88706f2543Smrg * Carry arguments from InitOutput through driver initialization
89706f2543Smrg * to KdScreenInit
90706f2543Smrg */
91706f2543Smrg
92706f2543SmrgKdOsFuncs	*kdOsFuncs;
93706f2543Smrg
94706f2543Smrgvoid
95706f2543SmrgKdSetRootClip (ScreenPtr pScreen, BOOL enable)
96706f2543Smrg{
97706f2543Smrg    WindowPtr	pWin = pScreen->root;
98706f2543Smrg    WindowPtr	pChild;
99706f2543Smrg    Bool	WasViewable;
100706f2543Smrg    Bool	anyMarked = FALSE;
101706f2543Smrg    WindowPtr   pLayerWin;
102706f2543Smrg    BoxRec	box;
103706f2543Smrg
104706f2543Smrg    if (!pWin)
105706f2543Smrg	return;
106706f2543Smrg    WasViewable = (Bool)(pWin->viewable);
107706f2543Smrg    if (WasViewable)
108706f2543Smrg    {
109706f2543Smrg	for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib)
110706f2543Smrg	{
111706f2543Smrg	    (void) (*pScreen->MarkOverlappedWindows)(pChild,
112706f2543Smrg						     pChild,
113706f2543Smrg						     &pLayerWin);
114706f2543Smrg	}
115706f2543Smrg	(*pScreen->MarkWindow) (pWin);
116706f2543Smrg	anyMarked = TRUE;
117706f2543Smrg	if (pWin->valdata)
118706f2543Smrg	{
119706f2543Smrg	    if (HasBorder (pWin))
120706f2543Smrg	    {
121706f2543Smrg		RegionPtr	borderVisible;
122706f2543Smrg
123706f2543Smrg		borderVisible = RegionCreate(NullBox, 1);
124706f2543Smrg		RegionSubtract(borderVisible,
125706f2543Smrg				&pWin->borderClip, &pWin->winSize);
126706f2543Smrg		pWin->valdata->before.borderVisible = borderVisible;
127706f2543Smrg	    }
128706f2543Smrg	    pWin->valdata->before.resized = TRUE;
129706f2543Smrg	}
130706f2543Smrg    }
131706f2543Smrg
132706f2543Smrg    if (enable)
133706f2543Smrg    {
134706f2543Smrg	box.x1 = 0;
135706f2543Smrg	box.y1 = 0;
136706f2543Smrg	box.x2 = pScreen->width;
137706f2543Smrg	box.y2 = pScreen->height;
138706f2543Smrg	pWin->drawable.width = pScreen->width;
139706f2543Smrg	pWin->drawable.height = pScreen->height;
140706f2543Smrg	RegionInit(&pWin->winSize, &box, 1);
141706f2543Smrg	RegionInit(&pWin->borderSize, &box, 1);
142706f2543Smrg	RegionReset(&pWin->borderClip, &box);
143706f2543Smrg	RegionBreak(&pWin->clipList);
144706f2543Smrg    }
145706f2543Smrg    else
146706f2543Smrg    {
147706f2543Smrg	RegionEmpty(&pWin->borderClip);
148706f2543Smrg	RegionBreak(&pWin->clipList);
149706f2543Smrg    }
150706f2543Smrg
151706f2543Smrg    ResizeChildrenWinSize (pWin, 0, 0, 0, 0);
152706f2543Smrg
153706f2543Smrg    if (WasViewable)
154706f2543Smrg    {
155706f2543Smrg	if (pWin->firstChild)
156706f2543Smrg	{
157706f2543Smrg	    anyMarked |= (*pScreen->MarkOverlappedWindows)(pWin->firstChild,
158706f2543Smrg							   pWin->firstChild,
159706f2543Smrg							   (WindowPtr *)NULL);
160706f2543Smrg	}
161706f2543Smrg	else
162706f2543Smrg	{
163706f2543Smrg	    (*pScreen->MarkWindow) (pWin);
164706f2543Smrg	    anyMarked = TRUE;
165706f2543Smrg	}
166706f2543Smrg
167706f2543Smrg
168706f2543Smrg	if (anyMarked)
169706f2543Smrg	    (*pScreen->ValidateTree)(pWin, NullWindow, VTOther);
170706f2543Smrg    }
171706f2543Smrg
172706f2543Smrg    if (WasViewable)
173706f2543Smrg    {
174706f2543Smrg	if (anyMarked)
175706f2543Smrg	    (*pScreen->HandleExposures)(pWin);
176706f2543Smrg	if (anyMarked && pScreen->PostValidateTree)
177706f2543Smrg	    (*pScreen->PostValidateTree)(pWin, NullWindow, VTOther);
178706f2543Smrg    }
179706f2543Smrg    if (pWin->realized)
180706f2543Smrg	WindowsRestructured ();
181706f2543Smrg}
182706f2543Smrg
183706f2543Smrgvoid
184706f2543SmrgKdDisableScreen (ScreenPtr pScreen)
185706f2543Smrg{
186706f2543Smrg    KdScreenPriv(pScreen);
187706f2543Smrg
188706f2543Smrg    if (!pScreenPriv->enabled)
189706f2543Smrg	return;
190706f2543Smrg    if (!pScreenPriv->closed)
191706f2543Smrg	KdSetRootClip (pScreen, FALSE);
192706f2543Smrg    KdDisableColormap (pScreen);
193706f2543Smrg    if (!pScreenPriv->screen->dumb && pScreenPriv->card->cfuncs->disableAccel)
194706f2543Smrg	(*pScreenPriv->card->cfuncs->disableAccel) (pScreen);
195706f2543Smrg    if (!pScreenPriv->screen->softCursor && pScreenPriv->card->cfuncs->disableCursor)
196706f2543Smrg	(*pScreenPriv->card->cfuncs->disableCursor) (pScreen);
197706f2543Smrg    if (pScreenPriv->card->cfuncs->dpms)
198706f2543Smrg	(*pScreenPriv->card->cfuncs->dpms) (pScreen, KD_DPMS_NORMAL);
199706f2543Smrg    pScreenPriv->enabled = FALSE;
200706f2543Smrg    if(pScreenPriv->card->cfuncs->disable)
201706f2543Smrg        (*pScreenPriv->card->cfuncs->disable) (pScreen);
202706f2543Smrg}
203706f2543Smrg
204706f2543Smrgstatic void
205706f2543SmrgKdDoSwitchCmd (char *reason)
206706f2543Smrg{
207706f2543Smrg    if (kdSwitchCmd)
208706f2543Smrg    {
209706f2543Smrg	char    *command = malloc(strlen (kdSwitchCmd) +
210706f2543Smrg				   1 +
211706f2543Smrg				   strlen (reason) +
212706f2543Smrg				   1);
213706f2543Smrg	if (!command)
214706f2543Smrg	    return;
215706f2543Smrg	strcpy (command, kdSwitchCmd);
216706f2543Smrg	strcat (command, " ");
217706f2543Smrg	strcat (command, reason);
218706f2543Smrg	system (command);
219706f2543Smrg	free(command);
220706f2543Smrg    }
221706f2543Smrg}
222706f2543Smrg
223706f2543Smrgvoid
224706f2543SmrgKdSuspend (void)
225706f2543Smrg{
226706f2543Smrg    KdCardInfo	    *card;
227706f2543Smrg    KdScreenInfo    *screen;
228706f2543Smrg
229706f2543Smrg    if (kdEnabled)
230706f2543Smrg    {
231706f2543Smrg	for (card = kdCardInfo; card; card = card->next)
232706f2543Smrg	{
233706f2543Smrg	    for (screen = card->screenList; screen; screen = screen->next)
234706f2543Smrg		if (screen->mynum == card->selected && screen->pScreen)
235706f2543Smrg		    KdDisableScreen (screen->pScreen);
236706f2543Smrg	    if (card->driver && card->cfuncs->restore)
237706f2543Smrg		(*card->cfuncs->restore) (card);
238706f2543Smrg	}
239706f2543Smrg	KdDisableInput ();
240706f2543Smrg	KdDoSwitchCmd ("suspend");
241706f2543Smrg    }
242706f2543Smrg}
243706f2543Smrg
244706f2543Smrgvoid
245706f2543SmrgKdDisableScreens (void)
246706f2543Smrg{
247706f2543Smrg    KdSuspend ();
248706f2543Smrg    if (kdEnabled)
249706f2543Smrg    {
250706f2543Smrg        if (kdOsFuncs->Disable)
251706f2543Smrg            (*kdOsFuncs->Disable) ();
252706f2543Smrg	kdEnabled = FALSE;
253706f2543Smrg    }
254706f2543Smrg}
255706f2543Smrg
256706f2543SmrgBool
257706f2543SmrgKdEnableScreen (ScreenPtr pScreen)
258706f2543Smrg{
259706f2543Smrg    KdScreenPriv (pScreen);
260706f2543Smrg
261706f2543Smrg    if (pScreenPriv->enabled)
262706f2543Smrg	return TRUE;
263706f2543Smrg    if(pScreenPriv->card->cfuncs->enable)
264706f2543Smrg	if (!(*pScreenPriv->card->cfuncs->enable) (pScreen))
265706f2543Smrg	    return FALSE;
266706f2543Smrg    pScreenPriv->enabled = TRUE;
267706f2543Smrg    pScreenPriv->dpmsState = KD_DPMS_NORMAL;
268706f2543Smrg    pScreenPriv->card->selected = pScreenPriv->screen->mynum;
269706f2543Smrg    if (!pScreenPriv->screen->softCursor && pScreenPriv->card->cfuncs->enableCursor)
270706f2543Smrg	(*pScreenPriv->card->cfuncs->enableCursor) (pScreen);
271706f2543Smrg    if (!pScreenPriv->screen->dumb && pScreenPriv->card->cfuncs->enableAccel)
272706f2543Smrg	(*pScreenPriv->card->cfuncs->enableAccel) (pScreen);
273706f2543Smrg    KdEnableColormap (pScreen);
274706f2543Smrg    KdSetRootClip (pScreen, TRUE);
275706f2543Smrg    if (pScreenPriv->card->cfuncs->dpms)
276706f2543Smrg	(*pScreenPriv->card->cfuncs->dpms) (pScreen, pScreenPriv->dpmsState);
277706f2543Smrg    return TRUE;
278706f2543Smrg}
279706f2543Smrg
280706f2543Smrgvoid
281706f2543SmrgKdResume (void)
282706f2543Smrg{
283706f2543Smrg    KdCardInfo	    *card;
284706f2543Smrg    KdScreenInfo    *screen;
285706f2543Smrg
286706f2543Smrg    if (kdEnabled)
287706f2543Smrg    {
288706f2543Smrg	KdDoSwitchCmd ("resume");
289706f2543Smrg	for (card = kdCardInfo; card; card = card->next)
290706f2543Smrg	{
291706f2543Smrg	    if(card->cfuncs->preserve)
292706f2543Smrg		(*card->cfuncs->preserve) (card);
293706f2543Smrg	    for (screen = card->screenList; screen; screen = screen->next)
294706f2543Smrg		if (screen->mynum == card->selected && screen->pScreen)
295706f2543Smrg		    KdEnableScreen (screen->pScreen);
296706f2543Smrg	}
297706f2543Smrg	KdEnableInput ();
298706f2543Smrg	KdReleaseAllKeys ();
299706f2543Smrg    }
300706f2543Smrg}
301706f2543Smrg
302706f2543Smrgvoid
303706f2543SmrgKdEnableScreens (void)
304706f2543Smrg{
305706f2543Smrg    if (!kdEnabled)
306706f2543Smrg    {
307706f2543Smrg	kdEnabled = TRUE;
308706f2543Smrg        if (kdOsFuncs->Enable)
309706f2543Smrg            (*kdOsFuncs->Enable) ();
310706f2543Smrg    }
311706f2543Smrg    KdResume ();
312706f2543Smrg}
313706f2543Smrg
314706f2543Smrgvoid
315706f2543SmrgKdProcessSwitch (void)
316706f2543Smrg{
317706f2543Smrg    if (kdEnabled)
318706f2543Smrg	KdDisableScreens ();
319706f2543Smrg    else
320706f2543Smrg	KdEnableScreens ();
321706f2543Smrg}
322706f2543Smrg
323706f2543Smrgvoid
324706f2543SmrgAbortDDX(void)
325706f2543Smrg{
326706f2543Smrg    KdDisableScreens ();
327706f2543Smrg    if (kdOsFuncs)
328706f2543Smrg    {
329706f2543Smrg	if (kdEnabled && kdOsFuncs->Disable)
330706f2543Smrg	    (*kdOsFuncs->Disable) ();
331706f2543Smrg        if (kdOsFuncs->Fini)
332706f2543Smrg            (*kdOsFuncs->Fini) ();
333706f2543Smrg	KdDoSwitchCmd ("stop");
334706f2543Smrg    }
335706f2543Smrg
336706f2543Smrg    if (kdCaughtSignal)
337706f2543Smrg        OsAbort();
338706f2543Smrg}
339706f2543Smrg
340706f2543Smrgvoid
341706f2543SmrgddxGiveUp (void)
342706f2543Smrg{
343706f2543Smrg    AbortDDX ();
344706f2543Smrg}
345706f2543Smrg
346706f2543SmrgBool	kdDumbDriver;
347706f2543SmrgBool	kdSoftCursor;
348706f2543Smrg
349706f2543Smrgchar *
350706f2543SmrgKdParseFindNext (char *cur, char *delim, char *save, char *last)
351706f2543Smrg{
352706f2543Smrg    while (*cur && !strchr (delim, *cur))
353706f2543Smrg    {
354706f2543Smrg	*save++ = *cur++;
355706f2543Smrg    }
356706f2543Smrg    *save = 0;
357706f2543Smrg    *last = *cur;
358706f2543Smrg    if (*cur)
359706f2543Smrg	cur++;
360706f2543Smrg    return cur;
361706f2543Smrg}
362706f2543Smrg
363706f2543SmrgRotation
364706f2543SmrgKdAddRotation (Rotation a, Rotation b)
365706f2543Smrg{
366706f2543Smrg    Rotation	rotate = (a & RR_Rotate_All) * (b & RR_Rotate_All);
367706f2543Smrg    Rotation	reflect = (a & RR_Reflect_All) ^ (b & RR_Reflect_All);
368706f2543Smrg
369706f2543Smrg    if (rotate > RR_Rotate_270)
370706f2543Smrg	rotate /= (RR_Rotate_270 * RR_Rotate_90);
371706f2543Smrg    return reflect | rotate;
372706f2543Smrg}
373706f2543Smrg
374706f2543SmrgRotation
375706f2543SmrgKdSubRotation (Rotation a, Rotation b)
376706f2543Smrg{
377706f2543Smrg    Rotation	rotate = (a & RR_Rotate_All) * 16 / (b & RR_Rotate_All);
378706f2543Smrg    Rotation	reflect = (a & RR_Reflect_All) ^ (b & RR_Reflect_All);
379706f2543Smrg
380706f2543Smrg    if (rotate > RR_Rotate_270)
381706f2543Smrg	rotate /= (RR_Rotate_270 * RR_Rotate_90);
382706f2543Smrg    return reflect | rotate;
383706f2543Smrg}
384706f2543Smrg
385706f2543Smrgvoid
386706f2543SmrgKdParseScreen (KdScreenInfo *screen,
387706f2543Smrg	       char	    *arg)
388706f2543Smrg{
389706f2543Smrg    char    delim;
390706f2543Smrg    char    save[1024];
391706f2543Smrg    int	    i;
392706f2543Smrg    int	    pixels, mm;
393706f2543Smrg
394706f2543Smrg    screen->dumb = kdDumbDriver;
395706f2543Smrg    screen->softCursor = kdSoftCursor;
396706f2543Smrg    screen->origin = kdOrigin;
397706f2543Smrg    screen->randr = RR_Rotate_0;
398706f2543Smrg    screen->width = 0;
399706f2543Smrg    screen->height = 0;
400706f2543Smrg    screen->width_mm = 0;
401706f2543Smrg    screen->height_mm = 0;
402706f2543Smrg    screen->subpixel_order = kdSubpixelOrder;
403706f2543Smrg    screen->rate = 0;
404706f2543Smrg    screen->fb.depth = 0;
405706f2543Smrg    if (!arg)
406706f2543Smrg	return;
407706f2543Smrg    if (strlen (arg) >= sizeof (save))
408706f2543Smrg	return;
409706f2543Smrg
410706f2543Smrg    for (i = 0; i < 2; i++)
411706f2543Smrg    {
412706f2543Smrg	arg = KdParseFindNext (arg, "x/@XY", save, &delim);
413706f2543Smrg	if (!save[0])
414706f2543Smrg	    return;
415706f2543Smrg
416706f2543Smrg	pixels = atoi(save);
417706f2543Smrg	mm = 0;
418706f2543Smrg
419706f2543Smrg	if (delim == '/')
420706f2543Smrg	{
421706f2543Smrg	    arg = KdParseFindNext (arg, "x@XY", save, &delim);
422706f2543Smrg	    if (!save[0])
423706f2543Smrg		return;
424706f2543Smrg	    mm = atoi(save);
425706f2543Smrg	}
426706f2543Smrg
427706f2543Smrg	if (i == 0)
428706f2543Smrg	{
429706f2543Smrg	    screen->width = pixels;
430706f2543Smrg	    screen->width_mm = mm;
431706f2543Smrg	}
432706f2543Smrg	else
433706f2543Smrg	{
434706f2543Smrg	    screen->height = pixels;
435706f2543Smrg	    screen->height_mm = mm;
436706f2543Smrg	}
437706f2543Smrg	if (delim != 'x' && delim != '@' && delim != 'X' && delim != 'Y')
438706f2543Smrg	    return;
439706f2543Smrg    }
440706f2543Smrg
441706f2543Smrg    kdOrigin.x += screen->width;
442706f2543Smrg    kdOrigin.y = 0;
443706f2543Smrg    kdDumbDriver = FALSE;
444706f2543Smrg    kdSoftCursor = FALSE;
445706f2543Smrg    kdSubpixelOrder = SubPixelUnknown;
446706f2543Smrg
447706f2543Smrg    if (delim == '@')
448706f2543Smrg    {
449706f2543Smrg	arg = KdParseFindNext (arg, "xXY", save, &delim);
450706f2543Smrg	if (save[0])
451706f2543Smrg	{
452706f2543Smrg	    int	    rotate = atoi (save);
453706f2543Smrg	    if (rotate < 45)
454706f2543Smrg		screen->randr = RR_Rotate_0;
455706f2543Smrg	    else if (rotate < 135)
456706f2543Smrg		screen->randr = RR_Rotate_90;
457706f2543Smrg	    else if (rotate < 225)
458706f2543Smrg		screen->randr = RR_Rotate_180;
459706f2543Smrg	    else if (rotate < 315)
460706f2543Smrg		screen->randr = RR_Rotate_270;
461706f2543Smrg	    else
462706f2543Smrg		screen->randr = RR_Rotate_0;
463706f2543Smrg	}
464706f2543Smrg    }
465706f2543Smrg    if (delim == 'X')
466706f2543Smrg    {
467706f2543Smrg	arg = KdParseFindNext (arg, "xY", save, &delim);
468706f2543Smrg	screen->randr |= RR_Reflect_X;
469706f2543Smrg    }
470706f2543Smrg
471706f2543Smrg    if (delim == 'Y')
472706f2543Smrg    {
473706f2543Smrg	arg = KdParseFindNext (arg, "xY", save, &delim);
474706f2543Smrg	screen->randr |= RR_Reflect_Y;
475706f2543Smrg    }
476706f2543Smrg
477706f2543Smrg    arg = KdParseFindNext (arg, "x/,", save, &delim);
478706f2543Smrg    if (save[0])
479706f2543Smrg    {
480706f2543Smrg	screen->fb.depth = atoi(save);
481706f2543Smrg	if (delim == '/')
482706f2543Smrg	{
483706f2543Smrg	    arg = KdParseFindNext (arg, "x,", save, &delim);
484706f2543Smrg	    if (save[0])
485706f2543Smrg		screen->fb.bitsPerPixel = atoi (save);
486706f2543Smrg	}
487706f2543Smrg	else
488706f2543Smrg	    screen->fb.bitsPerPixel = 0;
489706f2543Smrg    }
490706f2543Smrg
491706f2543Smrg    if (delim == 'x')
492706f2543Smrg    {
493706f2543Smrg	arg = KdParseFindNext (arg, "x", save, &delim);
494706f2543Smrg	if (save[0])
495706f2543Smrg	    screen->rate = atoi(save);
496706f2543Smrg    }
497706f2543Smrg}
498706f2543Smrg
499706f2543Smrg/*
500706f2543Smrg * Mouse argument syntax:
501706f2543Smrg *
502706f2543Smrg *  device,protocol,options...
503706f2543Smrg *
504706f2543Smrg *  Options are any of:
505706f2543Smrg *	1-5	    n button mouse
506706f2543Smrg *	2button	    emulate middle button
507706f2543Smrg *	{NMO}	    Reorder buttons
508706f2543Smrg */
509706f2543Smrg
510706f2543Smrgvoid
511706f2543SmrgKdParseRgba (char *rgba)
512706f2543Smrg{
513706f2543Smrg    if (!strcmp (rgba, "rgb"))
514706f2543Smrg	kdSubpixelOrder = SubPixelHorizontalRGB;
515706f2543Smrg    else if (!strcmp (rgba, "bgr"))
516706f2543Smrg	kdSubpixelOrder = SubPixelHorizontalBGR;
517706f2543Smrg    else if (!strcmp (rgba, "vrgb"))
518706f2543Smrg	kdSubpixelOrder = SubPixelVerticalRGB;
519706f2543Smrg    else if (!strcmp (rgba, "vbgr"))
520706f2543Smrg	kdSubpixelOrder = SubPixelVerticalBGR;
521706f2543Smrg    else if (!strcmp (rgba, "none"))
522706f2543Smrg	kdSubpixelOrder = SubPixelNone;
523706f2543Smrg    else
524706f2543Smrg	kdSubpixelOrder = SubPixelUnknown;
525706f2543Smrg}
526706f2543Smrg
527706f2543Smrgvoid
528706f2543SmrgKdUseMsg (void)
529706f2543Smrg{
530706f2543Smrg    ErrorF("\nTinyX Device Dependent Usage:\n");
531706f2543Smrg    ErrorF("-screen WIDTH[/WIDTHMM]xHEIGHT[/HEIGHTMM][@ROTATION][X][Y][xDEPTH/BPP[xFREQ]]  Specify screen characteristics\n");
532706f2543Smrg    ErrorF("-rgba rgb/bgr/vrgb/vbgr/none   Specify subpixel ordering for LCD panels\n");
533706f2543Smrg    ErrorF("-mouse driver [,n,,options]    Specify the pointer driver and its options (n is the number of buttons)\n");
534706f2543Smrg    ErrorF("-keybd driver [,,options]      Specify the keyboard driver and its options\n");
535706f2543Smrg    ErrorF("-zaphod          Disable cursor screen switching\n");
536706f2543Smrg    ErrorF("-2button         Emulate 3 button mouse\n");
537706f2543Smrg    ErrorF("-3button         Disable 3 button mouse emulation\n");
538706f2543Smrg    ErrorF("-rawcoord        Don't transform pointer coordinates on rotation\n");
539706f2543Smrg    ErrorF("-dumb            Disable hardware acceleration\n");
540706f2543Smrg    ErrorF("-softCursor      Force software cursor\n");
541706f2543Smrg    ErrorF("-videoTest       Start the server, pause momentarily and exit\n");
542706f2543Smrg    ErrorF("-origin X,Y      Locates the next screen in the the virtual screen (Xinerama)\n");
543706f2543Smrg    ErrorF("-switchCmd       Command to execute on vt switch\n");
544706f2543Smrg    ErrorF("-zap             Terminate server on Ctrl+Alt+Backspace\n");
545706f2543Smrg    ErrorF("vtxx             Use virtual terminal xx instead of the next available\n");
546706f2543Smrg}
547706f2543Smrg
548706f2543Smrgint
549706f2543SmrgKdProcessArgument (int argc, char **argv, int i)
550706f2543Smrg{
551706f2543Smrg    KdCardInfo	    *card;
552706f2543Smrg    KdScreenInfo    *screen;
553706f2543Smrg
554706f2543Smrg    if (!strcmp (argv[i], "-screen"))
555706f2543Smrg    {
556706f2543Smrg	if ((i+1) < argc)
557706f2543Smrg	{
558706f2543Smrg	    card = KdCardInfoLast ();
559706f2543Smrg	    if (!card)
560706f2543Smrg	    {
561706f2543Smrg		InitCard (0);
562706f2543Smrg		card = KdCardInfoLast ();
563706f2543Smrg	    }
564706f2543Smrg	    if (card) {
565706f2543Smrg		screen = KdScreenInfoAdd (card);
566706f2543Smrg		KdParseScreen (screen, argv[i+1]);
567706f2543Smrg	    } else
568706f2543Smrg		ErrorF("No matching card found!\n");
569706f2543Smrg	}
570706f2543Smrg	else
571706f2543Smrg	    UseMsg ();
572706f2543Smrg	return 2;
573706f2543Smrg    }
574706f2543Smrg    if (!strcmp (argv[i], "-zaphod"))
575706f2543Smrg    {
576706f2543Smrg	kdDisableZaphod = TRUE;
577706f2543Smrg	return 1;
578706f2543Smrg    }
579706f2543Smrg    if (!strcmp (argv[i], "-zap"))
580706f2543Smrg    {
581706f2543Smrg	kdAllowZap = TRUE;
582706f2543Smrg	return 1;
583706f2543Smrg    }
584706f2543Smrg    if (!strcmp (argv[i], "-3button"))
585706f2543Smrg    {
586706f2543Smrg	kdEmulateMiddleButton = FALSE;
587706f2543Smrg	return 1;
588706f2543Smrg    }
589706f2543Smrg    if (!strcmp (argv[i], "-2button"))
590706f2543Smrg    {
591706f2543Smrg	kdEmulateMiddleButton = TRUE;
592706f2543Smrg	return 1;
593706f2543Smrg    }
594706f2543Smrg    if (!strcmp (argv[i], "-rawcoord"))
595706f2543Smrg    {
596706f2543Smrg	kdRawPointerCoordinates = 1;
597706f2543Smrg	return 1;
598706f2543Smrg    }
599706f2543Smrg    if (!strcmp (argv[i], "-dumb"))
600706f2543Smrg    {
601706f2543Smrg	kdDumbDriver = TRUE;
602706f2543Smrg	return 1;
603706f2543Smrg    }
604706f2543Smrg    if (!strcmp (argv[i], "-softCursor"))
605706f2543Smrg    {
606706f2543Smrg	kdSoftCursor = TRUE;
607706f2543Smrg	return 1;
608706f2543Smrg    }
609706f2543Smrg    if (!strcmp (argv[i], "-videoTest"))
610706f2543Smrg    {
611706f2543Smrg	kdVideoTest = TRUE;
612706f2543Smrg	return 1;
613706f2543Smrg    }
614706f2543Smrg    if (!strcmp (argv[i], "-origin"))
615706f2543Smrg    {
616706f2543Smrg	if ((i+1) < argc)
617706f2543Smrg	{
618706f2543Smrg	    char    *x = argv[i+1];
619706f2543Smrg	    char    *y = strchr (x, ',');
620706f2543Smrg	    if (x)
621706f2543Smrg		kdOrigin.x = atoi (x);
622706f2543Smrg	    else
623706f2543Smrg		kdOrigin.x = 0;
624706f2543Smrg	    if (y)
625706f2543Smrg		kdOrigin.y = atoi(y+1);
626706f2543Smrg	    else
627706f2543Smrg		kdOrigin.y = 0;
628706f2543Smrg	}
629706f2543Smrg	else
630706f2543Smrg	    UseMsg ();
631706f2543Smrg	return 2;
632706f2543Smrg    }
633706f2543Smrg    if (!strcmp (argv[i], "-rgba"))
634706f2543Smrg    {
635706f2543Smrg	if ((i+1) < argc)
636706f2543Smrg	    KdParseRgba (argv[i+1]);
637706f2543Smrg	else
638706f2543Smrg	    UseMsg ();
639706f2543Smrg	return 2;
640706f2543Smrg    }
641706f2543Smrg    if (!strcmp (argv[i], "-switchCmd"))
642706f2543Smrg    {
643706f2543Smrg	if ((i+1) < argc)
644706f2543Smrg	    kdSwitchCmd = argv[i+1];
645706f2543Smrg	else
646706f2543Smrg	    UseMsg ();
647706f2543Smrg	return 2;
648706f2543Smrg    }
649706f2543Smrg    if (!strncmp (argv[i], "vt", 2) &&
650706f2543Smrg	sscanf (argv[i], "vt%2d", &kdVirtualTerminal) == 1)
651706f2543Smrg    {
652706f2543Smrg	return 1;
653706f2543Smrg    }
654706f2543Smrg    if (!strcmp (argv[i], "-mouse") ||
655706f2543Smrg        !strcmp (argv[i], "-pointer")) {
656706f2543Smrg        if (i + 1 >= argc)
657706f2543Smrg            UseMsg();
658706f2543Smrg        KdAddConfigPointer(argv[i + 1]);
659706f2543Smrg	kdHasPointer = TRUE;
660706f2543Smrg        return 2;
661706f2543Smrg    }
662706f2543Smrg    if (!strcmp (argv[i], "-keybd")) {
663706f2543Smrg        if (i + 1 >= argc)
664706f2543Smrg            UseMsg();
665706f2543Smrg        KdAddConfigKeyboard(argv[i + 1]);
666706f2543Smrg	kdHasKbd = TRUE;
667706f2543Smrg        return 2;
668706f2543Smrg    }
669706f2543Smrg
670706f2543Smrg    return 0;
671706f2543Smrg}
672706f2543Smrg
673706f2543Smrg/*
674706f2543Smrg * These are getting tossed in here until I can think of where
675706f2543Smrg * they really belong
676706f2543Smrg */
677706f2543Smrg
678706f2543Smrgvoid
679706f2543SmrgKdOsInit (KdOsFuncs *pOsFuncs)
680706f2543Smrg{
681706f2543Smrg    kdOsFuncs = pOsFuncs;
682706f2543Smrg    if (pOsFuncs)
683706f2543Smrg    {
684706f2543Smrg	if (serverGeneration == 1)
685706f2543Smrg	{
686706f2543Smrg	    KdDoSwitchCmd ("start");
687706f2543Smrg            if (pOsFuncs->Init)
688706f2543Smrg                (*pOsFuncs->Init) ();
689706f2543Smrg	}
690706f2543Smrg    }
691706f2543Smrg}
692706f2543Smrg
693706f2543SmrgBool
694706f2543SmrgKdAllocatePrivates (ScreenPtr pScreen)
695706f2543Smrg{
696706f2543Smrg    KdPrivScreenPtr	pScreenPriv;
697706f2543Smrg
698706f2543Smrg    if (kdGeneration != serverGeneration)
699706f2543Smrg	kdGeneration = serverGeneration;
700706f2543Smrg
701706f2543Smrg    if (!dixRegisterPrivateKey(&kdScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
702706f2543Smrg	return FALSE;
703706f2543Smrg
704706f2543Smrg    pScreenPriv = calloc(1, sizeof (*pScreenPriv));
705706f2543Smrg    if (!pScreenPriv)
706706f2543Smrg	return FALSE;
707706f2543Smrg    KdSetScreenPriv (pScreen, pScreenPriv);
708706f2543Smrg    return TRUE;
709706f2543Smrg}
710706f2543Smrg
711706f2543SmrgBool
712706f2543SmrgKdCreateScreenResources (ScreenPtr pScreen)
713706f2543Smrg{
714706f2543Smrg    KdScreenPriv(pScreen);
715706f2543Smrg    KdCardInfo	    *card = pScreenPriv->card;
716706f2543Smrg    Bool ret;
717706f2543Smrg
718706f2543Smrg    pScreen->CreateScreenResources = pScreenPriv->CreateScreenResources;
719706f2543Smrg    if(pScreen->CreateScreenResources)
720706f2543Smrg	ret = (*pScreen->CreateScreenResources) (pScreen);
721706f2543Smrg    else
722706f2543Smrg	ret= -1;
723706f2543Smrg    pScreenPriv->CreateScreenResources = pScreen->CreateScreenResources;
724706f2543Smrg    pScreen->CreateScreenResources = KdCreateScreenResources;
725706f2543Smrg    if (ret && card->cfuncs->createRes)
726706f2543Smrg	ret = (*card->cfuncs->createRes) (pScreen);
727706f2543Smrg    return ret;
728706f2543Smrg}
729706f2543Smrg
730706f2543SmrgBool
731706f2543SmrgKdCloseScreen (int index, ScreenPtr pScreen)
732706f2543Smrg{
733706f2543Smrg    KdScreenPriv(pScreen);
734706f2543Smrg    KdScreenInfo    *screen = pScreenPriv->screen;
735706f2543Smrg    KdCardInfo	    *card = pScreenPriv->card;
736706f2543Smrg    Bool	    ret;
737706f2543Smrg
738706f2543Smrg    pScreenPriv->closed = TRUE;
739706f2543Smrg    pScreen->CloseScreen = pScreenPriv->CloseScreen;
740706f2543Smrg    if(pScreen->CloseScreen)
741706f2543Smrg        ret = (*pScreen->CloseScreen) (index, pScreen);
742706f2543Smrg    else
743706f2543Smrg	ret = TRUE;
744706f2543Smrg
745706f2543Smrg    if (pScreenPriv->dpmsState != KD_DPMS_NORMAL)
746706f2543Smrg	(*card->cfuncs->dpms) (pScreen, KD_DPMS_NORMAL);
747706f2543Smrg
748706f2543Smrg    if (screen->mynum == card->selected)
749706f2543Smrg	KdDisableScreen (pScreen);
750706f2543Smrg
751706f2543Smrg    /*
752706f2543Smrg     * Restore video hardware when last screen is closed
753706f2543Smrg     */
754706f2543Smrg    if (screen == card->screenList)
755706f2543Smrg    {
756706f2543Smrg	if (kdEnabled && card->cfuncs->restore)
757706f2543Smrg	    (*card->cfuncs->restore) (card);
758706f2543Smrg    }
759706f2543Smrg
760706f2543Smrg    if (!pScreenPriv->screen->dumb && card->cfuncs->finiAccel)
761706f2543Smrg	(*card->cfuncs->finiAccel) (pScreen);
762706f2543Smrg
763706f2543Smrg    if (!pScreenPriv->screen->softCursor && card->cfuncs->finiCursor)
764706f2543Smrg	(*card->cfuncs->finiCursor) (pScreen);
765706f2543Smrg
766706f2543Smrg    if(card->cfuncs->scrfini)
767706f2543Smrg        (*card->cfuncs->scrfini) (screen);
768706f2543Smrg
769706f2543Smrg    /*
770706f2543Smrg     * Clean up card when last screen is closed, DIX closes them in
771706f2543Smrg     * reverse order, thus we check for when the first in the list is closed
772706f2543Smrg     */
773706f2543Smrg    if (screen == card->screenList)
774706f2543Smrg    {
775706f2543Smrg	if(card->cfuncs->cardfini)
776706f2543Smrg	    (*card->cfuncs->cardfini) (card);
777706f2543Smrg	/*
778706f2543Smrg	 * Clean up OS when last card is closed
779706f2543Smrg	 */
780706f2543Smrg	if (card == kdCardInfo)
781706f2543Smrg	{
782706f2543Smrg	    if (kdEnabled)
783706f2543Smrg	    {
784706f2543Smrg		kdEnabled = FALSE;
785706f2543Smrg		if(kdOsFuncs->Disable)
786706f2543Smrg		    (*kdOsFuncs->Disable) ();
787706f2543Smrg	    }
788706f2543Smrg	}
789706f2543Smrg    }
790706f2543Smrg
791706f2543Smrg    pScreenPriv->screen->pScreen = 0;
792706f2543Smrg
793706f2543Smrg    free((pointer) pScreenPriv);
794706f2543Smrg    return ret;
795706f2543Smrg}
796706f2543Smrg
797706f2543SmrgBool
798706f2543SmrgKdSaveScreen (ScreenPtr pScreen, int on)
799706f2543Smrg{
800706f2543Smrg    KdScreenPriv(pScreen);
801706f2543Smrg    int	    dpmsState;
802706f2543Smrg
803706f2543Smrg    if (!pScreenPriv->card->cfuncs->dpms)
804706f2543Smrg	return FALSE;
805706f2543Smrg
806706f2543Smrg    dpmsState = pScreenPriv->dpmsState;
807706f2543Smrg    switch (on) {
808706f2543Smrg    case SCREEN_SAVER_OFF:
809706f2543Smrg	dpmsState = KD_DPMS_NORMAL;
810706f2543Smrg	break;
811706f2543Smrg    case SCREEN_SAVER_ON:
812706f2543Smrg	if (dpmsState == KD_DPMS_NORMAL)
813706f2543Smrg	    dpmsState = KD_DPMS_NORMAL+1;
814706f2543Smrg	break;
815706f2543Smrg    case SCREEN_SAVER_CYCLE:
816706f2543Smrg	if (dpmsState < KD_DPMS_MAX)
817706f2543Smrg	    dpmsState++;
818706f2543Smrg	break;
819706f2543Smrg    case SCREEN_SAVER_FORCER:
820706f2543Smrg	break;
821706f2543Smrg    }
822706f2543Smrg    if (dpmsState != pScreenPriv->dpmsState)
823706f2543Smrg    {
824706f2543Smrg	if (pScreenPriv->enabled)
825706f2543Smrg	    (*pScreenPriv->card->cfuncs->dpms) (pScreen, dpmsState);
826706f2543Smrg	pScreenPriv->dpmsState = dpmsState;
827706f2543Smrg    }
828706f2543Smrg    return TRUE;
829706f2543Smrg}
830706f2543Smrg
831706f2543Smrgstatic Bool
832706f2543SmrgKdCreateWindow (WindowPtr pWin)
833706f2543Smrg{
834706f2543Smrg#ifndef PHOENIX
835706f2543Smrg    if (!pWin->parent)
836706f2543Smrg    {
837706f2543Smrg	KdScreenPriv(pWin->drawable.pScreen);
838706f2543Smrg
839706f2543Smrg	if (!pScreenPriv->enabled)
840706f2543Smrg	{
841706f2543Smrg	    RegionEmpty(&pWin->borderClip);
842706f2543Smrg	    RegionBreak(&pWin->clipList);
843706f2543Smrg	}
844706f2543Smrg    }
845706f2543Smrg#endif
846706f2543Smrg    return fbCreateWindow (pWin);
847706f2543Smrg}
848706f2543Smrg
849706f2543Smrgvoid
850706f2543SmrgKdSetSubpixelOrder (ScreenPtr pScreen, Rotation randr)
851706f2543Smrg{
852706f2543Smrg    KdScreenPriv(pScreen);
853706f2543Smrg    KdScreenInfo	*screen = pScreenPriv->screen;
854706f2543Smrg    int			subpixel_order = screen->subpixel_order;
855706f2543Smrg    Rotation		subpixel_dir;
856706f2543Smrg    int			i;
857706f2543Smrg
858706f2543Smrg    static struct {
859706f2543Smrg	int	    subpixel_order;
860706f2543Smrg	Rotation    direction;
861706f2543Smrg    } orders[] = {
862706f2543Smrg	{ SubPixelHorizontalRGB, 	RR_Rotate_0 },
863706f2543Smrg	{ SubPixelHorizontalBGR,	RR_Rotate_180 },
864706f2543Smrg	{ SubPixelVerticalRGB,		RR_Rotate_270 },
865706f2543Smrg	{ SubPixelVerticalBGR,		RR_Rotate_90 },
866706f2543Smrg    };
867706f2543Smrg
868706f2543Smrg    static struct {
869706f2543Smrg	int	bit;
870706f2543Smrg	int	normal;
871706f2543Smrg	int	reflect;
872706f2543Smrg    } reflects[] = {
873706f2543Smrg	{ RR_Reflect_X, SubPixelHorizontalRGB,	SubPixelHorizontalBGR },
874706f2543Smrg	{ RR_Reflect_X, SubPixelHorizontalBGR,	SubPixelHorizontalRGB },
875706f2543Smrg	{ RR_Reflect_Y, SubPixelVerticalRGB,	SubPixelVerticalBGR },
876706f2543Smrg	{ RR_Reflect_Y, SubPixelVerticalRGB,	SubPixelVerticalRGB },
877706f2543Smrg    };
878706f2543Smrg
879706f2543Smrg    /* map subpixel to direction */
880706f2543Smrg    for (i = 0; i < 4; i++)
881706f2543Smrg	if (orders[i].subpixel_order == subpixel_order)
882706f2543Smrg	    break;
883706f2543Smrg    if (i < 4)
884706f2543Smrg    {
885706f2543Smrg	subpixel_dir = KdAddRotation (randr & RR_Rotate_All, orders[i].direction);
886706f2543Smrg
887706f2543Smrg	/* map back to subpixel order */
888706f2543Smrg	for (i = 0; i < 4; i++)
889706f2543Smrg	    if (orders[i].direction & subpixel_dir)
890706f2543Smrg	    {
891706f2543Smrg		subpixel_order = orders[i].subpixel_order;
892706f2543Smrg		break;
893706f2543Smrg	    }
894706f2543Smrg	/* reflect */
895706f2543Smrg	for (i = 0; i < 4; i++)
896706f2543Smrg	    if ((randr & reflects[i].bit) &&
897706f2543Smrg		reflects[i].normal == subpixel_order)
898706f2543Smrg	    {
899706f2543Smrg		subpixel_order = reflects[i].reflect;
900706f2543Smrg		break;
901706f2543Smrg	    }
902706f2543Smrg    }
903706f2543Smrg    PictureSetSubpixelOrder (pScreen, subpixel_order);
904706f2543Smrg}
905706f2543Smrg
906706f2543Smrg/* Pass through AddScreen, which doesn't take any closure */
907706f2543Smrgstatic KdScreenInfo *kdCurrentScreen;
908706f2543Smrg
909706f2543SmrgBool
910706f2543SmrgKdScreenInit(int index, ScreenPtr pScreen, int argc, char **argv)
911706f2543Smrg{
912706f2543Smrg    KdScreenInfo	*screen = kdCurrentScreen;
913706f2543Smrg    KdCardInfo		*card = screen->card;
914706f2543Smrg    KdPrivScreenPtr	pScreenPriv;
915706f2543Smrg    /*
916706f2543Smrg     * note that screen->fb is set up for the nominal orientation
917706f2543Smrg     * of the screen; that means if randr is rotated, the values
918706f2543Smrg     * there should reflect a rotated frame buffer (or shadow).
919706f2543Smrg     */
920706f2543Smrg    Bool		rotated = (screen->randr & (RR_Rotate_90|RR_Rotate_270)) != 0;
921706f2543Smrg    int			width, height, *width_mmp, *height_mmp;
922706f2543Smrg
923706f2543Smrg    KdAllocatePrivates (pScreen);
924706f2543Smrg
925706f2543Smrg    pScreenPriv = KdGetScreenPriv(pScreen);
926706f2543Smrg
927706f2543Smrg    if (!rotated)
928706f2543Smrg    {
929706f2543Smrg	width = screen->width;
930706f2543Smrg	height = screen->height;
931706f2543Smrg	width_mmp = &screen->width_mm;
932706f2543Smrg	height_mmp = &screen->height_mm;
933706f2543Smrg    }
934706f2543Smrg    else
935706f2543Smrg    {
936706f2543Smrg	width = screen->height;
937706f2543Smrg	height = screen->width;
938706f2543Smrg	width_mmp = &screen->height_mm;
939706f2543Smrg	height_mmp = &screen->width_mm;
940706f2543Smrg    }
941706f2543Smrg    screen->pScreen = pScreen;
942706f2543Smrg    pScreenPriv->screen = screen;
943706f2543Smrg    pScreenPriv->card = card;
944706f2543Smrg    pScreenPriv->bytesPerPixel = screen->fb.bitsPerPixel >> 3;
945706f2543Smrg    pScreenPriv->dpmsState = KD_DPMS_NORMAL;
946706f2543Smrg    pScreen->x = screen->origin.x;
947706f2543Smrg    pScreen->y = screen->origin.y;
948706f2543Smrg
949706f2543Smrg    if (!monitorResolution)
950706f2543Smrg	monitorResolution = 75;
951706f2543Smrg    /*
952706f2543Smrg     * This is done in this order so that backing store wraps
953706f2543Smrg     * our GC functions; fbFinishScreenInit initializes MI
954706f2543Smrg     * backing store
955706f2543Smrg     */
956706f2543Smrg    if (!fbSetupScreen (pScreen,
957706f2543Smrg			screen->fb.frameBuffer,
958706f2543Smrg			width, height,
959706f2543Smrg			monitorResolution, monitorResolution,
960706f2543Smrg			screen->fb.pixelStride,
961706f2543Smrg			screen->fb.bitsPerPixel))
962706f2543Smrg    {
963706f2543Smrg	return FALSE;
964706f2543Smrg    }
965706f2543Smrg
966706f2543Smrg    /*
967706f2543Smrg     * Set colormap functions
968706f2543Smrg     */
969706f2543Smrg    pScreen->InstallColormap	= KdInstallColormap;
970706f2543Smrg    pScreen->UninstallColormap	= KdUninstallColormap;
971706f2543Smrg    pScreen->ListInstalledColormaps = KdListInstalledColormaps;
972706f2543Smrg    pScreen->StoreColors	= KdStoreColors;
973706f2543Smrg
974706f2543Smrg    pScreen->SaveScreen		= KdSaveScreen;
975706f2543Smrg    pScreen->CreateWindow	= KdCreateWindow;
976706f2543Smrg
977706f2543Smrg    if (!fbFinishScreenInit (pScreen,
978706f2543Smrg			     screen->fb.frameBuffer,
979706f2543Smrg			     width, height,
980706f2543Smrg			     monitorResolution, monitorResolution,
981706f2543Smrg			     screen->fb.pixelStride,
982706f2543Smrg			     screen->fb.bitsPerPixel))
983706f2543Smrg    {
984706f2543Smrg	return FALSE;
985706f2543Smrg    }
986706f2543Smrg
987706f2543Smrg    /*
988706f2543Smrg     * Fix screen sizes; for some reason mi takes dpi instead of mm.
989706f2543Smrg     * Rounding errors are annoying
990706f2543Smrg     */
991706f2543Smrg    if (*width_mmp)
992706f2543Smrg	pScreen->mmWidth = *width_mmp;
993706f2543Smrg    else
994706f2543Smrg	*width_mmp = pScreen->mmWidth;
995706f2543Smrg    if (*height_mmp)
996706f2543Smrg	pScreen->mmHeight = *height_mmp;
997706f2543Smrg    else
998706f2543Smrg	*height_mmp = pScreen->mmHeight;
999706f2543Smrg
1000706f2543Smrg    /*
1001706f2543Smrg     * Plug in our own block/wakeup handlers.
1002706f2543Smrg     * miScreenInit installs NoopDDA in both places
1003706f2543Smrg     */
1004706f2543Smrg    pScreen->BlockHandler	= KdBlockHandler;
1005706f2543Smrg    pScreen->WakeupHandler	= KdWakeupHandler;
1006706f2543Smrg
1007706f2543Smrg    if (!fbPictureInit (pScreen, 0, 0))
1008706f2543Smrg	return FALSE;
1009706f2543Smrg    if (card->cfuncs->initScreen)
1010706f2543Smrg	if (!(*card->cfuncs->initScreen) (pScreen))
1011706f2543Smrg	    return FALSE;
1012706f2543Smrg
1013706f2543Smrg    if (!screen->dumb && card->cfuncs->initAccel)
1014706f2543Smrg	if (!(*card->cfuncs->initAccel) (pScreen))
1015706f2543Smrg	    screen->dumb = TRUE;
1016706f2543Smrg
1017706f2543Smrg    if (card->cfuncs->finishInitScreen)
1018706f2543Smrg	if (!(*card->cfuncs->finishInitScreen) (pScreen))
1019706f2543Smrg	    return FALSE;
1020706f2543Smrg
1021706f2543Smrg#if 0
1022706f2543Smrg    fbInitValidateTree (pScreen);
1023706f2543Smrg#endif
1024706f2543Smrg
1025706f2543Smrg    /*
1026706f2543Smrg     * Wrap CloseScreen, the order now is:
1027706f2543Smrg     *	KdCloseScreen
1028706f2543Smrg     *	miBSCloseScreen
1029706f2543Smrg     *	fbCloseScreen
1030706f2543Smrg     */
1031706f2543Smrg    pScreenPriv->CloseScreen = pScreen->CloseScreen;
1032706f2543Smrg    pScreen->CloseScreen = KdCloseScreen;
1033706f2543Smrg
1034706f2543Smrg    pScreenPriv->CreateScreenResources = pScreen->CreateScreenResources;
1035706f2543Smrg    pScreen->CreateScreenResources = KdCreateScreenResources;
1036706f2543Smrg
1037706f2543Smrg    if (screen->softCursor ||
1038706f2543Smrg	!card->cfuncs->initCursor ||
1039706f2543Smrg	!(*card->cfuncs->initCursor) (pScreen))
1040706f2543Smrg    {
1041706f2543Smrg	/* Use MI for cursor display and event queueing. */
1042706f2543Smrg	screen->softCursor = TRUE;
1043706f2543Smrg	miDCInitialize(pScreen, &kdPointerScreenFuncs);
1044706f2543Smrg    }
1045706f2543Smrg
1046706f2543Smrg
1047706f2543Smrg    if (!fbCreateDefColormap (pScreen))
1048706f2543Smrg    {
1049706f2543Smrg	return FALSE;
1050706f2543Smrg    }
1051706f2543Smrg
1052706f2543Smrg    KdSetSubpixelOrder (pScreen, screen->randr);
1053706f2543Smrg
1054706f2543Smrg    /*
1055706f2543Smrg     * Enable the hardware
1056706f2543Smrg     */
1057706f2543Smrg    if (!kdEnabled)
1058706f2543Smrg    {
1059706f2543Smrg	kdEnabled = TRUE;
1060706f2543Smrg	if(kdOsFuncs->Enable)
1061706f2543Smrg	    (*kdOsFuncs->Enable) ();
1062706f2543Smrg    }
1063706f2543Smrg
1064706f2543Smrg    if (screen->mynum == card->selected)
1065706f2543Smrg    {
1066706f2543Smrg	if(card->cfuncs->preserve)
1067706f2543Smrg	    (*card->cfuncs->preserve) (card);
1068706f2543Smrg	if(card->cfuncs->enable)
1069706f2543Smrg	    if (!(*card->cfuncs->enable) (pScreen))
1070706f2543Smrg		return FALSE;
1071706f2543Smrg	pScreenPriv->enabled = TRUE;
1072706f2543Smrg	if (!screen->softCursor && card->cfuncs->enableCursor)
1073706f2543Smrg	    (*card->cfuncs->enableCursor) (pScreen);
1074706f2543Smrg	KdEnableColormap (pScreen);
1075706f2543Smrg	if (!screen->dumb && card->cfuncs->enableAccel)
1076706f2543Smrg	    (*card->cfuncs->enableAccel) (pScreen);
1077706f2543Smrg    }
1078706f2543Smrg
1079706f2543Smrg    return TRUE;
1080706f2543Smrg}
1081706f2543Smrg
1082706f2543Smrgvoid
1083706f2543SmrgKdInitScreen (ScreenInfo    *pScreenInfo,
1084706f2543Smrg	      KdScreenInfo  *screen,
1085706f2543Smrg	      int	    argc,
1086706f2543Smrg	      char	    **argv)
1087706f2543Smrg{
1088706f2543Smrg    KdCardInfo	*card = screen->card;
1089706f2543Smrg
1090706f2543Smrg    (*card->cfuncs->scrinit) (screen);
1091706f2543Smrg
1092706f2543Smrg    if (!card->cfuncs->initAccel)
1093706f2543Smrg	screen->dumb = TRUE;
1094706f2543Smrg    if (!card->cfuncs->initCursor)
1095706f2543Smrg	screen->softCursor = TRUE;
1096706f2543Smrg}
1097706f2543Smrg
1098706f2543Smrgstatic Bool
1099706f2543SmrgKdSetPixmapFormats (ScreenInfo	*pScreenInfo)
1100706f2543Smrg{
1101706f2543Smrg    CARD8	    depthToBpp[33];	/* depth -> bpp map */
1102706f2543Smrg    KdCardInfo	    *card;
1103706f2543Smrg    KdScreenInfo    *screen;
1104706f2543Smrg    int		    i;
1105706f2543Smrg    int		    bpp;
1106706f2543Smrg    PixmapFormatRec *format;
1107706f2543Smrg
1108706f2543Smrg    for (i = 1; i <= 32; i++)
1109706f2543Smrg	depthToBpp[i] = 0;
1110706f2543Smrg
1111706f2543Smrg    /*
1112706f2543Smrg     * Generate mappings between bitsPerPixel and depth,
1113706f2543Smrg     * also ensure that all screens comply with protocol
1114706f2543Smrg     * restrictions on equivalent formats for the same
1115706f2543Smrg     * depth on different screens
1116706f2543Smrg     */
1117706f2543Smrg    for (card = kdCardInfo; card; card = card->next)
1118706f2543Smrg    {
1119706f2543Smrg	for (screen = card->screenList; screen; screen = screen->next)
1120706f2543Smrg	{
1121706f2543Smrg	    bpp = screen->fb.bitsPerPixel;
1122706f2543Smrg	    if (bpp == 24)
1123706f2543Smrg		bpp = 32;
1124706f2543Smrg	    if (!depthToBpp[screen->fb.depth])
1125706f2543Smrg		depthToBpp[screen->fb.depth] = bpp;
1126706f2543Smrg	    else if (depthToBpp[screen->fb.depth] != bpp)
1127706f2543Smrg		return FALSE;
1128706f2543Smrg	}
1129706f2543Smrg    }
1130706f2543Smrg
1131706f2543Smrg    /*
1132706f2543Smrg     * Fill in additional formats
1133706f2543Smrg     */
1134706f2543Smrg    for (i = 0; i < NUM_KD_DEPTHS; i++)
1135706f2543Smrg	if (!depthToBpp[kdDepths[i].depth])
1136706f2543Smrg	    depthToBpp[kdDepths[i].depth] = kdDepths[i].bpp;
1137706f2543Smrg
1138706f2543Smrg    pScreenInfo->imageByteOrder     = IMAGE_BYTE_ORDER;
1139706f2543Smrg    pScreenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
1140706f2543Smrg    pScreenInfo->bitmapScanlinePad  = BITMAP_SCANLINE_PAD;
1141706f2543Smrg    pScreenInfo->bitmapBitOrder     = BITMAP_BIT_ORDER;
1142706f2543Smrg
1143706f2543Smrg    pScreenInfo->numPixmapFormats = 0;
1144706f2543Smrg
1145706f2543Smrg    for (i = 1; i <= 32; i++)
1146706f2543Smrg    {
1147706f2543Smrg	if (depthToBpp[i])
1148706f2543Smrg	{
1149706f2543Smrg	    format = &pScreenInfo->formats[pScreenInfo->numPixmapFormats++];
1150706f2543Smrg	    format->depth = i;
1151706f2543Smrg	    format->bitsPerPixel = depthToBpp[i];
1152706f2543Smrg	    format->scanlinePad = BITMAP_SCANLINE_PAD;
1153706f2543Smrg	}
1154706f2543Smrg    }
1155706f2543Smrg
1156706f2543Smrg    return TRUE;
1157706f2543Smrg}
1158706f2543Smrg
1159706f2543Smrgstatic void
1160706f2543SmrgKdAddScreen (ScreenInfo	    *pScreenInfo,
1161706f2543Smrg	     KdScreenInfo   *screen,
1162706f2543Smrg	     int	    argc,
1163706f2543Smrg	     char	    **argv)
1164706f2543Smrg{
1165706f2543Smrg    int	    i;
1166706f2543Smrg    /*
1167706f2543Smrg     * Fill in fb visual type masks for this screen
1168706f2543Smrg     */
1169706f2543Smrg    for (i = 0; i < pScreenInfo->numPixmapFormats; i++)
1170706f2543Smrg    {
1171706f2543Smrg	unsigned long	visuals;
1172706f2543Smrg	Pixel		rm, gm, bm;
1173706f2543Smrg
1174706f2543Smrg	visuals = 0;
1175706f2543Smrg	rm = gm = bm = 0;
1176706f2543Smrg	if (pScreenInfo->formats[i].depth == screen->fb.depth)
1177706f2543Smrg	{
1178706f2543Smrg	    visuals = screen->fb.visuals;
1179706f2543Smrg	    rm = screen->fb.redMask;
1180706f2543Smrg	    gm = screen->fb.greenMask;
1181706f2543Smrg	    bm = screen->fb.blueMask;
1182706f2543Smrg	}
1183706f2543Smrg	fbSetVisualTypesAndMasks (pScreenInfo->formats[i].depth,
1184706f2543Smrg				  visuals,
1185706f2543Smrg				  8,
1186706f2543Smrg				  rm, gm, bm);
1187706f2543Smrg    }
1188706f2543Smrg
1189706f2543Smrg    kdCurrentScreen = screen;
1190706f2543Smrg
1191706f2543Smrg    AddScreen (KdScreenInit, argc, argv);
1192706f2543Smrg}
1193706f2543Smrg
1194706f2543Smrg#if 0 /* This function is not used currently */
1195706f2543Smrg
1196706f2543Smrgint
1197706f2543SmrgKdDepthToFb (ScreenPtr	pScreen, int depth)
1198706f2543Smrg{
1199706f2543Smrg    KdScreenPriv(pScreen);
1200706f2543Smrg
1201706f2543Smrg    for (fb = 0; fb <= KD_MAX_FB && pScreenPriv->screen->fb.frameBuffer; fb++)
1202706f2543Smrg	if (pScreenPriv->screen->fb.depth == depth)
1203706f2543Smrg	    return fb;
1204706f2543Smrg}
1205706f2543Smrg
1206706f2543Smrg#endif
1207706f2543Smrg
1208706f2543Smrgstatic int
1209706f2543SmrgKdSignalWrapper (int signum)
1210706f2543Smrg{
1211706f2543Smrg    kdCaughtSignal = TRUE;
1212706f2543Smrg    return 1; /* use generic OS layer cleanup & abort */
1213706f2543Smrg}
1214706f2543Smrg
1215706f2543Smrgvoid
1216706f2543SmrgKdInitOutput (ScreenInfo    *pScreenInfo,
1217706f2543Smrg	      int	    argc,
1218706f2543Smrg	      char	    **argv)
1219706f2543Smrg{
1220706f2543Smrg    KdCardInfo	    *card;
1221706f2543Smrg    KdScreenInfo    *screen;
1222706f2543Smrg
1223706f2543Smrg    if (!kdCardInfo)
1224706f2543Smrg    {
1225706f2543Smrg	InitCard (0);
1226706f2543Smrg	if (!(card = KdCardInfoLast ()))
1227706f2543Smrg	    FatalError("No matching cards found!\n");
1228706f2543Smrg	screen = KdScreenInfoAdd (card);
1229706f2543Smrg	KdParseScreen (screen, 0);
1230706f2543Smrg    }
1231706f2543Smrg    /*
1232706f2543Smrg     * Initialize all of the screens for all of the cards
1233706f2543Smrg     */
1234706f2543Smrg    for (card = kdCardInfo; card; card = card->next)
1235706f2543Smrg    {
1236706f2543Smrg	int ret=1;
1237706f2543Smrg	if(card->cfuncs->cardinit)
1238706f2543Smrg		ret=(*card->cfuncs->cardinit) (card);
1239706f2543Smrg	if (ret)
1240706f2543Smrg	{
1241706f2543Smrg	    for (screen = card->screenList; screen; screen = screen->next)
1242706f2543Smrg		KdInitScreen (pScreenInfo, screen, argc, argv);
1243706f2543Smrg	}
1244706f2543Smrg    }
1245706f2543Smrg
1246706f2543Smrg    /*
1247706f2543Smrg     * Merge the various pixmap formats together, this can fail
1248706f2543Smrg     * when two screens share depth but not bitsPerPixel
1249706f2543Smrg     */
1250706f2543Smrg    if (!KdSetPixmapFormats (pScreenInfo))
1251706f2543Smrg	return;
1252706f2543Smrg
1253706f2543Smrg    /*
1254706f2543Smrg     * Add all of the screens
1255706f2543Smrg     */
1256706f2543Smrg    for (card = kdCardInfo; card; card = card->next)
1257706f2543Smrg	for (screen = card->screenList; screen; screen = screen->next)
1258706f2543Smrg	    KdAddScreen (pScreenInfo, screen, argc, argv);
1259706f2543Smrg
1260706f2543Smrg    OsRegisterSigWrapper(KdSignalWrapper);
1261706f2543Smrg}
1262706f2543Smrg
1263706f2543Smrgvoid
1264706f2543SmrgOsVendorFatalError(void)
1265706f2543Smrg{
1266706f2543Smrg}
1267706f2543Smrg
1268706f2543Smrgint
1269706f2543SmrgDPMSSet(ClientPtr client, int level)
1270706f2543Smrg{
1271706f2543Smrg    return Success;
1272706f2543Smrg}
1273706f2543Smrg
1274706f2543SmrgBool
1275706f2543SmrgDPMSSupported (void)
1276706f2543Smrg{
1277706f2543Smrg    return FALSE;
1278706f2543Smrg}
1279