* [Qemu-devel] [patch] cocoa.m - Core Graphics support
@ 2008-01-21 16:18 Mike Kronenberg
2008-01-30 18:59 ` Alexander Graf
0 siblings, 1 reply; 15+ messages in thread
From: Mike Kronenberg @ 2008-01-21 16:18 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 39223 bytes --]
This is a complete rewrite of cocoa.m to support Core Graphics.
As mentioned in earlier threads, the QuickDraw API is depreciated
starting with OS X 10.4.
Now with OS X 10.5 it won't even compile QuickDraw code on x86_64.
This implementation of cocoa.m has the following features:
[new] partial drawing of the window as needed, implemented with CG.
[new] fullscreen support
[new] tablet support
[new] View menu and item to enter Fullscreen (cmd-f)
[new] Help menu and items to show qemu-doc.html (cmd-?) and qemu-
tec.html in the OS X "Help Viewer"
[new] -name is shown in Title-bar of window
[fix] Application menu creation for 10.4+ (API is private as of 10.4)
[fix] Mouse-clicks on the guests window widgets are no longer
intercepted
[fix] apple keyboard shortcuts forwarded (minimize (cmd-m), hide QEMU
(cmd-h), quit QEMU (cmd-q))
It should compile on ppc/intel starting form 10.3 (10.2 with the known
workarounds).
Please test and comment
Mike
File as .gz
http://www.kberg.ch/qemu/091patches/cocoa.m.gz
/*
* QEMU Cocoa CG display driver
*
* Copyright (c) 2008 Mike Kronenberg
*
* Permission is hereby granted, free of charge, to any person
obtaining a copy
* of this software and associated documentation files (the
"Software"), to deal
* in the Software without restriction, including without limitation
the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/
or sell
* copies of the Software, and to permit persons to whom the Software
is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN
* THE SOFTWARE.
*/
#import <Cocoa/Cocoa.h>
#include "qemu-common.h"
#include "console.h"
#include "sysemu.h"
//#define DEBUG
#ifdef DEBUG
#define COCOA_DEBUG(...) { (void) fprintf (stdout, __VA_ARGS__); }
#else
#define COCOA_DEBUG(...) ((void) 0)
#endif
#define cgrect(nsrect) (*(CGRect *)&(nsrect))
#define COCOA_MOUSE_EVENT \
if (isTabletEnabled) { \
kbd_mouse_event((int)(p.x * 0x7FFF / screen.width), (int)
((screen.height - p.y) * 0x7FFF / screen.height), 0, buttons); \
} else if (isMouseGrabed) { \
kbd_mouse_event((int)[event deltaX], (int)[event deltaY],
0, buttons); \
} else { \
[NSApp sendEvent:event]; \
}
typedef struct {
int width;
int height;
int bitsPerComponent;
int bitsPerPixel;
} QEMUScreen;
int qemu_main(int argc, char **argv); // main defined in qemu/vl.c
NSWindow *normalWindow;
id cocoaView;
static void *screenBuffer;
int gArgc;
char **gArgv;
// keymap conversion
int keymap[] =
{
// SdlI macI macH SdlH 104xtH 104xtC sdl
30, // 0 0x00 0x1e A QZ_a
31, // 1 0x01 0x1f S QZ_s
32, // 2 0x02 0x20 D QZ_d
33, // 3 0x03 0x21 F QZ_f
35, // 4 0x04 0x23 H QZ_h
34, // 5 0x05 0x22 G QZ_g
44, // 6 0x06 0x2c Z QZ_z
45, // 7 0x07 0x2d X QZ_x
46, // 8 0x08 0x2e C QZ_c
47, // 9 0x09 0x2f V QZ_v
0, // 10 0x0A Undefined
48, // 11 0x0B 0x30 B QZ_b
16, // 12 0x0C 0x10 Q QZ_q
17, // 13 0x0D 0x11 W QZ_w
18, // 14 0x0E 0x12 E QZ_e
19, // 15 0x0F 0x13 R QZ_r
21, // 16 0x10 0x15 Y QZ_y
20, // 17 0x11 0x14 T QZ_t
2, // 18 0x12 0x02 1 QZ_1
3, // 19 0x13 0x03 2 QZ_2
4, // 20 0x14 0x04 3 QZ_3
5, // 21 0x15 0x05 4 QZ_4
7, // 22 0x16 0x07 6 QZ_6
6, // 23 0x17 0x06 5 QZ_5
13, // 24 0x18 0x0d = QZ_EQUALS
10, // 25 0x19 0x0a 9 QZ_9
8, // 26 0x1A 0x08 7 QZ_7
12, // 27 0x1B 0x0c - QZ_MINUS
9, // 28 0x1C 0x09 8 QZ_8
11, // 29 0x1D 0x0b 0 QZ_0
27, // 30 0x1E 0x1b ] QZ_RIGHTBRACKET
24, // 31 0x1F 0x18 O QZ_o
22, // 32 0x20 0x16 U QZ_u
26, // 33 0x21 0x1a [ QZ_LEFTBRACKET
23, // 34 0x22 0x17 I QZ_i
25, // 35 0x23 0x19 P QZ_p
28, // 36 0x24 0x1c ENTER QZ_RETURN
38, // 37 0x25 0x26 L QZ_l
36, // 38 0x26 0x24 J QZ_j
40, // 39 0x27 0x28 ' QZ_QUOTE
37, // 40 0x28 0x25 K QZ_k
39, // 41 0x29 0x27 ; QZ_SEMICOLON
43, // 42 0x2A 0x2b \ QZ_BACKSLASH
51, // 43 0x2B 0x33 , QZ_COMMA
53, // 44 0x2C 0x35 / QZ_SLASH
49, // 45 0x2D 0x31 N QZ_n
50, // 46 0x2E 0x32 M QZ_m
52, // 47 0x2F 0x34 . QZ_PERIOD
15, // 48 0x30 0x0f TAB QZ_TAB
57, // 49 0x31 0x39 SPACE QZ_SPACE
41, // 50 0x32 0x29 ` QZ_BACKQUOTE
14, // 51 0x33 0x0e BKSP QZ_BACKSPACE
0, // 52 0x34 Undefined
1, // 53 0x35 0x01 ESC QZ_ESCAPE
0, // 54 0x36 QZ_RMETA
0, // 55 0x37 QZ_LMETA
42, // 56 0x38 0x2a L SHFT QZ_LSHIFT
58, // 57 0x39 0x3a CAPS QZ_CAPSLOCK
56, // 58 0x3A 0x38 L ALT QZ_LALT
29, // 59 0x3B 0x1d L CTRL QZ_LCTRL
54, // 60 0x3C 0x36 R SHFT QZ_RSHIFT
184,// 61 0x3D 0xb8 E0,38 R ALT QZ_RALT
157,// 62 0x3E 0x9d E0,1D R CTRL QZ_RCTRL
0, // 63 0x3F Undefined
0, // 64 0x40 Undefined
0, // 65 0x41 Undefined
0, // 66 0x42 Undefined
55, // 67 0x43 0x37 KP * QZ_KP_MULTIPLY
0, // 68 0x44 Undefined
78, // 69 0x45 0x4e KP + QZ_KP_PLUS
0, // 70 0x46 Undefined
69, // 71 0x47 0x45 NUM QZ_NUMLOCK
0, // 72 0x48 Undefined
0, // 73 0x49 Undefined
0, // 74 0x4A Undefined
181,// 75 0x4B 0xb5 E0,35 KP / QZ_KP_DIVIDE
152,// 76 0x4C 0x9c E0,1C KP EN QZ_KP_ENTER
0, // 77 0x4D undefined
74, // 78 0x4E 0x4a KP - QZ_KP_MINUS
0, // 79 0x4F Undefined
0, // 80 0x50 Undefined
0, // 81 0x51 QZ_KP_EQUALS
82, // 82 0x52 0x52 KP 0 QZ_KP0
79, // 83 0x53 0x4f KP 1 QZ_KP1
80, // 84 0x54 0x50 KP 2 QZ_KP2
81, // 85 0x55 0x51 KP 3 QZ_KP3
75, // 86 0x56 0x4b KP 4 QZ_KP4
76, // 87 0x57 0x4c KP 5 QZ_KP5
77, // 88 0x58 0x4d KP 6 QZ_KP6
71, // 89 0x59 0x47 KP 7 QZ_KP7
0, // 90 0x5A Undefined
72, // 91 0x5B 0x48 KP 8 QZ_KP8
73, // 92 0x5C 0x49 KP 9 QZ_KP9
0, // 93 0x5D Undefined
0, // 94 0x5E Undefined
0, // 95 0x5F Undefined
63, // 96 0x60 0x3f F5 QZ_F5
64, // 97 0x61 0x40 F6 QZ_F6
65, // 98 0x62 0x41 F7 QZ_F7
61, // 99 0x63 0x3d F3 QZ_F3
66, // 100 0x64 0x42 F8 QZ_F8
67, // 101 0x65 0x43 F9 QZ_F9
0, // 102 0x66 Undefined
87, // 103 0x67 0x57 F11 QZ_F11
0, // 104 0x68 Undefined
183,// 105 0x69 0xb7 QZ_PRINT
0, // 106 0x6A Undefined
70, // 107 0x6B 0x46 SCROLL QZ_SCROLLOCK
0, // 108 0x6C Undefined
68, // 109 0x6D 0x44 F10 QZ_F10
0, // 110 0x6E Undefined
88, // 111 0x6F 0x58 F12 QZ_F12
0, // 112 0x70 Undefined
110,// 113 0x71 0x0 QZ_PAUSE
210,// 114 0x72 0xd2 E0,52 INSERT QZ_INSERT
199,// 115 0x73 0xc7 E0,47 HOME QZ_HOME
201,// 116 0x74 0xc9 E0,49 PG UP QZ_PAGEUP
211,// 117 0x75 0xd3 E0,53 DELETE QZ_DELETE
62, // 118 0x76 0x3e F4 QZ_F4
207,// 119 0x77 0xcf E0,4f END QZ_END
60, // 120 0x78 0x3c F2 QZ_F2
209,// 121 0x79 0xd1 E0,51 PG DN QZ_PAGEDOWN
59, // 122 0x7A 0x3b F1 QZ_F1
203,// 123 0x7B 0xcb e0,4B L ARROW QZ_LEFT
205,// 124 0x7C 0xcd e0,4D R ARROW QZ_RIGHT
208,// 125 0x7D 0xd0 E0,50 D ARROW QZ_DOWN
200,// 126 0x7E 0xc8 E0,48 U ARROW QZ_UP
/* completed according to http://www.libsdl.org/cgi/cvsweb.cgi/SDL12/src/video/quartz/SDL_QuartzKeys.h?rev=1.6&content-type=text/x-cvsweb-markup
*/
/* Aditional 104 Key XP-Keyboard Scancodes from http://www.computer-engineering.org/ps2keyboard/scancodes1.html
*/
/*
219 // 0xdb e0,5b L GUI
220 // 0xdc e0,5c R GUI
221 // 0xdd e0,5d APPS
// E0,2A,E0,37 PRNT SCRN
// E1,1D,45,E1,9D,C5 PAUSE
83 // 0x53 0x53 KP .
// ACPI Scan Codes
222 // 0xde E0, 5E Power
223 // 0xdf E0, 5F Sleep
227 // 0xe3 E0, 63 Wake
// Windows Multimedia Scan Codes
153 // 0x99 E0, 19 Next Track
144 // 0x90 E0, 10 Previous Track
164 // 0xa4 E0, 24 Stop
162 // 0xa2 E0, 22 Play/Pause
160 // 0xa0 E0, 20 Mute
176 // 0xb0 E0, 30 Volume Up
174 // 0xae E0, 2E Volume Down
237 // 0xed E0, 6D Media Select
236 // 0xec E0, 6C E-Mail
161 // 0xa1 E0, 21 Calculator
235 // 0xeb E0, 6B My Computer
229 // 0xe5 E0, 65 WWW Search
178 // 0xb2 E0, 32 WWW Home
234 // 0xea E0, 6A WWW Back
233 // 0xe9 E0, 69 WWW Forward
232 // 0xe8 E0, 68 WWW Stop
231 // 0xe7 E0, 67 WWW Refresh
230 // 0xe6 E0, 66 WWW Favorites
*/
};
int cocoa_keycode_to_qemu(int keycode)
{
if((sizeof(keymap)/sizeof(int)) <= keycode)
{
printf("(cocoa) warning unknow keycode 0x%x\n", keycode);
return 0;
}
return keymap[keycode];
}
/*
------------------------------------------------------
QemuCocoaView
------------------------------------------------------
*/
@interface QemuCocoaView : NSView
{
QEMUScreen screen;
NSWindow *fullScreenWindow;
float cx,cy,cw,ch,cdx,cdy;
CGDataProviderRef dataProviderRef;
int modifiers_state[256];
BOOL isMouseGrabed;
BOOL isFullscreen;
BOOL isAbsoluteEnabled;
BOOL isTabletEnabled;
}
- (void) resizeContentToWidth:(int)w height:(int)h displayState:
(DisplayState *)ds;
- (void) grabMouse;
- (void) ungrabMouse;
- (void) toggleFullScreen:(id)sender;
- (void) handleEvent:(NSEvent *)event;
- (void) setAbsoluteEnabled:(BOOL)tIsAbsoluteEnabled;
- (BOOL) isMouseGrabed;
- (BOOL) isAbsoluteEnabled;
- (float) cdx;
- (float) cdy;
- (QEMUScreen) gscreen;
@end
@implementation QemuCocoaView
- (id)initWithFrame:(NSRect)frameRect
{
COCOA_DEBUG("QemuCocoaView: initWithFrame\n");
self = [super initWithFrame:frameRect];
if (self) {
screen.bitsPerComponent = 8;
screen.bitsPerPixel = 32;
screen.width = frameRect.size.width;
screen.height = frameRect.size.height;
}
return self;
}
- (void) dealloc
{
COCOA_DEBUG("QemuCocoaView: dealloc\n");
if (screenBuffer)
free(screenBuffer);
if (dataProviderRef)
CGDataProviderRelease(dataProviderRef);
[super dealloc];
}
- (void) drawRect:(NSRect) rect
{
COCOA_DEBUG("QemuCocoaView: drawRect\n");
if ((int)screenBuffer == -1)
return;
// get CoreGraphic context
CGContextRef viewContextRef = [[NSGraphicsContext currentContext]
graphicsPort];
CGContextSetInterpolationQuality (viewContextRef,
kCGInterpolationNone);
CGContextSetShouldAntialias (viewContextRef, NO);
// draw screen bitmap directly to Core Graphics context
if (dataProviderRef) {
CGImageRef imageRef = CGImageCreate(
screen.width, //width
screen.height, //height
screen.bitsPerComponent, //bitsPerComponent
screen.bitsPerPixel, //bitsPerPixel
(screen.width * 4), //bytesPerRow
#if __LITTLE_ENDIAN__
CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB), //
colorspace for OS X >= 10.4
kCGImageAlphaNoneSkipLast,
#else
CGColorSpaceCreateDeviceRGB(), //colorspace for OS X <
10.4 (actually ppc)
kCGImageAlphaNoneSkipFirst, //bitmapInfo
#endif
dataProviderRef, //provider
NULL, //decode
0, //interpolate
kCGRenderingIntentDefault //intent
);
// test if host support "CGImageCreateWithImageInRect" at compiletime
#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
if (CGImageCreateWithImageInRect == NULL) { // test if
"CGImageCreateWithImageInRect" is supported on host at runtime
#endif
// compatibility drawing code (draws everything) (OS X <
10.4)
CGContextDrawImage (viewContextRef, CGRectMake(0, 0,
[self bounds].size.width, [self bounds].size.height), imageRef);
#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
} else {
// selective drawing code (draws only dirty rectangles)
(OS X >= 10.4)
const NSRect *rectList;
int rectCount;
int i;
CGImageRef clipImageRef;
CGRect clipRect;
[self getRectsBeingDrawn:&rectList count:&rectCount];
for (i = 0; i < rectCount; i++) {
clipRect.origin.x = rectList[i].origin.x / cdx;
clipRect.origin.y = (float)screen.height -
(rectList[i].origin.y + rectList[i].size.height) / cdy;
clipRect.size.width = rectList[i].size.width / cdx;
clipRect.size.height = rectList[i].size.height / cdy;
clipImageRef = CGImageCreateWithImageInRect(
imageRef,
clipRect
);
CGContextDrawImage (viewContextRef,
cgrect(rectList[i]), clipImageRef);
CGImageRelease (clipImageRef);
}
}
#endif
CGImageRelease (imageRef);
}
}
- (void) setContentDimensions
{
COCOA_DEBUG("QemuCocoaView: setContentDimensions\n");
if (isFullscreen) {
cdx = [[NSScreen mainScreen] frame].size.width /
(float)screen.width;
cdy = [[NSScreen mainScreen] frame].size.height /
(float)screen.height;
cw = screen.width * cdx;
ch = screen.height * cdy;
cx = ([[NSScreen mainScreen] frame].size.width - cw) / 2.0;
cy = ([[NSScreen mainScreen] frame].size.height - ch) / 2.0;
} else {
cx = 0;
cy = 0;
cw = screen.width;
ch = screen.height;
cdx = 1.0;
cdy = 1.0;
}
}
- (void) resizeContentToWidth:(int)w height:(int)h displayState:
(DisplayState *)ds
{
COCOA_DEBUG("QemuCocoaView: resizeContent\n");
// update screenBuffer
if (dataProviderRef)
CGDataProviderRelease(dataProviderRef);
if (screenBuffer)
free(screenBuffer);
screenBuffer = malloc( w * 4 * h );
ds->data = screenBuffer;
ds->linesize = (w * 4);
ds->depth = 32;
ds->width = w;
ds->height = h;
#ifdef __LITTLE_ENDIAN__
ds->bgr = 1;
#else
ds->bgr = 0;
#endif
dataProviderRef = CGDataProviderCreateWithData(NULL,
screenBuffer, w * 4 * h, NULL);
// update windows
if (isFullscreen) {
[[fullScreenWindow contentView] setFrame:[[NSScreen
mainScreen] frame]];
[normalWindow setFrame:NSMakeRect([normalWindow
frame].origin.x, [normalWindow frame].origin.y - h + screen.height, w,
h + [normalWindow frame].size.height - screen.height) display:NO
animate:NO];
} else {
if (qemu_name)
[normalWindow setTitle:[NSString stringWithFormat:@"QEMU
%s", qemu_name]];
[normalWindow setFrame:NSMakeRect([normalWindow
frame].origin.x, [normalWindow frame].origin.y - h + screen.height, w,
h + [normalWindow frame].size.height - screen.height) display:YES
animate:YES];
}
screen.width = w;
screen.height = h;
[self setContentDimensions];
[self setFrame:NSMakeRect(cx, cy, cw, ch)];
}
- (void) toggleFullScreen:(id)sender
{
COCOA_DEBUG("QemuCocoaView: toggleFullScreen\n");
if (isFullscreen) { // switch from fullscreen to desktop
isFullscreen = FALSE;
[self ungrabMouse];
[self setContentDimensions];
// test if host support "enterFullScreenMode:withOptions" at compiletime
#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
if ([NSView
respondsToSelector:@selector(exitFullScreenModeWithOptions:)]) { //
test if "exitFullScreenModeWithOptions" is supported on host at runtime
[self exitFullScreenModeWithOptions:nil];
} else {
#endif
[fullScreenWindow close];
[normalWindow setContentView: self];
[normalWindow makeKeyAndOrderFront: self];
[NSMenu setMenuBarVisible:YES];
#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
}
#endif
} else { // switch from desktop to fullscreen
isFullscreen = TRUE;
[self grabMouse];
[self setContentDimensions];
// test if host support "enterFullScreenMode:withOptions" at compiletime
#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
if ([NSView
respondsToSelector:@selector(enterFullScreenMode:withOptions:)]) { //
test if "enterFullScreenMode:withOptions" is supported on host at
runtime
[self enterFullScreenMode:[NSScreen mainScreen]
withOptions:[NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:NO],
NSFullScreenModeAllScreens,
[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber
numberWithBool:NO], kCGDisplayModeIsStretched, nil],
NSFullScreenModeSetting,
nil]];
} else {
#endif
[NSMenu setMenuBarVisible:NO];
fullScreenWindow = [[NSWindow alloc] initWithContentRect:
[[NSScreen mainScreen] frame]
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered
defer:NO];
[fullScreenWindow setHasShadow:NO];
[fullScreenWindow setContentView:self];
[fullScreenWindow makeKeyAndOrderFront:self];
#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
}
#endif
}
}
- (void) handleEvent:(NSEvent *)event
{
COCOA_DEBUG("QemuCocoaView: handleEvent\n");
int buttons = 0;
int keycode;
NSPoint p = [event locationInWindow];
switch ([event type]) {
case NSFlagsChanged:
keycode = cocoa_keycode_to_qemu([event keyCode]);
if (keycode) {
if (keycode == 58 || keycode == 69) { // emulate caps
lock and num lock keydown and keyup
kbd_put_keycode(keycode);
kbd_put_keycode(keycode | 0x80);
} else if (is_graphic_console()) {
if (keycode & 0x80)
kbd_put_keycode(0xe0);
if (modifiers_state[keycode] == 0) { // keydown
kbd_put_keycode(keycode & 0x7f);
modifiers_state[keycode] = 1;
} else { // keyup
kbd_put_keycode(keycode | 0x80);
modifiers_state[keycode] = 0;
}
}
}
// release Mouse grab when pressing ctrl+alt
if (!isFullscreen && ([event modifierFlags] &
NSControlKeyMask) && ([event modifierFlags] & NSAlternateKeyMask)) {
[self ungrabMouse];
}
break;
case NSKeyDown:
// forward command Key Combos
if ([event modifierFlags] & NSCommandKeyMask) {
[NSApp sendEvent:event];
return;
}
// default
keycode = cocoa_keycode_to_qemu([event keyCode]);
// handle control + alt Key Combos (ctrl+alt is reserved
for QEMU)
if (([event modifierFlags] & NSControlKeyMask) && ([event
modifierFlags] & NSAlternateKeyMask)) {
switch (keycode) {
// enable graphic console
case 0x02 ... 0x0a: // '1' to '9' keys
console_select(keycode - 0x02);
break;
}
// handle keys for graphic console
} else if (is_graphic_console()) {
if (keycode & 0x80) //check bit for e0 in front
kbd_put_keycode(0xe0);
kbd_put_keycode(keycode & 0x7f); //remove e0 bit in
front
// handlekeys for Monitor
} else {
int keysym = 0;
switch([event keyCode]) {
case 115:
keysym = QEMU_KEY_HOME;
break;
case 117:
keysym = QEMU_KEY_DELETE;
break;
case 119:
keysym = QEMU_KEY_END;
break;
case 123:
keysym = QEMU_KEY_LEFT;
break;
case 124:
keysym = QEMU_KEY_RIGHT;
break;
case 125:
keysym = QEMU_KEY_DOWN;
break;
case 126:
keysym = QEMU_KEY_UP;
break;
default:
{
NSString *ks = [event characters];
if ([ks length] > 0)
keysym = [ks characterAtIndex:0];
}
}
if (keysym)
kbd_put_keysym(keysym);
}
break;
case NSKeyUp:
keycode = cocoa_keycode_to_qemu([event keyCode]);
if (is_graphic_console()) {
if (keycode & 0x80)
kbd_put_keycode(0xe0);
kbd_put_keycode(keycode | 0x80); //add 128 to signal
release of key
}
break;
case NSMouseMoved:
if (isAbsoluteEnabled) {
if (p.x < 0 || p.x > screen.width || p.y < 0 || p.y >
screen.height || ![[self window] isKeyWindow]) {
if (isTabletEnabled) { // if we leave the window,
deactivate the tablet
[NSCursor unhide];
isTabletEnabled = FALSE;
}
} else {
if (!isTabletEnabled) { // if we enter the
window, activate the tablet
[NSCursor hide];
isTabletEnabled = TRUE;
}
}
}
COCOA_MOUSE_EVENT
break;
case NSLeftMouseDown:
if ([event modifierFlags] & NSCommandKeyMask) {
buttons |= MOUSE_EVENT_RBUTTON;
} else {
buttons |= MOUSE_EVENT_LBUTTON;
}
COCOA_MOUSE_EVENT
break;
case NSRightMouseDown:
buttons |= MOUSE_EVENT_RBUTTON;
COCOA_MOUSE_EVENT
break;
case NSOtherMouseDown:
buttons |= MOUSE_EVENT_MBUTTON;
COCOA_MOUSE_EVENT
break;
case NSLeftMouseDragged:
if ([event modifierFlags] & NSCommandKeyMask) {
buttons |= MOUSE_EVENT_RBUTTON;
} else {
buttons |= MOUSE_EVENT_LBUTTON;
}
COCOA_MOUSE_EVENT
break;
case NSRightMouseDragged:
buttons |= MOUSE_EVENT_RBUTTON;
COCOA_MOUSE_EVENT
break;
case NSOtherMouseDragged:
buttons |= MOUSE_EVENT_MBUTTON;
COCOA_MOUSE_EVENT
break;
case NSLeftMouseUp:
if (isTabletEnabled) {
COCOA_MOUSE_EVENT
} else if (!isMouseGrabed) {
if (p.x > -1 && p.x < screen.width && p.y > -1 && p.y
< screen.height) {
[self grabMouse];
} else {
[NSApp sendEvent:event];
}
} else {
COCOA_MOUSE_EVENT
}
break;
case NSRightMouseUp:
COCOA_MOUSE_EVENT
break;
case NSOtherMouseUp:
COCOA_MOUSE_EVENT
break;
case NSScrollWheel:
if (isTabletEnabled || isMouseGrabed) {
kbd_mouse_event(0, 0, -[event deltaY], 0);
} else {
[NSApp sendEvent:event];
}
break;
default:
[NSApp sendEvent:event];
}
}
- (void) grabMouse
{
COCOA_DEBUG("QemuCocoaView: grabMouse\n");
if (!isFullscreen) {
if (qemu_name)
[normalWindow setTitle:[NSString stringWithFormat:@"QEMU
%s - (Press ctrl + alt to release Mouse)", qemu_name]];
else
[normalWindow setTitle:@"QEMU - (Press ctrl + alt to
release Mouse)"];
}
[NSCursor hide];
CGAssociateMouseAndMouseCursorPosition(FALSE);
isMouseGrabed = TRUE; // while isMouseGrabed = TRUE, QemuCocoaApp
sends all events to [cocoaView handleEvent:]
}
- (void) ungrabMouse
{
COCOA_DEBUG("QemuCocoaView: ungrabMouse\n");
if (!isFullscreen) {
if (qemu_name)
[normalWindow setTitle:[NSString stringWithFormat:@"QEMU
%s", qemu_name]];
else
[normalWindow setTitle:@"QEMU"];
}
[NSCursor unhide];
CGAssociateMouseAndMouseCursorPosition(TRUE);
isMouseGrabed = FALSE;
}
- (void) setAbsoluteEnabled:(BOOL)tIsAbsoluteEnabled
{isAbsoluteEnabled = tIsAbsoluteEnabled;}
- (BOOL) isMouseGrabed {return isMouseGrabed;}
- (BOOL) isAbsoluteEnabled {return isAbsoluteEnabled;}
- (float) cdx {return cdx;}
- (float) cdy {return cdy;}
- (QEMUScreen) gscreen {return screen;}
@end
/*
------------------------------------------------------
QemuCocoaAppController
------------------------------------------------------
*/
@interface QemuCocoaAppController : NSObject
{
}
- (void)startEmulationWithArgc:(int)argc argv:(char**)argv;
- (void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:
(int)returnCode contextInfo:(void *)contextInfo;
- (void)toggleFullScreen:(id)sender;
- (void)showQEMUDoc:(id)sender;
- (void)showQEMUTec:(id)sender;
@end
@implementation QemuCocoaAppController
- (id) init
{
COCOA_DEBUG("QemuCocoaAppController: init\n");
self = [super init];
if (self) {
// create a view and add it to the window
cocoaView = [[QemuCocoaView alloc]
initWithFrame:NSMakeRect(0.0, 0.0, 640.0, 480.0)];
if(!cocoaView) {
fprintf(stderr, "(cocoa) can't create a view\n");
exit(1);
}
// create a window
normalWindow = [[NSWindow alloc] initWithContentRect:
[cocoaView frame]
styleMask:NSTitledWindowMask|NSMiniaturizableWindowMask|
NSClosableWindowMask
backing:NSBackingStoreBuffered defer:NO];
if(!normalWindow) {
fprintf(stderr, "(cocoa) can't create window\n");
exit(1);
}
[normalWindow setAcceptsMouseMovedEvents:YES];
[normalWindow setTitle:[NSString stringWithFormat:@"QEMU"]];
[normalWindow setContentView:cocoaView];
[normalWindow makeKeyAndOrderFront:self];
}
return self;
}
- (void) dealloc
{
COCOA_DEBUG("QemuCocoaAppController: dealloc\n");
if (cocoaView)
[cocoaView release];
[super dealloc];
}
- (void)applicationDidFinishLaunching: (NSNotification *) note
{
COCOA_DEBUG("QemuCocoaAppController: applicationDidFinishLaunching
\n");
// Display an open dialog box if no argument were passed or
// if qemu was launched from the finder ( the Finder passes "-
psn" )
if( gArgc <= 1 || strncmp ((char *)gArgv[1], "-psn", 4) == 0) {
NSOpenPanel *op = [[NSOpenPanel alloc] init];
[op setPrompt:@"Boot image"];
[op setMessage:@"Select the disk image you want to boot.\n
\nHit the \"Cancel\" button to quit"];
[op beginSheetForDirectory:nil file:nil types:[NSArray
arrayWithObjects
:@"img",@"iso",@"dmg",@"qcow",@"cow",@"cloop",@"vmdk",nil]
modalForWindow:normalWindow modalDelegate:self
didEndSelector:@selector(openPanelDidEnd:returnCode:contextInfo:)
contextInfo:NULL];
} else {
// or Launch Qemu, with the global args
[self startEmulationWithArgc:gArgc argv:(char **)gArgv];
}
}
- (void)applicationWillTerminate:(NSNotification *)aNotification
{
COCOA_DEBUG("QemuCocoaAppController: applicationWillTerminate\n");
qemu_system_shutdown_request();
exit(0);
}
- (void)startEmulationWithArgc:(int)argc argv:(char**)argv
{
COCOA_DEBUG("QemuCocoaAppController: startEmulationWithArgc\n");
int status;
status = qemu_main(argc, argv);
exit(status);
}
- (void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:
(int)returnCode contextInfo:(void *)contextInfo
{
COCOA_DEBUG("QemuCocoaAppController: openPanelDidEnd\n");
if(returnCode == NSCancelButton) {
exit(0);
} else if(returnCode == NSOKButton) {
char *bin = "qemu";
char *img = (char*)[ [ sheet filename ]
cStringUsingEncoding:NSASCIIStringEncoding];
char **argv = (char**)malloc( sizeof(char*)*3 );
asprintf(&argv[0], "%s", bin);
asprintf(&argv[1], "-hda");
asprintf(&argv[2], "%s", img);
printf("Using argc %d argv %s -hda %s\n", 3, bin, img);
[self startEmulationWithArgc:3 argv:(char**)argv];
}
}
- (void)toggleFullScreen:(id)sender
{
COCOA_DEBUG("QemuCocoaAppController: toggleFullScreen\n");
[cocoaView toggleFullScreen:sender];
}
- (void)showQEMUDoc:(id)sender
{
COCOA_DEBUG("QemuCocoaAppController: showQEMUDoc\n");
[[NSWorkspace sharedWorkspace] openFile:[NSString
stringWithFormat:@"%@/../doc/qemu/qemu-doc.html",
[[NSBundle mainBundle] resourcePath]] withApplication:@"Help
Viewer"];
}
- (void)showQEMUTec:(id)sender
{
COCOA_DEBUG("QemuCocoaAppController: showQEMUTec\n");
[[NSWorkspace sharedWorkspace] openFile:[NSString
stringWithFormat:@"%@/../doc/qemu/qemu-tech.html",
[[NSBundle mainBundle] resourcePath]] withApplication:@"Help
Viewer"];
}
@end
// Dock Connection
typedef struct CPSProcessSerNum
{
UInt32 lo;
UInt32 hi;
} CPSProcessSerNum;
extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn);
extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn,
UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5);
extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn);
int main (int argc, const char * argv[]) {
gArgc = argc;
gArgv = (char **)argv;
CPSProcessSerNum PSN;
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
[NSApplication sharedApplication];
if (!CPSGetCurrentProcess(&PSN))
if (!CPSEnableForegroundOperation(&PSN,0x03,0x3C,0x2C,0x1103))
if (!CPSSetFrontProcess(&PSN))
[NSApplication sharedApplication];
// Add menus
NSMenu *menu;
NSMenuItem *menuItem;
[NSApp setMainMenu:[[NSMenu alloc] init]];
// Application menu
menu = [[NSMenu alloc] initWithTitle:@""];
[menu addItemWithTitle:@"About QEMU"
action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; //
About QEMU
[menu addItem:[NSMenuItem separatorItem]]; //Separator
[menu addItemWithTitle:@"Hide QEMU" action:@selector(hide:)
keyEquivalent:@"h"]; //Hide QEMU
menuItem = (NSMenuItem *)[menu addItemWithTitle:@"Hide Others"
action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; // Hide
Others
[menuItem setKeyEquivalentModifierMask:(NSAlternateKeyMask|
NSCommandKeyMask)];
[menu addItemWithTitle:@"Show All"
action:@selector(unhideAllApplications:) keyEquivalent:@""]; // Show All
[menu addItem:[NSMenuItem separatorItem]]; //Separator
[menu addItemWithTitle:@"Quit QEMU" action:@selector(terminate:)
keyEquivalent:@"q"];
menuItem = [[NSMenuItem alloc] initWithTitle:@"Apple" action:nil
keyEquivalent:@""];
[menuItem setSubmenu:menu];
[[NSApp mainMenu] addItem:menuItem];
[NSApp performSelector:@selector(setAppleMenu:)
withObject:menu]; // Workaround (this method is private since 10.4+)
// View menu
menu = [[NSMenu alloc] initWithTitle:@"View"];
[menu addItem: [[[NSMenuItem alloc] initWithTitle:@"Enter
Fullscreen" action:@selector(toggleFullScreen:) keyEquivalent:@"f"]
autorelease]]; // Fullscreen
menuItem = [[[NSMenuItem alloc] initWithTitle:@"View" action:nil
keyEquivalent:@""] autorelease];
[menuItem setSubmenu:menu];
[[NSApp mainMenu] addItem:menuItem];
// Window menu
menu = [[NSMenu alloc] initWithTitle:@"Window"];
[menu addItem: [[[NSMenuItem alloc] initWithTitle:@"Minimize"
action:@selector(performMiniaturize:) keyEquivalent:@"m"]
autorelease]]; // Miniaturize
menuItem = [[[NSMenuItem alloc] initWithTitle:@"Window"
action:nil keyEquivalent:@""] autorelease];
[menuItem setSubmenu:menu];
[[NSApp mainMenu] addItem:menuItem];
[NSApp setWindowsMenu:menu];
// Help menu
menu = [[NSMenu alloc] initWithTitle:@"Help"];
[menu addItem: [[[NSMenuItem alloc] initWithTitle:@"QEMU
Documentation" action:@selector(showQEMUDoc:) keyEquivalent:@"?"]
autorelease]]; // QEMU Help
[menu addItem: [[[NSMenuItem alloc] initWithTitle:@"QEMU
Technology" action:@selector(showQEMUTec:) keyEquivalent:@""]
autorelease]]; // QEMU Help
menuItem = [[[NSMenuItem alloc] initWithTitle:@"Window"
action:nil keyEquivalent:@""] autorelease];
[menuItem setSubmenu:menu];
[[NSApp mainMenu] addItem:menuItem];
// Create an Application controller
QemuCocoaAppController *appController = [[QemuCocoaAppController
alloc] init];
[NSApp setDelegate:appController];
// Start the main event loop
[NSApp run];
[appController release];
[pool release];
return 0;
}
#pragma mark qemu
static void cocoa_update(DisplayState *ds, int x, int y, int w, int h)
{
COCOA_DEBUG("qemu_cocoa: cocoa_update\n");
NSRect rect;
if ([cocoaView cdx] == 1.0) {
rect = NSMakeRect(x, [cocoaView gscreen].height - y - h, w, h);
} else {
rect = NSMakeRect(
x * [cocoaView cdx],
([cocoaView gscreen].height - y - h) * [cocoaView cdy],
w * [cocoaView cdx],
h * [cocoaView cdy]);
}
[cocoaView displayRect:rect];
}
static void cocoa_resize(DisplayState *ds, int w, int h)
{
COCOA_DEBUG("qemu_cocoa: cocoa_resize\n");
[cocoaView resizeContentToWidth:w height:h displayState:ds];
}
static void cocoa_refresh(DisplayState *ds)
{
COCOA_DEBUG("qemu_cocoa: cocoa_refresh\n");
if (kbd_mouse_is_absolute()) {
if (![cocoaView isAbsoluteEnabled]) {
if ([cocoaView isMouseGrabed]) {
[cocoaView ungrabMouse];
}
}
[cocoaView setAbsoluteEnabled:YES];
}
NSDate *distantPast;
NSEvent *event;
distantPast = [NSDate distantPast];
do {
event = [NSApp nextEventMatchingMask:NSAnyEventMask
untilDate:distantPast
inMode: NSDefaultRunLoopMode dequeue:YES];
if (event != nil) {
[cocoaView handleEvent:event];
}
} while(event != nil);
vga_hw_update();
}
static void cocoa_cleanup(void)
{
COCOA_DEBUG("qemu_cocoa: cocoa_cleanup\n");
}
void cocoa_display_init(DisplayState *ds, int full_screen)
{
COCOA_DEBUG("qemu_cocoa: cocoa_display_init\n");
// register vga outpu callbacks
ds->dpy_update = cocoa_update;
ds->dpy_resize = cocoa_resize;
ds->dpy_refresh = cocoa_refresh;
// give window a initial Size
cocoa_resize(ds, 640, 400);
// register cleanup function
atexit(cocoa_cleanup);
}
[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 2111 bytes --]
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [patch] cocoa.m - Core Graphics support
2008-01-21 16:18 [Qemu-devel] [patch] cocoa.m - Core Graphics support Mike Kronenberg
@ 2008-01-30 18:59 ` Alexander Graf
2008-01-30 19:05 ` Alexander Graf
` (2 more replies)
0 siblings, 3 replies; 15+ messages in thread
From: Alexander Graf @ 2008-01-30 18:59 UTC (permalink / raw)
To: qemu-devel
On Jan 21, 2008, at 5:18 PM, Mike Kronenberg wrote:
> This is a complete rewrite of cocoa.m to support Core Graphics.
>
> As mentioned in earlier threads, the QuickDraw API is depreciated
> starting with OS X 10.4.
> Now with OS X 10.5 it won't even compile QuickDraw code on x86_64.
>
>
> This implementation of cocoa.m has the following features:
>
> [new] partial drawing of the window as needed, implemented with CG.
> [new] fullscreen support
> [new] tablet support
> [new] View menu and item to enter Fullscreen (cmd-f)
> [new] Help menu and items to show qemu-doc.html (cmd-?) and qemu-
> tec.html in the OS X "Help Viewer"
> [new] -name is shown in Title-bar of window
> [fix] Application menu creation for 10.4+ (API is private as of 10.4)
> [fix] Mouse-clicks on the guests window widgets are no longer
> intercepted
> [fix] apple keyboard shortcuts forwarded (minimize (cmd-m), hide
> QEMU (cmd-h), quit QEMU (cmd-q))
>
> It should compile on ppc/intel starting form 10.3 (10.2 with the
> known workarounds).
>
> Please test and comment
I'm sorry that I didn't find the time to test this implementation
before.
It's damn slow.
I ran it using my x86_64 on 10.5.1, targetting x86_64-softmmu and
booting a linux kernel. I could literally see every like getting
repainted (which btw did not happen with my quick hacky version I sent
to the list some time ago).
I think the major problem is that too much is being done during
drawRect. If I understand the code correctly, you create CGImage
objects on every repaint, which is prone to be slow.
Why not simply reuse the framebuffer qemu provides anyway and leave
everything else to CG?
Alex
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [patch] cocoa.m - Core Graphics support
2008-01-30 18:59 ` Alexander Graf
@ 2008-01-30 19:05 ` Alexander Graf
2008-01-30 20:30 ` Mike Kronenberg
2008-01-30 20:44 ` Mike Kronenberg
2 siblings, 0 replies; 15+ messages in thread
From: Alexander Graf @ 2008-01-30 19:05 UTC (permalink / raw)
To: qemu-devel
On Jan 30, 2008, at 7:59 PM, Alexander Graf wrote:
>
> On Jan 21, 2008, at 5:18 PM, Mike Kronenberg wrote:
>
>> This is a complete rewrite of cocoa.m to support Core Graphics.
>>
>> As mentioned in earlier threads, the QuickDraw API is depreciated
>> starting with OS X 10.4.
>> Now with OS X 10.5 it won't even compile QuickDraw code on x86_64.
>>
>>
>> This implementation of cocoa.m has the following features:
>>
>> [new] partial drawing of the window as needed, implemented with CG.
>> [new] fullscreen support
>> [new] tablet support
>> [new] View menu and item to enter Fullscreen (cmd-f)
>> [new] Help menu and items to show qemu-doc.html (cmd-?) and qemu-
>> tec.html in the OS X "Help Viewer"
>> [new] -name is shown in Title-bar of window
>> [fix] Application menu creation for 10.4+ (API is private as of 10.4)
>> [fix] Mouse-clicks on the guests window widgets are no longer
>> intercepted
>> [fix] apple keyboard shortcuts forwarded (minimize (cmd-m), hide
>> QEMU (cmd-h), quit QEMU (cmd-q))
>>
>> It should compile on ppc/intel starting form 10.3 (10.2 with the
>> known workarounds).
>>
>> Please test and comment
>
> I'm sorry that I didn't find the time to test this implementation
> before.
>
> It's damn slow.
>
> I ran it using my x86_64 on 10.5.1, targetting x86_64-softmmu and
> booting a linux kernel. I could literally see every like getting
> repainted (which btw did not happen with my quick hacky version I
> sent to the list some time ago).
>
> I think the major problem is that too much is being done during
> drawRect. If I understand the code correctly, you create CGImage
> objects on every repaint, which is prone to be slow.
>
> Why not simply reuse the framebuffer qemu provides anyway and leave
> everything else to CG?
I just reread my mail again and realized that I didn't say anything
positive. Sorry about that.
It's great to see someone working on Mac OS X support and thanks a lot
for writing a compatible implementation of cocoa.m that works with
every Mac OS X version out there.
Alex
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [patch] cocoa.m - Core Graphics support
2008-01-30 18:59 ` Alexander Graf
2008-01-30 19:05 ` Alexander Graf
@ 2008-01-30 20:30 ` Mike Kronenberg
2008-01-30 20:39 ` Johannes Schindelin
` (3 more replies)
2008-01-30 20:44 ` Mike Kronenberg
2 siblings, 4 replies; 15+ messages in thread
From: Mike Kronenberg @ 2008-01-30 20:30 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 2918 bytes --]
On 30.01.2008, at 19:59, Alexander Graf wrote:
>
> On Jan 21, 2008, at 5:18 PM, Mike Kronenberg wrote:
>
>> This is a complete rewrite of cocoa.m to support Core Graphics.
>>
>> As mentioned in earlier threads, the QuickDraw API is depreciated
>> starting with OS X 10.4.
>> Now with OS X 10.5 it won't even compile QuickDraw code on x86_64.
>>
>>
>> This implementation of cocoa.m has the following features:
>>
>> [new] partial drawing of the window as needed, implemented with CG.
>> [new] fullscreen support
>> [new] tablet support
>> [new] View menu and item to enter Fullscreen (cmd-f)
>> [new] Help menu and items to show qemu-doc.html (cmd-?) and qemu-
>> tec.html in the OS X "Help Viewer"
>> [new] -name is shown in Title-bar of window
>> [fix] Application menu creation for 10.4+ (API is private as of 10.4)
>> [fix] Mouse-clicks on the guests window widgets are no longer
>> intercepted
>> [fix] apple keyboard shortcuts forwarded (minimize (cmd-m), hide
>> QEMU (cmd-h), quit QEMU (cmd-q))
>>
>> It should compile on ppc/intel starting form 10.3 (10.2 with the
>> known workarounds).
>>
>> Please test and comment
>
> I'm sorry that I didn't find the time to test this implementation
> before.
>
> It's damn slow.
>
> I ran it using my x86_64 on 10.5.1, targetting x86_64-softmmu and
> booting a linux kernel. I could literally see every like getting
> repainted (which btw did not happen with my quick hacky version I
> sent to the list some time ago).
>
> I think the major problem is that too much is being done during
> drawRect. If I understand the code correctly, you create CGImage
> objects on every repaint, which is prone to be slow.
>
> Why not simply reuse the framebuffer qemu provides anyway and leave
> everything else to CG?
>
> Alex
>
>
Hi Alex,
yes, as stated earlyer, it is slower than Quickdraw, especially if the
whole screen is redrawn. Overal emulation speed for GUI apps is
faster, dough, as only small portions of the screen are redrawn.
Unfortunateley, there is no "official" direct access to the
framebuffer anymore, since apple depreciated QuickDraw. [1]
This way, there is no sharing/direct mapping of the cg framebuffer and
qemu screenbuffer anymore.
Every time, a section needs display, that part of the qemu
screenbuffer is mapped to a cg image and then copied on top of the CG
stack.
CG is fully OpenGL based, so basically, if it needs to refresh an
area, it has to load the area as texture, hence the copy.
Offtoppic about updated regions in Windows:
While testing with Quartzdebug, I realized, that qemu is updating
always the whole screenwidth even if only the mouse is moved... is
this a qemu problem, or is this the default windows behaviour?
Mike
[1] http://developer.apple.com/documentation/Carbon/Conceptual/QuickDrawToQuartz2D/tq_image_data/chapter_6_section_2.html#/
/apple_ref/doc/uid/TP40001098-CH227-BBCFFDBB
[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 2111 bytes --]
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [patch] cocoa.m - Core Graphics support
2008-01-30 20:30 ` Mike Kronenberg
@ 2008-01-30 20:39 ` Johannes Schindelin
2008-01-30 21:18 ` andrzej zaborowski
2008-01-30 21:00 ` Pierre d'Herbemont
` (2 subsequent siblings)
3 siblings, 1 reply; 15+ messages in thread
From: Johannes Schindelin @ 2008-01-30 20:39 UTC (permalink / raw)
To: Mike Kronenberg; +Cc: qemu-devel
Hi,
On Wed, 30 Jan 2008, Mike Kronenberg wrote:
> Offtoppic about updated regions in Windows: While testing with
> Quartzdebug, I realized, that qemu is updating always the whole
> screenwidth even if only the mouse is moved... is this a qemu problem,
> or is this the default windows behaviour?
As far as I remember, this is a QEmu "problem". It only marks lines as
dirty, not pixels.
Ciao,
Dscho
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [patch] cocoa.m - Core Graphics support
2008-01-30 20:39 ` Johannes Schindelin
@ 2008-01-30 21:18 ` andrzej zaborowski
2008-01-31 9:15 ` Jamie Lokier
0 siblings, 1 reply; 15+ messages in thread
From: andrzej zaborowski @ 2008-01-30 21:18 UTC (permalink / raw)
To: qemu-devel
On 30/01/2008, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
> Hi,
>
> On Wed, 30 Jan 2008, Mike Kronenberg wrote:
>
> > Offtoppic about updated regions in Windows: While testing with
> > Quartzdebug, I realized, that qemu is updating always the whole
> > screenwidth even if only the mouse is moved... is this a qemu problem,
> > or is this the default windows behaviour?
>
> As far as I remember, this is a QEmu "problem". It only marks lines as
> dirty, not pixels.
In addition lines are not marked dirty because they have a dirty pixel
in them but because they have a pixel in a dirty page. That means more
lines are updated than those containing dirty pixels.
Cheers
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [patch] cocoa.m - Core Graphics support
2008-01-30 21:18 ` andrzej zaborowski
@ 2008-01-31 9:15 ` Jamie Lokier
0 siblings, 0 replies; 15+ messages in thread
From: Jamie Lokier @ 2008-01-31 9:15 UTC (permalink / raw)
To: qemu-devel
andrzej zaborowski wrote:
> > > Offtoppic about updated regions in Windows: While testing with
> > > Quartzdebug, I realized, that qemu is updating always the whole
> > > screenwidth even if only the mouse is moved... is this a qemu problem,
> > > or is this the default windows behaviour?
> >
> > As far as I remember, this is a QEmu "problem". It only marks lines as
> > dirty, not pixels.
>
> In addition lines are not marked dirty because they have a dirty pixel
> in them but because they have a pixel in a dirty page. That means more
> lines are updated than those containing dirty pixels.
However, if there's an emulated "hardware mouse cursor", just moving
the mouse could be optimised to those pixels only.
-- Jamie
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [patch] cocoa.m - Core Graphics support
2008-01-30 20:30 ` Mike Kronenberg
2008-01-30 20:39 ` Johannes Schindelin
@ 2008-01-30 21:00 ` Pierre d'Herbemont
2008-01-30 21:54 ` Anthony Liguori
2008-01-31 8:29 ` Alexander Graf
3 siblings, 0 replies; 15+ messages in thread
From: Pierre d'Herbemont @ 2008-01-30 21:00 UTC (permalink / raw)
To: qemu-devel
On Jan 30, 2008, at 9:30 PM, Mike Kronenberg wrote:
> Unfortunateley, there is no "official" direct access to the
> framebuffer anymore, since apple depreciated QuickDraw. [1]
Well, you can using OpenGL and Apple's Extension have a nearly direct
VRAM access, the idea is to use
glEnable( GL_UNPACK_CLIENT_STORAGE_APPLE );
glPixelStorei( GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE );
and
glTexParameteri( VLCGL_TARGET, GL_TEXTURE_STORAGE_HINT_APPLE,
GL_STORAGE_SHARED_APPLE );
On the texture on which you want to draw. See:
http://developer.apple.com/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_texturedata/chapter_10_section_2.html
Pierre.
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [patch] cocoa.m - Core Graphics support
2008-01-30 20:30 ` Mike Kronenberg
2008-01-30 20:39 ` Johannes Schindelin
2008-01-30 21:00 ` Pierre d'Herbemont
@ 2008-01-30 21:54 ` Anthony Liguori
2008-01-31 9:46 ` Jamie Lokier
2008-01-31 8:29 ` Alexander Graf
3 siblings, 1 reply; 15+ messages in thread
From: Anthony Liguori @ 2008-01-30 21:54 UTC (permalink / raw)
To: qemu-devel
Mike Kronenberg wrote:
> While testing with Quartzdebug, I realized, that qemu is updating
> always the whole screenwidth even if only the mouse is moved... is
> this a qemu problem, or is this the default windows behaviour?
VGA framebuffer operations come in as memory operations. They're
tracked by watching what memory gets dirtied. This can only operate at
a page-granularity so this results in scan-line granularity updates.
The VNC front-end goes to great lengths to keep a shadowed framebuffer
and reduce these updates to a smaller update region. You could possibly
look at refactoring that code. However...
I would be amazed if screen updates on OS X are so slow that it would
make a difference if updates are in scanline granularities. The copying
latency is nothing compared to the other latencies in QEMU. A modern
processor can move memory at an extremely high speed.
At a refresh rate of 30 times per second, this is only ~4MB of data for
mouse movements. A typical processor can easily handle many GB of data
per second.
Regards,
Anthony Liguori
> Mike
>
> [1]
> http://developer.apple.com/documentation/Carbon/Conceptual/QuickDrawToQuartz2D/tq_image_data/chapter_6_section_2.html#//apple_ref/doc/uid/TP40001098-CH227-BBCFFDBB
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [patch] cocoa.m - Core Graphics support
2008-01-30 21:54 ` Anthony Liguori
@ 2008-01-31 9:46 ` Jamie Lokier
2008-01-31 11:38 ` Julian Seward
2008-01-31 22:40 ` Anthony Liguori
0 siblings, 2 replies; 15+ messages in thread
From: Jamie Lokier @ 2008-01-31 9:46 UTC (permalink / raw)
To: qemu-devel
Anthony Liguori wrote:
> VGA framebuffer operations come in as memory operations. They're
> tracked by watching what memory gets dirtied. This can only operate at
> a page-granularity so this results in scan-line granularity updates.
> The VNC front-end goes to great lengths to keep a shadowed framebuffer
> and reduce these updates to a smaller update region. You could possibly
> look at refactoring that code. However...
That update region code should probably be moved to something generic
and made into a generic display option.
Reducing update region is logically orthogonal, and could work with
any update method (e.g. local X11, remote X11, local X11-OpenGL,
remote X11-OpenGL, SDL etc.). With some of those, for some people
(especially some but not all remote setups) it might be worth it.
> I would be amazed if screen updates on OS X are so slow that it would
> make a difference if updates are in scanline granularities. The copying
> latency is nothing compared to the other latencies in QEMU. A modern
> processor can move memory at an extremely high speed.
>
> At a refresh rate of 30 times per second, this is only ~4MB of data for
> mouse movements. A typical processor can easily handle many GB of data
> per second.
That's 16MB/frame on an Apple Cinema display at 32bpp, which is
0.5GB/sec. Not too much, but not free either :-)
-- Jamie
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [patch] cocoa.m - Core Graphics support
2008-01-31 9:46 ` Jamie Lokier
@ 2008-01-31 11:38 ` Julian Seward
2008-01-31 22:40 ` Anthony Liguori
1 sibling, 0 replies; 15+ messages in thread
From: Julian Seward @ 2008-01-31 11:38 UTC (permalink / raw)
To: qemu-devel
On Thursday 31 January 2008 10:46, Jamie Lokier wrote:
> Anthony Liguori wrote:
> > VGA framebuffer operations come in as memory operations. They're
> > tracked by watching what memory gets dirtied. This can only operate at
> > a page-granularity so this results in scan-line granularity updates.
> > The VNC front-end goes to great lengths to keep a shadowed framebuffer
> > and reduce these updates to a smaller update region. You could possibly
> > look at refactoring that code. However...
>
> That update region code should probably be moved to something generic
> and made into a generic display option.
>
> Reducing update region is logically orthogonal, and could work with
> any update method (e.g. local X11, remote X11, local X11-OpenGL,
> remote X11-OpenGL, SDL etc.). With some of those, for some people
> (especially some but not all remote setups) it might be worth it.
For exactly these reasons I developed a shadow framebuffer patch
which ...
> makes QEMU's graphics emulation much more usable over remote
> X connections, by reducing the amount of data sent to the X server.
> This is particularly noticeable for small display updates, most
> importantly mouse cursor movements, which become faster and so
> generally make the guest's GUI more pleasant to use.
See
http://lists.gnu.org/archive/html/qemu-devel/2007-03/msg00141.html
for the patch and short associated thread. It never got included,
though.
J
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [patch] cocoa.m - Core Graphics support
2008-01-31 9:46 ` Jamie Lokier
2008-01-31 11:38 ` Julian Seward
@ 2008-01-31 22:40 ` Anthony Liguori
2008-01-31 23:03 ` Jamie Lokier
1 sibling, 1 reply; 15+ messages in thread
From: Anthony Liguori @ 2008-01-31 22:40 UTC (permalink / raw)
To: qemu-devel
Jamie Lokier wrote:
> Anthony Liguori wrote:
>
>> VGA framebuffer operations come in as memory operations. They're
>> tracked by watching what memory gets dirtied. This can only operate at
>> a page-granularity so this results in scan-line granularity updates.
>> The VNC front-end goes to great lengths to keep a shadowed framebuffer
>> and reduce these updates to a smaller update region. You could possibly
>> look at refactoring that code. However...
>>
>
> That update region code should probably be moved to something generic
> and made into a generic display option.
>
> Reducing update region is logically orthogonal, and could work with
> any update method (e.g. local X11, remote X11, local X11-OpenGL,
> remote X11-OpenGL, SDL etc.). With some of those, for some people
> (especially some but not all remote setups) it might be worth it.
>
>
>> I would be amazed if screen updates on OS X are so slow that it would
>> make a difference if updates are in scanline granularities. The copying
>> latency is nothing compared to the other latencies in QEMU. A modern
>> processor can move memory at an extremely high speed.
>>
>> At a refresh rate of 30 times per second, this is only ~4MB of data for
>> mouse movements. A typical processor can easily handle many GB of data
>> per second.
>>
>
> That's 16MB/frame on an Apple Cinema display at 32bpp, which is
> 0.5GB/sec. Not too much, but not free either :-)
>
But your guest isn't displaying to the entire screen... I was assuming
a 32-pixel height, 1024 pixel wide region.
Regards,
Anthony Liguori
> -- Jamie
>
>
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [patch] cocoa.m - Core Graphics support
2008-01-31 22:40 ` Anthony Liguori
@ 2008-01-31 23:03 ` Jamie Lokier
0 siblings, 0 replies; 15+ messages in thread
From: Jamie Lokier @ 2008-01-31 23:03 UTC (permalink / raw)
To: qemu-devel
Anthony Liguori wrote:
> >That's 16MB/frame on an Apple Cinema display at 32bpp, which is
> >0.5GB/sec. Not too much, but not free either :-)
> >
>
> But your guest isn't displaying to the entire screen... I was assuming
> a 32-pixel height, 1024 pixel wide region.
I don't know about you; I quite like running Qemu in full screen mode
on my biggest screen when I want to do some work in another OS. (I
don't have a Cinema display, though, it was just to make the point).
But this is not an important thing, let's leave it.
-- Jamie
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [patch] cocoa.m - Core Graphics support
2008-01-30 20:30 ` Mike Kronenberg
` (2 preceding siblings ...)
2008-01-30 21:54 ` Anthony Liguori
@ 2008-01-31 8:29 ` Alexander Graf
3 siblings, 0 replies; 15+ messages in thread
From: Alexander Graf @ 2008-01-31 8:29 UTC (permalink / raw)
To: qemu-devel
On Jan 30, 2008, at 9:30 PM, Mike Kronenberg wrote:
>
> On 30.01.2008, at 19:59, Alexander Graf wrote:
>
>>
>> On Jan 21, 2008, at 5:18 PM, Mike Kronenberg wrote:
>>
>>> This is a complete rewrite of cocoa.m to support Core Graphics.
>>>
>>> As mentioned in earlier threads, the QuickDraw API is depreciated
>>> starting with OS X 10.4.
>>> Now with OS X 10.5 it won't even compile QuickDraw code on x86_64.
>>>
>>>
>>> This implementation of cocoa.m has the following features:
>>>
>>> [new] partial drawing of the window as needed, implemented with CG.
>>> [new] fullscreen support
>>> [new] tablet support
>>> [new] View menu and item to enter Fullscreen (cmd-f)
>>> [new] Help menu and items to show qemu-doc.html (cmd-?) and qemu-
>>> tec.html in the OS X "Help Viewer"
>>> [new] -name is shown in Title-bar of window
>>> [fix] Application menu creation for 10.4+ (API is private as of
>>> 10.4)
>>> [fix] Mouse-clicks on the guests window widgets are no longer
>>> intercepted
>>> [fix] apple keyboard shortcuts forwarded (minimize (cmd-m), hide
>>> QEMU (cmd-h), quit QEMU (cmd-q))
>>>
>>> It should compile on ppc/intel starting form 10.3 (10.2 with the
>>> known workarounds).
>>>
>>> Please test and comment
>>
>> I'm sorry that I didn't find the time to test this implementation
>> before.
>>
>> It's damn slow.
>>
>> I ran it using my x86_64 on 10.5.1, targetting x86_64-softmmu and
>> booting a linux kernel. I could literally see every like getting
>> repainted (which btw did not happen with my quick hacky version I
>> sent to the list some time ago).
>>
>> I think the major problem is that too much is being done during
>> drawRect. If I understand the code correctly, you create CGImage
>> objects on every repaint, which is prone to be slow.
>>
>> Why not simply reuse the framebuffer qemu provides anyway and leave
>> everything else to CG?
>>
>> Alex
>>
>>
>
>
> Hi Alex,
>
> yes, as stated earlyer, it is slower than Quickdraw, especially if
> the whole screen is redrawn. Overal emulation speed for GUI apps is
> faster, dough, as only small portions of the screen are redrawn.
That's good to hear. I tend to use Linux in command line mode in qemu
quite often though, so for me the most important thing is full screen
update, which apparently became slower. Merely running an SDL targeted
qemu (did this on x86_64 linux) vs a cocoa one shows that something
feels wrong on cocoa. Maybe there is no other way around this, but I
still don't like seeing the screen scroll line for line ;-).
Unfortunately I don't have the time right now to investigate this in
detail and I am really not into graphics programming usually. So for
the time being it is still _way_ better than a solution that doesn't
even compile.
The one thing I want to stress here is that maybe it might be worth
looking into alternatives. If I find the time to do it, I will do so.
I somehow like the idea of having a GL based video output.
Alex
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [Qemu-devel] [patch] cocoa.m - Core Graphics support
2008-01-30 18:59 ` Alexander Graf
2008-01-30 19:05 ` Alexander Graf
2008-01-30 20:30 ` Mike Kronenberg
@ 2008-01-30 20:44 ` Mike Kronenberg
2 siblings, 0 replies; 15+ messages in thread
From: Mike Kronenberg @ 2008-01-30 20:44 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 747 bytes --]
>
> I ran it using my x86_64 on 10.5.1, targetting x86_64-softmmu and
> booting a linux kernel. I could literally see every like getting
> repainted (which btw did not happen with my quick hacky version I
> sent to the list some time ago).
You did not notice the effect with Your implementation, because the
the whole screen is redrawn every time.
With this implementation, only the parts requested by qemu are updated.
If You take a dosprompt, every line that moves up, triggers a redraw
(only for the specific line) - this is why you notice the redraw.
You can test this easily with the Quartz debugger.
But never the less, overall speed is much faster with partial redraw,
than if You redraw the whole screen every time.
Mike
[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 2111 bytes --]
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2008-02-01 0:34 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-01-21 16:18 [Qemu-devel] [patch] cocoa.m - Core Graphics support Mike Kronenberg
2008-01-30 18:59 ` Alexander Graf
2008-01-30 19:05 ` Alexander Graf
2008-01-30 20:30 ` Mike Kronenberg
2008-01-30 20:39 ` Johannes Schindelin
2008-01-30 21:18 ` andrzej zaborowski
2008-01-31 9:15 ` Jamie Lokier
2008-01-30 21:00 ` Pierre d'Herbemont
2008-01-30 21:54 ` Anthony Liguori
2008-01-31 9:46 ` Jamie Lokier
2008-01-31 11:38 ` Julian Seward
2008-01-31 22:40 ` Anthony Liguori
2008-01-31 23:03 ` Jamie Lokier
2008-01-31 8:29 ` Alexander Graf
2008-01-30 20:44 ` Mike Kronenberg
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).