[GTK3] Use GtkGLArea render event in GbScreen
This commit is contained in:
parent
d63560d3c1
commit
337f396eff
119
gtk3/gb_screen.c
119
gtk3/gb_screen.c
@ -7,7 +7,6 @@ struct _GbScreen {
|
|||||||
GtkBin parent;
|
GtkBin parent;
|
||||||
|
|
||||||
GtkGLArea *gl_area;
|
GtkGLArea *gl_area;
|
||||||
GtkDrawingArea *fallback;
|
|
||||||
|
|
||||||
bool use_gl;
|
bool use_gl;
|
||||||
shader_t shader;
|
shader_t shader;
|
||||||
@ -73,54 +72,44 @@ static void gb_screen_get_natural_size(GbScreen *self, gint *natural_width, gint
|
|||||||
if (scale_y_ptr) *scale_y_ptr = scale_y;
|
if (scale_y_ptr) *scale_y_ptr = scale_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean gb_screen_draw(GtkWidget *widget, cairo_t *cr) {
|
static void gb_screen_calculate_viewport(GbScreen *self, Rect *viewport_ptr, gint *scaled_width_ptr, gint *scaled_height_ptr, double *scale_x_ptr, double *scale_y_ptr) {
|
||||||
GTK_WIDGET_CLASS(gb_screen_parent_class)->draw(widget, cr);
|
gint scaled_width, scaled_height;
|
||||||
|
double scale_x, scale_y;
|
||||||
|
|
||||||
static gint scaled_width, scaled_height;
|
GtkWidget *widget = GTK_WIDGET(self);
|
||||||
static double scale_x, scale_y;
|
|
||||||
|
|
||||||
GbScreen *self = (GbScreen *) widget;
|
|
||||||
|
|
||||||
GtkStyleContext *context = gtk_widget_get_style_context(widget);
|
|
||||||
int width = gtk_widget_get_allocated_width(widget);
|
int width = gtk_widget_get_allocated_width(widget);
|
||||||
int height = gtk_widget_get_allocated_height(widget);
|
int height = gtk_widget_get_allocated_height(widget);
|
||||||
|
|
||||||
gtk_render_background(context, cr, 0, 0, width, height);
|
|
||||||
gtk_render_frame(context, cr, 0, 0, width, height);
|
|
||||||
gb_screen_get_natural_size(self, &scaled_width, &scaled_height, &scale_x, &scale_y);
|
gb_screen_get_natural_size(self, &scaled_width, &scaled_height, &scale_x, &scale_y);
|
||||||
|
|
||||||
Rect viewport = {
|
if (viewport_ptr) {
|
||||||
(width - scaled_width) / 2,
|
*viewport_ptr = (Rect){
|
||||||
(height - scaled_height) / 2,
|
(width - scaled_width) / 2,
|
||||||
scaled_width,
|
(height - scaled_height) / 2,
|
||||||
scaled_height
|
scaled_width,
|
||||||
};
|
scaled_height
|
||||||
|
};
|
||||||
if (self->use_gl) {
|
|
||||||
glViewport(viewport.x, viewport.y, scaled_width, scaled_height);
|
|
||||||
|
|
||||||
uint32_t *pixels = gb_screen_get_current_buffer(self);
|
|
||||||
uint32_t *previous = gb_screen_get_previous_buffer(self);
|
|
||||||
|
|
||||||
static void *_pixels = NULL;
|
|
||||||
|
|
||||||
if (pixels) {
|
|
||||||
_pixels = pixels;
|
|
||||||
}
|
|
||||||
|
|
||||||
glClearColor(0, 0, 0, 1);
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
|
||||||
|
|
||||||
render_bitmap_with_shader(
|
|
||||||
&self->shader, _pixels, previous,
|
|
||||||
self->screen_width, self->screen_height,
|
|
||||||
viewport.x, viewport.y, viewport.width, viewport.height,
|
|
||||||
self->blending_mode
|
|
||||||
);
|
|
||||||
|
|
||||||
// gtk_gl_area_queue_render(self->gl_area);
|
|
||||||
}
|
}
|
||||||
else {
|
if (scaled_width_ptr) *scaled_width_ptr = scaled_width;
|
||||||
|
if (scaled_height_ptr) *scaled_height_ptr = scaled_height;
|
||||||
|
if (scale_x_ptr) *scale_x_ptr = scale_x;
|
||||||
|
if (scale_y_ptr) *scale_y_ptr = scale_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean gb_screen_draw(GtkWidget *widget, cairo_t *cr) {
|
||||||
|
GbScreen *self = (GbScreen *)widget;
|
||||||
|
|
||||||
|
if (!self->use_gl) {
|
||||||
|
int width = gtk_widget_get_allocated_width(widget);
|
||||||
|
int height = gtk_widget_get_allocated_height(widget);
|
||||||
|
|
||||||
|
GtkStyleContext *context = gtk_widget_get_style_context(widget);
|
||||||
|
gtk_render_background(context, cr, 0, 0, width, height);
|
||||||
|
gtk_render_frame(context, cr, 0, 0, width, height);
|
||||||
|
|
||||||
|
Rect viewport;
|
||||||
|
double scale_x, scale_y;
|
||||||
|
gb_screen_calculate_viewport(self, &viewport, NULL, NULL, &scale_x, &scale_y);
|
||||||
|
|
||||||
cairo_surface_t *surface = cairo_image_surface_create_for_data(
|
cairo_surface_t *surface = cairo_image_surface_create_for_data(
|
||||||
(unsigned char *) gb_screen_get_current_buffer(self),
|
(unsigned char *) gb_screen_get_current_buffer(self),
|
||||||
CAIRO_FORMAT_RGB24,
|
CAIRO_FORMAT_RGB24,
|
||||||
@ -137,6 +126,9 @@ static gboolean gb_screen_draw(GtkWidget *widget, cairo_t *cr) {
|
|||||||
|
|
||||||
cairo_surface_destroy(surface);
|
cairo_surface_destroy(surface);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
GTK_WIDGET_CLASS(gb_screen_parent_class)->draw(widget, cr);
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -181,6 +173,35 @@ static void gb_screen_get_property(GObject *object, guint property_id, GValue *v
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void gb_screen_gl_area_render(GtkGLArea *gl_area, GdkGLContext *context, GObject *object) {
|
||||||
|
GbScreen *self = (GbScreen *)object;
|
||||||
|
|
||||||
|
Rect viewport;
|
||||||
|
gint scaled_width, scaled_height;
|
||||||
|
gb_screen_calculate_viewport(self, &viewport, &scaled_width, &scaled_height, NULL, NULL);
|
||||||
|
|
||||||
|
glViewport(viewport.x, viewport.y, scaled_width, scaled_height);
|
||||||
|
|
||||||
|
uint32_t *pixels = gb_screen_get_current_buffer(self);
|
||||||
|
uint32_t *previous = gb_screen_get_previous_buffer(self);
|
||||||
|
|
||||||
|
static void *_pixels = NULL;
|
||||||
|
|
||||||
|
if (pixels) {
|
||||||
|
_pixels = pixels;
|
||||||
|
}
|
||||||
|
|
||||||
|
glClearColor(0, 0, 0, 1);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
render_bitmap_with_shader(
|
||||||
|
&self->shader, _pixels, previous,
|
||||||
|
self->screen_width, self->screen_height,
|
||||||
|
viewport.x, viewport.y, viewport.width, viewport.height,
|
||||||
|
self->blending_mode
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
static void gb_screen_gl_area_realized(GtkWidget *widget, GObject *object) {
|
static void gb_screen_gl_area_realized(GtkWidget *widget, GObject *object) {
|
||||||
GbScreen *self = (GbScreen *)object;
|
GbScreen *self = (GbScreen *)object;
|
||||||
GtkGLArea *gl_area = GTK_GL_AREA(widget);
|
GtkGLArea *gl_area = GTK_GL_AREA(widget);
|
||||||
@ -231,6 +252,7 @@ static void gb_screen_constructed(GObject *object) {
|
|||||||
if (self->use_gl) {
|
if (self->use_gl) {
|
||||||
self->gl_area = GTK_GL_AREA(gtk_gl_area_new());
|
self->gl_area = GTK_GL_AREA(gtk_gl_area_new());
|
||||||
g_signal_connect(self->gl_area, "realize", G_CALLBACK(gb_screen_gl_area_realized), object);
|
g_signal_connect(self->gl_area, "realize", G_CALLBACK(gb_screen_gl_area_realized), object);
|
||||||
|
g_signal_connect(self->gl_area, "render", G_CALLBACK(gb_screen_gl_area_render), object);
|
||||||
|
|
||||||
gtk_gl_area_set_required_version(self->gl_area, 3, 2);
|
gtk_gl_area_set_required_version(self->gl_area, 3, 2);
|
||||||
gtk_gl_area_set_auto_render(self->gl_area, false);
|
gtk_gl_area_set_auto_render(self->gl_area, false);
|
||||||
@ -249,7 +271,7 @@ static void gb_screen_class_init(GbScreenClass *class) {
|
|||||||
obj_properties[PROP_USE_GL] = g_param_spec_boolean(
|
obj_properties[PROP_USE_GL] = g_param_spec_boolean(
|
||||||
"use-gl", "Use OpenGL", "Whether to use OpenGL for rendering.",
|
"use-gl", "Use OpenGL", "Whether to use OpenGL for rendering.",
|
||||||
true,
|
true,
|
||||||
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_PRIVATE
|
G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE
|
||||||
);
|
);
|
||||||
|
|
||||||
G_OBJECT_CLASS(class)->finalize = gb_screen_finalize;
|
G_OBJECT_CLASS(class)->finalize = gb_screen_finalize;
|
||||||
@ -270,7 +292,6 @@ static void gb_screen_init(GbScreen *self) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
GbScreen *gb_screen_new(bool force_fallback) {
|
GbScreen *gb_screen_new(bool force_fallback) {
|
||||||
g_debug("force_fallback: %d", force_fallback);
|
|
||||||
return g_object_new(GB_SCREEN_TYPE, "use-gl", !force_fallback, NULL);
|
return g_object_new(GB_SCREEN_TYPE, "use-gl", !force_fallback, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -337,3 +358,11 @@ void gb_screen_set_shader(GbScreen *self, const char *shader_name) {
|
|||||||
free_shader(&self->shader);
|
free_shader(&self->shader);
|
||||||
init_shader_with_name(&self->shader, shader_name);
|
init_shader_with_name(&self->shader, shader_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gb_screen_queue_render(GbScreen *self) {
|
||||||
|
if (self->use_gl) {
|
||||||
|
gtk_gl_area_queue_render(self->gl_area);
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_widget_queue_draw(GTK_WIDGET(self));
|
||||||
|
}
|
@ -21,5 +21,6 @@ void gb_screen_flip(GbScreen *self);
|
|||||||
void gb_screen_set_resolution(GbScreen *self, unsigned width, unsigned height);
|
void gb_screen_set_resolution(GbScreen *self, unsigned width, unsigned height);
|
||||||
void gb_screen_set_blending_mode(GbScreen *self, GB_frame_blending_mode_t mode);
|
void gb_screen_set_blending_mode(GbScreen *self, GB_frame_blending_mode_t mode);
|
||||||
void gb_screen_set_shader(GbScreen *self, const char *shader_name);
|
void gb_screen_set_shader(GbScreen *self, const char *shader_name);
|
||||||
|
void gb_screen_queue_render(GbScreen *self);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -671,7 +671,7 @@ static void stop(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean on_vblank(GB_gameboy_t *gb) {
|
static gboolean on_vblank(GB_gameboy_t *gb) {
|
||||||
gtk_widget_queue_draw(GTK_WIDGET(gui_data.screen));
|
gb_screen_queue_render(gui_data.screen);
|
||||||
gtk_widget_queue_draw(GTK_WIDGET(gui_data.vram_viewer));
|
gtk_widget_queue_draw(GTK_WIDGET(gui_data.vram_viewer));
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -1384,8 +1384,6 @@ static void shutdown(GApplication *app, GFile **files, gint n_files, const gchar
|
|||||||
|
|
||||||
stop();
|
stop();
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
|
|
||||||
gtk_widget_destroy(GTK_WIDGET(gui_data.screen));
|
|
||||||
GB_free(&gb);
|
GB_free(&gb);
|
||||||
|
|
||||||
g_object_unref(gui_data.builder);
|
g_object_unref(gui_data.builder);
|
||||||
@ -1449,7 +1447,7 @@ static void close_rom(void) {
|
|||||||
GB_free(&gb);
|
GB_free(&gb);
|
||||||
|
|
||||||
gb_screen_clear(gui_data.screen);
|
gb_screen_clear(gui_data.screen);
|
||||||
gtk_widget_queue_draw(GTK_WIDGET(gui_data.screen));
|
gb_screen_queue_render(gui_data.screen);
|
||||||
|
|
||||||
vram_viewer_clear(gui_data.vram_viewer);
|
vram_viewer_clear(gui_data.vram_viewer);
|
||||||
gtk_widget_queue_draw(GTK_WIDGET(gui_data.vram_viewer));
|
gtk_widget_queue_draw(GTK_WIDGET(gui_data.vram_viewer));
|
||||||
|
Loading…
Reference in New Issue
Block a user