From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1DaMYn-0002Vg-EZ for qemu-devel@nongnu.org; Mon, 23 May 2005 19:42:13 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1DaMXA-0002HQ-0v for qemu-devel@nongnu.org; Mon, 23 May 2005 19:40:46 -0400 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1DaMX9-0002ET-Kc for qemu-devel@nongnu.org; Mon, 23 May 2005 19:40:31 -0400 Received: from [64.233.170.193] (helo=rproxy.gmail.com) by monty-python.gnu.org with esmtp (Exim 4.34) id 1DaMMV-00055T-Rf for qemu-devel@nongnu.org; Mon, 23 May 2005 19:29:32 -0400 Received: by rproxy.gmail.com with SMTP id f1so1417523rne for ; Mon, 23 May 2005 16:29:27 -0700 (PDT) Mime-Version: 1.0 (Apple Message framework v622) Content-Transfer-Encoding: 7bit Message-Id: <16d65796e962fc2648b2bd8804a62afc@gmail.com> Content-Type: text/plain; charset=US-ASCII; delsp=yes; format=flowed From: Peter Stewart Subject: Re: [Qemu-devel] cocoa.m using openGL Date: Tue, 24 May 2005 01:29:18 +0200 Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Hi, Sorry, kind of new at this... Here is the diff -u version of cocoa.m, I guess you got the Makefile.target fix :-) diff -u cocoa.m.orig cocoa.m > cocoa.m.diff enjoy, peter. --- cocoa.m.orig Sat May 21 17:19:45 2005 +++ cocoa.m Mon May 23 19:24:00 2005 @@ -37,16 +37,23 @@ #import +#include +#include + #include "vl.h" -NSWindow *window = NULL; -NSQuickDrawView *qd_view = NULL; +static NSWindow *window = NULL; +static NSOpenGLView *ogl_view = NULL; +#define SCREEN_BPP 32 int gArgc; char **gArgv; DisplayState current_ds; +GLint screen_tex = 0; +GLuint display_list_tex = 0; + /* main defined in qemu/vl.c */ int qemu_main(int argc, char **argv); @@ -62,6 +69,7 @@ ------------------------------------------------------ */ + /* ------------------------------------------------------ cocoa_update @@ -70,22 +78,22 @@ static void cocoa_update(DisplayState *ds, int x, int y, int w, int h) { //printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h); + + // Make this context current + [[ogl_view openGLContext] makeCurrentContext]; + + // Bind, update and draw new image + glBindTexture(GL_TEXTURE_RECTANGLE_EXT, screen_tex); + + // glTexSubImage2D is faster when not using a texture range + glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA, (GLint)ds->width, (GLint)ds->height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, ds->data); + + // Use the compiled display list + glCallList(display_list_tex); + + // Swap buffer to screen + [[ogl_view openGLContext] flushBuffer]; - /* Use QDFlushPortBuffer() to flush content to display */ - RgnHandle dirty = NewRgn (); - RgnHandle temp = NewRgn (); - - SetEmptyRgn (dirty); - - /* Build the region of dirty rectangles */ - MacSetRectRgn (temp, x, y, - x + w, y + h); - MacUnionRgn (dirty, temp, dirty); - - /* Flush the dirty region */ - QDFlushPortBuffer ( [ qd_view qdPort ], dirty ); - DisposeRgn (dirty); - DisposeRgn (temp); } /* @@ -95,74 +103,96 @@ */ static void cocoa_resize(DisplayState *ds, int w, int h) { - const int device_bpp = 32; - static void *screen_pixels; - static int screen_pitch; + NSRect contentRect; + + // printf("resizing to %d %d\n", w, h); - //printf("resizing to %d %d\n", w, h); - - contentRect = NSMakeRect (0, 0, w, h); - if(window) - { - [window close]; - [window release]; - } - window = [ [ QemuWindow alloc ] initWithContentRect:contentRect - styleMask: NSTitledWindowMask|NSMiniaturizableWindowMask|NSClosableWindowMask - backing:NSBackingStoreBuffered defer:NO]; - if(!window) - { - fprintf(stderr, "(cocoa) can't create window\n"); - exit(1); - } - - if(qd_view) - [qd_view release]; - - qd_view = [ [ NSQuickDrawView alloc ] initWithFrame:contentRect ]; - - if(!qd_view) - { - fprintf(stderr, "(cocoa) can't create qd_view\n"); - exit(1); - } - - [ window setAcceptsMouseMovedEvents:YES ]; - [ window setTitle:@"Qemu" ]; - [ window setReleasedWhenClosed:NO ]; - - /* Set screen to black */ - [ window setBackgroundColor: [NSColor blackColor] ]; - - /* set window position */ - [ window center ]; - - [ qd_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ]; - [ [ window contentView ] addSubview:qd_view ]; - [ qd_view release ]; - [ window makeKeyAndOrderFront:nil ]; - - /* Careful here, the window seems to have to be onscreen to do that */ - LockPortBits ( [ qd_view qdPort ] ); - screen_pixels = GetPixBaseAddr ( GetPortPixMap ( [ qd_view qdPort ] ) ); - screen_pitch = GetPixRowBytes ( GetPortPixMap ( [ qd_view qdPort ] ) ); - UnlockPortBits ( [ qd_view qdPort ] ); - { - int vOffset = [ window frame ].size.height - - [ qd_view frame ].size.height - [ qd_view frame ].origin.y; - - int hOffset = [ qd_view frame ].origin.x; - - screen_pixels += (vOffset * screen_pitch) + hOffset * (device_bpp/8); - } - ds->data = screen_pixels; - ds->linesize = screen_pitch; - ds->depth = device_bpp; + contentRect = NSMakeRect (0, 0, w, h); + + [window setContentSize:contentRect.size]; + [window update]; + + [[ogl_view openGLContext] makeCurrentContext]; + [[ogl_view openGLContext] update]; + + glViewport(0, 0, (int) contentRect.size.width, (int) contentRect.size.height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + // This is used as a init'd flag as well... + if(screen_tex != 0) { + glDeleteTextures(1, &screen_tex); + glDeleteLists(display_list_tex, 1); + } + + screen_tex = 1; + + if(ds->data != NULL) free(ds->data); + ds->data = (GLubyte *) malloc(w * h * (SCREEN_BPP >> 3)); + assert(ds->data != NULL); + ds->linesize = w * (SCREEN_BPP >> 3); + ds->depth = SCREEN_BPP; ds->width = w; ds->height = h; - - current_ds = *ds; + + // Setup some basic OpenGL stuff as from Apple + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + + glEnable(GL_TEXTURE_RECTANGLE_EXT); + glBindTexture(GL_TEXTURE_RECTANGLE_EXT, screen_tex); + + glTextureRangeAPPLE(GL_TEXTURE_RECTANGLE_EXT, w * h * (SCREEN_BPP >> 3), ds->data); + + // Use CACHED for VRAM+reused tex Use SHARED for AGP+used once tex + // Note the texture is always changing so use SHARED + glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_STORAGE_HINT_APPLE , GL_STORAGE_SHARED_APPLE); + glPixelStorei(GL_UNPACK_CLIENT_STORAGE_APPLE, GL_TRUE); + glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_RECTANGLE_EXT, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + + glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0, GL_RGBA, w, h, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, ds->data); + + glFlush(); + + // Setup a display list to save all the operations below + + display_list_tex = glGenLists(1); + glNewList(display_list_tex, GL_COMPILE); + + glBegin(GL_QUADS); + + glTexCoord2f(0.0f, 0.0f); + glVertex2f(-1.0f, 1.0f); + + glTexCoord2f(0.0f, (GLfloat)h); + glVertex2f(-1.0f, -1.0f); + + glTexCoord2f((GLfloat)w, (GLfloat)h); + glVertex2f(1.0f, -1.0f); + + glTexCoord2f((GLfloat)w, 0.0f); + glVertex2f(1.0f, 1.0f); + + glEnd(); + + glEndList(); + + + // Swap buffer to screen + [[ogl_view openGLContext] flushBuffer]; + + memcpy(¤t_ds, ds, sizeof(DisplayState)); } /* @@ -243,19 +273,16 @@ static void cocoa_refresh(DisplayState *ds) { //printf("cocoa_refresh \n"); - NSDate *distantPast; NSEvent *event; - NSAutoreleasePool *pool; int grab = 1; - - pool = [ [ NSAutoreleasePool alloc ] init ]; - distantPast = [ NSDate distantPast ]; - + NSDate *distantPast = [ NSDate distantPast ];; + if (is_active_console(vga_console)) vga_update_display(); + do { - event = [ NSApp nextEventMatchingMask:NSAnyEventMask untilDate:distantPast - inMode: NSDefaultRunLoopMode dequeue:YES ]; + event = [ window nextEventMatchingMask:NSAnyEventMask untilDate:distantPast inMode: NSDefaultRunLoopMode dequeue:YES ]; + if (event != nil) { switch ([event type]) { case NSKeyDown: @@ -278,26 +305,74 @@ kbd_put_keycode(keycode | 0x80); } break; + + case NSScrollWheel: - - case NSLeftMouseDown: - case NSLeftMouseUp: - - case NSOtherMouseDown: - case NSRightMouseDown: - - case NSOtherMouseUp: - case NSRightMouseUp: - + if(grab) + { + int dz = [event deltaZ]; + + kbd_mouse_event(0, 0, dz, 0); + } + break; + + case NSMouseMoved: + if(grab) + { + int dx = [event deltaX]; + int dy = [event deltaY]; + + kbd_mouse_event(dx, dy, 0, 0); + } + break; + + + case NSOtherMouseDown: + case NSOtherMouseUp: case NSOtherMouseDragged: + if(grab) + { + int dx = [event deltaX]; + int dy = [event deltaY]; + int dz = [event deltaZ]; + + kbd_mouse_event(dx, dy, dz, MOUSE_EVENT_MBUTTON); + } + break; + + case NSRightMouseDown: + case NSRightMouseUp: case NSRightMouseDragged: + if(grab) + { + int dx = [event deltaX]; + int dy = [event deltaY]; + int dz = [event deltaZ]; + + kbd_mouse_event(dx, dy, dz, MOUSE_EVENT_RBUTTON); + } + break; + + case NSLeftMouseDown: + case NSLeftMouseUp: case NSLeftMouseDragged: - - default: [NSApp sendEvent:event]; + if(grab) + { + int dx = [event deltaX]; + int dy = [event deltaY]; + int dz = [event deltaZ]; + + kbd_mouse_event(dx, dy, dz, MOUSE_EVENT_LBUTTON); + } + break; + + default: + [NSApp sendEvent:event]; } } } while(event != nil); + } /* @@ -319,12 +394,72 @@ void cocoa_display_init(DisplayState *ds, int full_screen) { - ds->dpy_update = cocoa_update; - ds->dpy_resize = cocoa_resize; - ds->dpy_refresh = cocoa_refresh; + //printf("resizing to %d %d\n", w, h); + + const int w = 640; + const int h = 400; + + if(window == nil) + { + // Init pixel format attribs + NSOpenGLPixelFormatAttribute attrs[] = + { + NSOpenGLPFAAccelerated, + NSOpenGLPFANoRecovery, + NSOpenGLPFADoubleBuffer, + 0 + }; + + NSRect contentRect = NSMakeRect (0, 0, w, h); + + // Get pixel format from OpenGL + NSOpenGLPixelFormat* pixFmt = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs]; + if (!pixFmt) + { + fprintf(stderr, "No pixel format -- exiting"); + exit(1); + } + + window = [ [ QemuWindow alloc ] initWithContentRect:contentRect + styleMask: NSTitledWindowMask|NSMiniaturizableWindowMask|NSClosableWindowMask + backing:NSBackingStoreBuffered defer:NO]; + if(!window) + { + fprintf(stderr, "(cocoa) can't create window\n"); + exit(1); + } + + ogl_view = [ [ NSOpenGLView alloc ] initWithFrame:contentRect pixelFormat:pixFmt ]; + + if(!ogl_view) + { + fprintf(stderr, "(cocoa) can't create ogl_view\n"); + exit(1); + } + + [ window setAcceptsMouseMovedEvents:YES ]; + [ window setTitle:@"Qemu" ]; + [ window setReleasedWhenClosed:NO ]; + + /* set window position */ + [ window center ]; + [ window makeKeyAndOrderFront:nil ]; + + [ ogl_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ]; + [ window setContentView:ogl_view ]; + [ ogl_view release ]; + } + + ds->dpy_update = cocoa_update; + ds->dpy_resize = cocoa_resize; + ds->dpy_refresh = cocoa_refresh; cocoa_resize(ds, 640, 400); - + + [ window display ]; + [ window makeMainWindow ]; + [ window makeKeyWindow ]; + atexit(cocoa_cleanup); } @@ -341,30 +476,13 @@ Some trick from SDL to use miniwindow ------------------------------------------------------ */ -static void QZ_SetPortAlphaOpaque () -{ - /* Assume 32 bit if( bpp == 32 )*/ - if ( 1 ) { - - uint32_t *pixels = (uint32_t*) current_ds.data; - uint32_t rowPixels = current_ds.linesize / 4; - uint32_t i, j; - - for (i = 0; i < current_ds.height; i++) - for (j = 0; j < current_ds.width; j++) { - - pixels[ (i * rowPixels) + j ] |= 0xFF000000; - } - } -} + @implementation QemuWindow - (void)miniaturize:(id)sender { - /* make the alpha channel opaque so anim won't have holes in it */ - QZ_SetPortAlphaOpaque (); - + /* make the alpha channel opaque so anim won't have holes in it */ [ super miniaturize:sender ]; } @@ -377,12 +495,10 @@ UI elements, and restore the SDL surface. This way, no expose event is required, and the deminiaturize works perfectly. */ - - /* make sure pixels are fully opaque */ - QZ_SetPortAlphaOpaque (); + /* save current visible SDL surface */ - [ self cacheImageInRect:[ qd_view frame ] ]; + [ self cacheImageInRect:[ ogl_view frame ] ]; /* let the window manager redraw controls, border, etc */ [ super display ]; @@ -424,8 +540,8 @@ { NSOpenPanel *op = [[NSOpenPanel alloc] init]; - cocoa_resize(¤t_ds, 640, 400); - + cocoa_display_init(¤t_ds, 0); + [op setPrompt:@"Boot image"]; [op setMessage:@"Select the disk image you want to boot.\n\nHit the \"Cancel\" button to quit"]; @@ -449,9 +565,16 @@ exit(0); } + + + + + - (void)openPanelDidEnd:(NSOpenPanel *)sheet returnCode:(int)returnCode contextInfo:(void *)contextInfo { - if(returnCode == NSCancelButton) + [sheet close]; + + if(returnCode == NSCancelButton) { exit(0); }