qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [RfC PATCH 2/3] sdl2: add support for display rendering usi


From: Gerd Hoffmann
Subject: [Qemu-devel] [RfC PATCH 2/3] sdl2: add support for display rendering using opengl.
Date: Thu, 11 Dec 2014 12:05:55 +0100

Add new sdl2-gl.c file, with display
rendering functions using opengl.

Signed-off-by: Gerd Hoffmann <address@hidden>
---
 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 <SDL.h>
+#include <SDL_syswm.h>
+#include <SDL_opengl.h>
+
+#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. */
-- 
1.8.3.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]