From patchwork Thu Dec 11 11:05:55 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gerd Hoffmann X-Patchwork-Id: 420027 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 9E2D21400D5 for ; Thu, 11 Dec 2014 22:06:54 +1100 (AEDT) Received: from localhost ([::1]:50237 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Xz1a8-0006GB-Pd for incoming@patchwork.ozlabs.org; Thu, 11 Dec 2014 06:06:52 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:57347) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Xz1Zb-0005Wr-HW for qemu-devel@nongnu.org; Thu, 11 Dec 2014 06:06:25 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Xz1ZM-0004pK-OG for qemu-devel@nongnu.org; Thu, 11 Dec 2014 06:06:19 -0500 Received: from mx1.redhat.com ([209.132.183.28]:58439) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Xz1ZM-0004ow-Es for qemu-devel@nongnu.org; Thu, 11 Dec 2014 06:06:04 -0500 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id sBBB60Px024480 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL); Thu, 11 Dec 2014 06:06:01 -0500 Received: from nilsson.home.kraxel.org (ovpn-116-68.ams2.redhat.com [10.36.116.68]) by int-mx13.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id sBBB5xZY014118; Thu, 11 Dec 2014 06:06:00 -0500 Received: by nilsson.home.kraxel.org (Postfix, from userid 500) id 5B98082BE0; Thu, 11 Dec 2014 12:05:58 +0100 (CET) From: Gerd Hoffmann To: qemu-devel@nongnu.org Date: Thu, 11 Dec 2014 12:05:55 +0100 Message-Id: <1418295956-22479-3-git-send-email-kraxel@redhat.com> In-Reply-To: <1418295956-22479-1-git-send-email-kraxel@redhat.com> References: <1418295956-22479-1-git-send-email-kraxel@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.26 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 209.132.183.28 Cc: Gerd Hoffmann , Anthony Liguori Subject: [Qemu-devel] [RfC PATCH 2/3] sdl2: add support for display rendering using opengl. X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Add new sdl2-gl.c file, with display rendering functions using opengl. Signed-off-by: Gerd Hoffmann --- include/ui/sdl2.h | 10 ++++ ui/Makefile.objs | 4 ++ ui/sdl2-2d.c | 6 +++ ui/sdl2-gl.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ ui/sdl2.c | 50 ++++++++++++++++--- 5 files changed, 206 insertions(+), 7 deletions(-) create mode 100644 ui/sdl2-gl.c diff --git a/include/ui/sdl2.h b/include/ui/sdl2.h index 9e9a92d..ba90a91 100644 --- a/include/ui/sdl2.h +++ b/include/ui/sdl2.h @@ -8,6 +8,9 @@ struct sdl2_console { int last_vm_running; /* per console for caption reasons */ int x, y; int hidden; + int opengl; + int updates; + SDL_GLContext winctx; }; void sdl2_window_create(struct sdl2_console *scon); @@ -25,3 +28,10 @@ void sdl2_2d_switch(DisplayChangeListener *dcl, DisplaySurface *new_surface); void sdl2_2d_refresh(DisplayChangeListener *dcl); void sdl2_2d_redraw(struct sdl2_console *scon); + +void sdl2_gl_update(DisplayChangeListener *dcl, + int x, int y, int w, int h); +void sdl2_gl_switch(DisplayChangeListener *dcl, + DisplaySurface *new_surface); +void sdl2_gl_refresh(DisplayChangeListener *dcl); +void sdl2_gl_redraw(struct sdl2_console *scon); diff --git a/ui/Makefile.objs b/ui/Makefile.objs index 13b5cfb..b86bdb1 100644 --- a/ui/Makefile.objs +++ b/ui/Makefile.objs @@ -21,6 +21,10 @@ sdl.mo-objs := sdl.o sdl_zoom.o endif ifeq ($(CONFIG_SDLABI),2.0) sdl.mo-objs := sdl2.o sdl2-input.o sdl2-2d.o +ifeq ($(CONFIG_OPENGL),y) +sdl.mo-objs += sdl2-gl.o +libs_softmmu += $(OPENGL_LIBS) +endif endif sdl.mo-cflags := $(SDL_CFLAGS) diff --git a/ui/sdl2-2d.c b/ui/sdl2-2d.c index 9c60075..85f1be4 100644 --- a/ui/sdl2-2d.c +++ b/ui/sdl2-2d.c @@ -42,6 +42,8 @@ void sdl2_2d_update(DisplayChangeListener *dcl, DisplaySurface *surf = qemu_console_surface(dcl->con); SDL_Rect rect; + assert(!scon->opengl); + if (!surf) { return; } @@ -67,6 +69,8 @@ void sdl2_2d_switch(DisplayChangeListener *dcl, DisplaySurface *old_surface = scon->surface; int format = 0; + assert(!scon->opengl); + scon->surface = new_surface; if (scon->texture) { @@ -114,6 +118,8 @@ void sdl2_2d_refresh(DisplayChangeListener *dcl) void sdl2_2d_redraw(struct sdl2_console *scon) { + assert(!scon->opengl); + if (!scon->surface) { return; } diff --git a/ui/sdl2-gl.c b/ui/sdl2-gl.c new file mode 100644 index 0000000..30018d4 --- /dev/null +++ b/ui/sdl2-gl.c @@ -0,0 +1,143 @@ +/* + * QEMU SDL display driver + * + * Copyright (c) 2003 Fabrice Bellard + * + * 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. + */ +/* Ported SDL 1.2 code to 2.0 by Dave Airlie. */ + +/* Avoid compiler warning because macro is redefined in SDL_syswm.h. */ +#undef WIN32_LEAN_AND_MEAN + +#include +#include +#include + +#include "qemu-common.h" +#include "ui/console.h" +#include "ui/input.h" +#include "ui/sdl2.h" +#include "sysemu/sysemu.h" + +static void sdl2_gl_render_surface(struct sdl2_console *scon) +{ + int gw, gh, ww, wh, stripe; + float sw, sh; + GLuint tex; + + gw = surface_width(scon->surface); + gh = surface_height(scon->surface); + SDL_GetWindowSize(scon->real_window, &ww, &wh); + SDL_GL_MakeCurrent(scon->real_window, scon->winctx); + + sw = (float)ww/gw; + sh = (float)wh/gh; + if (sw < sh) { + stripe = wh - wh*sw/sh; + glViewport(0, stripe / 2, ww, wh - stripe); + } else { + stripe = ww - ww*sh/sw; + glViewport(stripe / 2, 0, ww - stripe, wh); + } + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glClearColor(0.0, 0.0, 0.0, 0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glGenTextures(1, &tex); + glBindTexture(GL_TEXTURE_2D, tex); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, gw, gh, + 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, + surface_data(scon->surface)); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + glEnable(GL_TEXTURE_2D); + glBegin(GL_QUADS); + glTexCoord2f(0, 1); glVertex3f(-1, -1, 0); + glTexCoord2f(0, 0); glVertex3f(-1, 1, 0); + glTexCoord2f(1, 0); glVertex3f(1, 1, 0); + glTexCoord2f(1, 1); glVertex3f(1, -1, 0); + glEnd(); + + SDL_GL_SwapWindow(scon->real_window); + + glDisable(GL_TEXTURE_2D); + glDeleteTextures(1, &tex); +} + +void sdl2_gl_update(DisplayChangeListener *dcl, + int x, int y, int w, int h) +{ + struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl); + + assert(scon->opengl); + scon->updates++; +} + +void sdl2_gl_switch(DisplayChangeListener *dcl, + DisplaySurface *new_surface) +{ + struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl); + DisplaySurface *old_surface = scon->surface; + + assert(scon->opengl); + + scon->surface = new_surface; + + if (!new_surface) { + sdl2_window_destroy(scon); + return; + } + + if (!scon->real_window) { + sdl2_window_create(scon); + } else if (old_surface && + ((surface_width(old_surface) != surface_width(new_surface)) || + (surface_height(old_surface) != surface_height(new_surface)))) { + sdl2_window_resize(scon); + } +} + +void sdl2_gl_refresh(DisplayChangeListener *dcl) +{ + struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl); + + assert(scon->opengl); + graphic_hw_update(dcl->con); + if (scon->updates && scon->surface) { + scon->updates = 0; + sdl2_gl_render_surface(scon); + } + sdl2_poll_events(scon); +} + +void sdl2_gl_redraw(struct sdl2_console *scon) +{ + assert(scon->opengl); + if (scon->surface) { + sdl2_gl_render_surface(scon); + } +} diff --git a/ui/sdl2.c b/ui/sdl2.c index a1def81..1e14a2a 100644 --- a/ui/sdl2.c +++ b/ui/sdl2.c @@ -92,6 +92,9 @@ void sdl2_window_create(struct sdl2_console *scon) surface_height(scon->surface), flags); scon->real_renderer = SDL_CreateRenderer(scon->real_window, -1, 0); + if (scon->opengl) { + scon->winctx = SDL_GL_GetCurrentContext(); + } sdl_update_caption(scon); } @@ -118,6 +121,17 @@ void sdl2_window_resize(struct sdl2_console *scon) surface_height(scon->surface)); } +static void sdl2_redraw(struct sdl2_console *scon) +{ + if (scon->opengl) { +#ifdef CONFIG_OPENGL + sdl2_gl_redraw(scon); +#endif + } else { + sdl2_2d_redraw(scon); + } +} + static void sdl_update_caption(struct sdl2_console *scon) { char win_title[1024]; @@ -316,7 +330,7 @@ static void toggle_full_screen(struct sdl2_console *scon) } SDL_SetWindowFullscreen(scon->real_window, 0); } - sdl2_2d_redraw(scon); + sdl2_redraw(scon); } static void handle_keydown(SDL_Event *ev) @@ -364,8 +378,10 @@ static void handle_keydown(SDL_Event *ev) case SDL_SCANCODE_U: sdl2_window_destroy(scon); sdl2_window_create(scon); - /* re-create texture */ - sdl2_2d_switch(&scon->dcl, scon->surface); + if (!scon->opengl) { + /* re-create scon->texture */ + sdl2_2d_switch(&scon->dcl, scon->surface); + } gui_keysym = 1; break; #if 0 @@ -384,7 +400,7 @@ static void handle_keydown(SDL_Event *ev) fprintf(stderr, "%s: scale to %dx%d\n", __func__, width, height); sdl_scale(scon, width, height); - sdl2_2d_redraw(scon); + sdl2_redraw(scon); gui_keysym = 1; } #endif @@ -518,10 +534,10 @@ static void handle_windowevent(struct sdl2_console *scon, SDL_Event *ev) info.height = ev->window.data2; dpy_set_ui_info(scon->dcl.con, &info); } - sdl2_2d_redraw(scon); + sdl2_redraw(scon); break; case SDL_WINDOWEVENT_EXPOSED: - sdl2_2d_redraw(scon); + sdl2_redraw(scon); break; case SDL_WINDOWEVENT_FOCUS_GAINED: case SDL_WINDOWEVENT_ENTER: @@ -664,8 +680,22 @@ static const DisplayChangeListenerOps dcl_2d_ops = { .dpy_cursor_define = sdl_mouse_define, }; +#ifdef CONFIG_OPENGL +static const DisplayChangeListenerOps dcl_gl_ops = { + .dpy_name = "sdl2-gl", + .dpy_gfx_update = sdl2_gl_update, + .dpy_gfx_switch = sdl2_gl_switch, + .dpy_refresh = sdl2_gl_refresh, + .dpy_mouse_set = sdl_mouse_warp, + .dpy_cursor_define = sdl_mouse_define, +}; +#endif + void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) { +#ifdef CONFIG_OPENGL + int opengl = 1; +#endif int flags; uint8_t data = 0; char *filename; @@ -709,10 +739,16 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) if (!qemu_console_is_graphic(con)) { sdl2_console[i].hidden = true; } + sdl2_console[i].idx = i; +#ifdef CONFIG_OPENGL + sdl2_console[i].opengl = opengl; + sdl2_console[i].dcl.ops = opengl ? &dcl_gl_ops : &dcl_2d_ops; +#else + sdl2_console[i].opengl = 0; sdl2_console[i].dcl.ops = &dcl_2d_ops; +#endif sdl2_console[i].dcl.con = con; register_displaychangelistener(&sdl2_console[i].dcl); - sdl2_console[i].idx = i; } /* Load a 32x32x4 image. White pixels are transparent. */