Commit | Line | Data |
---|---|---|
a09e091a JB |
1 | /* |
2 | * Copyright © 1999 Keith Packard | |
3 | * | |
4 | * Permission to use, copy, modify, distribute, and sell this software and its | |
5 | * documentation for any purpose is hereby granted without fee, provided that | |
6 | * the above copyright notice appear in all copies and that both that | |
7 | * copyright notice and this permission notice appear in supporting | |
8 | * documentation, and that the name of Keith Packard not be used in | |
9 | * advertising or publicity pertaining to distribution of the software without | |
10 | * specific, written prior permission. Keith Packard makes no | |
11 | * representations about the suitability of this software for any purpose. It | |
12 | * is provided "as is" without express or implied warranty. | |
13 | * | |
14 | * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | |
15 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO | |
16 | * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR | |
17 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, | |
18 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | |
19 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | |
20 | * PERFORMANCE OF THIS SOFTWARE. | |
21 | */ | |
22 | ||
23 | #ifdef HAVE_CONFIG_H | |
24 | #include <kdrive-config.h> | |
25 | #endif | |
26 | #include "kdrive.h" | |
27 | #include <mivalidate.h> | |
28 | #include <dixstruct.h> | |
29 | #include "privates.h" | |
30 | #ifdef RANDR | |
31 | #include <randrstr.h> | |
32 | #endif | |
33 | ||
34 | #ifdef XV | |
35 | #include "kxv.h" | |
36 | #endif | |
37 | ||
38 | #ifdef DPMSExtension | |
39 | #include "dpmsproc.h" | |
40 | #endif | |
41 | ||
42 | #ifdef HAVE_EXECINFO_H | |
43 | #include <execinfo.h> | |
44 | #endif | |
45 | ||
46 | #include <signal.h> | |
47 | ||
48 | typedef struct _kdDepths { | |
49 | CARD8 depth; | |
50 | CARD8 bpp; | |
51 | } KdDepths; | |
52 | ||
53 | KdDepths kdDepths[] = { | |
54 | {1, 1}, | |
55 | {4, 4}, | |
56 | {8, 8}, | |
57 | {15, 16}, | |
58 | {16, 16}, | |
59 | {24, 32}, | |
60 | {32, 32} | |
61 | }; | |
62 | ||
63 | #define NUM_KD_DEPTHS (sizeof (kdDepths) / sizeof (kdDepths[0])) | |
64 | ||
65 | #define KD_DEFAULT_BUTTONS 5 | |
66 | ||
67 | DevPrivateKeyRec kdScreenPrivateKeyRec; | |
68 | unsigned long kdGeneration; | |
69 | ||
70 | Bool kdVideoTest; | |
71 | unsigned long kdVideoTestTime; | |
72 | Bool kdEmulateMiddleButton; | |
73 | Bool kdRawPointerCoordinates; | |
74 | Bool kdDisableZaphod; | |
75 | Bool kdAllowZap; | |
76 | Bool kdEnabled; | |
77 | int kdSubpixelOrder; | |
78 | int kdVirtualTerminal = -1; | |
79 | Bool kdSwitchPending; | |
80 | char *kdSwitchCmd; | |
81 | DDXPointRec kdOrigin; | |
82 | Bool kdHasPointer = FALSE; | |
83 | Bool kdHasKbd = FALSE; | |
84 | ||
85 | static Bool kdCaughtSignal = FALSE; | |
86 | ||
87 | /* | |
88 | * Carry arguments from InitOutput through driver initialization | |
89 | * to KdScreenInit | |
90 | */ | |
91 | ||
92 | KdOsFuncs *kdOsFuncs; | |
93 | ||
94 | void | |
95 | KdDisableScreen(ScreenPtr pScreen) | |
96 | { | |
97 | KdScreenPriv(pScreen); | |
98 | ||
99 | if (!pScreenPriv->enabled) | |
100 | return; | |
101 | if (!pScreenPriv->closed) | |
102 | SetRootClip(pScreen, FALSE); | |
103 | KdDisableColormap(pScreen); | |
104 | if (!pScreenPriv->screen->dumb && pScreenPriv->card->cfuncs->disableAccel) | |
105 | (*pScreenPriv->card->cfuncs->disableAccel) (pScreen); | |
106 | if (!pScreenPriv->screen->softCursor && | |
107 | pScreenPriv->card->cfuncs->disableCursor) | |
108 | (*pScreenPriv->card->cfuncs->disableCursor) (pScreen); | |
109 | if (pScreenPriv->card->cfuncs->dpms) | |
110 | (*pScreenPriv->card->cfuncs->dpms) (pScreen, KD_DPMS_NORMAL); | |
111 | pScreenPriv->enabled = FALSE; | |
112 | if (pScreenPriv->card->cfuncs->disable) | |
113 | (*pScreenPriv->card->cfuncs->disable) (pScreen); | |
114 | } | |
115 | ||
116 | static void | |
117 | KdDoSwitchCmd(const char *reason) | |
118 | { | |
119 | if (kdSwitchCmd) { | |
120 | char *command; | |
121 | ||
122 | if (asprintf(&command, "%s %s", kdSwitchCmd, reason) == -1) | |
123 | return; | |
124 | system(command); | |
125 | free(command); | |
126 | } | |
127 | } | |
128 | ||
129 | void | |
130 | KdSuspend(void) | |
131 | { | |
132 | KdCardInfo *card; | |
133 | KdScreenInfo *screen; | |
134 | ||
135 | if (kdEnabled) { | |
136 | for (card = kdCardInfo; card; card = card->next) { | |
137 | for (screen = card->screenList; screen; screen = screen->next) | |
138 | if (screen->mynum == card->selected && screen->pScreen) | |
139 | KdDisableScreen(screen->pScreen); | |
140 | if (card->driver && card->cfuncs->restore) | |
141 | (*card->cfuncs->restore) (card); | |
142 | } | |
143 | KdDisableInput(); | |
144 | KdDoSwitchCmd("suspend"); | |
145 | } | |
146 | } | |
147 | ||
148 | void | |
149 | KdDisableScreens(void) | |
150 | { | |
151 | KdSuspend(); | |
152 | if (kdEnabled) { | |
153 | if (kdOsFuncs->Disable) | |
154 | (*kdOsFuncs->Disable) (); | |
155 | kdEnabled = FALSE; | |
156 | } | |
157 | } | |
158 | ||
159 | Bool | |
160 | KdEnableScreen(ScreenPtr pScreen) | |
161 | { | |
162 | KdScreenPriv(pScreen); | |
163 | ||
164 | if (pScreenPriv->enabled) | |
165 | return TRUE; | |
166 | if (pScreenPriv->card->cfuncs->enable) | |
167 | if (!(*pScreenPriv->card->cfuncs->enable) (pScreen)) | |
168 | return FALSE; | |
169 | pScreenPriv->enabled = TRUE; | |
170 | pScreenPriv->dpmsState = KD_DPMS_NORMAL; | |
171 | pScreenPriv->card->selected = pScreenPriv->screen->mynum; | |
172 | if (!pScreenPriv->screen->softCursor && | |
173 | pScreenPriv->card->cfuncs->enableCursor) | |
174 | (*pScreenPriv->card->cfuncs->enableCursor) (pScreen); | |
175 | if (!pScreenPriv->screen->dumb && pScreenPriv->card->cfuncs->enableAccel) | |
176 | (*pScreenPriv->card->cfuncs->enableAccel) (pScreen); | |
177 | KdEnableColormap(pScreen); | |
178 | SetRootClip(pScreen, TRUE); | |
179 | if (pScreenPriv->card->cfuncs->dpms) | |
180 | (*pScreenPriv->card->cfuncs->dpms) (pScreen, pScreenPriv->dpmsState); | |
181 | return TRUE; | |
182 | } | |
183 | ||
184 | void | |
185 | KdResume(void) | |
186 | { | |
187 | KdCardInfo *card; | |
188 | KdScreenInfo *screen; | |
189 | ||
190 | if (kdEnabled) { | |
191 | KdDoSwitchCmd("resume"); | |
192 | for (card = kdCardInfo; card; card = card->next) { | |
193 | if (card->cfuncs->preserve) | |
194 | (*card->cfuncs->preserve) (card); | |
195 | for (screen = card->screenList; screen; screen = screen->next) | |
196 | if (screen->mynum == card->selected && screen->pScreen) | |
197 | KdEnableScreen(screen->pScreen); | |
198 | } | |
199 | KdEnableInput(); | |
200 | KdReleaseAllKeys(); | |
201 | } | |
202 | } | |
203 | ||
204 | void | |
205 | KdEnableScreens(void) | |
206 | { | |
207 | if (!kdEnabled) { | |
208 | kdEnabled = TRUE; | |
209 | if (kdOsFuncs->Enable) | |
210 | (*kdOsFuncs->Enable) (); | |
211 | } | |
212 | KdResume(); | |
213 | } | |
214 | ||
215 | void | |
216 | KdProcessSwitch(void) | |
217 | { | |
218 | if (kdEnabled) | |
219 | KdDisableScreens(); | |
220 | else | |
221 | KdEnableScreens(); | |
222 | } | |
223 | ||
224 | void | |
225 | AbortDDX(enum ExitCode error) | |
226 | { | |
227 | KdDisableScreens(); | |
228 | if (kdOsFuncs) { | |
229 | if (kdEnabled && kdOsFuncs->Disable) | |
230 | (*kdOsFuncs->Disable) (); | |
231 | if (kdOsFuncs->Fini) | |
232 | (*kdOsFuncs->Fini) (); | |
233 | KdDoSwitchCmd("stop"); | |
234 | } | |
235 | ||
236 | if (kdCaughtSignal) | |
237 | OsAbort(); | |
238 | } | |
239 | ||
240 | void | |
241 | ddxGiveUp(enum ExitCode error) | |
242 | { | |
243 | AbortDDX(error); | |
244 | } | |
245 | ||
246 | Bool kdDumbDriver; | |
247 | Bool kdSoftCursor; | |
248 | ||
249 | const char * | |
250 | KdParseFindNext(const char *cur, const char *delim, char *save, char *last) | |
251 | { | |
252 | while (*cur && !strchr(delim, *cur)) { | |
253 | *save++ = *cur++; | |
254 | } | |
255 | *save = 0; | |
256 | *last = *cur; | |
257 | if (*cur) | |
258 | cur++; | |
259 | return cur; | |
260 | } | |
261 | ||
262 | Rotation | |
263 | KdAddRotation(Rotation a, Rotation b) | |
264 | { | |
265 | Rotation rotate = (a & RR_Rotate_All) * (b & RR_Rotate_All); | |
266 | Rotation reflect = (a & RR_Reflect_All) ^ (b & RR_Reflect_All); | |
267 | ||
268 | if (rotate > RR_Rotate_270) | |
269 | rotate /= (RR_Rotate_270 * RR_Rotate_90); | |
270 | return reflect | rotate; | |
271 | } | |
272 | ||
273 | Rotation | |
274 | KdSubRotation(Rotation a, Rotation b) | |
275 | { | |
276 | Rotation rotate = (a & RR_Rotate_All) * 16 / (b & RR_Rotate_All); | |
277 | Rotation reflect = (a & RR_Reflect_All) ^ (b & RR_Reflect_All); | |
278 | ||
279 | if (rotate > RR_Rotate_270) | |
280 | rotate /= (RR_Rotate_270 * RR_Rotate_90); | |
281 | return reflect | rotate; | |
282 | } | |
283 | ||
284 | void | |
285 | KdParseScreen(KdScreenInfo * screen, const char *arg) | |
286 | { | |
287 | char delim; | |
288 | char save[1024]; | |
289 | int i; | |
290 | int pixels, mm; | |
291 | ||
292 | screen->dumb = kdDumbDriver; | |
293 | screen->softCursor = kdSoftCursor; | |
294 | screen->origin = kdOrigin; | |
295 | screen->randr = RR_Rotate_0; | |
296 | screen->width = 0; | |
297 | screen->height = 0; | |
298 | screen->width_mm = 0; | |
299 | screen->height_mm = 0; | |
300 | screen->subpixel_order = kdSubpixelOrder; | |
301 | screen->rate = 0; | |
302 | screen->fb.depth = 0; | |
303 | if (!arg) | |
304 | return; | |
305 | if (strlen(arg) >= sizeof(save)) | |
306 | return; | |
307 | ||
308 | for (i = 0; i < 2; i++) { | |
309 | arg = KdParseFindNext(arg, "x/@XY", save, &delim); | |
310 | if (!save[0]) | |
311 | return; | |
312 | ||
313 | pixels = atoi(save); | |
314 | mm = 0; | |
315 | ||
316 | if (delim == '/') { | |
317 | arg = KdParseFindNext(arg, "x@XY", save, &delim); | |
318 | if (!save[0]) | |
319 | return; | |
320 | mm = atoi(save); | |
321 | } | |
322 | ||
323 | if (i == 0) { | |
324 | screen->width = pixels; | |
325 | screen->width_mm = mm; | |
326 | } | |
327 | else { | |
328 | screen->height = pixels; | |
329 | screen->height_mm = mm; | |
330 | } | |
331 | if (delim != 'x' && delim != '@' && delim != 'X' && delim != 'Y' && | |
332 | (delim != '\0' || i == 0)) | |
333 | return; | |
334 | } | |
335 | ||
336 | kdOrigin.x += screen->width; | |
337 | kdOrigin.y = 0; | |
338 | kdDumbDriver = FALSE; | |
339 | kdSoftCursor = FALSE; | |
340 | kdSubpixelOrder = SubPixelUnknown; | |
341 | ||
342 | if (delim == '@') { | |
343 | arg = KdParseFindNext(arg, "xXY", save, &delim); | |
344 | if (save[0]) { | |
345 | int rotate = atoi(save); | |
346 | ||
347 | if (rotate < 45) | |
348 | screen->randr = RR_Rotate_0; | |
349 | else if (rotate < 135) | |
350 | screen->randr = RR_Rotate_90; | |
351 | else if (rotate < 225) | |
352 | screen->randr = RR_Rotate_180; | |
353 | else if (rotate < 315) | |
354 | screen->randr = RR_Rotate_270; | |
355 | else | |
356 | screen->randr = RR_Rotate_0; | |
357 | } | |
358 | } | |
359 | if (delim == 'X') { | |
360 | arg = KdParseFindNext(arg, "xY", save, &delim); | |
361 | screen->randr |= RR_Reflect_X; | |
362 | } | |
363 | ||
364 | if (delim == 'Y') { | |
365 | arg = KdParseFindNext(arg, "xY", save, &delim); | |
366 | screen->randr |= RR_Reflect_Y; | |
367 | } | |
368 | ||
369 | arg = KdParseFindNext(arg, "x/,", save, &delim); | |
370 | if (save[0]) { | |
371 | screen->fb.depth = atoi(save); | |
372 | if (delim == '/') { | |
373 | arg = KdParseFindNext(arg, "x,", save, &delim); | |
374 | if (save[0]) | |
375 | screen->fb.bitsPerPixel = atoi(save); | |
376 | } | |
377 | else | |
378 | screen->fb.bitsPerPixel = 0; | |
379 | } | |
380 | ||
381 | if (delim == 'x') { | |
382 | arg = KdParseFindNext(arg, "x", save, &delim); | |
383 | if (save[0]) | |
384 | screen->rate = atoi(save); | |
385 | } | |
386 | } | |
387 | ||
388 | /* | |
389 | * Mouse argument syntax: | |
390 | * | |
391 | * device,protocol,options... | |
392 | * | |
393 | * Options are any of: | |
394 | * 1-5 n button mouse | |
395 | * 2button emulate middle button | |
396 | * {NMO} Reorder buttons | |
397 | */ | |
398 | ||
399 | void | |
400 | KdParseRgba(char *rgba) | |
401 | { | |
402 | if (!strcmp(rgba, "rgb")) | |
403 | kdSubpixelOrder = SubPixelHorizontalRGB; | |
404 | else if (!strcmp(rgba, "bgr")) | |
405 | kdSubpixelOrder = SubPixelHorizontalBGR; | |
406 | else if (!strcmp(rgba, "vrgb")) | |
407 | kdSubpixelOrder = SubPixelVerticalRGB; | |
408 | else if (!strcmp(rgba, "vbgr")) | |
409 | kdSubpixelOrder = SubPixelVerticalBGR; | |
410 | else if (!strcmp(rgba, "none")) | |
411 | kdSubpixelOrder = SubPixelNone; | |
412 | else | |
413 | kdSubpixelOrder = SubPixelUnknown; | |
414 | } | |
415 | ||
416 | void | |
417 | KdUseMsg(void) | |
418 | { | |
419 | ErrorF("\nTinyX Device Dependent Usage:\n"); | |
420 | ErrorF | |
421 | ("-screen WIDTH[/WIDTHMM]xHEIGHT[/HEIGHTMM][@ROTATION][X][Y][xDEPTH/BPP[xFREQ]] Specify screen characteristics\n"); | |
422 | ErrorF | |
423 | ("-rgba rgb/bgr/vrgb/vbgr/none Specify subpixel ordering for LCD panels\n"); | |
424 | ErrorF | |
425 | ("-mouse driver [,n,,options] Specify the pointer driver and its options (n is the number of buttons)\n"); | |
426 | ErrorF | |
427 | ("-keybd driver [,,options] Specify the keyboard driver and its options\n"); | |
428 | ErrorF("-zaphod Disable cursor screen switching\n"); | |
429 | ErrorF("-2button Emulate 3 button mouse\n"); | |
430 | ErrorF("-3button Disable 3 button mouse emulation\n"); | |
431 | ErrorF | |
432 | ("-rawcoord Don't transform pointer coordinates on rotation\n"); | |
433 | ErrorF("-dumb Disable hardware acceleration\n"); | |
434 | ErrorF("-softCursor Force software cursor\n"); | |
435 | ErrorF("-videoTest Start the server, pause momentarily and exit\n"); | |
436 | ErrorF | |
437 | ("-origin X,Y Locates the next screen in the the virtual screen (Xinerama)\n"); | |
438 | ErrorF("-switchCmd Command to execute on vt switch\n"); | |
439 | ErrorF("-zap Terminate server on Ctrl+Alt+Backspace\n"); | |
440 | ErrorF | |
441 | ("vtxx Use virtual terminal xx instead of the next available\n"); | |
442 | } | |
443 | ||
444 | int | |
445 | KdProcessArgument(int argc, char **argv, int i) | |
446 | { | |
447 | KdCardInfo *card; | |
448 | KdScreenInfo *screen; | |
449 | ||
450 | if (!strcmp(argv[i], "-screen")) { | |
451 | if ((i + 1) < argc) { | |
452 | card = KdCardInfoLast(); | |
453 | if (!card) { | |
454 | InitCard(0); | |
455 | card = KdCardInfoLast(); | |
456 | } | |
457 | if (card) { | |
458 | screen = KdScreenInfoAdd(card); | |
459 | KdParseScreen(screen, argv[i + 1]); | |
460 | } | |
461 | else | |
462 | ErrorF("No matching card found!\n"); | |
463 | } | |
464 | else | |
465 | UseMsg(); | |
466 | return 2; | |
467 | } | |
468 | if (!strcmp(argv[i], "-zaphod")) { | |
469 | kdDisableZaphod = TRUE; | |
470 | return 1; | |
471 | } | |
472 | if (!strcmp(argv[i], "-zap")) { | |
473 | kdAllowZap = TRUE; | |
474 | return 1; | |
475 | } | |
476 | if (!strcmp(argv[i], "-3button")) { | |
477 | kdEmulateMiddleButton = FALSE; | |
478 | return 1; | |
479 | } | |
480 | if (!strcmp(argv[i], "-2button")) { | |
481 | kdEmulateMiddleButton = TRUE; | |
482 | return 1; | |
483 | } | |
484 | if (!strcmp(argv[i], "-rawcoord")) { | |
485 | kdRawPointerCoordinates = 1; | |
486 | return 1; | |
487 | } | |
488 | if (!strcmp(argv[i], "-dumb")) { | |
489 | kdDumbDriver = TRUE; | |
490 | return 1; | |
491 | } | |
492 | if (!strcmp(argv[i], "-softCursor")) { | |
493 | kdSoftCursor = TRUE; | |
494 | return 1; | |
495 | } | |
496 | if (!strcmp(argv[i], "-videoTest")) { | |
497 | kdVideoTest = TRUE; | |
498 | return 1; | |
499 | } | |
500 | if (!strcmp(argv[i], "-origin")) { | |
501 | if ((i + 1) < argc) { | |
502 | char *x = argv[i + 1]; | |
503 | char *y = strchr(x, ','); | |
504 | ||
505 | if (x) | |
506 | kdOrigin.x = atoi(x); | |
507 | else | |
508 | kdOrigin.x = 0; | |
509 | if (y) | |
510 | kdOrigin.y = atoi(y + 1); | |
511 | else | |
512 | kdOrigin.y = 0; | |
513 | } | |
514 | else | |
515 | UseMsg(); | |
516 | return 2; | |
517 | } | |
518 | if (!strcmp(argv[i], "-rgba")) { | |
519 | if ((i + 1) < argc) | |
520 | KdParseRgba(argv[i + 1]); | |
521 | else | |
522 | UseMsg(); | |
523 | return 2; | |
524 | } | |
525 | if (!strcmp(argv[i], "-switchCmd")) { | |
526 | if ((i + 1) < argc) | |
527 | kdSwitchCmd = argv[i + 1]; | |
528 | else | |
529 | UseMsg(); | |
530 | return 2; | |
531 | } | |
532 | if (!strncmp(argv[i], "vt", 2) && | |
533 | sscanf(argv[i], "vt%2d", &kdVirtualTerminal) == 1) { | |
534 | return 1; | |
535 | } | |
536 | if (!strcmp(argv[i], "-mouse") || !strcmp(argv[i], "-pointer")) { | |
537 | if (i + 1 >= argc) | |
538 | UseMsg(); | |
539 | KdAddConfigPointer(argv[i + 1]); | |
540 | kdHasPointer = TRUE; | |
541 | return 2; | |
542 | } | |
543 | if (!strcmp(argv[i], "-keybd")) { | |
544 | if (i + 1 >= argc) | |
545 | UseMsg(); | |
546 | KdAddConfigKeyboard(argv[i + 1]); | |
547 | kdHasKbd = TRUE; | |
548 | return 2; | |
549 | } | |
550 | ||
551 | return 0; | |
552 | } | |
553 | ||
554 | /* | |
555 | * These are getting tossed in here until I can think of where | |
556 | * they really belong | |
557 | */ | |
558 | ||
559 | void | |
560 | KdOsInit(KdOsFuncs * pOsFuncs) | |
561 | { | |
562 | kdOsFuncs = pOsFuncs; | |
563 | if (pOsFuncs) { | |
564 | if (serverGeneration == 1) { | |
565 | KdDoSwitchCmd("start"); | |
566 | if (pOsFuncs->Init) | |
567 | (*pOsFuncs->Init) (); | |
568 | } | |
569 | } | |
570 | } | |
571 | ||
572 | Bool | |
573 | KdAllocatePrivates(ScreenPtr pScreen) | |
574 | { | |
575 | KdPrivScreenPtr pScreenPriv; | |
576 | ||
577 | if (kdGeneration != serverGeneration) | |
578 | kdGeneration = serverGeneration; | |
579 | ||
580 | if (!dixRegisterPrivateKey(&kdScreenPrivateKeyRec, PRIVATE_SCREEN, 0)) | |
581 | return FALSE; | |
582 | ||
583 | pScreenPriv = calloc(1, sizeof(*pScreenPriv)); | |
584 | if (!pScreenPriv) | |
585 | return FALSE; | |
586 | KdSetScreenPriv(pScreen, pScreenPriv); | |
587 | return TRUE; | |
588 | } | |
589 | ||
590 | Bool | |
591 | KdCreateScreenResources(ScreenPtr pScreen) | |
592 | { | |
593 | KdScreenPriv(pScreen); | |
594 | KdCardInfo *card = pScreenPriv->card; | |
595 | Bool ret; | |
596 | ||
597 | pScreen->CreateScreenResources = pScreenPriv->CreateScreenResources; | |
598 | if (pScreen->CreateScreenResources) | |
599 | ret = (*pScreen->CreateScreenResources) (pScreen); | |
600 | else | |
601 | ret = -1; | |
602 | pScreenPriv->CreateScreenResources = pScreen->CreateScreenResources; | |
603 | pScreen->CreateScreenResources = KdCreateScreenResources; | |
604 | if (ret && card->cfuncs->createRes) | |
605 | ret = (*card->cfuncs->createRes) (pScreen); | |
606 | return ret; | |
607 | } | |
608 | ||
609 | Bool | |
610 | KdCloseScreen(ScreenPtr pScreen) | |
611 | { | |
612 | KdScreenPriv(pScreen); | |
613 | KdScreenInfo *screen = pScreenPriv->screen; | |
614 | KdCardInfo *card = pScreenPriv->card; | |
615 | Bool ret; | |
616 | ||
617 | pScreenPriv->closed = TRUE; | |
618 | pScreen->CloseScreen = pScreenPriv->CloseScreen; | |
619 | if (pScreen->CloseScreen) | |
620 | ret = (*pScreen->CloseScreen) (pScreen); | |
621 | else | |
622 | ret = TRUE; | |
623 | ||
624 | if (pScreenPriv->dpmsState != KD_DPMS_NORMAL) | |
625 | (*card->cfuncs->dpms) (pScreen, KD_DPMS_NORMAL); | |
626 | ||
627 | if (screen->mynum == card->selected) | |
628 | KdDisableScreen(pScreen); | |
629 | ||
630 | /* | |
631 | * Restore video hardware when last screen is closed | |
632 | */ | |
633 | if (screen == card->screenList) { | |
634 | if (kdEnabled && card->cfuncs->restore) | |
635 | (*card->cfuncs->restore) (card); | |
636 | } | |
637 | ||
638 | if (!pScreenPriv->screen->dumb && card->cfuncs->finiAccel) | |
639 | (*card->cfuncs->finiAccel) (pScreen); | |
640 | ||
641 | if (!pScreenPriv->screen->softCursor && card->cfuncs->finiCursor) | |
642 | (*card->cfuncs->finiCursor) (pScreen); | |
643 | ||
644 | if (card->cfuncs->scrfini) | |
645 | (*card->cfuncs->scrfini) (screen); | |
646 | ||
647 | /* | |
648 | * Clean up card when last screen is closed, DIX closes them in | |
649 | * reverse order, thus we check for when the first in the list is closed | |
650 | */ | |
651 | if (screen == card->screenList) { | |
652 | if (card->cfuncs->cardfini) | |
653 | (*card->cfuncs->cardfini) (card); | |
654 | /* | |
655 | * Clean up OS when last card is closed | |
656 | */ | |
657 | if (card == kdCardInfo) { | |
658 | if (kdEnabled) { | |
659 | kdEnabled = FALSE; | |
660 | if (kdOsFuncs->Disable) | |
661 | (*kdOsFuncs->Disable) (); | |
662 | } | |
663 | } | |
664 | } | |
665 | ||
666 | pScreenPriv->screen->pScreen = 0; | |
667 | ||
668 | free((pointer) pScreenPriv); | |
669 | return ret; | |
670 | } | |
671 | ||
672 | Bool | |
673 | KdSaveScreen(ScreenPtr pScreen, int on) | |
674 | { | |
675 | KdScreenPriv(pScreen); | |
676 | int dpmsState; | |
677 | ||
678 | if (!pScreenPriv->card->cfuncs->dpms) | |
679 | return FALSE; | |
680 | ||
681 | dpmsState = pScreenPriv->dpmsState; | |
682 | switch (on) { | |
683 | case SCREEN_SAVER_OFF: | |
684 | dpmsState = KD_DPMS_NORMAL; | |
685 | break; | |
686 | case SCREEN_SAVER_ON: | |
687 | if (dpmsState == KD_DPMS_NORMAL) | |
688 | dpmsState = KD_DPMS_NORMAL + 1; | |
689 | break; | |
690 | case SCREEN_SAVER_CYCLE: | |
691 | if (dpmsState < KD_DPMS_MAX) | |
692 | dpmsState++; | |
693 | break; | |
694 | case SCREEN_SAVER_FORCER: | |
695 | break; | |
696 | } | |
697 | if (dpmsState != pScreenPriv->dpmsState) { | |
698 | if (pScreenPriv->enabled) | |
699 | (*pScreenPriv->card->cfuncs->dpms) (pScreen, dpmsState); | |
700 | pScreenPriv->dpmsState = dpmsState; | |
701 | } | |
702 | return TRUE; | |
703 | } | |
704 | ||
705 | static Bool | |
706 | KdCreateWindow(WindowPtr pWin) | |
707 | { | |
708 | #ifndef PHOENIX | |
709 | if (!pWin->parent) { | |
710 | KdScreenPriv(pWin->drawable.pScreen); | |
711 | ||
712 | if (!pScreenPriv->enabled) { | |
713 | RegionEmpty(&pWin->borderClip); | |
714 | RegionBreak(&pWin->clipList); | |
715 | } | |
716 | } | |
717 | #endif | |
718 | return fbCreateWindow(pWin); | |
719 | } | |
720 | ||
721 | void | |
722 | KdSetSubpixelOrder(ScreenPtr pScreen, Rotation randr) | |
723 | { | |
724 | KdScreenPriv(pScreen); | |
725 | KdScreenInfo *screen = pScreenPriv->screen; | |
726 | int subpixel_order = screen->subpixel_order; | |
727 | Rotation subpixel_dir; | |
728 | int i; | |
729 | ||
730 | static struct { | |
731 | int subpixel_order; | |
732 | Rotation direction; | |
733 | } orders[] = { | |
734 | {SubPixelHorizontalRGB, RR_Rotate_0}, | |
735 | {SubPixelHorizontalBGR, RR_Rotate_180}, | |
736 | {SubPixelVerticalRGB, RR_Rotate_270}, | |
737 | {SubPixelVerticalBGR, RR_Rotate_90}, | |
738 | }; | |
739 | ||
740 | static struct { | |
741 | int bit; | |
742 | int normal; | |
743 | int reflect; | |
744 | } reflects[] = { | |
745 | {RR_Reflect_X, SubPixelHorizontalRGB, SubPixelHorizontalBGR}, | |
746 | {RR_Reflect_X, SubPixelHorizontalBGR, SubPixelHorizontalRGB}, | |
747 | {RR_Reflect_Y, SubPixelVerticalRGB, SubPixelVerticalBGR}, | |
748 | {RR_Reflect_Y, SubPixelVerticalRGB, SubPixelVerticalRGB}, | |
749 | }; | |
750 | ||
751 | /* map subpixel to direction */ | |
752 | for (i = 0; i < 4; i++) | |
753 | if (orders[i].subpixel_order == subpixel_order) | |
754 | break; | |
755 | if (i < 4) { | |
756 | subpixel_dir = | |
757 | KdAddRotation(randr & RR_Rotate_All, orders[i].direction); | |
758 | ||
759 | /* map back to subpixel order */ | |
760 | for (i = 0; i < 4; i++) | |
761 | if (orders[i].direction & subpixel_dir) { | |
762 | subpixel_order = orders[i].subpixel_order; | |
763 | break; | |
764 | } | |
765 | /* reflect */ | |
766 | for (i = 0; i < 4; i++) | |
767 | if ((randr & reflects[i].bit) && | |
768 | reflects[i].normal == subpixel_order) { | |
769 | subpixel_order = reflects[i].reflect; | |
770 | break; | |
771 | } | |
772 | } | |
773 | PictureSetSubpixelOrder(pScreen, subpixel_order); | |
774 | } | |
775 | ||
776 | /* Pass through AddScreen, which doesn't take any closure */ | |
777 | static KdScreenInfo *kdCurrentScreen; | |
778 | ||
779 | Bool | |
780 | KdScreenInit(ScreenPtr pScreen, int argc, char **argv) | |
781 | { | |
782 | KdScreenInfo *screen = kdCurrentScreen; | |
783 | KdCardInfo *card = screen->card; | |
784 | KdPrivScreenPtr pScreenPriv; | |
785 | ||
786 | /* | |
787 | * note that screen->fb is set up for the nominal orientation | |
788 | * of the screen; that means if randr is rotated, the values | |
789 | * there should reflect a rotated frame buffer (or shadow). | |
790 | */ | |
791 | Bool rotated = (screen->randr & (RR_Rotate_90 | RR_Rotate_270)) != 0; | |
792 | int width, height, *width_mmp, *height_mmp; | |
793 | ||
794 | KdAllocatePrivates(pScreen); | |
795 | ||
796 | pScreenPriv = KdGetScreenPriv(pScreen); | |
797 | ||
798 | if (!rotated) { | |
799 | width = screen->width; | |
800 | height = screen->height; | |
801 | width_mmp = &screen->width_mm; | |
802 | height_mmp = &screen->height_mm; | |
803 | } | |
804 | else { | |
805 | width = screen->height; | |
806 | height = screen->width; | |
807 | width_mmp = &screen->height_mm; | |
808 | height_mmp = &screen->width_mm; | |
809 | } | |
810 | screen->pScreen = pScreen; | |
811 | pScreenPriv->screen = screen; | |
812 | pScreenPriv->card = card; | |
813 | pScreenPriv->bytesPerPixel = screen->fb.bitsPerPixel >> 3; | |
814 | pScreenPriv->dpmsState = KD_DPMS_NORMAL; | |
815 | pScreen->x = screen->origin.x; | |
816 | pScreen->y = screen->origin.y; | |
817 | ||
818 | if (!monitorResolution) | |
819 | monitorResolution = 75; | |
820 | /* | |
821 | * This is done in this order so that backing store wraps | |
822 | * our GC functions; fbFinishScreenInit initializes MI | |
823 | * backing store | |
824 | */ | |
825 | if (!fbSetupScreen(pScreen, | |
826 | screen->fb.frameBuffer, | |
827 | width, height, | |
828 | monitorResolution, monitorResolution, | |
829 | screen->fb.pixelStride, screen->fb.bitsPerPixel)) { | |
830 | return FALSE; | |
831 | } | |
832 | ||
833 | /* | |
834 | * Set colormap functions | |
835 | */ | |
836 | pScreen->InstallColormap = KdInstallColormap; | |
837 | pScreen->UninstallColormap = KdUninstallColormap; | |
838 | pScreen->ListInstalledColormaps = KdListInstalledColormaps; | |
839 | pScreen->StoreColors = KdStoreColors; | |
840 | ||
841 | pScreen->SaveScreen = KdSaveScreen; | |
842 | pScreen->CreateWindow = KdCreateWindow; | |
843 | ||
844 | if (!fbFinishScreenInit(pScreen, | |
845 | screen->fb.frameBuffer, | |
846 | width, height, | |
847 | monitorResolution, monitorResolution, | |
848 | screen->fb.pixelStride, screen->fb.bitsPerPixel)) { | |
849 | return FALSE; | |
850 | } | |
851 | ||
852 | /* | |
853 | * Fix screen sizes; for some reason mi takes dpi instead of mm. | |
854 | * Rounding errors are annoying | |
855 | */ | |
856 | if (*width_mmp) | |
857 | pScreen->mmWidth = *width_mmp; | |
858 | else | |
859 | *width_mmp = pScreen->mmWidth; | |
860 | if (*height_mmp) | |
861 | pScreen->mmHeight = *height_mmp; | |
862 | else | |
863 | *height_mmp = pScreen->mmHeight; | |
864 | ||
865 | /* | |
866 | * Plug in our own block/wakeup handlers. | |
867 | * miScreenInit installs NoopDDA in both places | |
868 | */ | |
869 | pScreen->BlockHandler = KdBlockHandler; | |
870 | pScreen->WakeupHandler = KdWakeupHandler; | |
871 | ||
872 | if (!fbPictureInit(pScreen, 0, 0)) | |
873 | return FALSE; | |
874 | if (card->cfuncs->initScreen) | |
875 | if (!(*card->cfuncs->initScreen) (pScreen)) | |
876 | return FALSE; | |
877 | ||
878 | if (!screen->dumb && card->cfuncs->initAccel) | |
879 | if (!(*card->cfuncs->initAccel) (pScreen)) | |
880 | screen->dumb = TRUE; | |
881 | ||
882 | if (card->cfuncs->finishInitScreen) | |
883 | if (!(*card->cfuncs->finishInitScreen) (pScreen)) | |
884 | return FALSE; | |
885 | ||
886 | #if 0 | |
887 | fbInitValidateTree(pScreen); | |
888 | #endif | |
889 | ||
890 | /* | |
891 | * Wrap CloseScreen, the order now is: | |
892 | * KdCloseScreen | |
893 | * miBSCloseScreen | |
894 | * fbCloseScreen | |
895 | */ | |
896 | pScreenPriv->CloseScreen = pScreen->CloseScreen; | |
897 | pScreen->CloseScreen = KdCloseScreen; | |
898 | ||
899 | pScreenPriv->CreateScreenResources = pScreen->CreateScreenResources; | |
900 | pScreen->CreateScreenResources = KdCreateScreenResources; | |
901 | ||
902 | if (screen->softCursor || | |
903 | !card->cfuncs->initCursor || !(*card->cfuncs->initCursor) (pScreen)) { | |
904 | /* Use MI for cursor display and event queueing. */ | |
905 | screen->softCursor = TRUE; | |
906 | miDCInitialize(pScreen, &kdPointerScreenFuncs); | |
907 | } | |
908 | ||
909 | if (!fbCreateDefColormap(pScreen)) { | |
910 | return FALSE; | |
911 | } | |
912 | ||
913 | KdSetSubpixelOrder(pScreen, screen->randr); | |
914 | ||
915 | /* | |
916 | * Enable the hardware | |
917 | */ | |
918 | if (!kdEnabled) { | |
919 | kdEnabled = TRUE; | |
920 | if (kdOsFuncs->Enable) | |
921 | (*kdOsFuncs->Enable) (); | |
922 | } | |
923 | ||
924 | if (screen->mynum == card->selected) { | |
925 | if (card->cfuncs->preserve) | |
926 | (*card->cfuncs->preserve) (card); | |
927 | if (card->cfuncs->enable) | |
928 | if (!(*card->cfuncs->enable) (pScreen)) | |
929 | return FALSE; | |
930 | pScreenPriv->enabled = TRUE; | |
931 | if (!screen->softCursor && card->cfuncs->enableCursor) | |
932 | (*card->cfuncs->enableCursor) (pScreen); | |
933 | KdEnableColormap(pScreen); | |
934 | if (!screen->dumb && card->cfuncs->enableAccel) | |
935 | (*card->cfuncs->enableAccel) (pScreen); | |
936 | } | |
937 | ||
938 | return TRUE; | |
939 | } | |
940 | ||
941 | void | |
942 | KdInitScreen(ScreenInfo * pScreenInfo, | |
943 | KdScreenInfo * screen, int argc, char **argv) | |
944 | { | |
945 | KdCardInfo *card = screen->card; | |
946 | ||
947 | if (!(*card->cfuncs->scrinit) (screen)) | |
948 | FatalError("Screen initialization failed!\n"); | |
949 | ||
950 | if (!card->cfuncs->initAccel) | |
951 | screen->dumb = TRUE; | |
952 | if (!card->cfuncs->initCursor) | |
953 | screen->softCursor = TRUE; | |
954 | } | |
955 | ||
956 | static Bool | |
957 | KdSetPixmapFormats(ScreenInfo * pScreenInfo) | |
958 | { | |
959 | CARD8 depthToBpp[33]; /* depth -> bpp map */ | |
960 | KdCardInfo *card; | |
961 | KdScreenInfo *screen; | |
962 | int i; | |
963 | int bpp; | |
964 | PixmapFormatRec *format; | |
965 | ||
966 | for (i = 1; i <= 32; i++) | |
967 | depthToBpp[i] = 0; | |
968 | ||
969 | /* | |
970 | * Generate mappings between bitsPerPixel and depth, | |
971 | * also ensure that all screens comply with protocol | |
972 | * restrictions on equivalent formats for the same | |
973 | * depth on different screens | |
974 | */ | |
975 | for (card = kdCardInfo; card; card = card->next) { | |
976 | for (screen = card->screenList; screen; screen = screen->next) { | |
977 | bpp = screen->fb.bitsPerPixel; | |
978 | if (bpp == 24) | |
979 | bpp = 32; | |
980 | if (!depthToBpp[screen->fb.depth]) | |
981 | depthToBpp[screen->fb.depth] = bpp; | |
982 | else if (depthToBpp[screen->fb.depth] != bpp) | |
983 | return FALSE; | |
984 | } | |
985 | } | |
986 | ||
987 | /* | |
988 | * Fill in additional formats | |
989 | */ | |
990 | for (i = 0; i < NUM_KD_DEPTHS; i++) | |
991 | if (!depthToBpp[kdDepths[i].depth]) | |
992 | depthToBpp[kdDepths[i].depth] = kdDepths[i].bpp; | |
993 | ||
994 | pScreenInfo->imageByteOrder = IMAGE_BYTE_ORDER; | |
995 | pScreenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT; | |
996 | pScreenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD; | |
997 | pScreenInfo->bitmapBitOrder = BITMAP_BIT_ORDER; | |
998 | ||
999 | pScreenInfo->numPixmapFormats = 0; | |
1000 | ||
1001 | for (i = 1; i <= 32; i++) { | |
1002 | if (depthToBpp[i]) { | |
1003 | format = &pScreenInfo->formats[pScreenInfo->numPixmapFormats++]; | |
1004 | format->depth = i; | |
1005 | format->bitsPerPixel = depthToBpp[i]; | |
1006 | format->scanlinePad = BITMAP_SCANLINE_PAD; | |
1007 | } | |
1008 | } | |
1009 | ||
1010 | return TRUE; | |
1011 | } | |
1012 | ||
1013 | static void | |
1014 | KdAddScreen(ScreenInfo * pScreenInfo, | |
1015 | KdScreenInfo * screen, int argc, char **argv) | |
1016 | { | |
1017 | int i; | |
1018 | ||
1019 | /* | |
1020 | * Fill in fb visual type masks for this screen | |
1021 | */ | |
1022 | for (i = 0; i < pScreenInfo->numPixmapFormats; i++) { | |
1023 | unsigned long visuals; | |
1024 | Pixel rm, gm, bm; | |
1025 | ||
1026 | visuals = 0; | |
1027 | rm = gm = bm = 0; | |
1028 | if (pScreenInfo->formats[i].depth == screen->fb.depth) { | |
1029 | visuals = screen->fb.visuals; | |
1030 | rm = screen->fb.redMask; | |
1031 | gm = screen->fb.greenMask; | |
1032 | bm = screen->fb.blueMask; | |
1033 | } | |
1034 | fbSetVisualTypesAndMasks(pScreenInfo->formats[i].depth, | |
1035 | visuals, 8, rm, gm, bm); | |
1036 | } | |
1037 | ||
1038 | kdCurrentScreen = screen; | |
1039 | ||
1040 | AddScreen(KdScreenInit, argc, argv); | |
1041 | } | |
1042 | ||
1043 | #if 0 /* This function is not used currently */ | |
1044 | ||
1045 | int | |
1046 | KdDepthToFb(ScreenPtr pScreen, int depth) | |
1047 | { | |
1048 | KdScreenPriv(pScreen); | |
1049 | ||
1050 | for (fb = 0; fb <= KD_MAX_FB && pScreenPriv->screen->fb.frameBuffer; fb++) | |
1051 | if (pScreenPriv->screen->fb.depth == depth) | |
1052 | return fb; | |
1053 | } | |
1054 | ||
1055 | #endif | |
1056 | ||
1057 | static int | |
1058 | KdSignalWrapper(int signum) | |
1059 | { | |
1060 | kdCaughtSignal = TRUE; | |
1061 | return 1; /* use generic OS layer cleanup & abort */ | |
1062 | } | |
1063 | ||
1064 | void | |
1065 | KdInitOutput(ScreenInfo * pScreenInfo, int argc, char **argv) | |
1066 | { | |
1067 | KdCardInfo *card; | |
1068 | KdScreenInfo *screen; | |
1069 | ||
1070 | if (!kdCardInfo) { | |
1071 | InitCard(0); | |
1072 | if (!(card = KdCardInfoLast())) | |
1073 | FatalError("No matching cards found!\n"); | |
1074 | screen = KdScreenInfoAdd(card); | |
1075 | KdParseScreen(screen, 0); | |
1076 | } | |
1077 | /* | |
1078 | * Initialize all of the screens for all of the cards | |
1079 | */ | |
1080 | for (card = kdCardInfo; card; card = card->next) { | |
1081 | int ret = 1; | |
1082 | ||
1083 | if (card->cfuncs->cardinit) | |
1084 | ret = (*card->cfuncs->cardinit) (card); | |
1085 | if (ret) { | |
1086 | for (screen = card->screenList; screen; screen = screen->next) | |
1087 | KdInitScreen(pScreenInfo, screen, argc, argv); | |
1088 | } | |
1089 | } | |
1090 | ||
1091 | /* | |
1092 | * Merge the various pixmap formats together, this can fail | |
1093 | * when two screens share depth but not bitsPerPixel | |
1094 | */ | |
1095 | if (!KdSetPixmapFormats(pScreenInfo)) | |
1096 | return; | |
1097 | ||
1098 | /* | |
1099 | * Add all of the screens | |
1100 | */ | |
1101 | for (card = kdCardInfo; card; card = card->next) | |
1102 | for (screen = card->screenList; screen; screen = screen->next) | |
1103 | KdAddScreen(pScreenInfo, screen, argc, argv); | |
1104 | ||
1105 | OsRegisterSigWrapper(KdSignalWrapper); | |
1106 | } | |
1107 | ||
1108 | void | |
1109 | OsVendorFatalError(const char *f, va_list args) | |
1110 | { | |
1111 | } | |
1112 | ||
1113 | int | |
1114 | DPMSSet(ClientPtr client, int level) | |
1115 | { | |
1116 | return Success; | |
1117 | } | |
1118 | ||
1119 | Bool | |
1120 | DPMSSupported(void) | |
1121 | { | |
1122 | return FALSE; | |
1123 | } |