snes9x/gtk/src/gtk_display_driver_gtk.cpp

286 lines
7.1 KiB
C++
Raw Normal View History

2010-09-25 17:46:12 +02:00
#include <gtk/gtk.h>
2010-09-26 11:19:15 +02:00
#include <gdk/gdk.h>
#include <cairo.h>
2010-09-25 17:46:12 +02:00
#include "gtk_display.h"
#include "gtk_display_driver_gtk.h"
S9xGTKDisplayDriver::S9xGTKDisplayDriver (Snes9xWindow *window,
Snes9xConfig *config)
{
this->window = window;
this->config = config;
this->drawing_area = GTK_WIDGET (window->drawing_area);
2010-09-26 11:19:15 +02:00
this->pixbuf = NULL;
2010-09-25 17:46:12 +02:00
return;
}
void
2018-05-05 00:12:22 +02:00
S9xGTKDisplayDriver::update (int width, int height, int yoffset)
2010-09-25 17:46:12 +02:00
{
2010-09-26 11:19:15 +02:00
int x, y, w, h;
int c_width, c_height, final_pitch;
uint8 *final_buffer;
GtkAllocation allocation;
2010-09-25 17:46:12 +02:00
2010-09-26 11:19:15 +02:00
gtk_widget_get_allocation (drawing_area, &allocation);
c_width = allocation.width;
c_height = allocation.height;
2010-09-25 17:46:12 +02:00
if (width <= 0)
return;
if (config->scale_method > 0)
{
uint8 *src_buffer = (uint8 *) padded_buffer[0];
uint8 *dst_buffer = (uint8 *) padded_buffer[1];
int src_pitch = image_width * image_bpp;
int dst_pitch = scaled_max_width * image_bpp;
2018-05-05 00:12:22 +02:00
src_buffer += (src_pitch * yoffset);
2010-09-25 17:46:12 +02:00
S9xFilter (src_buffer,
src_pitch,
dst_buffer,
dst_pitch,
width,
height);
final_buffer = (uint8 *) padded_buffer[1];
final_pitch = dst_pitch;
}
else
{
final_buffer = (uint8 *) padded_buffer[0];
final_pitch = image_width * image_bpp;
2018-05-05 00:12:22 +02:00
final_buffer += (final_pitch * yoffset);
2010-09-25 17:46:12 +02:00
}
2010-09-26 11:19:15 +02:00
x = width; y = height; w = c_width; h = c_height;
S9xApplyAspect (x, y, w, h);
2010-09-26 11:19:15 +02:00
output (final_buffer, final_pitch, x, y, width, height, w, h);
2010-09-25 17:46:12 +02:00
return;
}
void
S9xGTKDisplayDriver::output (void *src,
int src_pitch,
int x,
int y,
int width,
int height,
int dst_width,
int dst_height)
{
if (width != gdk_buffer_width || height != gdk_buffer_height)
2010-09-26 11:19:15 +02:00
{
gdk_buffer_width = width;
gdk_buffer_height = height;
2010-09-26 11:19:15 +02:00
g_object_unref (pixbuf);
2010-09-26 11:19:15 +02:00
padded_buffer[2] = realloc (padded_buffer[2],
gdk_buffer_width * gdk_buffer_height * 3);
pixbuf = gdk_pixbuf_new_from_data ((guchar *) padded_buffer[2],
GDK_COLORSPACE_RGB,
FALSE,
8,
gdk_buffer_width,
gdk_buffer_height,
gdk_buffer_width * 3,
NULL,
NULL);
}
2010-09-25 17:46:12 +02:00
if (last_known_width != dst_width || last_known_height != dst_height)
{
clear ();
last_known_width = dst_width;
last_known_height = dst_height;
}
S9xConvert (src,
padded_buffer[2],
src_pitch,
gdk_buffer_width * 3,
width,
height,
24);
2010-09-25 17:46:12 +02:00
2017-12-07 19:24:29 +01:00
cairo_t *cr = window->get_cairo ();
2010-09-26 11:19:15 +02:00
gdk_cairo_set_source_pixbuf (cr, pixbuf, x, y);
if (width != dst_width || height != dst_height)
{
cairo_matrix_t matrix;
cairo_pattern_t *pattern = cairo_get_source (cr);;
cairo_matrix_init_identity (&matrix);
cairo_matrix_scale (&matrix,
(double) width / (double) dst_width,
(double) height / (double) dst_height);
cairo_matrix_translate (&matrix, -x, -y);
cairo_pattern_set_matrix (pattern, &matrix);
cairo_pattern_set_filter (pattern,
Settings.BilinearFilter
? CAIRO_FILTER_BILINEAR
: CAIRO_FILTER_NEAREST);
}
2010-09-26 11:19:15 +02:00
cairo_rectangle (cr, x, y, dst_width, dst_height);
cairo_fill (cr);
2017-12-07 19:24:29 +01:00
window->release_cairo ();
2010-09-25 17:46:12 +02:00
window->set_mouseable_area (x, y, width, height);
return;
}
int
S9xGTKDisplayDriver::init (void)
{
2010-09-26 11:19:15 +02:00
GtkAllocation allocation;
2010-09-25 17:46:12 +02:00
buffer[0] = malloc (image_padded_size);
buffer[1] = malloc (scaled_padded_size);
2018-05-05 00:12:22 +02:00
padded_buffer[0] = (void *) (((uint8 *) buffer[0]) + image_padded_offset);
padded_buffer[1] = (void *) (((uint8 *) buffer[1]) + scaled_padded_offset);
2010-09-25 17:46:12 +02:00
2010-09-26 11:19:15 +02:00
gtk_widget_get_allocation (drawing_area, &allocation);
gdk_buffer_width = allocation.width;
gdk_buffer_height = allocation.height;
2010-09-25 17:46:12 +02:00
padded_buffer[2] = malloc (gdk_buffer_width * gdk_buffer_height * 3);
2010-09-26 11:19:15 +02:00
pixbuf = gdk_pixbuf_new_from_data ((guchar *) padded_buffer[2],
GDK_COLORSPACE_RGB,
FALSE,
8,
gdk_buffer_width,
gdk_buffer_height,
gdk_buffer_width * 3,
NULL,
NULL);
S9xSetEndianess (ENDIAN_SWAPPED);
2010-09-25 17:46:12 +02:00
memset (buffer[0], 0, image_padded_size);
memset (buffer[1], 0, scaled_padded_size);
GFX.Screen = (uint16 *) padded_buffer[0];
GFX.Pitch = image_width * image_bpp;
return 0;
}
void
S9xGTKDisplayDriver::deinit (void)
{
padded_buffer[0] = NULL;
padded_buffer[1] = NULL;
free (buffer[0]);
free (buffer[1]);
2010-09-26 11:19:15 +02:00
g_object_unref (pixbuf);
2010-09-25 17:46:12 +02:00
free (padded_buffer[2]);
return;
}
void
S9xGTKDisplayDriver::clear (void)
{
2010-09-26 11:19:15 +02:00
int x, y, w, h;
int width, height;
GtkAllocation allocation;
gtk_widget_get_allocation (drawing_area, &allocation);
width = allocation.width;
height = allocation.height;
2010-09-25 17:46:12 +02:00
2017-12-07 19:24:29 +01:00
cairo_t *cr = window->get_cairo ();
2010-09-26 11:19:15 +02:00
cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
2010-09-25 17:46:12 +02:00
if (window->last_width <= 0 || window->last_height <= 0)
{
2010-09-26 11:19:15 +02:00
cairo_paint (cr);
2017-12-07 19:24:29 +01:00
window->release_cairo ();
2010-09-26 11:19:15 +02:00
2010-09-25 17:46:12 +02:00
return;
}
2010-09-26 11:19:15 +02:00
x = window->last_width;
y = window->last_height;
get_filter_scale (x, y);
w = width;
h = height;
S9xApplyAspect (x, y, w, h);
2010-09-25 17:46:12 +02:00
2010-09-26 11:19:15 +02:00
if (x > 0)
2010-09-25 17:46:12 +02:00
{
2010-09-26 11:19:15 +02:00
cairo_rectangle (cr, 0, y, x, h);
2010-09-25 17:46:12 +02:00
}
2010-09-26 11:19:15 +02:00
if (x + w < width)
{
cairo_rectangle (cr, x + w, y, width - (x + w), h);
}
if (y > 0)
{
cairo_rectangle (cr, 0, 0, width, y);
}
if (y + h < height)
2010-09-25 17:46:12 +02:00
{
2010-09-26 11:19:15 +02:00
cairo_rectangle (cr, 0, y + h, width, height - (y + h));
2010-09-25 17:46:12 +02:00
}
2010-09-26 11:19:15 +02:00
cairo_fill (cr);
2017-12-07 19:24:29 +01:00
window->release_cairo ();
2010-09-26 11:19:15 +02:00
2010-09-25 17:46:12 +02:00
return;
}
void
S9xGTKDisplayDriver::refresh (int width, int height)
{
clear ();
return;
}
uint16 *
S9xGTKDisplayDriver::get_next_buffer (void)
{
return (uint16 *) padded_buffer[0];
}
uint16 *
S9xGTKDisplayDriver::get_current_buffer (void)
{
return (uint16 *) padded_buffer[0];
}
void
S9xGTKDisplayDriver::push_buffer (uint16 *src)
{
memmove (GFX.Screen, src, image_size);
return;
}
void
S9xGTKDisplayDriver::clear_buffers (void)
{
memset (buffer[0], 0, image_padded_size);
memset (buffer[1], 0, scaled_padded_size);
return;
}