3 Copyright (c) 2004 - 2009, Intel Corporation. All rights reserved.<BR>
4 Portions copyright (c) 2008 - 2011, Apple Inc. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
21 #include <X11/Xutil.h>
23 #include <X11/extensions/XShm.h>
24 #include <X11/keysym.h>
25 #include <X11/cursorfont.h>
27 #define KEYSYM_LOWER 0
28 #define KEYSYM_UPPER 1
32 struct uga_drv_shift_mask
{
40 EMU_GRAPHICS_WINDOW_PROTOCOL GraphicsIo
;
43 int screen
; /* values for window_size in main */
51 unsigned int line_bytes
;
52 unsigned int pixel_shift
;
53 unsigned char *image_data
;
55 struct uga_drv_shift_mask r
, g
, b
;
58 XShmSegmentInfo xshm_info
;
63 unsigned int key_count
;
64 EFI_KEY_DATA keys
[NBR_KEYS
];
66 EFI_KEY_STATE KeyState
;
68 EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK MakeRegisterdKeyCallback
;
69 EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK BreakRegisterdKeyCallback
;
70 VOID
*RegisterdKeyCallbackContext
;
74 EFI_SIMPLE_POINTER_STATE pointer_state
;
75 int pointer_state_changed
;
76 } GRAPHICS_IO_PRIVATE
;
79 HandleEvents(GRAPHICS_IO_PRIVATE
*drv
);
82 fill_shift_mask (struct uga_drv_shift_mask
*sm
, unsigned long mask
)
86 while ((mask
& 1) == 0)
96 sm
->csize
= 8 - sm
->size
;
101 IN GRAPHICS_IO_PRIVATE
*drv
104 drv
->image
= XShmCreateImage (drv
->display
, drv
->visual
,
105 drv
->depth
, ZPixmap
, NULL
, &drv
->xshm_info
,
106 drv
->width
, drv
->height
);
107 if (drv
->image
== NULL
)
110 switch (drv
->image
->bitmap_unit
) {
112 drv
->pixel_shift
= 2;
115 drv
->pixel_shift
= 1;
118 drv
->pixel_shift
= 0;
122 drv
->xshm_info
.shmid
= shmget
123 (IPC_PRIVATE
, drv
->image
->bytes_per_line
* drv
->image
->height
,
125 if (drv
->xshm_info
.shmid
< 0) {
126 XDestroyImage(drv
->image
);
130 drv
->image_data
= shmat (drv
->xshm_info
.shmid
, NULL
, 0);
131 if(!drv
->image_data
) {
132 shmctl (drv
->xshm_info
.shmid
, IPC_RMID
, NULL
);
133 XDestroyImage(drv
->image
);
139 // This closes shared memory in real time on OS X. Only closes after folks quit using
142 /* Can this fail ? */
143 shmctl (drv
->xshm_info
.shmid
, IPC_RMID
, NULL
);
146 drv
->xshm_info
.shmaddr
= (char*)drv
->image_data
;
147 drv
->image
->data
= (char*)drv
->image_data
;
149 if (!XShmAttach (drv
->display
, &drv
->xshm_info
)) {
150 shmdt (drv
->image_data
);
151 XDestroyImage(drv
->image
);
160 IN EMU_GRAPHICS_WINDOW_PROTOCOL
*GraphicsIo
,
165 GRAPHICS_IO_PRIVATE
*drv
= (GRAPHICS_IO_PRIVATE
*)GraphicsIo
;
166 XSizeHints size_hints
;
168 /* Destroy current buffer if created. */
169 if (drv
->image
!= NULL
)
171 /* Before destroy buffer, need to make sure the buffer available for access. */
172 XDestroyImage(drv
->image
);
175 shmdt (drv
->image_data
);
177 drv
->image_data
= NULL
;
182 drv
->height
= Height
;
183 XResizeWindow (drv
->display
, drv
->win
, Width
, Height
);
185 /* Allocate image. */
186 if (XShmQueryExtension(drv
->display
) && TryCreateShmImage(drv
)) {
191 drv
->pixel_shift
= 2;
192 else if (drv
->depth
> 8)
193 drv
->pixel_shift
= 1;
195 drv
->pixel_shift
= 0;
197 drv
->image_data
= malloc((drv
->width
* drv
->height
) << drv
->pixel_shift
);
198 drv
->image
= XCreateImage (drv
->display
, drv
->visual
, drv
->depth
,
199 ZPixmap
, 0, (char *)drv
->image_data
,
200 drv
->width
, drv
->height
,
201 8 << drv
->pixel_shift
, 0);
203 drv
->line_bytes
= drv
->image
->bytes_per_line
;
204 fill_shift_mask (&drv
->r
, drv
->image
->red_mask
);
205 fill_shift_mask (&drv
->g
, drv
->image
->green_mask
);
206 fill_shift_mask (&drv
->b
, drv
->image
->blue_mask
);
209 size_hints
.flags
= PSize
| PMinSize
| PMaxSize
;
210 size_hints
.min_width
= size_hints
.max_width
= size_hints
.base_width
= Width
;
211 size_hints
.min_height
= size_hints
.max_height
= size_hints
.base_height
= Height
;
212 XSetWMNormalHints (drv
->display
, drv
->win
, &size_hints
);
214 XMapWindow (drv
->display
, drv
->win
);
220 handleKeyEvent(GRAPHICS_IO_PRIVATE
*drv
, XEvent
*ev
, BOOLEAN Make
)
223 EFI_KEY_DATA KeyData
;
227 if (drv
->key_count
== NBR_KEYS
) {
232 // keycode is a physical key on the keyboard
233 // KeySym is a mapping of a physical key
234 // KeyboardMapping is the array of KeySym for a given keycode. key, shifted key, option key, command key, ...
236 // Returns an array of KeySymArraySize of KeySym for the keycode. [0] is lower case, [1] is upper case,
237 // [2] and [3] are based on option and command modifiers. The problem we have is command V
238 // could be mapped to a crazy Unicode character so the old scheme of returning a string.
240 KeySym
= XGetKeyboardMapping (drv
->display
, ev
->xkey
.keycode
, 1, &KeySymArraySize
);
242 KeyData
.Key
.ScanCode
= 0;
243 KeyData
.Key
.UnicodeChar
= 0;
244 KeyData
.KeyState
.KeyShiftState
= 0;
247 // Skipping EFI_SCROLL_LOCK_ACTIVE & EFI_NUM_LOCK_ACTIVE since they are not on Macs
249 if ((ev
->xkey
.state
& LockMask
) == 0) {
250 drv
->KeyState
.KeyToggleState
&= ~EFI_CAPS_LOCK_ACTIVE
;
253 drv
->KeyState
.KeyToggleState
|= EFI_CAPS_LOCK_ACTIVE
;
257 // Skipping EFI_MENU_KEY_PRESSED and EFI_SYS_REQ_PRESSED
262 drv
->KeyState
.KeyShiftState
|= EFI_RIGHT_CONTROL_PRESSED
;
264 drv
->KeyState
.KeyShiftState
&= ~EFI_RIGHT_CONTROL_PRESSED
;
269 drv
->KeyState
.KeyShiftState
|= EFI_LEFT_CONTROL_PRESSED
;
271 drv
->KeyState
.KeyShiftState
&= ~EFI_LEFT_CONTROL_PRESSED
;
277 drv
->KeyState
.KeyShiftState
|= EFI_RIGHT_SHIFT_PRESSED
;
279 drv
->KeyState
.KeyShiftState
&= ~EFI_RIGHT_SHIFT_PRESSED
;
284 drv
->KeyState
.KeyShiftState
|= EFI_LEFT_SHIFT_PRESSED
;
286 drv
->KeyState
.KeyShiftState
&= ~EFI_LEFT_SHIFT_PRESSED
;
292 drv
->KeyState
.KeyShiftState
|= EFI_LEFT_ALT_PRESSED
;
294 drv
->KeyState
.KeyShiftState
&= ~EFI_LEFT_ALT_PRESSED
;
300 drv
->KeyState
.KeyShiftState
|= EFI_RIGHT_LOGO_PRESSED
;
302 drv
->KeyState
.KeyShiftState
&= ~EFI_RIGHT_LOGO_PRESSED
;
307 drv
->KeyState
.KeyShiftState
|= EFI_LEFT_LOGO_PRESSED
;
309 drv
->KeyState
.KeyShiftState
&= ~EFI_LEFT_LOGO_PRESSED
;
314 case XK_Home
: KeyData
.Key
.ScanCode
= SCAN_HOME
; break;
317 case XK_End
: KeyData
.Key
.ScanCode
= SCAN_END
; break;
320 case XK_Left
: KeyData
.Key
.ScanCode
= SCAN_LEFT
; break;
323 case XK_Right
: KeyData
.Key
.ScanCode
= SCAN_RIGHT
; break;
326 case XK_Up
: KeyData
.Key
.ScanCode
= SCAN_UP
; break;
329 case XK_Down
: KeyData
.Key
.ScanCode
= SCAN_DOWN
; break;
332 case XK_Delete
: KeyData
.Key
.ScanCode
= SCAN_DELETE
; break;
335 case XK_Insert
: KeyData
.Key
.ScanCode
= SCAN_INSERT
; break;
338 case XK_Page_Up
: KeyData
.Key
.ScanCode
= SCAN_PAGE_UP
; break;
340 case XK_KP_Page_Down
:
341 case XK_Page_Down
: KeyData
.Key
.ScanCode
= SCAN_PAGE_DOWN
; break;
343 case XK_Escape
: KeyData
.Key
.ScanCode
= SCAN_ESC
; break;
347 case XK_F1
: KeyData
.Key
.ScanCode
= SCAN_F1
; break;
350 case XK_F2
: KeyData
.Key
.ScanCode
= SCAN_F2
; break;
353 case XK_F3
: KeyData
.Key
.ScanCode
= SCAN_F3
; break;
356 case XK_F4
: KeyData
.Key
.ScanCode
= SCAN_F4
; break;
358 case XK_F5
: KeyData
.Key
.ScanCode
= SCAN_F5
; break;
359 case XK_F6
: KeyData
.Key
.ScanCode
= SCAN_F6
; break;
360 case XK_F7
: KeyData
.Key
.ScanCode
= SCAN_F7
; break;
362 // Don't map into X11 by default on a Mac
363 // System Preferences->Keyboard->Keyboard Shortcuts can be configured
364 // to not use higher function keys as shortcuts and the will show up
366 case XK_F8
: KeyData
.Key
.ScanCode
= SCAN_F8
; break;
367 case XK_F9
: KeyData
.Key
.ScanCode
= SCAN_F9
; break;
368 case XK_F10
: KeyData
.Key
.ScanCode
= SCAN_F10
; break;
370 case XK_F11
: KeyData
.Key
.ScanCode
= SCAN_F11
; break;
371 case XK_F12
: KeyData
.Key
.ScanCode
= SCAN_F12
; break;
373 case XK_F13
: KeyData
.Key
.ScanCode
= SCAN_F13
; break;
374 case XK_F14
: KeyData
.Key
.ScanCode
= SCAN_F14
; break;
375 case XK_F15
: KeyData
.Key
.ScanCode
= SCAN_F15
; break;
376 case XK_F16
: KeyData
.Key
.ScanCode
= SCAN_F16
; break;
377 case XK_F17
: KeyData
.Key
.ScanCode
= SCAN_F17
; break;
378 case XK_F18
: KeyData
.Key
.ScanCode
= SCAN_F18
; break;
379 case XK_F19
: KeyData
.Key
.ScanCode
= SCAN_F19
; break;
380 case XK_F20
: KeyData
.Key
.ScanCode
= SCAN_F20
; break;
381 case XK_F21
: KeyData
.Key
.ScanCode
= SCAN_F21
; break;
382 case XK_F22
: KeyData
.Key
.ScanCode
= SCAN_F22
; break;
383 case XK_F23
: KeyData
.Key
.ScanCode
= SCAN_F23
; break;
384 case XK_F24
: KeyData
.Key
.ScanCode
= SCAN_F24
; break;
387 //case XK_: KeyData.Key.ScanCode = SCAN_MUTE; break;
388 //case XK_: KeyData.Key.ScanCode = SCAN_VOLUME_UP; break;
389 //case XK_: KeyData.Key.ScanCode = SCAN_VOLUME_DOWN; break;
390 //case XK_: KeyData.Key.ScanCode = SCAN_BRIGHTNESS_UP; break;
391 //case XK_: KeyData.Key.ScanCode = SCAN_BRIGHTNESS_DOWN; break;
392 //case XK_: KeyData.Key.ScanCode = SCAN_SUSPEND; break;
393 //case XK_: KeyData.Key.ScanCode = SCAN_HIBERNATE; break;
394 //case XK_: KeyData.Key.ScanCode = SCAN_TOGGLE_DISPLAY; break;
395 //case XK_: KeyData.Key.ScanCode = SCAN_RECOVERY; break;
396 //case XK_: KeyData.Key.ScanCode = SCAN_EJECT; break;
398 case XK_BackSpace
: KeyData
.Key
.UnicodeChar
= 0x0008; break;
401 case XK_Tab
: KeyData
.Key
.UnicodeChar
= 0x0009; break;
403 case XK_Linefeed
: KeyData
.Key
.UnicodeChar
= 0x000a; break;
406 case XK_Return
: KeyData
.Key
.UnicodeChar
= 0x000d; break;
408 case XK_KP_Equal
: KeyData
.Key
.UnicodeChar
= L
'='; break;
409 case XK_KP_Multiply
: KeyData
.Key
.UnicodeChar
= L
'*'; break;
410 case XK_KP_Add
: KeyData
.Key
.UnicodeChar
= L
'+'; break;
411 case XK_KP_Separator
: KeyData
.Key
.UnicodeChar
= L
'~'; break;
412 case XK_KP_Subtract
: KeyData
.Key
.UnicodeChar
= L
'-'; break;
413 case XK_KP_Decimal
: KeyData
.Key
.UnicodeChar
= L
'.'; break;
414 case XK_KP_Divide
: KeyData
.Key
.UnicodeChar
= L
'/'; break;
416 case XK_KP_0
: KeyData
.Key
.UnicodeChar
= L
'0'; break;
417 case XK_KP_1
: KeyData
.Key
.UnicodeChar
= L
'1'; break;
418 case XK_KP_2
: KeyData
.Key
.UnicodeChar
= L
'2'; break;
419 case XK_KP_3
: KeyData
.Key
.UnicodeChar
= L
'3'; break;
420 case XK_KP_4
: KeyData
.Key
.UnicodeChar
= L
'4'; break;
421 case XK_KP_5
: KeyData
.Key
.UnicodeChar
= L
'5'; break;
422 case XK_KP_6
: KeyData
.Key
.UnicodeChar
= L
'6'; break;
423 case XK_KP_7
: KeyData
.Key
.UnicodeChar
= L
'7'; break;
424 case XK_KP_8
: KeyData
.Key
.UnicodeChar
= L
'8'; break;
425 case XK_KP_9
: KeyData
.Key
.UnicodeChar
= L
'9'; break;
431 // The global state is our state
432 KeyData
.KeyState
.KeyShiftState
= drv
->KeyState
.KeyShiftState
;
433 KeyData
.KeyState
.KeyToggleState
= drv
->KeyState
.KeyToggleState
;
435 if (*KeySym
< XK_BackSpace
) {
436 if (((drv
->KeyState
.KeyShiftState
& (EFI_LEFT_SHIFT_PRESSED
| EFI_RIGHT_SHIFT_PRESSED
)) != 0) ||
437 ((drv
->KeyState
.KeyToggleState
& EFI_CAPS_LOCK_ACTIVE
) != 0) ) {
439 KeyData
.Key
.UnicodeChar
= (CHAR16
)KeySym
[KEYSYM_UPPER
];
441 // Per UEFI spec since we converted the Unicode clear the shift bits we pass up
442 KeyData
.KeyState
.KeyShiftState
&= ~(EFI_LEFT_SHIFT_PRESSED
| EFI_RIGHT_SHIFT_PRESSED
);
444 KeyData
.Key
.UnicodeChar
= (CHAR16
)KeySym
[KEYSYM_LOWER
];
447 // XK_BackSpace is the start of XK_MISCELLANY. These are the XK_? keys we process in this file
452 memcpy (&drv
->keys
[drv
->key_wr
], &KeyData
, sizeof (EFI_KEY_DATA
));
453 drv
->key_wr
= (drv
->key_wr
+ 1) % NBR_KEYS
;
455 if (drv
->MakeRegisterdKeyCallback
!= NULL
) {
456 ReverseGasketUint64Uint64 (drv
->MakeRegisterdKeyCallback
,drv
->RegisterdKeyCallbackContext
, &KeyData
);
459 if (drv
->BreakRegisterdKeyCallback
!= NULL
) {
460 ReverseGasketUint64Uint64 (drv
->BreakRegisterdKeyCallback
,drv
->RegisterdKeyCallbackContext
, &KeyData
);
467 handleMouseMoved(GRAPHICS_IO_PRIVATE
*drv
, XEvent
*ev
)
469 if ( ev
->xmotion
.x
!= drv
->previous_x
)
471 drv
->pointer_state
.RelativeMovementX
+= ( ev
->xmotion
.x
- drv
->previous_x
);
472 drv
->previous_x
= ev
->xmotion
.x
;
473 drv
->pointer_state_changed
= 1;
476 if ( ev
->xmotion
.y
!= drv
->previous_y
)
478 drv
->pointer_state
.RelativeMovementY
+= ( ev
->xmotion
.y
- drv
->previous_y
);
479 drv
->previous_y
= ev
->xmotion
.y
;
480 drv
->pointer_state_changed
= 1;
483 drv
->pointer_state
.RelativeMovementZ
= 0;
487 handleMouseDown(GRAPHICS_IO_PRIVATE
*drv
, XEvent
*ev
, BOOLEAN Pressed
)
489 if ( ev
->xbutton
.button
== Button1
)
491 drv
->pointer_state_changed
= ( drv
->pointer_state
.LeftButton
!= Pressed
);
492 drv
->pointer_state
.LeftButton
= Pressed
;
494 if ( ev
->xbutton
.button
== Button2
)
496 drv
->pointer_state_changed
= ( drv
->pointer_state
.RightButton
!= Pressed
);
497 drv
->pointer_state
.RightButton
= Pressed
;
502 Redraw(GRAPHICS_IO_PRIVATE
*drv
, UINTN X
, UINTN Y
, UINTN Width
, UINTN Height
)
505 XShmPutImage (drv
->display
, drv
->win
, drv
->gc
, drv
->image
,
506 X
, Y
, X
, Y
, Width
, Height
, False
);
508 XPutImage (drv
->display
, drv
->win
, drv
->gc
, drv
->image
,
509 X
, Y
, X
, Y
, Width
, Height
);
510 XFlush(drv
->display
);
514 HandleEvent(GRAPHICS_IO_PRIVATE
*drv
, XEvent
*ev
)
519 Redraw(drv
, ev
->xexpose
.x
, ev
->xexpose
.y
,
520 ev
->xexpose
.width
, ev
->xexpose
.height
);
523 Redraw(drv
, ev
->xgraphicsexpose
.x
, ev
->xgraphicsexpose
.y
,
524 ev
->xgraphicsexpose
.width
, ev
->xgraphicsexpose
.height
);
527 handleKeyEvent(drv
, ev
, TRUE
);
530 handleKeyEvent(drv
, ev
, FALSE
);
533 XRefreshKeyboardMapping(&ev
->xmapping
);
536 handleMouseMoved(drv
, ev
);
539 handleMouseDown(drv
, ev
, TRUE
);
542 handleMouseDown(drv
, ev
, FALSE
);
546 XCloseDisplay (drv
->display
);
557 HandleEvents(GRAPHICS_IO_PRIVATE
*drv
)
559 while (XPending(drv
->display
) != 0)
563 XNextEvent (drv
->display
, &ev
);
564 HandleEvent(drv
, &ev
);
569 X11PixelToColor (GRAPHICS_IO_PRIVATE
*drv
, EFI_UGA_PIXEL pixel
)
571 return ((pixel
.Red
>> drv
->r
.csize
) << drv
->r
.shift
)
572 | ((pixel
.Green
>> drv
->g
.csize
) << drv
->g
.shift
)
573 | ((pixel
.Blue
>> drv
->b
.csize
) << drv
->b
.shift
);
577 X11ColorToPixel (GRAPHICS_IO_PRIVATE
*drv
, unsigned long val
)
581 memset (&res
, 0, sizeof (EFI_UGA_PIXEL
));
582 /* FIXME: should round instead of truncate. */
583 res
.Red
= (val
>> drv
->r
.shift
) << drv
->r
.csize
;
584 res
.Green
= (val
>> drv
->g
.shift
) << drv
->g
.csize
;
585 res
.Blue
= (val
>> drv
->b
.shift
) << drv
->b
.csize
;
591 CheckKeyInternal( GRAPHICS_IO_PRIVATE
*drv
, BOOLEAN delay
)
594 if (drv
->key_count
!= 0)
597 /* EFI is polling. Be CPU-friendly. */
599 return EFI_NOT_READY
;
603 X11CheckKey(EMU_GRAPHICS_WINDOW_PROTOCOL
*GraphicsIo
)
605 GRAPHICS_IO_PRIVATE
*drv
= (GRAPHICS_IO_PRIVATE
*)GraphicsIo
;
606 return CheckKeyInternal(drv
, TRUE
);
612 IN EMU_GRAPHICS_WINDOW_PROTOCOL
*GraphicsIo
,
613 IN EFI_KEY_DATA
*KeyData
616 GRAPHICS_IO_PRIVATE
*drv
= (GRAPHICS_IO_PRIVATE
*)GraphicsIo
;
619 status
= CheckKeyInternal(drv
, FALSE
);
620 if (status
!= EFI_SUCCESS
)
623 CopyMem (KeyData
, &drv
->keys
[drv
->key_rd
], sizeof (EFI_KEY_DATA
));
624 drv
->key_rd
= (drv
->key_rd
+ 1) % NBR_KEYS
;
633 IN EMU_GRAPHICS_WINDOW_PROTOCOL
*GraphicsIo
,
634 IN EFI_KEY_TOGGLE_STATE
*KeyToggleState
637 GRAPHICS_IO_PRIVATE
*drv
= (GRAPHICS_IO_PRIVATE
*)GraphicsIo
;
640 if (*KeyToggleState
& EFI_CAPS_LOCK_ACTIVE
) {
641 if ((drv
->KeyState
.KeyToggleState
& EFI_CAPS_LOCK_ACTIVE
) == 0) {
643 // We could create an XKeyEvent and send a XK_Caps_Lock to
644 // the UGA/GOP Window
649 drv
->KeyState
.KeyToggleState
= *KeyToggleState
;
656 X11RegisterKeyNotify (
657 IN EMU_GRAPHICS_WINDOW_PROTOCOL
*GraphicsIo
,
658 IN EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK MakeCallBack
,
659 IN EMU_GRAPHICS_WINDOW_REGISTER_KEY_NOTIFY_CALLBACK BreakCallBack
,
663 GRAPHICS_IO_PRIVATE
*drv
= (GRAPHICS_IO_PRIVATE
*)GraphicsIo
;
665 drv
->MakeRegisterdKeyCallback
= MakeCallBack
;
666 drv
->BreakRegisterdKeyCallback
= BreakCallBack
;
667 drv
->RegisterdKeyCallbackContext
= Context
;
675 IN EMU_GRAPHICS_WINDOW_PROTOCOL
*GraphicsIo
,
676 IN EFI_UGA_PIXEL
*BltBuffer OPTIONAL
,
677 IN EFI_UGA_BLT_OPERATION BltOperation
,
678 IN EMU_GRAPHICS_WINDOWS__BLT_ARGS
*Args
681 GRAPHICS_IO_PRIVATE
*Private
= (GRAPHICS_IO_PRIVATE
*)GraphicsIo
;
696 if (BltOperation
== EfiUgaVideoToBltBuffer
697 || BltOperation
== EfiUgaVideoToVideo
) {
701 if (Args
->SourceY
+ Args
->Height
> Private
->height
) {
702 return EFI_INVALID_PARAMETER
;
705 if (Args
->SourceX
+ Args
->Width
> Private
->width
) {
706 return EFI_INVALID_PARAMETER
;
710 if (BltOperation
== EfiUgaBltBufferToVideo
711 || BltOperation
== EfiUgaVideoToVideo
712 || BltOperation
== EfiUgaVideoFill
) {
714 // Destination is Video
716 if (Args
->DestinationY
+ Args
->Height
> Private
->height
) {
717 return EFI_INVALID_PARAMETER
;
720 if (Args
->DestinationX
+ Args
->Width
> Private
->width
) {
721 return EFI_INVALID_PARAMETER
;
725 switch (BltOperation
) {
726 case EfiUgaVideoToBltBuffer
:
727 Blt
= (EFI_UGA_PIXEL
*)((UINT8
*)BltBuffer
+ (Args
->DestinationY
* Args
->Delta
) + Args
->DestinationX
* sizeof (EFI_UGA_PIXEL
));
728 Args
->Delta
-= Args
->Width
* sizeof (EFI_UGA_PIXEL
);
729 for (SrcY
= Args
->SourceY
; SrcY
< (Args
->Height
+ Args
->SourceY
); SrcY
++) {
730 for (SrcX
= Args
->SourceX
; SrcX
< (Args
->Width
+ Args
->SourceX
); SrcX
++) {
731 *Blt
++ = X11ColorToPixel(Private
,
732 XGetPixel(Private
->image
, SrcX
, SrcY
));
734 Blt
= (EFI_UGA_PIXEL
*) ((UINT8
*) Blt
+ Args
->Delta
);
737 case EfiUgaBltBufferToVideo
:
738 Blt
= (EFI_UGA_PIXEL
*)((UINT8
*)BltBuffer
+ (Args
->SourceY
* Args
->Delta
) + Args
->SourceX
* sizeof (EFI_UGA_PIXEL
));
739 Args
->Delta
-= Args
->Width
* sizeof (EFI_UGA_PIXEL
);
740 for (DstY
= Args
->DestinationY
; DstY
< (Args
->Height
+ Args
->DestinationY
); DstY
++) {
741 for (DstX
= Args
->DestinationX
; DstX
< (Args
->Width
+ Args
->DestinationX
); DstX
++) {
742 XPutPixel(Private
->image
, DstX
, DstY
, X11PixelToColor(Private
, *Blt
));
745 Blt
= (EFI_UGA_PIXEL
*) ((UINT8
*) Blt
+ Args
->Delta
);
748 case EfiUgaVideoToVideo
:
749 Dst
= Private
->image_data
+ (Args
->DestinationX
<< Private
->pixel_shift
)
750 + Args
->DestinationY
* Private
->line_bytes
;
751 Src
= Private
->image_data
+ (Args
->SourceX
<< Private
->pixel_shift
)
752 + Args
->SourceY
* Private
->line_bytes
;
753 Nbr
= Args
->Width
<< Private
->pixel_shift
;
754 if (Args
->DestinationY
< Args
->SourceY
) {
755 for (Index
= 0; Index
< Args
->Height
; Index
++) {
756 memcpy (Dst
, Src
, Nbr
);
757 Dst
+= Private
->line_bytes
;
758 Src
+= Private
->line_bytes
;
762 Dst
+= (Args
->Height
- 1) * Private
->line_bytes
;
763 Src
+= (Args
->Height
- 1) * Private
->line_bytes
;
764 for (Index
= 0; Index
< Args
->Height
; Index
++) {
766 // Source and Destination Y may be equal, therefore Dst and Src may
769 memmove (Dst
, Src
, Nbr
);
770 Dst
-= Private
->line_bytes
;
771 Src
-= Private
->line_bytes
;
775 case EfiUgaVideoFill
:
776 Color
= X11PixelToColor(Private
, *BltBuffer
);
777 for (DstY
= Args
->DestinationY
; DstY
< (Args
->Height
+ Args
->DestinationY
); DstY
++) {
778 for (DstX
= Args
->DestinationX
; DstX
< (Args
->Width
+ Args
->DestinationX
); DstX
++) {
779 XPutPixel(Private
->image
, DstX
, DstY
, Color
);
784 return EFI_INVALID_PARAMETER
;
790 switch (BltOperation
) {
791 case EfiUgaVideoToVideo
:
792 XCopyArea(Private
->display
, Private
->win
, Private
->win
, Private
->gc
,
793 Args
->SourceX
, Args
->SourceY
, Args
->Width
, Args
->Height
, Args
->DestinationX
, Args
->DestinationY
);
797 XNextEvent (Private
->display
, &ev
);
798 HandleEvent(Private
, &ev
);
799 if (ev
.type
== NoExpose
|| ev
.type
== GraphicsExpose
)
803 case EfiUgaVideoFill
:
804 Color
= X11PixelToColor(Private
, *BltBuffer
);
805 XSetForeground(Private
->display
, Private
->gc
, Color
);
806 XFillRectangle(Private
->display
, Private
->win
, Private
->gc
,
807 Args
->DestinationX
, Args
->DestinationY
, Args
->Width
, Args
->Height
);
808 XFlush(Private
->display
);
810 case EfiUgaBltBufferToVideo
:
811 Redraw(Private
, Args
->DestinationX
, Args
->DestinationY
, Args
->Width
, Args
->Height
);
820 CheckPointerInternal( GRAPHICS_IO_PRIVATE
*drv
, BOOLEAN delay
)
823 if (drv
->pointer_state_changed
!= 0)
826 /* EFI is polling. Be CPU-friendly. */
828 return EFI_NOT_READY
;
832 X11CheckPointer(EMU_GRAPHICS_WINDOW_PROTOCOL
*GraphicsIo
)
834 GRAPHICS_IO_PRIVATE
*drv
= (GRAPHICS_IO_PRIVATE
*)GraphicsIo
;
835 return( CheckPointerInternal( drv
, TRUE
) );
839 X11GetPointerState (EMU_GRAPHICS_WINDOW_PROTOCOL
*GraphicsIo
, EFI_SIMPLE_POINTER_STATE
*state
)
841 GRAPHICS_IO_PRIVATE
*drv
= (GRAPHICS_IO_PRIVATE
*)GraphicsIo
;
844 status
= CheckPointerInternal( drv
, FALSE
);
845 if (status
!= EFI_SUCCESS
)
848 memcpy( state
, &drv
->pointer_state
, sizeof( EFI_SIMPLE_POINTER_STATE
) );
850 drv
->pointer_state
.RelativeMovementX
= 0;
851 drv
->pointer_state
.RelativeMovementY
= 0;
852 drv
->pointer_state
.RelativeMovementZ
= 0;
853 drv
->pointer_state_changed
= 0;
860 X11GraphicsWindowOpen (
861 IN EMU_IO_THUNK_PROTOCOL
*This
864 GRAPHICS_IO_PRIVATE
*drv
;
865 unsigned int border_width
= 0;
866 char *display_name
= NULL
;
869 drv
= (GRAPHICS_IO_PRIVATE
*)calloc (1, sizeof (GRAPHICS_IO_PRIVATE
));
871 return EFI_OUT_OF_RESOURCES
;
873 drv
->GraphicsIo
.Size
= GasketX11Size
;
874 drv
->GraphicsIo
.CheckKey
= GasketX11CheckKey
;
875 drv
->GraphicsIo
.GetKey
= GasketX11GetKey
;
876 drv
->GraphicsIo
.KeySetState
= GasketX11KeySetState
;
877 drv
->GraphicsIo
.RegisterKeyNotify
= GasketX11RegisterKeyNotify
;
878 drv
->GraphicsIo
.Blt
= GasketX11Blt
;
879 drv
->GraphicsIo
.CheckPointer
= GasketX11CheckPointer
;
880 drv
->GraphicsIo
.GetPointerState
= GasketX11GetPointerState
;
886 drv
->KeyState
.KeyShiftState
= EFI_SHIFT_STATE_VALID
;
887 drv
->KeyState
.KeyToggleState
= EFI_TOGGLE_STATE_VALID
;
888 drv
->MakeRegisterdKeyCallback
= NULL
;
889 drv
->BreakRegisterdKeyCallback
= NULL
;
890 drv
->RegisterdKeyCallbackContext
= NULL
;
893 drv
->display
= XOpenDisplay (display_name
);
894 if (drv
->display
== NULL
) {
895 fprintf (stderr
, "uga: cannot connect to X server %s\n", XDisplayName (display_name
));
897 return EFI_DEVICE_ERROR
;
899 drv
->screen
= DefaultScreen (drv
->display
);
900 drv
->visual
= DefaultVisual (drv
->display
, drv
->screen
);
901 drv
->win
= XCreateSimpleWindow
902 (drv
->display
, RootWindow (drv
->display
, drv
->screen
),
903 0, 0, 4, 4, border_width
,
904 WhitePixel (drv
->display
, drv
->screen
),
905 BlackPixel (drv
->display
, drv
->screen
));
907 drv
->depth
= DefaultDepth (drv
->display
, drv
->screen
);
908 XDefineCursor (drv
->display
, drv
->win
, XCreateFontCursor (drv
->display
, XC_pirate
));
910 /* Compute title len and convert to Ascii. */
911 for (title_len
= 0; This
->ConfigString
[title_len
] != 0; title_len
++)
914 char title
[title_len
+ 1];
916 for (i
= 0; i
< title_len
; i
++)
917 title
[i
] = This
->ConfigString
[i
];
920 XStoreName (drv
->display
, drv
->win
, title
);
923 // XAutoRepeatOff (drv->display);
924 XSelectInput (drv
->display
, drv
->win
,
925 ExposureMask
| KeyPressMask
| KeyReleaseMask
| PointerMotionMask
| ButtonPressMask
| ButtonReleaseMask
);
926 drv
->gc
= DefaultGC (drv
->display
, drv
->screen
);
928 This
->Private
= (VOID
*)drv
;
929 This
->Interface
= (VOID
*)drv
;
935 X11GraphicsWindowClose (
936 IN EMU_IO_THUNK_PROTOCOL
*This
939 GRAPHICS_IO_PRIVATE
*drv
= (GRAPHICS_IO_PRIVATE
*)This
->Private
;
943 if (drv
->image
!= NULL
)
945 XDestroyImage(drv
->image
);
948 shmdt (drv
->image_data
);
950 drv
->image_data
= NULL
;
953 XDestroyWindow(drv
->display
, drv
->win
);
954 XCloseDisplay(drv
->display
);
957 // Free up the shared memory
958 shmctl (drv
->xshm_info
.shmid
, IPC_RMID
, NULL
);
966 EMU_IO_THUNK_PROTOCOL gX11ThunkIo
= {
967 &gEmuGraphicsWindowProtocolGuid
,
971 GasketX11GraphicsWindowOpen
,
972 GasketX11GraphicsWindowClose
,