mirror of https://github.com/xemu-project/xemu.git
sdl2: add opengl support
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAABAgAGBQJVSI8ZAAoJEEy22O7T6HE466UP/AoBptoGXuk4e4/XMRBydTbg SEEYHDL0iLQMhnsiVbdPKcRvgmsjuUgM8t5iwcK2YHiyxfhH5VxEgeK24llrSYye EBZtOAUq9hqgmJUZ/ma4PDv0B+4muqEQetoPV20zF8hmabw4tKQ7X49tI0K947Zy KYgOaoo4BkIuzXKjVo/kdk/Lj123muNAfs1zBzvMWsriHyQ1MI5GYerryIOaUVpA 64sruQytgsimErUdYdeWRkd+7PR8JkWRc8kUQCFkRSYpfqYGFCdh733SCQbYNAkg mmtWuAfOR7drf/01c1xO7/W9BRiVEYgjdRgM0vus6LIdmPhh9kilOpz9txnkAMO6 1reYchCdj8SgKIEoSMs8yhdRFnHx+au3wLWw6GhEH0WbBTrI3J42nzhxUI+vvC7M wxxOv1WvaTYm212pzmpxH72/T8BMhhZ5jb1/7gTduxn82OetuzT0zPKrhmbiIxVf azD48H9VK75vPHeoXUCWetK5L5V5pC49jGRfFcv+xtvNLbwAV8wTlCK2MV8HeVTM pmtxl8mtJ9PxkcbtXom5L+3DGCTFtuTPNRQMT/aI7V8bawLSsbs75FTjNDWzxFwz T19nh2+Id+tSuT1huY67D84UBBuRo4RvVeNO55pQlp1RhXOp04b9fJ45bgIVF0BF zrJ4mNoTQAAq5Ie8PO33 =QrjG -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/kraxel/tags/pull-sdl-20150505-1' into staging sdl2: add opengl support # gpg: Signature made Tue May 5 10:36:25 2015 BST using RSA key ID D3E87138 # gpg: Good signature from "Gerd Hoffmann (work) <kraxel@redhat.com>" # gpg: aka "Gerd Hoffmann <gerd@kraxel.org>" # gpg: aka "Gerd Hoffmann (private) <kraxel@gmail.com>" * remotes/kraxel/tags/pull-sdl-20150505-1: sdl2: Fix RGB555 sdl2: add support for display rendering using opengl. sdl2: move SDL_* includes to sdl2.h console-gl: add opengl rendering helper functions opengl: add shader helper functions. opengl: add shader build infrastructure Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
874e9aeeeb
17
Makefile
17
Makefile
|
@ -296,6 +296,7 @@ clean:
|
||||||
rm -f fsdev/*.pod
|
rm -f fsdev/*.pod
|
||||||
rm -rf .libs */.libs
|
rm -rf .libs */.libs
|
||||||
rm -f qemu-img-cmds.h
|
rm -f qemu-img-cmds.h
|
||||||
|
rm -f ui/shader/*-vert.h ui/shader/*-frag.h
|
||||||
@# May not be present in GENERATED_HEADERS
|
@# May not be present in GENERATED_HEADERS
|
||||||
rm -f trace/generated-tracers-dtrace.dtrace*
|
rm -f trace/generated-tracers-dtrace.dtrace*
|
||||||
rm -f trace/generated-tracers-dtrace.h*
|
rm -f trace/generated-tracers-dtrace.h*
|
||||||
|
@ -441,6 +442,22 @@ cscope:
|
||||||
find "$(SRC_PATH)" -name "*.[chsS]" -print | sed 's,^\./,,' > ./cscope.files
|
find "$(SRC_PATH)" -name "*.[chsS]" -print | sed 's,^\./,,' > ./cscope.files
|
||||||
cscope -b
|
cscope -b
|
||||||
|
|
||||||
|
# opengl shader programs
|
||||||
|
ui/shader/%-vert.h: $(SRC_PATH)/ui/shader/%.vert $(SRC_PATH)/scripts/shaderinclude.pl
|
||||||
|
@mkdir -p $(dir $@)
|
||||||
|
$(call quiet-command,\
|
||||||
|
perl $(SRC_PATH)/scripts/shaderinclude.pl $< > $@,\
|
||||||
|
" VERT $@")
|
||||||
|
|
||||||
|
ui/shader/%-frag.h: $(SRC_PATH)/ui/shader/%.frag $(SRC_PATH)/scripts/shaderinclude.pl
|
||||||
|
@mkdir -p $(dir $@)
|
||||||
|
$(call quiet-command,\
|
||||||
|
perl $(SRC_PATH)/scripts/shaderinclude.pl $< > $@,\
|
||||||
|
" FRAG $@")
|
||||||
|
|
||||||
|
ui/console-gl.o: $(SRC_PATH)/ui/console-gl.c \
|
||||||
|
ui/shader/texture-blit-vert.h ui/shader/texture-blit-frag.h
|
||||||
|
|
||||||
# documentation
|
# documentation
|
||||||
MAKEINFO=makeinfo
|
MAKEINFO=makeinfo
|
||||||
MAKEINFOFLAGS=--no-headers --no-split --number-sections
|
MAKEINFOFLAGS=--no-headers --no-split --number-sections
|
||||||
|
|
|
@ -3142,7 +3142,7 @@ else
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test "$opengl" != "no" ; then
|
if test "$opengl" != "no" ; then
|
||||||
opengl_pkgs="gl"
|
opengl_pkgs="gl glesv2"
|
||||||
if $pkg_config $opengl_pkgs x11 && test "$have_glx" = "yes"; then
|
if $pkg_config $opengl_pkgs x11 && test "$have_glx" = "yes"; then
|
||||||
opengl_cflags="$($pkg_config --cflags $opengl_pkgs) $x11_cflags"
|
opengl_cflags="$($pkg_config --cflags $opengl_pkgs) $x11_cflags"
|
||||||
opengl_libs="$($pkg_config --libs $opengl_pkgs) $x11_libs"
|
opengl_libs="$($pkg_config --libs $opengl_pkgs) $x11_libs"
|
||||||
|
|
|
@ -9,6 +9,11 @@
|
||||||
#include "qapi-types.h"
|
#include "qapi-types.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
|
|
||||||
|
#ifdef CONFIG_OPENGL
|
||||||
|
# include <GLES2/gl2.h>
|
||||||
|
# include <GLES2/gl2ext.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/* keyboard/mouse support */
|
/* keyboard/mouse support */
|
||||||
|
|
||||||
#define MOUSE_EVENT_LBUTTON 0x01
|
#define MOUSE_EVENT_LBUTTON 0x01
|
||||||
|
@ -117,6 +122,11 @@ struct DisplaySurface {
|
||||||
pixman_format_code_t format;
|
pixman_format_code_t format;
|
||||||
pixman_image_t *image;
|
pixman_image_t *image;
|
||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
|
#ifdef CONFIG_OPENGL
|
||||||
|
GLenum glformat;
|
||||||
|
GLenum gltype;
|
||||||
|
GLuint texture;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct QemuUIInfo {
|
typedef struct QemuUIInfo {
|
||||||
|
@ -270,6 +280,11 @@ static inline int surface_bytes_per_pixel(DisplaySurface *s)
|
||||||
return (bits + 7) / 8;
|
return (bits + 7) / 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline pixman_format_code_t surface_format(DisplaySurface *s)
|
||||||
|
{
|
||||||
|
return s->format;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_CURSES
|
#ifdef CONFIG_CURSES
|
||||||
#include <curses.h>
|
#include <curses.h>
|
||||||
typedef chtype console_ch_t;
|
typedef chtype console_ch_t;
|
||||||
|
@ -322,7 +337,29 @@ void qemu_console_copy(QemuConsole *con, int src_x, int src_y,
|
||||||
int dst_x, int dst_y, int w, int h);
|
int dst_x, int dst_y, int w, int h);
|
||||||
DisplaySurface *qemu_console_surface(QemuConsole *con);
|
DisplaySurface *qemu_console_surface(QemuConsole *con);
|
||||||
|
|
||||||
|
/* console-gl.c */
|
||||||
|
typedef struct ConsoleGLState ConsoleGLState;
|
||||||
|
#ifdef CONFIG_OPENGL
|
||||||
|
ConsoleGLState *console_gl_init_context(void);
|
||||||
|
void console_gl_fini_context(ConsoleGLState *gls);
|
||||||
|
bool console_gl_check_format(DisplayChangeListener *dcl,
|
||||||
|
pixman_format_code_t format);
|
||||||
|
void surface_gl_create_texture(ConsoleGLState *gls,
|
||||||
|
DisplaySurface *surface);
|
||||||
|
void surface_gl_update_texture(ConsoleGLState *gls,
|
||||||
|
DisplaySurface *surface,
|
||||||
|
int x, int y, int w, int h);
|
||||||
|
void surface_gl_render_texture(ConsoleGLState *gls,
|
||||||
|
DisplaySurface *surface);
|
||||||
|
void surface_gl_destroy_texture(ConsoleGLState *gls,
|
||||||
|
DisplaySurface *surface);
|
||||||
|
void surface_gl_setup_viewport(ConsoleGLState *gls,
|
||||||
|
DisplaySurface *surface,
|
||||||
|
int ww, int wh);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* sdl.c */
|
/* sdl.c */
|
||||||
|
void sdl_display_early_init(int opengl);
|
||||||
void sdl_display_init(DisplayState *ds, int full_screen, int no_frame);
|
void sdl_display_init(DisplayState *ds, int full_screen, int no_frame);
|
||||||
|
|
||||||
/* cocoa.m */
|
/* cocoa.m */
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
#ifndef SDL2_H
|
#ifndef SDL2_H
|
||||||
#define SDL2_H
|
#define SDL2_H
|
||||||
|
|
||||||
|
/* Avoid compiler warning because macro is redefined in SDL_syswm.h. */
|
||||||
|
#undef WIN32_LEAN_AND_MEAN
|
||||||
|
|
||||||
|
#include <SDL.h>
|
||||||
|
#include <SDL_syswm.h>
|
||||||
|
|
||||||
struct sdl2_console {
|
struct sdl2_console {
|
||||||
DisplayChangeListener dcl;
|
DisplayChangeListener dcl;
|
||||||
DisplaySurface *surface;
|
DisplaySurface *surface;
|
||||||
|
@ -11,6 +17,10 @@ struct sdl2_console {
|
||||||
int last_vm_running; /* per console for caption reasons */
|
int last_vm_running; /* per console for caption reasons */
|
||||||
int x, y;
|
int x, y;
|
||||||
int hidden;
|
int hidden;
|
||||||
|
int opengl;
|
||||||
|
int updates;
|
||||||
|
SDL_GLContext winctx;
|
||||||
|
ConsoleGLState *gls;
|
||||||
};
|
};
|
||||||
|
|
||||||
void sdl2_window_create(struct sdl2_console *scon);
|
void sdl2_window_create(struct sdl2_console *scon);
|
||||||
|
@ -31,4 +41,11 @@ void sdl2_2d_redraw(struct sdl2_console *scon);
|
||||||
bool sdl2_2d_check_format(DisplayChangeListener *dcl,
|
bool sdl2_2d_check_format(DisplayChangeListener *dcl,
|
||||||
pixman_format_code_t format);
|
pixman_format_code_t format);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
#endif /* SDL2_H */
|
#endif /* SDL2_H */
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
#ifdef CONFIG_OPENGL
|
||||||
|
# include <GLES2/gl2.h>
|
||||||
|
# include <GLES2/gl2ext.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void qemu_gl_run_texture_blit(GLint texture_blit_prog);
|
||||||
|
|
||||||
|
GLuint qemu_gl_create_compile_shader(GLenum type, const GLchar *src);
|
||||||
|
GLuint qemu_gl_create_link_program(GLuint vert, GLuint frag);
|
||||||
|
GLuint qemu_gl_create_compile_link_program(const GLchar *vert_src,
|
||||||
|
const GLchar *frag_src);
|
|
@ -0,0 +1,16 @@
|
||||||
|
#!/usr/bin/perl
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
my $file = shift;
|
||||||
|
open FILE, "<", $file or die "open $file: $!";
|
||||||
|
my $name = $file;
|
||||||
|
$name =~ s|.*/||;
|
||||||
|
$name =~ s/[-.]/_/g;
|
||||||
|
print "static GLchar ${name}_src[] =\n";
|
||||||
|
while (<FILE>) {
|
||||||
|
chomp;
|
||||||
|
printf " \"%s\\n\"\n", $_;
|
||||||
|
}
|
||||||
|
print " \"\\n\";\n";
|
||||||
|
close FILE;
|
|
@ -21,7 +21,20 @@ sdl.mo-objs := sdl.o sdl_zoom.o
|
||||||
endif
|
endif
|
||||||
ifeq ($(CONFIG_SDLABI),2.0)
|
ifeq ($(CONFIG_SDLABI),2.0)
|
||||||
sdl.mo-objs := sdl2.o sdl2-input.o sdl2-2d.o
|
sdl.mo-objs := sdl2.o sdl2-input.o sdl2-2d.o
|
||||||
|
ifeq ($(CONFIG_OPENGL),y)
|
||||||
|
sdl.mo-objs += sdl2-gl.o
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
sdl.mo-cflags := $(SDL_CFLAGS)
|
sdl.mo-cflags := $(SDL_CFLAGS)
|
||||||
|
|
||||||
|
ifeq ($(CONFIG_OPENGL),y)
|
||||||
|
common-obj-y += shader.o
|
||||||
|
common-obj-y += console-gl.o
|
||||||
|
endif
|
||||||
|
|
||||||
gtk.o-cflags := $(GTK_CFLAGS) $(VTE_CFLAGS)
|
gtk.o-cflags := $(GTK_CFLAGS) $(VTE_CFLAGS)
|
||||||
|
shader.o-cflags += $(OPENGL_CFLAGS)
|
||||||
|
console-gl.o-cflags += $(OPENGL_CFLAGS)
|
||||||
|
|
||||||
|
shader.o-libs += $(OPENGL_LIBS)
|
||||||
|
console-gl.o-libs += $(OPENGL_LIBS)
|
||||||
|
|
|
@ -0,0 +1,168 @@
|
||||||
|
/*
|
||||||
|
* QEMU graphical console -- opengl helper bits
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 Red Hat
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Gerd Hoffmann <kraxel@redhat.com>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
#include "qemu-common.h"
|
||||||
|
#include "ui/console.h"
|
||||||
|
#include "ui/shader.h"
|
||||||
|
|
||||||
|
#include "shader/texture-blit-vert.h"
|
||||||
|
#include "shader/texture-blit-frag.h"
|
||||||
|
|
||||||
|
struct ConsoleGLState {
|
||||||
|
GLint texture_blit_prog;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
ConsoleGLState *console_gl_init_context(void)
|
||||||
|
{
|
||||||
|
ConsoleGLState *gls = g_new0(ConsoleGLState, 1);
|
||||||
|
|
||||||
|
gls->texture_blit_prog = qemu_gl_create_compile_link_program
|
||||||
|
(texture_blit_vert_src, texture_blit_frag_src);
|
||||||
|
if (!gls->texture_blit_prog) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return gls;
|
||||||
|
}
|
||||||
|
|
||||||
|
void console_gl_fini_context(ConsoleGLState *gls)
|
||||||
|
{
|
||||||
|
if (!gls) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g_free(gls);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool console_gl_check_format(DisplayChangeListener *dcl,
|
||||||
|
pixman_format_code_t format)
|
||||||
|
{
|
||||||
|
switch (format) {
|
||||||
|
case PIXMAN_BE_b8g8r8x8:
|
||||||
|
case PIXMAN_BE_b8g8r8a8:
|
||||||
|
case PIXMAN_r5g6b5:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void surface_gl_create_texture(ConsoleGLState *gls,
|
||||||
|
DisplaySurface *surface)
|
||||||
|
{
|
||||||
|
assert(gls);
|
||||||
|
assert(surface_stride(surface) % surface_bytes_per_pixel(surface) == 0);
|
||||||
|
|
||||||
|
switch (surface->format) {
|
||||||
|
case PIXMAN_BE_b8g8r8x8:
|
||||||
|
case PIXMAN_BE_b8g8r8a8:
|
||||||
|
surface->glformat = GL_BGRA_EXT;
|
||||||
|
surface->gltype = GL_UNSIGNED_BYTE;
|
||||||
|
break;
|
||||||
|
case PIXMAN_r5g6b5:
|
||||||
|
surface->glformat = GL_RGB;
|
||||||
|
surface->gltype = GL_UNSIGNED_SHORT_5_6_5;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
glGenTextures(1, &surface->texture);
|
||||||
|
glEnable(GL_TEXTURE_2D);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, surface->texture);
|
||||||
|
glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT,
|
||||||
|
surface_stride(surface) / surface_bytes_per_pixel(surface));
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
|
||||||
|
surface_width(surface),
|
||||||
|
surface_height(surface),
|
||||||
|
0, surface->glformat, surface->gltype,
|
||||||
|
surface_data(surface));
|
||||||
|
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
}
|
||||||
|
|
||||||
|
void surface_gl_update_texture(ConsoleGLState *gls,
|
||||||
|
DisplaySurface *surface,
|
||||||
|
int x, int y, int w, int h)
|
||||||
|
{
|
||||||
|
uint8_t *data = (void *)surface_data(surface);
|
||||||
|
|
||||||
|
assert(gls);
|
||||||
|
|
||||||
|
glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT,
|
||||||
|
surface_stride(surface) / surface_bytes_per_pixel(surface));
|
||||||
|
glTexSubImage2D(GL_TEXTURE_2D, 0,
|
||||||
|
x, y, w, h,
|
||||||
|
surface->glformat, surface->gltype,
|
||||||
|
data + surface_stride(surface) * y
|
||||||
|
+ surface_bytes_per_pixel(surface) * x);
|
||||||
|
}
|
||||||
|
|
||||||
|
void surface_gl_render_texture(ConsoleGLState *gls,
|
||||||
|
DisplaySurface *surface)
|
||||||
|
{
|
||||||
|
assert(gls);
|
||||||
|
|
||||||
|
glClearColor(0.1f, 0.1f, 0.1f, 0.0f);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
qemu_gl_run_texture_blit(gls->texture_blit_prog);
|
||||||
|
}
|
||||||
|
|
||||||
|
void surface_gl_destroy_texture(ConsoleGLState *gls,
|
||||||
|
DisplaySurface *surface)
|
||||||
|
{
|
||||||
|
if (!surface || !surface->texture) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
glDeleteTextures(1, &surface->texture);
|
||||||
|
surface->texture = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void surface_gl_setup_viewport(ConsoleGLState *gls,
|
||||||
|
DisplaySurface *surface,
|
||||||
|
int ww, int wh)
|
||||||
|
{
|
||||||
|
int gw, gh, stripe;
|
||||||
|
float sw, sh;
|
||||||
|
|
||||||
|
assert(gls);
|
||||||
|
|
||||||
|
gw = surface_width(surface);
|
||||||
|
gh = surface_height(surface);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
10
ui/sdl.c
10
ui/sdl.c
|
@ -908,6 +908,16 @@ static const DisplayChangeListenerOps dcl_ops = {
|
||||||
.dpy_cursor_define = sdl_mouse_define,
|
.dpy_cursor_define = sdl_mouse_define,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void sdl_display_early_init(int opengl)
|
||||||
|
{
|
||||||
|
if (opengl == 1 /* on */) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"SDL1 display code has no opengl support.\n"
|
||||||
|
"Please recompile qemu with SDL2, using\n"
|
||||||
|
"./configure --enable-sdl --with-sdlabi=2.0\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
|
void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
|
||||||
{
|
{
|
||||||
int flags;
|
int flags;
|
||||||
|
|
28
ui/sdl2-2d.c
28
ui/sdl2-2d.c
|
@ -23,12 +23,6 @@
|
||||||
*/
|
*/
|
||||||
/* Ported SDL 1.2 code to 2.0 by Dave Airlie. */
|
/* 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 "qemu-common.h"
|
#include "qemu-common.h"
|
||||||
#include "ui/console.h"
|
#include "ui/console.h"
|
||||||
#include "ui/input.h"
|
#include "ui/input.h"
|
||||||
|
@ -42,6 +36,8 @@ void sdl2_2d_update(DisplayChangeListener *dcl,
|
||||||
DisplaySurface *surf = qemu_console_surface(dcl->con);
|
DisplaySurface *surf = qemu_console_surface(dcl->con);
|
||||||
SDL_Rect rect;
|
SDL_Rect rect;
|
||||||
|
|
||||||
|
assert(!scon->opengl);
|
||||||
|
|
||||||
if (!surf) {
|
if (!surf) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -67,6 +63,8 @@ void sdl2_2d_switch(DisplayChangeListener *dcl,
|
||||||
DisplaySurface *old_surface = scon->surface;
|
DisplaySurface *old_surface = scon->surface;
|
||||||
int format = 0;
|
int format = 0;
|
||||||
|
|
||||||
|
assert(!scon->opengl);
|
||||||
|
|
||||||
scon->surface = new_surface;
|
scon->surface = new_surface;
|
||||||
|
|
||||||
if (scon->texture) {
|
if (scon->texture) {
|
||||||
|
@ -91,10 +89,21 @@ void sdl2_2d_switch(DisplayChangeListener *dcl,
|
||||||
surface_width(new_surface),
|
surface_width(new_surface),
|
||||||
surface_height(new_surface));
|
surface_height(new_surface));
|
||||||
|
|
||||||
if (surface_bits_per_pixel(scon->surface) == 16) {
|
switch (surface_format(scon->surface)) {
|
||||||
|
case PIXMAN_x1r5g5b5:
|
||||||
|
format = SDL_PIXELFORMAT_ARGB1555;
|
||||||
|
break;
|
||||||
|
case PIXMAN_r5g6b5:
|
||||||
format = SDL_PIXELFORMAT_RGB565;
|
format = SDL_PIXELFORMAT_RGB565;
|
||||||
} else if (surface_bits_per_pixel(scon->surface) == 32) {
|
break;
|
||||||
|
case PIXMAN_x8r8g8b8:
|
||||||
format = SDL_PIXELFORMAT_ARGB8888;
|
format = SDL_PIXELFORMAT_ARGB8888;
|
||||||
|
break;
|
||||||
|
case PIXMAN_r8g8b8x8:
|
||||||
|
format = SDL_PIXELFORMAT_RGBA8888;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
scon->texture = SDL_CreateTexture(scon->real_renderer, format,
|
scon->texture = SDL_CreateTexture(scon->real_renderer, format,
|
||||||
SDL_TEXTUREACCESS_STREAMING,
|
SDL_TEXTUREACCESS_STREAMING,
|
||||||
|
@ -107,12 +116,15 @@ void sdl2_2d_refresh(DisplayChangeListener *dcl)
|
||||||
{
|
{
|
||||||
struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl);
|
struct sdl2_console *scon = container_of(dcl, struct sdl2_console, dcl);
|
||||||
|
|
||||||
|
assert(!scon->opengl);
|
||||||
graphic_hw_update(dcl->con);
|
graphic_hw_update(dcl->con);
|
||||||
sdl2_poll_events(scon);
|
sdl2_poll_events(scon);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sdl2_2d_redraw(struct sdl2_console *scon)
|
void sdl2_2d_redraw(struct sdl2_console *scon)
|
||||||
{
|
{
|
||||||
|
assert(!scon->opengl);
|
||||||
|
|
||||||
if (!scon->surface) {
|
if (!scon->surface) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
/*
|
||||||
|
* QEMU SDL display driver -- opengl support
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 Red Hat
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Gerd Hoffmann <kraxel@redhat.com>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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 ww, wh;
|
||||||
|
|
||||||
|
SDL_GL_MakeCurrent(scon->real_window, scon->winctx);
|
||||||
|
|
||||||
|
SDL_GetWindowSize(scon->real_window, &ww, &wh);
|
||||||
|
surface_gl_setup_viewport(scon->gls, scon->surface, ww, wh);
|
||||||
|
|
||||||
|
surface_gl_render_texture(scon->gls, scon->surface);
|
||||||
|
SDL_GL_SwapWindow(scon->real_window);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
SDL_GL_MakeCurrent(scon->real_window, scon->winctx);
|
||||||
|
surface_gl_update_texture(scon->gls, scon->surface, x, y, w, h);
|
||||||
|
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);
|
||||||
|
|
||||||
|
SDL_GL_MakeCurrent(scon->real_window, scon->winctx);
|
||||||
|
surface_gl_destroy_texture(scon->gls, scon->surface);
|
||||||
|
|
||||||
|
scon->surface = new_surface;
|
||||||
|
|
||||||
|
if (!new_surface) {
|
||||||
|
console_gl_fini_context(scon->gls);
|
||||||
|
scon->gls = NULL;
|
||||||
|
sdl2_window_destroy(scon);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!scon->real_window) {
|
||||||
|
sdl2_window_create(scon);
|
||||||
|
scon->gls = console_gl_init_context();
|
||||||
|
} else if (old_surface &&
|
||||||
|
((surface_width(old_surface) != surface_width(new_surface)) ||
|
||||||
|
(surface_height(old_surface) != surface_height(new_surface)))) {
|
||||||
|
sdl2_window_resize(scon);
|
||||||
|
}
|
||||||
|
|
||||||
|
surface_gl_create_texture(scon->gls, scon->surface);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,12 +23,6 @@
|
||||||
*/
|
*/
|
||||||
/* Ported SDL 1.2 code to 2.0 by Dave Airlie. */
|
/* 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 "qemu-common.h"
|
#include "qemu-common.h"
|
||||||
#include "ui/console.h"
|
#include "ui/console.h"
|
||||||
#include "ui/input.h"
|
#include "ui/input.h"
|
||||||
|
|
71
ui/sdl2.c
71
ui/sdl2.c
|
@ -23,12 +23,6 @@
|
||||||
*/
|
*/
|
||||||
/* Ported SDL 1.2 code to 2.0 by Dave Airlie. */
|
/* 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 "qemu-common.h"
|
#include "qemu-common.h"
|
||||||
#include "ui/console.h"
|
#include "ui/console.h"
|
||||||
#include "ui/input.h"
|
#include "ui/input.h"
|
||||||
|
@ -92,6 +86,9 @@ void sdl2_window_create(struct sdl2_console *scon)
|
||||||
surface_height(scon->surface),
|
surface_height(scon->surface),
|
||||||
flags);
|
flags);
|
||||||
scon->real_renderer = SDL_CreateRenderer(scon->real_window, -1, 0);
|
scon->real_renderer = SDL_CreateRenderer(scon->real_window, -1, 0);
|
||||||
|
if (scon->opengl) {
|
||||||
|
scon->winctx = SDL_GL_GetCurrentContext();
|
||||||
|
}
|
||||||
sdl_update_caption(scon);
|
sdl_update_caption(scon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,6 +115,17 @@ void sdl2_window_resize(struct sdl2_console *scon)
|
||||||
surface_height(scon->surface));
|
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)
|
static void sdl_update_caption(struct sdl2_console *scon)
|
||||||
{
|
{
|
||||||
char win_title[1024];
|
char win_title[1024];
|
||||||
|
@ -316,7 +324,7 @@ static void toggle_full_screen(struct sdl2_console *scon)
|
||||||
}
|
}
|
||||||
SDL_SetWindowFullscreen(scon->real_window, 0);
|
SDL_SetWindowFullscreen(scon->real_window, 0);
|
||||||
}
|
}
|
||||||
sdl2_2d_redraw(scon);
|
sdl2_redraw(scon);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_keydown(SDL_Event *ev)
|
static void handle_keydown(SDL_Event *ev)
|
||||||
|
@ -364,8 +372,10 @@ static void handle_keydown(SDL_Event *ev)
|
||||||
case SDL_SCANCODE_U:
|
case SDL_SCANCODE_U:
|
||||||
sdl2_window_destroy(scon);
|
sdl2_window_destroy(scon);
|
||||||
sdl2_window_create(scon);
|
sdl2_window_create(scon);
|
||||||
/* re-create texture */
|
if (!scon->opengl) {
|
||||||
sdl2_2d_switch(&scon->dcl, scon->surface);
|
/* re-create scon->texture */
|
||||||
|
sdl2_2d_switch(&scon->dcl, scon->surface);
|
||||||
|
}
|
||||||
gui_keysym = 1;
|
gui_keysym = 1;
|
||||||
break;
|
break;
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -384,7 +394,7 @@ static void handle_keydown(SDL_Event *ev)
|
||||||
fprintf(stderr, "%s: scale to %dx%d\n",
|
fprintf(stderr, "%s: scale to %dx%d\n",
|
||||||
__func__, width, height);
|
__func__, width, height);
|
||||||
sdl_scale(scon, width, height);
|
sdl_scale(scon, width, height);
|
||||||
sdl2_2d_redraw(scon);
|
sdl2_redraw(scon);
|
||||||
gui_keysym = 1;
|
gui_keysym = 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -520,10 +530,10 @@ static void handle_windowevent(SDL_Event *ev)
|
||||||
info.height = ev->window.data2;
|
info.height = ev->window.data2;
|
||||||
dpy_set_ui_info(scon->dcl.con, &info);
|
dpy_set_ui_info(scon->dcl.con, &info);
|
||||||
}
|
}
|
||||||
sdl2_2d_redraw(scon);
|
sdl2_redraw(scon);
|
||||||
break;
|
break;
|
||||||
case SDL_WINDOWEVENT_EXPOSED:
|
case SDL_WINDOWEVENT_EXPOSED:
|
||||||
sdl2_2d_redraw(scon);
|
sdl2_redraw(scon);
|
||||||
break;
|
break;
|
||||||
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
||||||
case SDL_WINDOWEVENT_ENTER:
|
case SDL_WINDOWEVENT_ENTER:
|
||||||
|
@ -677,6 +687,35 @@ static const DisplayChangeListenerOps dcl_2d_ops = {
|
||||||
.dpy_cursor_define = sdl_mouse_define,
|
.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_gfx_check_format = console_gl_check_format,
|
||||||
|
.dpy_refresh = sdl2_gl_refresh,
|
||||||
|
.dpy_mouse_set = sdl_mouse_warp,
|
||||||
|
.dpy_cursor_define = sdl_mouse_define,
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void sdl_display_early_init(int opengl)
|
||||||
|
{
|
||||||
|
switch (opengl) {
|
||||||
|
case -1: /* default */
|
||||||
|
case 0: /* off */
|
||||||
|
break;
|
||||||
|
case 1: /* on */
|
||||||
|
#ifdef CONFIG_OPENGL
|
||||||
|
display_opengl = 1;
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
|
void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
|
||||||
{
|
{
|
||||||
int flags;
|
int flags;
|
||||||
|
@ -722,10 +761,16 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
|
||||||
if (!qemu_console_is_graphic(con)) {
|
if (!qemu_console_is_graphic(con)) {
|
||||||
sdl2_console[i].hidden = true;
|
sdl2_console[i].hidden = true;
|
||||||
}
|
}
|
||||||
|
sdl2_console[i].idx = i;
|
||||||
|
#ifdef CONFIG_OPENGL
|
||||||
|
sdl2_console[i].opengl = display_opengl;
|
||||||
|
sdl2_console[i].dcl.ops = display_opengl ? &dcl_gl_ops : &dcl_2d_ops;
|
||||||
|
#else
|
||||||
|
sdl2_console[i].opengl = 0;
|
||||||
sdl2_console[i].dcl.ops = &dcl_2d_ops;
|
sdl2_console[i].dcl.ops = &dcl_2d_ops;
|
||||||
|
#endif
|
||||||
sdl2_console[i].dcl.con = con;
|
sdl2_console[i].dcl.con = con;
|
||||||
register_displaychangelistener(&sdl2_console[i].dcl);
|
register_displaychangelistener(&sdl2_console[i].dcl);
|
||||||
sdl2_console[i].idx = i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Load a 32x32x4 image. White pixels are transparent. */
|
/* Load a 32x32x4 image. White pixels are transparent. */
|
||||||
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
/*
|
||||||
|
* QEMU opengl shader helper functions
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 Red Hat
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Gerd Hoffmann <kraxel@redhat.com>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
#include "qemu-common.h"
|
||||||
|
#include "ui/shader.h"
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
void qemu_gl_run_texture_blit(GLint texture_blit_prog)
|
||||||
|
{
|
||||||
|
GLfloat in_position[] = {
|
||||||
|
-1, -1,
|
||||||
|
1, -1,
|
||||||
|
-1, 1,
|
||||||
|
1, 1,
|
||||||
|
};
|
||||||
|
GLint l_position;
|
||||||
|
|
||||||
|
glUseProgram(texture_blit_prog);
|
||||||
|
l_position = glGetAttribLocation(texture_blit_prog, "in_position");
|
||||||
|
glVertexAttribPointer(l_position, 2, GL_FLOAT, GL_FALSE, 0, in_position);
|
||||||
|
glEnableVertexAttribArray(l_position);
|
||||||
|
glDrawArrays(GL_TRIANGLE_STRIP, l_position, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
GLuint qemu_gl_create_compile_shader(GLenum type, const GLchar *src)
|
||||||
|
{
|
||||||
|
GLuint shader;
|
||||||
|
GLint status, length;
|
||||||
|
char *errmsg;
|
||||||
|
|
||||||
|
shader = glCreateShader(type);
|
||||||
|
glShaderSource(shader, 1, &src, 0);
|
||||||
|
glCompileShader(shader);
|
||||||
|
|
||||||
|
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
|
||||||
|
if (!status) {
|
||||||
|
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
|
||||||
|
errmsg = malloc(length);
|
||||||
|
glGetShaderInfoLog(shader, length, &length, errmsg);
|
||||||
|
fprintf(stderr, "%s: compile %s error\n%s\n", __func__,
|
||||||
|
(type == GL_VERTEX_SHADER) ? "vertex" : "fragment",
|
||||||
|
errmsg);
|
||||||
|
free(errmsg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint qemu_gl_create_link_program(GLuint vert, GLuint frag)
|
||||||
|
{
|
||||||
|
GLuint program;
|
||||||
|
GLint status, length;
|
||||||
|
char *errmsg;
|
||||||
|
|
||||||
|
program = glCreateProgram();
|
||||||
|
glAttachShader(program, vert);
|
||||||
|
glAttachShader(program, frag);
|
||||||
|
glLinkProgram(program);
|
||||||
|
|
||||||
|
glGetProgramiv(program, GL_LINK_STATUS, &status);
|
||||||
|
if (!status) {
|
||||||
|
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
|
||||||
|
errmsg = malloc(length);
|
||||||
|
glGetProgramInfoLog(program, length, &length, errmsg);
|
||||||
|
fprintf(stderr, "%s: link program: %s\n", __func__, errmsg);
|
||||||
|
free(errmsg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return program;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint qemu_gl_create_compile_link_program(const GLchar *vert_src,
|
||||||
|
const GLchar *frag_src)
|
||||||
|
{
|
||||||
|
GLuint vert_shader, frag_shader, program;
|
||||||
|
|
||||||
|
vert_shader = qemu_gl_create_compile_shader(GL_VERTEX_SHADER, vert_src);
|
||||||
|
frag_shader = qemu_gl_create_compile_shader(GL_FRAGMENT_SHADER, frag_src);
|
||||||
|
if (!vert_shader || !frag_shader) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
program = qemu_gl_create_link_program(vert_shader, frag_shader);
|
||||||
|
glDeleteShader(vert_shader);
|
||||||
|
glDeleteShader(frag_shader);
|
||||||
|
|
||||||
|
return program;
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
#version 300 es
|
||||||
|
|
||||||
|
uniform sampler2D image;
|
||||||
|
in mediump vec2 ex_tex_coord;
|
||||||
|
out mediump vec4 out_frag_color;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
out_frag_color = texture(image, ex_tex_coord);
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
#version 300 es
|
||||||
|
|
||||||
|
in vec2 in_position;
|
||||||
|
out vec2 ex_tex_coord;
|
||||||
|
|
||||||
|
void main(void) {
|
||||||
|
gl_Position = vec4(in_position, 0.0, 1.0);
|
||||||
|
ex_tex_coord = vec2(1.0 + in_position.x, 1.0 - in_position.y) * 0.5;
|
||||||
|
}
|
23
vl.c
23
vl.c
|
@ -130,6 +130,7 @@ static int data_dir_idx;
|
||||||
const char *bios_name = NULL;
|
const char *bios_name = NULL;
|
||||||
enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
|
enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
|
||||||
DisplayType display_type = DT_DEFAULT;
|
DisplayType display_type = DT_DEFAULT;
|
||||||
|
int request_opengl = -1;
|
||||||
int display_opengl;
|
int display_opengl;
|
||||||
static int display_remote;
|
static int display_remote;
|
||||||
const char* keyboard_layout = NULL;
|
const char* keyboard_layout = NULL;
|
||||||
|
@ -1990,6 +1991,15 @@ static DisplayType select_display(const char *p)
|
||||||
} else {
|
} else {
|
||||||
goto invalid_sdl_args;
|
goto invalid_sdl_args;
|
||||||
}
|
}
|
||||||
|
} else if (strstart(opts, ",gl=", &nextopt)) {
|
||||||
|
opts = nextopt;
|
||||||
|
if (strstart(opts, "on", &nextopt)) {
|
||||||
|
request_opengl = 1;
|
||||||
|
} else if (strstart(opts, "off", &nextopt)) {
|
||||||
|
request_opengl = 0;
|
||||||
|
} else {
|
||||||
|
goto invalid_sdl_args;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
invalid_sdl_args:
|
invalid_sdl_args:
|
||||||
fprintf(stderr, "Invalid SDL option string: %s\n", p);
|
fprintf(stderr, "Invalid SDL option string: %s\n", p);
|
||||||
|
@ -4005,6 +4015,19 @@ int main(int argc, char **argv, char **envp)
|
||||||
early_gtk_display_init();
|
early_gtk_display_init();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
#if defined(CONFIG_SDL)
|
||||||
|
if (display_type == DT_SDL) {
|
||||||
|
sdl_display_early_init(request_opengl);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (request_opengl == 1 && display_opengl == 0) {
|
||||||
|
#if defined(CONFIG_OPENGL)
|
||||||
|
fprintf(stderr, "OpenGL is not supported by the display.\n");
|
||||||
|
#else
|
||||||
|
fprintf(stderr, "QEMU was built without opengl support.\n");
|
||||||
|
#endif
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
socket_init();
|
socket_init();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue