mirror of https://github.com/snes9xgit/snes9x.git
GTK: Refactoring of display output code.
Moves buffer management to single location.
This commit is contained in:
parent
38bcabff68
commit
3c3ea985ef
File diff suppressed because it is too large
Load Diff
|
@ -123,7 +123,6 @@ void S9xFilter (uint8 *src_buffer,
|
||||||
int& height);
|
int& height);
|
||||||
void get_filter_scale (int& width, int& height);
|
void get_filter_scale (int& width, int& height);
|
||||||
void S9xDisplayRefresh (int width, int height);
|
void S9xDisplayRefresh (int width, int height);
|
||||||
void S9xDisplayClearBuffers ();
|
|
||||||
void S9xReinitDisplay ();
|
void S9xReinitDisplay ();
|
||||||
void S9xDisplayReconfigure ();
|
void S9xDisplayReconfigure ();
|
||||||
void S9xQueryDrivers ();
|
void S9xQueryDrivers ();
|
||||||
|
|
|
@ -11,46 +11,22 @@
|
||||||
|
|
||||||
class S9xDisplayDriver
|
class S9xDisplayDriver
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~S9xDisplayDriver() {}
|
virtual ~S9xDisplayDriver()
|
||||||
virtual void refresh (int width, int height) = 0;
|
{
|
||||||
virtual int init () = 0;
|
}
|
||||||
virtual void deinit () = 0;
|
virtual void refresh(int width, int height) = 0;
|
||||||
virtual void clear_buffers () = 0;
|
virtual int init() = 0;
|
||||||
virtual void update (int width, int height, int yoffset) = 0;
|
virtual void deinit() = 0;
|
||||||
virtual uint16 *get_next_buffer () = 0;
|
virtual void update(uint16_t *buffer, int width, int height, int stride_in_pixels) = 0;
|
||||||
virtual uint16 *get_current_buffer () = 0;
|
virtual void *get_parameters() = 0;
|
||||||
virtual void push_buffer (uint16 *src) = 0;
|
virtual void save(const char *filename) = 0;
|
||||||
virtual void *get_parameters () = 0;
|
virtual bool is_ready() = 0;
|
||||||
virtual void save (const char *filename) = 0;
|
|
||||||
virtual bool is_ready () = 0;
|
|
||||||
|
|
||||||
/* Namespaced sizing constants */
|
protected:
|
||||||
static const int image_width = 1024;
|
Snes9xWindow *window;
|
||||||
static const int image_height = 478;
|
Snes9xConfig *config;
|
||||||
static const int image_bpp = 2;
|
GtkWidget *drawing_area;
|
||||||
static const int scaled_max_width = 1024;
|
|
||||||
static const int scaled_max_height = 956;
|
|
||||||
|
|
||||||
static const int image_size = image_width * image_height * image_bpp;
|
|
||||||
static const int image_padded_size = (image_width + 8) *
|
|
||||||
(image_height + 8 + 30) *
|
|
||||||
image_bpp;
|
|
||||||
static const int image_padded_offset = (image_width + 8) * (4 + 30) + 4;
|
|
||||||
static const int scaled_size = scaled_max_width *
|
|
||||||
scaled_max_height *
|
|
||||||
image_bpp;
|
|
||||||
static const int scaled_padded_size = (scaled_max_width + 8) *
|
|
||||||
(scaled_max_height + 8) *
|
|
||||||
image_bpp;
|
|
||||||
static const int scaled_padded_offset = (scaled_max_width + 8) * 4 + 4;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Snes9xWindow *window;
|
|
||||||
Snes9xConfig *config;
|
|
||||||
GtkWidget *drawing_area;
|
|
||||||
uint8_t *padded_buffer[4];
|
|
||||||
uint8_t *buffer[4];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __GTK_DISPLAY_DRIVER_H*/
|
#endif /* __GTK_DISPLAY_DRIVER_H*/
|
||||||
|
|
|
@ -9,156 +9,106 @@
|
||||||
#include "gtk_display.h"
|
#include "gtk_display.h"
|
||||||
#include "gtk_display_driver_gtk.h"
|
#include "gtk_display_driver_gtk.h"
|
||||||
|
|
||||||
|
S9xGTKDisplayDriver::S9xGTKDisplayDriver(Snes9xWindow *window,
|
||||||
S9xGTKDisplayDriver::S9xGTKDisplayDriver (Snes9xWindow *window,
|
Snes9xConfig *config)
|
||||||
Snes9xConfig *config)
|
|
||||||
{
|
{
|
||||||
this->window = window;
|
this->window = window;
|
||||||
this->config = config;
|
this->config = config;
|
||||||
this->drawing_area = GTK_WIDGET (window->drawing_area);
|
this->drawing_area = GTK_WIDGET(window->drawing_area);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void S9xGTKDisplayDriver::update(uint16_t *buffer, int width, int height, int stride_in_pixels)
|
||||||
S9xGTKDisplayDriver::update (int width, int height, int yoffset)
|
|
||||||
{
|
{
|
||||||
int final_pitch;
|
|
||||||
uint8 *final_buffer;
|
|
||||||
GtkAllocation allocation;
|
GtkAllocation allocation;
|
||||||
|
|
||||||
if (width <= 0)
|
if (width <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
gtk_widget_get_allocation (drawing_area, &allocation);
|
gtk_widget_get_allocation(drawing_area, &allocation);
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
src_buffer += (src_pitch * yoffset);
|
|
||||||
|
|
||||||
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;
|
|
||||||
final_buffer += (final_pitch * yoffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
S9xRect dst = S9xApplyAspect(width, height, allocation.width, allocation.height);
|
S9xRect dst = S9xApplyAspect(width, height, allocation.width, allocation.height);
|
||||||
output (final_buffer, final_pitch, dst.x, dst.y, width, height, dst.w, dst.h);
|
output(buffer, stride_in_pixels * 2, dst.x, dst.y, width, height, dst.w, dst.h);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void S9xGTKDisplayDriver::output(void *src,
|
||||||
S9xGTKDisplayDriver::output (void *src,
|
int src_pitch,
|
||||||
int src_pitch,
|
int x,
|
||||||
int x,
|
int y,
|
||||||
int y,
|
int width,
|
||||||
int width,
|
int height,
|
||||||
int height,
|
int dst_width,
|
||||||
int dst_width,
|
int dst_height)
|
||||||
int dst_height)
|
|
||||||
{
|
{
|
||||||
if (last_known_width != dst_width || last_known_height != dst_height)
|
if (last_known_width != dst_width || last_known_height != dst_height)
|
||||||
{
|
{
|
||||||
clear ();
|
clear();
|
||||||
|
|
||||||
last_known_width = dst_width;
|
last_known_width = dst_width;
|
||||||
last_known_height = dst_height;
|
last_known_height = dst_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_t *cr = window->get_cairo ();
|
cairo_t *cr = window->get_cairo();
|
||||||
|
|
||||||
cairo_surface_t *surface;
|
cairo_surface_t *surface;
|
||||||
|
|
||||||
surface = cairo_image_surface_create_for_data ((unsigned char *) src, CAIRO_FORMAT_RGB16_565, width, height, src_pitch);
|
surface = cairo_image_surface_create_for_data((unsigned char *)src, CAIRO_FORMAT_RGB16_565, width, height, src_pitch);
|
||||||
|
|
||||||
cairo_set_source_surface (cr, surface, 0, 0);
|
cairo_set_source_surface(cr, surface, 0, 0);
|
||||||
|
|
||||||
if (width != dst_width || height != dst_height)
|
if (width != dst_width || height != dst_height)
|
||||||
{
|
{
|
||||||
cairo_matrix_t matrix;
|
cairo_matrix_t matrix;
|
||||||
cairo_pattern_t *pattern = cairo_get_source (cr);;
|
cairo_pattern_t *pattern = cairo_get_source(cr);
|
||||||
|
;
|
||||||
|
|
||||||
cairo_matrix_init_identity (&matrix);
|
cairo_matrix_init_identity(&matrix);
|
||||||
cairo_matrix_scale (&matrix,
|
cairo_matrix_scale(&matrix,
|
||||||
(double) width / (double) dst_width,
|
(double)width / (double)dst_width,
|
||||||
(double) height / (double) dst_height);
|
(double)height / (double)dst_height);
|
||||||
cairo_matrix_translate (&matrix, -x, -y);
|
cairo_matrix_translate(&matrix, -x, -y);
|
||||||
cairo_pattern_set_matrix (pattern, &matrix);
|
cairo_pattern_set_matrix(pattern, &matrix);
|
||||||
cairo_pattern_set_filter (pattern,
|
cairo_pattern_set_filter(pattern,
|
||||||
Settings.BilinearFilter
|
Settings.BilinearFilter
|
||||||
? CAIRO_FILTER_BILINEAR
|
? CAIRO_FILTER_BILINEAR
|
||||||
: CAIRO_FILTER_NEAREST);
|
: CAIRO_FILTER_NEAREST);
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_rectangle (cr, x, y, dst_width, dst_height);
|
cairo_rectangle(cr, x, y, dst_width, dst_height);
|
||||||
cairo_fill (cr);
|
cairo_fill(cr);
|
||||||
|
|
||||||
cairo_surface_finish (surface);
|
cairo_surface_finish(surface);
|
||||||
cairo_surface_destroy (surface);
|
cairo_surface_destroy(surface);
|
||||||
|
|
||||||
window->release_cairo ();
|
window->release_cairo();
|
||||||
window->set_mouseable_area (x, y, width, height);
|
window->set_mouseable_area(x, y, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int S9xGTKDisplayDriver::init()
|
||||||
S9xGTKDisplayDriver::init ()
|
|
||||||
{
|
{
|
||||||
buffer[0] = new uint8_t[image_padded_size];
|
|
||||||
buffer[1] = new uint8_t[scaled_padded_size];
|
|
||||||
|
|
||||||
padded_buffer[0] = &buffer[0][image_padded_offset];
|
|
||||||
padded_buffer[1] = &buffer[1][scaled_padded_offset];
|
|
||||||
|
|
||||||
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void S9xGTKDisplayDriver::deinit()
|
||||||
S9xGTKDisplayDriver::deinit ()
|
|
||||||
{
|
{
|
||||||
padded_buffer[0] = NULL;
|
|
||||||
padded_buffer[1] = NULL;
|
|
||||||
|
|
||||||
delete[] buffer[0];
|
|
||||||
delete[] buffer[1];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void S9xGTKDisplayDriver::clear()
|
||||||
S9xGTKDisplayDriver::clear ()
|
|
||||||
{
|
{
|
||||||
int width, height;
|
int width, height;
|
||||||
GtkAllocation allocation;
|
GtkAllocation allocation;
|
||||||
|
|
||||||
gtk_widget_get_allocation (drawing_area, &allocation);
|
gtk_widget_get_allocation(drawing_area, &allocation);
|
||||||
width = allocation.width;
|
width = allocation.width;
|
||||||
height = allocation.height;
|
height = allocation.height;
|
||||||
|
|
||||||
cairo_t *cr = window->get_cairo ();
|
cairo_t *cr = window->get_cairo();
|
||||||
|
|
||||||
cairo_set_source_rgb (cr, 0.0, 0.0, 0.0);
|
cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
|
||||||
|
|
||||||
if (window->last_width <= 0 || window->last_height <= 0)
|
if (window->last_width <= 0 || window->last_height <= 0)
|
||||||
{
|
{
|
||||||
cairo_paint (cr);
|
cairo_paint(cr);
|
||||||
window->release_cairo ();
|
window->release_cairo();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -171,53 +121,27 @@ S9xGTKDisplayDriver::clear ()
|
||||||
|
|
||||||
if (dst.x > 0)
|
if (dst.x > 0)
|
||||||
{
|
{
|
||||||
cairo_rectangle (cr, 0, dst.y, dst.x, dst.h);
|
cairo_rectangle(cr, 0, dst.y, dst.x, dst.h);
|
||||||
}
|
}
|
||||||
if (dst.x + dst.w < width)
|
if (dst.x + dst.w < width)
|
||||||
{
|
{
|
||||||
cairo_rectangle (cr, dst.x + dst.w, dst.y, width - (dst.x + dst.w), dst.h);
|
cairo_rectangle(cr, dst.x + dst.w, dst.y, width - (dst.x + dst.w), dst.h);
|
||||||
}
|
}
|
||||||
if (dst.y > 0)
|
if (dst.y > 0)
|
||||||
{
|
{
|
||||||
cairo_rectangle (cr, 0, 0, width, dst.y);
|
cairo_rectangle(cr, 0, 0, width, dst.y);
|
||||||
}
|
}
|
||||||
if (dst.y + dst.h < height)
|
if (dst.y + dst.h < height)
|
||||||
{
|
{
|
||||||
cairo_rectangle (cr, 0, dst.y + dst.h, width, height - (dst.y + dst.h));
|
cairo_rectangle(cr, 0, dst.y + dst.h, width, height - (dst.y + dst.h));
|
||||||
}
|
}
|
||||||
|
|
||||||
cairo_fill (cr);
|
cairo_fill(cr);
|
||||||
|
|
||||||
window->release_cairo ();
|
window->release_cairo();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void S9xGTKDisplayDriver::refresh(int width, int height)
|
||||||
S9xGTKDisplayDriver::refresh (int width, int height)
|
|
||||||
{
|
{
|
||||||
clear ();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16 *
|
|
||||||
S9xGTKDisplayDriver::get_next_buffer ()
|
|
||||||
{
|
|
||||||
return (uint16 *) padded_buffer[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16 *
|
|
||||||
S9xGTKDisplayDriver::get_current_buffer ()
|
|
||||||
{
|
|
||||||
return (uint16 *) padded_buffer[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
S9xGTKDisplayDriver::push_buffer (uint16 *src)
|
|
||||||
{
|
|
||||||
memmove (GFX.Screen, src, image_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
S9xGTKDisplayDriver::clear_buffers ()
|
|
||||||
{
|
|
||||||
memset (buffer[0], 0, image_padded_size);
|
|
||||||
memset (buffer[1], 0, scaled_padded_size);
|
|
||||||
}
|
|
|
@ -12,33 +12,37 @@
|
||||||
|
|
||||||
class S9xGTKDisplayDriver : public S9xDisplayDriver
|
class S9xGTKDisplayDriver : public S9xDisplayDriver
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
S9xGTKDisplayDriver (Snes9xWindow *window, Snes9xConfig *config);
|
S9xGTKDisplayDriver(Snes9xWindow *window, Snes9xConfig *config);
|
||||||
void refresh (int width, int height);
|
void refresh(int width, int height);
|
||||||
int init ();
|
int init();
|
||||||
void deinit ();
|
void deinit();
|
||||||
void clear_buffers ();
|
void update(uint16_t *buffer, int width, int height, int stride_in_pixels);
|
||||||
void update (int width, int height, int yoffset);
|
void *get_parameters()
|
||||||
uint16 *get_next_buffer ();
|
{
|
||||||
uint16 *get_current_buffer ();
|
return NULL;
|
||||||
void push_buffer (uint16 *src);
|
}
|
||||||
void *get_parameters () { return NULL; }
|
void save(const char *filename)
|
||||||
void save (const char *filename) { }
|
{
|
||||||
bool is_ready () { return true; }
|
}
|
||||||
|
bool is_ready()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void clear ();
|
void clear();
|
||||||
void output (void *src,
|
void output(void *src,
|
||||||
int src_pitch,
|
int src_pitch,
|
||||||
int x,
|
int x,
|
||||||
int y,
|
int y,
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
int dst_width,
|
int dst_width,
|
||||||
int dst_height);
|
int dst_height);
|
||||||
|
|
||||||
int last_known_width;
|
int last_known_width;
|
||||||
int last_known_height;
|
int last_known_height;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __GTK_DISPLAY_DRIVER_GTK_H */
|
#endif /* __GTK_DISPLAY_DRIVER_GTK_H */
|
||||||
|
|
|
@ -65,14 +65,14 @@ static const GLchar *stock_fragment_shader_140 =
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
||||||
|
|
||||||
static GLfloat coords[] = { -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f,
|
static GLfloat coords[] = { -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f,
|
||||||
0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, };
|
0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, };
|
||||||
|
|
||||||
static void S9xViewportCallback (int src_width, int src_height,
|
static void S9xViewportCallback(int src_width, int src_height,
|
||||||
int viewport_x, int viewport_y,
|
int viewport_x, int viewport_y,
|
||||||
int viewport_width, int viewport_height,
|
int viewport_width, int viewport_height,
|
||||||
int *out_x, int *out_y,
|
int *out_x, int *out_y,
|
||||||
int *out_width, int *out_height)
|
int *out_width, int *out_height)
|
||||||
{
|
{
|
||||||
S9xRect dst = S9xApplyAspect(src_width, src_height, viewport_width, viewport_height);
|
S9xRect dst = S9xApplyAspect(src_width, src_height, viewport_width, viewport_height);
|
||||||
*out_x = dst.x + viewport_x;
|
*out_x = dst.x + viewport_x;
|
||||||
|
@ -81,202 +81,129 @@ static void S9xViewportCallback (int src_width, int src_height,
|
||||||
*out_height = dst.h;
|
*out_height = dst.h;
|
||||||
}
|
}
|
||||||
|
|
||||||
S9xOpenGLDisplayDriver::S9xOpenGLDisplayDriver (Snes9xWindow *window,
|
S9xOpenGLDisplayDriver::S9xOpenGLDisplayDriver(Snes9xWindow *window, Snes9xConfig *config)
|
||||||
Snes9xConfig *config)
|
|
||||||
{
|
{
|
||||||
this->window = window;
|
this->window = window;
|
||||||
this->config = config;
|
this->config = config;
|
||||||
this->drawing_area = GTK_WIDGET (window->drawing_area);
|
this->drawing_area = GTK_WIDGET(window->drawing_area);
|
||||||
}
|
}
|
||||||
|
|
||||||
void S9xOpenGLDisplayDriver::update (int width, int height, int yoffset)
|
void S9xOpenGLDisplayDriver::update(uint16_t *buffer, int width, int height, int stride_in_pixels)
|
||||||
{
|
{
|
||||||
uint8 *final_buffer = NULL;
|
|
||||||
int final_pitch;
|
|
||||||
void *pbo_map = NULL;
|
|
||||||
|
|
||||||
GtkAllocation allocation;
|
GtkAllocation allocation;
|
||||||
gtk_widget_get_allocation (drawing_area, &allocation);
|
gtk_widget_get_allocation(drawing_area, &allocation);
|
||||||
|
|
||||||
if (output_window_width != allocation.width ||
|
if (output_window_width != allocation.width ||
|
||||||
output_window_height != allocation.height)
|
output_window_height != allocation.height)
|
||||||
{
|
{
|
||||||
resize ();
|
resize();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if GTK_CHECK_VERSION(3,10,0)
|
#if GTK_CHECK_VERSION(3, 10, 0)
|
||||||
int gdk_scale_factor = gdk_window_get_scale_factor (gdk_window);
|
int gdk_scale_factor = gdk_window_get_scale_factor(gdk_window);
|
||||||
|
|
||||||
allocation.width *= gdk_scale_factor;
|
allocation.width *= gdk_scale_factor;
|
||||||
allocation.height *= gdk_scale_factor;
|
allocation.height *= gdk_scale_factor;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!legacy)
|
if (!legacy)
|
||||||
glActiveTexture (GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glBindTexture (GL_TEXTURE_2D, texmap);
|
glBindTexture(GL_TEXTURE_2D, texmap);
|
||||||
GLint filter = Settings.BilinearFilter ? GL_LINEAR : GL_NEAREST;
|
GLint filter = Settings.BilinearFilter ? GL_LINEAR : GL_NEAREST;
|
||||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
|
||||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
|
||||||
GLint clamp = (using_glsl_shaders || !npot) ? GL_CLAMP_TO_BORDER : GL_CLAMP_TO_EDGE;
|
GLint clamp = (using_glsl_shaders || !npot) ? GL_CLAMP_TO_BORDER : GL_CLAMP_TO_EDGE;
|
||||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clamp);
|
||||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clamp);
|
||||||
|
|
||||||
glClear (GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
if (config->scale_method > 0)
|
S9xRect content = S9xApplyAspect(width, height, allocation.width, allocation.height);
|
||||||
{
|
glViewport(content.x, allocation.height - content.y - content.h, content.w, content.h);
|
||||||
uint8 *src_buffer = (uint8 *) padded_buffer[0];
|
window->set_mouseable_area(content.x, content.y, content.w, content.h);
|
||||||
int src_pitch = image_width * image_bpp;
|
|
||||||
uint8 *dst_buffer;
|
|
||||||
int dst_pitch;
|
|
||||||
|
|
||||||
src_buffer += (src_pitch * yoffset);
|
update_texture_size(width, height);
|
||||||
|
|
||||||
dst_buffer = (uint8 *) padded_buffer[1];
|
|
||||||
dst_pitch = scaled_max_width * image_bpp;
|
|
||||||
final_buffer = (uint8 *) padded_buffer[1];
|
|
||||||
final_pitch = scaled_max_width * image_bpp;
|
|
||||||
|
|
||||||
S9xFilter (src_buffer,
|
|
||||||
src_pitch,
|
|
||||||
dst_buffer,
|
|
||||||
dst_pitch,
|
|
||||||
width,
|
|
||||||
height);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
final_buffer = (uint8 *) padded_buffer[0];
|
|
||||||
final_pitch = image_width * image_bpp;
|
|
||||||
final_buffer += (final_pitch * yoffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
S9xRect r = S9xApplyAspect(width, height, allocation.width, allocation.height);
|
|
||||||
glViewport (r.x, allocation.height - r.y - r.h, r.w, r.h);
|
|
||||||
window->set_mouseable_area (r.x, r.y, r.w, r.h);
|
|
||||||
|
|
||||||
update_texture_size (width, height);
|
|
||||||
|
|
||||||
if (using_pbos)
|
if (using_pbos)
|
||||||
{
|
{
|
||||||
|
void *pbo_memory = NULL;
|
||||||
|
GLbitfield bits = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
|
||||||
|
|
||||||
if (config->pbo_format == 16)
|
if (config->pbo_format == 16)
|
||||||
{
|
{
|
||||||
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
|
||||||
glBindBuffer (GL_PIXEL_UNPACK_BUFFER, pbo);
|
glBufferData(GL_PIXEL_UNPACK_BUFFER, width * height * 2, NULL, GL_STREAM_DRAW);
|
||||||
glBufferData (GL_PIXEL_UNPACK_BUFFER,
|
|
||||||
width * height * 2,
|
|
||||||
NULL,
|
|
||||||
GL_STREAM_DRAW);
|
|
||||||
|
|
||||||
if (version >= 30)
|
if (version >= 30)
|
||||||
pbo_map = glMapBufferRange (
|
pbo_memory = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, width * height * 2, bits);
|
||||||
GL_PIXEL_UNPACK_BUFFER, 0, width * height * 2,
|
|
||||||
GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT |
|
|
||||||
GL_MAP_UNSYNCHRONIZED_BIT);
|
|
||||||
else
|
else
|
||||||
pbo_map = glMapBuffer (GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
|
pbo_memory = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
|
||||||
|
|
||||||
for (int y = 0; y < height; y++)
|
for (int y = 0; y < height; y++)
|
||||||
{
|
{
|
||||||
memcpy ((uint8 *) pbo_map + (width * y * 2),
|
uint16 *dst = (uint16_t *)pbo_memory + (width * y);
|
||||||
final_buffer + (y * final_pitch),
|
uint16 *src = &buffer[y * stride_in_pixels];
|
||||||
width * image_bpp);
|
memcpy(dst, src, width * 2);
|
||||||
}
|
}
|
||||||
|
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
|
||||||
|
|
||||||
glUnmapBuffer (GL_PIXEL_UNPACK_BUFFER);
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
|
||||||
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB,
|
||||||
|
GL_UNSIGNED_SHORT_5_6_5, BUFFER_OFFSET(0));
|
||||||
|
|
||||||
glPixelStorei (GL_UNPACK_ROW_LENGTH, width);
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||||
glTexSubImage2D (GL_TEXTURE_2D,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
GL_RGB,
|
|
||||||
GL_UNSIGNED_SHORT_5_6_5,
|
|
||||||
BUFFER_OFFSET (0));
|
|
||||||
|
|
||||||
glBindBuffer (GL_PIXEL_UNPACK_BUFFER, 0);
|
|
||||||
}
|
}
|
||||||
else /* 32-bit color */
|
else /* 32-bit color */
|
||||||
{
|
{
|
||||||
glBindBuffer (GL_PIXEL_UNPACK_BUFFER, pbo);
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
|
||||||
glBufferData (GL_PIXEL_UNPACK_BUFFER,
|
glBufferData(GL_PIXEL_UNPACK_BUFFER, width * height * 4, NULL, GL_STREAM_DRAW);
|
||||||
width * height * 4,
|
|
||||||
NULL,
|
|
||||||
GL_STREAM_DRAW);
|
|
||||||
|
|
||||||
if (version >= 30)
|
if (version >= 30)
|
||||||
pbo_map = glMapBufferRange (
|
pbo_memory = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, width * height * 4, bits);
|
||||||
GL_PIXEL_UNPACK_BUFFER, 0, width * height * 4,
|
|
||||||
GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT |
|
|
||||||
GL_MAP_UNSYNCHRONIZED_BIT);
|
|
||||||
else
|
else
|
||||||
pbo_map = glMapBuffer (GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
|
pbo_memory = glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
|
||||||
|
|
||||||
/* Pixel swizzling in software */
|
/* Pixel swizzling in software */
|
||||||
S9xSetEndianess (ENDIAN_NORMAL);
|
S9xSetEndianess(ENDIAN_NORMAL);
|
||||||
S9xConvert (final_buffer,
|
S9xConvert(buffer, pbo_memory, stride_in_pixels * 2, width * 4, width, height, 32);
|
||||||
pbo_map,
|
|
||||||
final_pitch,
|
|
||||||
width * 4,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
32);
|
|
||||||
|
|
||||||
glUnmapBuffer (GL_PIXEL_UNPACK_BUFFER);
|
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
|
||||||
|
|
||||||
glPixelStorei (GL_UNPACK_ROW_LENGTH, width);
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, width);
|
||||||
glTexSubImage2D (GL_TEXTURE_2D,
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_BGRA, GL_UNSIGNED_BYTE, BUFFER_OFFSET(0));
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
GL_BGRA,
|
|
||||||
GL_UNSIGNED_BYTE,
|
|
||||||
BUFFER_OFFSET (0));
|
|
||||||
|
|
||||||
glBindBuffer (GL_PIXEL_UNPACK_BUFFER, 0);
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
glPixelStorei (GL_UNPACK_ROW_LENGTH, final_pitch / image_bpp);
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, stride_in_pixels * 2);
|
||||||
glTexSubImage2D (GL_TEXTURE_2D,
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, buffer);
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
GL_RGB,
|
|
||||||
GL_UNSIGNED_SHORT_5_6_5,
|
|
||||||
final_buffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (using_glsl_shaders)
|
if (using_glsl_shaders)
|
||||||
{
|
{
|
||||||
glsl_shader->render (texmap, width, height, r.x, allocation.height - r.y - r.h, r.w, r.h, S9xViewportCallback);
|
glsl_shader->render(texmap, width, height, content.x, allocation.height - content.y - content.h, content.w, content.h, S9xViewportCallback);
|
||||||
swap_buffers ();
|
swap_buffers();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||||
|
|
||||||
swap_buffers ();
|
swap_buffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
void *S9xOpenGLDisplayDriver::get_parameters ()
|
void *S9xOpenGLDisplayDriver::get_parameters()
|
||||||
{
|
{
|
||||||
if (using_glsl_shaders && glsl_shader)
|
if (using_glsl_shaders && glsl_shader)
|
||||||
{
|
{
|
||||||
return (void *) &glsl_shader->param;
|
return (void *)&glsl_shader->param;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void S9xOpenGLDisplayDriver::save (const char *filename)
|
void S9xOpenGLDisplayDriver::save(const char *filename)
|
||||||
{
|
{
|
||||||
if (using_glsl_shaders && glsl_shader)
|
if (using_glsl_shaders && glsl_shader)
|
||||||
{
|
{
|
||||||
|
@ -284,82 +211,65 @@ void S9xOpenGLDisplayDriver::save (const char *filename)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void S9xOpenGLDisplayDriver::clear_buffers ()
|
void S9xOpenGLDisplayDriver::update_texture_size(int width, int height)
|
||||||
{
|
|
||||||
memset (buffer[0], 0, image_padded_size);
|
|
||||||
memset (buffer[1], 0, scaled_padded_size);
|
|
||||||
|
|
||||||
glPixelStorei (GL_UNPACK_ROW_LENGTH, scaled_max_width);
|
|
||||||
glTexSubImage2D (GL_TEXTURE_2D,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
MIN(scaled_max_width, texture_width),
|
|
||||||
MIN(scaled_max_height, texture_height),
|
|
||||||
GL_RGB,
|
|
||||||
GL_UNSIGNED_SHORT_5_6_5,
|
|
||||||
buffer[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
void S9xOpenGLDisplayDriver::update_texture_size (int width, int height)
|
|
||||||
{
|
{
|
||||||
if (width != texture_width || height != texture_height)
|
if (width != texture_width || height != texture_height)
|
||||||
{
|
{
|
||||||
if (npot)
|
if (npot)
|
||||||
{
|
{
|
||||||
glBindTexture (GL_TEXTURE_2D, texmap);
|
glBindTexture(GL_TEXTURE_2D, texmap);
|
||||||
|
|
||||||
if (using_pbos && config->pbo_format == 32)
|
if (using_pbos && config->pbo_format == 32)
|
||||||
{
|
{
|
||||||
glTexImage2D (GL_TEXTURE_2D,
|
glTexImage2D(GL_TEXTURE_2D,
|
||||||
0,
|
0,
|
||||||
GL_RGBA,
|
GL_RGBA,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
0,
|
0,
|
||||||
GL_BGRA,
|
GL_BGRA,
|
||||||
GL_UNSIGNED_BYTE,
|
GL_UNSIGNED_BYTE,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
glTexImage2D (GL_TEXTURE_2D,
|
glTexImage2D(GL_TEXTURE_2D,
|
||||||
0,
|
0,
|
||||||
GL_RGB565,
|
GL_RGB565,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
0,
|
0,
|
||||||
GL_RGB,
|
GL_RGB,
|
||||||
GL_UNSIGNED_SHORT_5_6_5,
|
GL_UNSIGNED_SHORT_5_6_5,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
coords[9] = 1.0f;
|
coords[9] = 1.0f;
|
||||||
coords[10] = 1.0f;
|
coords[10] = 1.0f;
|
||||||
coords[11] = 1.0f;
|
coords[11] = 1.0f;
|
||||||
coords[14] = 1.0f;
|
coords[14] = 1.0f;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
coords[9] = height / 1024.0f;
|
coords[9] = height / 1024.0f;
|
||||||
coords[10] = width / 1024.0f;
|
coords[10] = width / 1024.0f;
|
||||||
coords[11] = height / 1024.0f;
|
coords[11] = height / 1024.0f;
|
||||||
coords[14] = width / 1024.0f;
|
coords[14] = width / 1024.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
texture_width = width;
|
texture_width = width;
|
||||||
texture_height = height;
|
texture_height = height;
|
||||||
|
|
||||||
if (!legacy)
|
if (!legacy)
|
||||||
{
|
{
|
||||||
glBindBuffer (GL_ARRAY_BUFFER, coord_buffer);
|
glBindBuffer(GL_ARRAY_BUFFER, coord_buffer);
|
||||||
glBufferData (GL_ARRAY_BUFFER, sizeof (GLfloat) * 16, coords, GL_STATIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 16, coords, GL_STATIC_DRAW);
|
||||||
glBindBuffer (GL_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
glVertexPointer (2, GL_FLOAT, 0, coords);
|
glVertexPointer(2, GL_FLOAT, 0, coords);
|
||||||
glTexCoordPointer (2, GL_FLOAT, 0, &coords[8]);
|
glTexCoordPointer(2, GL_FLOAT, 0, &coords[8]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -417,7 +327,7 @@ bool S9xOpenGLDisplayDriver::opengl_defaults()
|
||||||
|
|
||||||
if (config->use_shaders)
|
if (config->use_shaders)
|
||||||
{
|
{
|
||||||
if (legacy || !load_shaders (config->shader_filename.c_str ()))
|
if (legacy || !load_shaders(config->shader_filename.c_str()))
|
||||||
{
|
{
|
||||||
config->use_shaders = false;
|
config->use_shaders = false;
|
||||||
}
|
}
|
||||||
|
@ -433,169 +343,169 @@ bool S9xOpenGLDisplayDriver::opengl_defaults()
|
||||||
|
|
||||||
if (legacy)
|
if (legacy)
|
||||||
{
|
{
|
||||||
glEnableClientState (GL_VERTEX_ARRAY);
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
glEnable (GL_TEXTURE_2D);
|
glEnable(GL_TEXTURE_2D);
|
||||||
glMatrixMode (GL_PROJECTION);
|
glMatrixMode(GL_PROJECTION);
|
||||||
glLoadIdentity ();
|
glLoadIdentity();
|
||||||
glMatrixMode (GL_MODELVIEW);
|
glMatrixMode(GL_MODELVIEW);
|
||||||
glLoadIdentity ();
|
glLoadIdentity();
|
||||||
|
|
||||||
glVertexPointer (2, GL_FLOAT, 0, coords);
|
glVertexPointer(2, GL_FLOAT, 0, coords);
|
||||||
glTexCoordPointer (2, GL_FLOAT, 0, &coords[8]);
|
glTexCoordPointer(2, GL_FLOAT, 0, &coords[8]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
stock_program = glCreateProgram ();
|
stock_program = glCreateProgram();
|
||||||
|
|
||||||
GLuint vertex_shader = glCreateShader (GL_VERTEX_SHADER);
|
GLuint vertex_shader = glCreateShader(GL_VERTEX_SHADER);
|
||||||
GLuint fragment_shader = glCreateShader (GL_FRAGMENT_SHADER);
|
GLuint fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||||
|
|
||||||
if (version < 30)
|
if (version < 30)
|
||||||
{
|
{
|
||||||
glShaderSource (vertex_shader, 1, &stock_vertex_shader_110, NULL);
|
glShaderSource(vertex_shader, 1, &stock_vertex_shader_110, NULL);
|
||||||
glShaderSource (fragment_shader, 1, &stock_fragment_shader_110, NULL);
|
glShaderSource(fragment_shader, 1, &stock_fragment_shader_110, NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
glShaderSource (vertex_shader, 1, &stock_vertex_shader_140, NULL);
|
glShaderSource(vertex_shader, 1, &stock_vertex_shader_140, NULL);
|
||||||
glShaderSource (fragment_shader, 1, &stock_fragment_shader_140, NULL);
|
glShaderSource(fragment_shader, 1, &stock_fragment_shader_140, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
glCompileShader (vertex_shader);
|
glCompileShader(vertex_shader);
|
||||||
glAttachShader (stock_program, vertex_shader);
|
glAttachShader(stock_program, vertex_shader);
|
||||||
glCompileShader (fragment_shader);
|
glCompileShader(fragment_shader);
|
||||||
glAttachShader (stock_program, fragment_shader);
|
glAttachShader(stock_program, fragment_shader);
|
||||||
|
|
||||||
glBindAttribLocation (stock_program, 0, "in_position");
|
glBindAttribLocation(stock_program, 0, "in_position");
|
||||||
glBindAttribLocation (stock_program, 1, "in_texcoord");
|
glBindAttribLocation(stock_program, 1, "in_texcoord");
|
||||||
|
|
||||||
glLinkProgram (stock_program);
|
glLinkProgram(stock_program);
|
||||||
glUseProgram (stock_program);
|
glUseProgram(stock_program);
|
||||||
|
|
||||||
glDeleteShader (vertex_shader);
|
glDeleteShader(vertex_shader);
|
||||||
glDeleteShader (fragment_shader);
|
glDeleteShader(fragment_shader);
|
||||||
|
|
||||||
GLint texture_uniform = glGetUniformLocation (stock_program, "texmap");
|
GLint texture_uniform = glGetUniformLocation(stock_program, "texmap");
|
||||||
glUniform1i (texture_uniform, 0);
|
glUniform1i(texture_uniform, 0);
|
||||||
|
|
||||||
if (core)
|
if (core)
|
||||||
{
|
{
|
||||||
GLuint vao;
|
GLuint vao;
|
||||||
glGenVertexArrays (1, &vao);
|
glGenVertexArrays(1, &vao);
|
||||||
glBindVertexArray (vao);
|
glBindVertexArray(vao);
|
||||||
}
|
}
|
||||||
|
|
||||||
glGenBuffers (1, &coord_buffer);
|
glGenBuffers(1, &coord_buffer);
|
||||||
glBindBuffer (GL_ARRAY_BUFFER, coord_buffer);
|
glBindBuffer(GL_ARRAY_BUFFER, coord_buffer);
|
||||||
glBufferData (GL_ARRAY_BUFFER, sizeof (GLfloat) * 16, coords, GL_STATIC_DRAW);
|
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 16, coords, GL_STATIC_DRAW);
|
||||||
|
|
||||||
glEnableVertexAttribArray (0);
|
glEnableVertexAttribArray(0);
|
||||||
glVertexAttribPointer (0, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET (0));
|
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
|
||||||
glEnableVertexAttribArray (1);
|
glEnableVertexAttribArray(1);
|
||||||
glVertexAttribPointer (1, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET (32));
|
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(32));
|
||||||
|
|
||||||
glBindBuffer (GL_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config->use_pbos)
|
if (config->use_pbos)
|
||||||
{
|
{
|
||||||
glGenBuffers (1, &pbo);
|
glGenBuffers(1, &pbo);
|
||||||
glGenTextures (1, &texmap);
|
glGenTextures(1, &texmap);
|
||||||
|
|
||||||
glBindTexture (GL_TEXTURE_2D, texmap);
|
glBindTexture(GL_TEXTURE_2D, texmap);
|
||||||
glTexImage2D (GL_TEXTURE_2D,
|
glTexImage2D(GL_TEXTURE_2D,
|
||||||
0,
|
0,
|
||||||
config->pbo_format == 16 ? GL_RGB565 : GL_RGBA,
|
config->pbo_format == 16 ? GL_RGB565 : GL_RGBA,
|
||||||
texture_width,
|
texture_width,
|
||||||
texture_height,
|
texture_height,
|
||||||
0,
|
0,
|
||||||
config->pbo_format == 16 ? GL_RGB : GL_BGRA,
|
config->pbo_format == 16 ? GL_RGB : GL_BGRA,
|
||||||
config->pbo_format == 16 ? GL_UNSIGNED_SHORT_5_6_5 : GL_UNSIGNED_BYTE,
|
config->pbo_format == 16 ? GL_UNSIGNED_SHORT_5_6_5 : GL_UNSIGNED_BYTE,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
glBindBuffer (GL_PIXEL_UNPACK_BUFFER, pbo);
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
|
||||||
glBufferData (GL_PIXEL_UNPACK_BUFFER,
|
glBufferData(GL_PIXEL_UNPACK_BUFFER,
|
||||||
texture_width * texture_height * 3,
|
texture_width * texture_height * 3,
|
||||||
NULL,
|
NULL,
|
||||||
GL_STREAM_DRAW);
|
GL_STREAM_DRAW);
|
||||||
|
|
||||||
glBindBuffer (GL_PIXEL_UNPACK_BUFFER, 0);
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
glGenTextures (1, &texmap);
|
glGenTextures(1, &texmap);
|
||||||
|
|
||||||
glBindTexture (GL_TEXTURE_2D, texmap);
|
glBindTexture(GL_TEXTURE_2D, texmap);
|
||||||
glTexImage2D (GL_TEXTURE_2D,
|
glTexImage2D(GL_TEXTURE_2D,
|
||||||
0,
|
0,
|
||||||
GL_RGB565,
|
GL_RGB565,
|
||||||
texture_width,
|
texture_width,
|
||||||
texture_height,
|
texture_height,
|
||||||
0,
|
0,
|
||||||
GL_RGB,
|
GL_RGB,
|
||||||
GL_UNSIGNED_SHORT_5_6_5,
|
GL_UNSIGNED_SHORT_5_6_5,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
glClearColor (0.0, 0.0, 0.0, 0.0);
|
glClearColor(0.0, 0.0, 0.0, 0.0);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void S9xOpenGLDisplayDriver::refresh (int width, int height)
|
void S9xOpenGLDisplayDriver::refresh(int width, int height)
|
||||||
{
|
{
|
||||||
resize ();
|
resize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void S9xOpenGLDisplayDriver::resize ()
|
void S9xOpenGLDisplayDriver::resize()
|
||||||
{
|
{
|
||||||
context->resize ();
|
context->resize();
|
||||||
context->swap_interval (config->sync_to_vblank);
|
context->swap_interval(config->sync_to_vblank);
|
||||||
output_window_width = context->width;
|
output_window_width = context->width;
|
||||||
output_window_height = context->height;
|
output_window_height = context->height;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool S9xOpenGLDisplayDriver::create_context()
|
bool S9xOpenGLDisplayDriver::create_context()
|
||||||
{
|
{
|
||||||
gdk_window = gtk_widget_get_window (drawing_area);
|
gdk_window = gtk_widget_get_window(drawing_area);
|
||||||
|
|
||||||
#ifdef GDK_WINDOWING_WAYLAND
|
#ifdef GDK_WINDOWING_WAYLAND
|
||||||
if (GDK_IS_WAYLAND_WINDOW (gdk_window))
|
if (GDK_IS_WAYLAND_WINDOW(gdk_window))
|
||||||
{
|
{
|
||||||
context = &wl;
|
context = &wl;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef GDK_WINDOWING_X11
|
#ifdef GDK_WINDOWING_X11
|
||||||
if (GDK_IS_X11_WINDOW (gdk_window))
|
if (GDK_IS_X11_WINDOW(gdk_window))
|
||||||
{
|
{
|
||||||
context = &glx;
|
context = &glx;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!context->attach (drawing_area))
|
if (!context->attach(drawing_area))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!context->create_context ())
|
if (!context->create_context())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
output_window_width = context->width;
|
output_window_width = context->width;
|
||||||
output_window_height = context->height;
|
output_window_height = context->height;
|
||||||
|
|
||||||
context->make_current ();
|
context->make_current();
|
||||||
|
|
||||||
legacy = false;
|
legacy = false;
|
||||||
version = epoxy_gl_version ();
|
version = epoxy_gl_version();
|
||||||
if (version < 20)
|
if (version < 20)
|
||||||
{
|
{
|
||||||
printf ("OpenGL version is only %d.%d. Recommended version is 2.0.\n",
|
printf("OpenGL version is only %d.%d. Recommended version is 2.0.\n",
|
||||||
version / 10,
|
version / 10,
|
||||||
version % 10);
|
version % 10);
|
||||||
legacy = true;
|
legacy = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int profile_mask = 0;
|
int profile_mask = 0;
|
||||||
glGetIntegerv (GL_CONTEXT_PROFILE_MASK, &profile_mask);
|
glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &profile_mask);
|
||||||
if (profile_mask & GL_CONTEXT_CORE_PROFILE_BIT)
|
if (profile_mask & GL_CONTEXT_CORE_PROFILE_BIT)
|
||||||
core = true;
|
core = true;
|
||||||
else
|
else
|
||||||
|
@ -604,113 +514,79 @@ bool S9xOpenGLDisplayDriver::create_context()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int S9xOpenGLDisplayDriver::init ()
|
int S9xOpenGLDisplayDriver::init()
|
||||||
{
|
{
|
||||||
initialized = false;
|
initialized = false;
|
||||||
|
|
||||||
if (!create_context ())
|
if (!create_context())
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!opengl_defaults ())
|
if (!opengl_defaults())
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer[0] = new uint8_t[image_padded_size];
|
context->swap_interval(config->sync_to_vblank);
|
||||||
buffer[1] = new uint8_t[scaled_padded_size];
|
|
||||||
|
|
||||||
clear_buffers ();
|
|
||||||
|
|
||||||
padded_buffer[0] = &buffer[0][image_padded_offset];
|
|
||||||
padded_buffer[1] = &buffer[1][scaled_padded_offset];
|
|
||||||
|
|
||||||
GFX.Screen = (uint16 *) padded_buffer[0];
|
|
||||||
GFX.Pitch = image_width * image_bpp;
|
|
||||||
|
|
||||||
context->swap_interval (config->sync_to_vblank);
|
|
||||||
|
|
||||||
initialized = true;
|
initialized = true;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16 *S9xOpenGLDisplayDriver::get_next_buffer ()
|
void S9xOpenGLDisplayDriver::swap_buffers()
|
||||||
{
|
{
|
||||||
return (uint16 *) padded_buffer[0];
|
context->swap_buffers();
|
||||||
}
|
|
||||||
|
|
||||||
void S9xOpenGLDisplayDriver::push_buffer (uint16 *src)
|
|
||||||
{
|
|
||||||
memmove (padded_buffer[0], src, image_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16 *S9xOpenGLDisplayDriver::get_current_buffer ()
|
|
||||||
{
|
|
||||||
return (uint16 *) padded_buffer[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
void S9xOpenGLDisplayDriver::swap_buffers ()
|
|
||||||
{
|
|
||||||
context->swap_buffers ();
|
|
||||||
|
|
||||||
if (config->use_glfinish && !config->use_sync_control)
|
if (config->use_glfinish && !config->use_sync_control)
|
||||||
{
|
{
|
||||||
usleep (0);
|
usleep(0);
|
||||||
glFinish ();
|
glFinish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void S9xOpenGLDisplayDriver::deinit ()
|
void S9xOpenGLDisplayDriver::deinit()
|
||||||
{
|
{
|
||||||
if (!initialized)
|
if (!initialized)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (using_glsl_shaders)
|
if (using_glsl_shaders)
|
||||||
{
|
{
|
||||||
window->enable_widget ("shader_parameters_item", false);
|
window->enable_widget("shader_parameters_item", false);
|
||||||
gtk_shader_parameters_dialog_close ();
|
gtk_shader_parameters_dialog_close();
|
||||||
glsl_shader->destroy();
|
glsl_shader->destroy();
|
||||||
delete glsl_shader;
|
delete glsl_shader;
|
||||||
}
|
}
|
||||||
|
|
||||||
GFX.Screen = NULL;
|
|
||||||
|
|
||||||
padded_buffer[0] = NULL;
|
|
||||||
padded_buffer[1] = NULL;
|
|
||||||
|
|
||||||
delete[] buffer[0];
|
|
||||||
delete[] buffer[1];
|
|
||||||
|
|
||||||
if (using_pbos)
|
if (using_pbos)
|
||||||
{
|
{
|
||||||
glBindBuffer (GL_PIXEL_UNPACK_BUFFER, 0);
|
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||||
glDeleteBuffers (1, &pbo);
|
glDeleteBuffers(1, &pbo);
|
||||||
}
|
}
|
||||||
|
|
||||||
glDeleteTextures (1, &texmap);
|
glDeleteTextures(1, &texmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
int S9xOpenGLDisplayDriver::query_availability ()
|
int S9xOpenGLDisplayDriver::query_availability()
|
||||||
{
|
{
|
||||||
GdkDisplay *gdk_display = gdk_display_get_default ();
|
GdkDisplay *gdk_display = gdk_display_get_default();
|
||||||
|
|
||||||
#ifdef GDK_WINDOWING_WAYLAND
|
#ifdef GDK_WINDOWING_WAYLAND
|
||||||
if (GDK_IS_WAYLAND_DISPLAY (gdk_display))
|
if (GDK_IS_WAYLAND_DISPLAY(gdk_display))
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef GDK_WINDOWING_X11
|
#ifdef GDK_WINDOWING_X11
|
||||||
if (GDK_IS_X11_DISPLAY (gdk_display))
|
if (GDK_IS_X11_DISPLAY(gdk_display))
|
||||||
{
|
{
|
||||||
Display *dpy = GDK_DISPLAY_XDISPLAY (gdk_display);
|
Display *dpy = GDK_DISPLAY_XDISPLAY(gdk_display);
|
||||||
|
|
||||||
if (glXQueryExtension (dpy, NULL, NULL) == True)
|
if (glXQueryExtension(dpy, NULL, NULL) == True)
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -721,7 +597,7 @@ int S9xOpenGLDisplayDriver::query_availability ()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool S9xOpenGLDisplayDriver::is_ready ()
|
bool S9xOpenGLDisplayDriver::is_ready()
|
||||||
{
|
{
|
||||||
if (context->ready())
|
if (context->ready())
|
||||||
{
|
{
|
||||||
|
|
|
@ -24,61 +24,57 @@
|
||||||
|
|
||||||
#include "shaders/glsl.h"
|
#include "shaders/glsl.h"
|
||||||
|
|
||||||
#define BUFFER_OFFSET(i) ((char *) (i))
|
#define BUFFER_OFFSET(i) ((char *)(i))
|
||||||
|
|
||||||
class S9xOpenGLDisplayDriver : public S9xDisplayDriver
|
class S9xOpenGLDisplayDriver : public S9xDisplayDriver
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
S9xOpenGLDisplayDriver (Snes9xWindow *window, Snes9xConfig *config);
|
S9xOpenGLDisplayDriver(Snes9xWindow *window, Snes9xConfig *config);
|
||||||
void refresh (int width, int height);
|
void refresh(int width, int height);
|
||||||
int init ();
|
int init();
|
||||||
void deinit ();
|
void deinit();
|
||||||
void clear_buffers ();
|
void update(uint16_t *buffer, int width, int height, int stride_in_pixels);
|
||||||
void update (int width, int height, int yoffset);
|
void *get_parameters();
|
||||||
uint16 *get_next_buffer ();
|
void save(const char *filename);
|
||||||
uint16 *get_current_buffer ();
|
static int query_availability();
|
||||||
void push_buffer (uint16 *src);
|
bool is_ready();
|
||||||
void *get_parameters ();
|
|
||||||
void save (const char *filename);
|
|
||||||
static int query_availability ();
|
|
||||||
bool is_ready ();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool opengl_defaults ();
|
bool opengl_defaults();
|
||||||
void swap_buffers ();
|
void swap_buffers();
|
||||||
bool load_shaders (const char *);
|
bool load_shaders(const char *);
|
||||||
void update_texture_size (int width, int height);
|
void update_texture_size(int width, int height);
|
||||||
bool create_context ();
|
bool create_context();
|
||||||
void resize ();
|
void resize();
|
||||||
|
|
||||||
GLuint stock_program;
|
GLuint stock_program;
|
||||||
GLuint coord_buffer;
|
GLuint coord_buffer;
|
||||||
GLint texture_width;
|
GLint texture_width;
|
||||||
GLint texture_height;
|
GLint texture_height;
|
||||||
GLuint texmap;
|
GLuint texmap;
|
||||||
GLuint pbo;
|
GLuint pbo;
|
||||||
|
|
||||||
bool legacy;
|
bool legacy;
|
||||||
bool core;
|
bool core;
|
||||||
int version;
|
int version;
|
||||||
bool npot;
|
bool npot;
|
||||||
bool using_pbos;
|
bool using_pbos;
|
||||||
bool initialized;
|
bool initialized;
|
||||||
|
|
||||||
bool using_glsl_shaders;
|
bool using_glsl_shaders;
|
||||||
GLSLShader *glsl_shader;
|
GLSLShader *glsl_shader;
|
||||||
|
|
||||||
GdkWindow *gdk_window;
|
GdkWindow *gdk_window;
|
||||||
int output_window_width;
|
int output_window_width;
|
||||||
int output_window_height;
|
int output_window_height;
|
||||||
|
|
||||||
OpenGLContext *context;
|
OpenGLContext *context;
|
||||||
|
|
||||||
#ifdef GDK_WINDOWING_X11
|
#ifdef GDK_WINDOWING_X11
|
||||||
GTKGLXContext glx;
|
GTKGLXContext glx;
|
||||||
#endif
|
#endif
|
||||||
#ifdef GDK_WINDOWING_WAYLAND
|
#ifdef GDK_WINDOWING_WAYLAND
|
||||||
WaylandEGLContext wl;
|
WaylandEGLContext wl;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -14,43 +14,44 @@
|
||||||
#include "gtk_display.h"
|
#include "gtk_display.h"
|
||||||
#include "gtk_display_driver_xv.h"
|
#include "gtk_display_driver_xv.h"
|
||||||
|
|
||||||
static int
|
static int get_inv_shift(uint32 mask, int bpp)
|
||||||
get_inv_shift (uint32 mask, int bpp)
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Find mask */
|
/* Find mask */
|
||||||
for (i = 0; (i < bpp) && !(mask & (1 << i)); i++) {};
|
for (i = 0; (i < bpp) && !(mask & (1 << i)); i++)
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
/* Find start of mask */
|
/* Find start of mask */
|
||||||
for (; (i < bpp) && (mask & (1 << i)); i++) {};
|
for (; (i < bpp) && (mask & (1 << i)); i++)
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
return (bpp - i);
|
return (bpp - i);
|
||||||
}
|
}
|
||||||
|
|
||||||
S9xXVDisplayDriver::S9xXVDisplayDriver (Snes9xWindow *window,
|
S9xXVDisplayDriver::S9xXVDisplayDriver(Snes9xWindow *window,
|
||||||
Snes9xConfig *config)
|
Snes9xConfig *config)
|
||||||
{
|
{
|
||||||
this->window = window;
|
this->window = window;
|
||||||
this->config = config;
|
this->config = config;
|
||||||
this->drawing_area = GTK_WIDGET (window->drawing_area);
|
this->drawing_area = GTK_WIDGET(window->drawing_area);
|
||||||
display =
|
display =
|
||||||
gdk_x11_display_get_xdisplay (gtk_widget_get_display (drawing_area));
|
gdk_x11_display_get_xdisplay(gtk_widget_get_display(drawing_area));
|
||||||
last_known_width = last_known_height = -1;
|
last_known_width = last_known_height = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void S9xXVDisplayDriver::resize_window(int width, int height)
|
||||||
S9xXVDisplayDriver::resize_window (int width, int height)
|
|
||||||
{
|
{
|
||||||
gdk_window_destroy (gdk_window);
|
gdk_window_destroy(gdk_window);
|
||||||
create_window (width, height);
|
create_window(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void S9xXVDisplayDriver::create_window(int width, int height)
|
||||||
S9xXVDisplayDriver::create_window (int width, int height)
|
|
||||||
{
|
{
|
||||||
GdkWindowAttr window_attr;
|
GdkWindowAttr window_attr;
|
||||||
memset (&window_attr, 0, sizeof (GdkWindowAttr));
|
memset(&window_attr, 0, sizeof(GdkWindowAttr));
|
||||||
window_attr.event_mask = GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK;
|
window_attr.event_mask = GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK;
|
||||||
window_attr.width = width;
|
window_attr.width = width;
|
||||||
window_attr.height = height;
|
window_attr.height = height;
|
||||||
|
@ -58,37 +59,35 @@ S9xXVDisplayDriver::create_window (int width, int height)
|
||||||
window_attr.y = 0;
|
window_attr.y = 0;
|
||||||
window_attr.wclass = GDK_INPUT_OUTPUT;
|
window_attr.wclass = GDK_INPUT_OUTPUT;
|
||||||
window_attr.window_type = GDK_WINDOW_CHILD;
|
window_attr.window_type = GDK_WINDOW_CHILD;
|
||||||
window_attr.visual = gdk_x11_screen_lookup_visual (gtk_widget_get_screen (drawing_area), vi->visualid);
|
window_attr.visual = gdk_x11_screen_lookup_visual(gtk_widget_get_screen(drawing_area), vi->visualid);
|
||||||
|
|
||||||
gdk_window = gdk_window_new (gtk_widget_get_window (drawing_area),
|
gdk_window = gdk_window_new(gtk_widget_get_window(drawing_area),
|
||||||
&window_attr,
|
&window_attr,
|
||||||
GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL);
|
GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL);
|
||||||
gdk_window_set_user_data (gdk_window, (gpointer) drawing_area);
|
gdk_window_set_user_data(gdk_window, (gpointer)drawing_area);
|
||||||
|
|
||||||
gdk_window_show (gdk_window);
|
gdk_window_show(gdk_window);
|
||||||
xwindow = gdk_x11_window_get_xid (gdk_window);
|
xwindow = gdk_x11_window_get_xid(gdk_window);
|
||||||
|
|
||||||
output_window_width = width;
|
output_window_width = width;
|
||||||
output_window_height = height;
|
output_window_height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void S9xXVDisplayDriver::update(uint16_t *buffer, int width, int height, int stride_in_pixels)
|
||||||
S9xXVDisplayDriver::update (int width, int height, int yoffset)
|
|
||||||
{
|
{
|
||||||
int current_width, current_height, final_pitch;
|
int current_width, current_height;
|
||||||
uint8 *final_buffer;
|
|
||||||
GtkAllocation allocation;
|
GtkAllocation allocation;
|
||||||
|
|
||||||
gtk_widget_get_allocation (drawing_area, &allocation);
|
gtk_widget_get_allocation(drawing_area, &allocation);
|
||||||
|
|
||||||
if (output_window_width != allocation.width ||
|
if (output_window_width != allocation.width ||
|
||||||
output_window_height != allocation.height)
|
output_window_height != allocation.height)
|
||||||
{
|
{
|
||||||
resize_window (allocation.width, allocation.height);
|
resize_window(allocation.width, allocation.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if GTK_CHECK_VERSION(3,10,0)
|
#if GTK_CHECK_VERSION(3, 10, 0)
|
||||||
int gdk_scale_factor = gdk_window_get_scale_factor (gdk_window);
|
int gdk_scale_factor = gdk_window_get_scale_factor(gdk_window);
|
||||||
|
|
||||||
allocation.width *= gdk_scale_factor;
|
allocation.width *= gdk_scale_factor;
|
||||||
allocation.height *= gdk_scale_factor;
|
allocation.height *= gdk_scale_factor;
|
||||||
|
@ -98,55 +97,29 @@ S9xXVDisplayDriver::update (int width, int height, int yoffset)
|
||||||
current_width = allocation.width;
|
current_width = allocation.width;
|
||||||
current_height = allocation.height;
|
current_height = allocation.height;
|
||||||
|
|
||||||
if (config->scale_method > 0)
|
update_image_size(width, height);
|
||||||
{
|
|
||||||
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;
|
|
||||||
|
|
||||||
src_buffer += (src_pitch * yoffset);
|
|
||||||
|
|
||||||
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;
|
|
||||||
final_buffer += (final_pitch * yoffset);
|
|
||||||
}
|
|
||||||
|
|
||||||
update_image_size (width, height);
|
|
||||||
|
|
||||||
if (format == FOURCC_YUY2)
|
if (format == FOURCC_YUY2)
|
||||||
{
|
{
|
||||||
S9xConvertYUV (final_buffer,
|
S9xConvertYUV(buffer,
|
||||||
(uint8 *) xv_image->data,
|
(uint8 *)xv_image->data,
|
||||||
final_pitch,
|
stride_in_pixels * 2,
|
||||||
2 * xv_image->width,
|
2 * xv_image->width,
|
||||||
width + (width < xv_image->width ? (width % 2) + 4 : 0),
|
width + (width < xv_image->width ? (width % 2) + 4 : 0),
|
||||||
height + (height < xv_image->height ? 4 : 0));
|
height + (height < xv_image->height ? 4 : 0));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
S9xConvertMask (final_buffer,
|
S9xConvertMask(buffer,
|
||||||
(uint8 *) xv_image->data,
|
(uint8 *)xv_image->data,
|
||||||
final_pitch,
|
stride_in_pixels * 2,
|
||||||
bytes_per_pixel * xv_image->width,
|
bytes_per_pixel * xv_image->width,
|
||||||
width + (width < xv_image->width ? (width % 2) + 4 : 0),
|
width + (width < xv_image->width ? (width % 2) + 4 : 0),
|
||||||
height + (height < xv_image->height ? 4 : 0),
|
height + (height < xv_image->height ? 4 : 0),
|
||||||
rshift,
|
rshift,
|
||||||
gshift,
|
gshift,
|
||||||
bshift,
|
bshift,
|
||||||
bpp);
|
bpp);
|
||||||
}
|
}
|
||||||
|
|
||||||
S9xRect dst = S9xApplyAspect(width, height, current_width, current_height);
|
S9xRect dst = S9xApplyAspect(width, height, current_width, current_height);
|
||||||
|
@ -155,60 +128,59 @@ S9xXVDisplayDriver::update (int width, int height, int yoffset)
|
||||||
{
|
{
|
||||||
last_known_width = dst.w;
|
last_known_width = dst.w;
|
||||||
last_known_height = dst.h;
|
last_known_height = dst.h;
|
||||||
clear ();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
XvShmPutImage (display,
|
XvShmPutImage(display,
|
||||||
xv_portid,
|
xv_portid,
|
||||||
xwindow,
|
xwindow,
|
||||||
XDefaultGC (display, XDefaultScreen (display)),
|
XDefaultGC(display, XDefaultScreen(display)),
|
||||||
xv_image,
|
xv_image,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
dst.x,
|
dst.x,
|
||||||
dst.y,
|
dst.y,
|
||||||
dst.w,
|
dst.w,
|
||||||
dst.h,
|
dst.h,
|
||||||
False);
|
False);
|
||||||
|
|
||||||
top_level->set_mouseable_area (dst.x, dst.y, dst.w, dst.h);
|
top_level->set_mouseable_area(dst.x, dst.y, dst.w, dst.h);
|
||||||
|
|
||||||
XSync (display, False);
|
XSync(display, False);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void S9xXVDisplayDriver::update_image_size(int width, int height)
|
||||||
S9xXVDisplayDriver::update_image_size (int width, int height)
|
|
||||||
{
|
{
|
||||||
if (desired_width != width || desired_height != height)
|
if (xv_image_width != width || xv_image_height != height)
|
||||||
{
|
{
|
||||||
XShmDetach (display, &shm);
|
XShmDetach(display, &shm);
|
||||||
XSync (display, 0);
|
XSync(display, 0);
|
||||||
|
|
||||||
shmctl (shm.shmid, IPC_RMID, 0);
|
shmctl(shm.shmid, IPC_RMID, 0);
|
||||||
shmdt (shm.shmaddr);
|
shmdt(shm.shmaddr);
|
||||||
|
|
||||||
xv_image = XvShmCreateImage (display,
|
xv_image = XvShmCreateImage(display,
|
||||||
xv_portid,
|
xv_portid,
|
||||||
format,
|
format,
|
||||||
0,
|
0,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
&shm);
|
&shm);
|
||||||
|
|
||||||
shm.shmid = shmget (IPC_PRIVATE, xv_image->data_size, IPC_CREAT | 0777);
|
shm.shmid = shmget(IPC_PRIVATE, xv_image->data_size, IPC_CREAT | 0777);
|
||||||
for (int tries = 0; tries <= 10; tries++)
|
for (int tries = 0; tries <= 10; tries++)
|
||||||
{
|
{
|
||||||
shm.shmaddr = (char *) shmat (shm.shmid, 0, 0);
|
shm.shmaddr = (char *)shmat(shm.shmid, 0, 0);
|
||||||
|
|
||||||
if (shm.shmaddr == (void *) -1 && tries >= 10)
|
if (shm.shmaddr == (void *)-1 && tries >= 10)
|
||||||
{
|
{
|
||||||
/* Can't recover, send exit. */
|
/* Can't recover, send exit. */
|
||||||
fprintf (stderr, "Couldn't reallocate shared memory.\n");
|
fprintf(stderr, "Couldn't reallocate shared memory.\n");
|
||||||
S9xExit ();
|
S9xExit();
|
||||||
}
|
}
|
||||||
else if (shm.shmaddr != (void *) -1)
|
else if (shm.shmaddr != (void *)-1)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -218,50 +190,48 @@ S9xXVDisplayDriver::update_image_size (int width, int height)
|
||||||
|
|
||||||
xv_image->data = shm.shmaddr;
|
xv_image->data = shm.shmaddr;
|
||||||
|
|
||||||
XShmAttach (display, &shm);
|
XShmAttach(display, &shm);
|
||||||
|
|
||||||
desired_width = width;
|
xv_image_width = width;
|
||||||
desired_height = height;
|
xv_image_height = height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int S9xXVDisplayDriver::init()
|
||||||
S9xXVDisplayDriver::init ()
|
|
||||||
{
|
{
|
||||||
int depth = 0, num_formats, num_attrs, highest_formats = 0;
|
int depth = 0, num_formats, num_attrs, highest_formats = 0;
|
||||||
XvImageFormatValues *formats = NULL;
|
XvImageFormatValues *formats = NULL;
|
||||||
XvAdaptorInfo *adaptors;
|
XvAdaptorInfo *adaptors;
|
||||||
XvAttribute *port_attr;
|
XvAttribute *port_attr;
|
||||||
VisualID visualid = None;
|
VisualID visualid = None;
|
||||||
unsigned int num_adaptors = 0;
|
unsigned int num_adaptors = 0;
|
||||||
GdkScreen *screen;
|
GdkScreen *screen;
|
||||||
GdkWindow *root;
|
GdkWindow *root;
|
||||||
|
|
||||||
/* Setup XV */
|
/* Setup XV */
|
||||||
gtk_widget_realize (drawing_area);
|
gtk_widget_realize(drawing_area);
|
||||||
|
|
||||||
display = gdk_x11_display_get_xdisplay (gtk_widget_get_display (drawing_area));
|
display = gdk_x11_display_get_xdisplay(gtk_widget_get_display(drawing_area));
|
||||||
screen = gtk_widget_get_screen (drawing_area);
|
screen = gtk_widget_get_screen(drawing_area);
|
||||||
root = gdk_screen_get_root_window (screen);
|
root = gdk_screen_get_root_window(screen);
|
||||||
|
|
||||||
xv_portid = -1;
|
xv_portid = -1;
|
||||||
if ((XvQueryAdaptors (display,
|
if ((XvQueryAdaptors(display,
|
||||||
gdk_x11_window_get_xid (root),
|
gdk_x11_window_get_xid(root),
|
||||||
&num_adaptors,
|
&num_adaptors,
|
||||||
&adaptors)) != Success)
|
&adaptors)) != Success)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "No Xv compatible adaptors.\n");
|
fprintf(stderr, "No Xv compatible adaptors.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < (int)num_adaptors; i++)
|
||||||
for (int i = 0; i < (int) num_adaptors; i++)
|
|
||||||
{
|
{
|
||||||
if (adaptors[i].type & XvInputMask &&
|
if (adaptors[i].type & XvInputMask &&
|
||||||
adaptors[i].type & XvImageMask)
|
adaptors[i].type & XvImageMask)
|
||||||
{
|
{
|
||||||
formats = XvListImageFormats (display,
|
formats = XvListImageFormats(display,
|
||||||
adaptors[i].base_id,
|
adaptors[i].base_id,
|
||||||
&num_formats);
|
&num_formats);
|
||||||
|
|
||||||
if (num_formats > highest_formats)
|
if (num_formats > highest_formats)
|
||||||
{
|
{
|
||||||
|
@ -270,30 +240,30 @@ S9xXVDisplayDriver::init ()
|
||||||
visualid = adaptors[i].formats->visual_id;
|
visualid = adaptors[i].formats->visual_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
free (formats);
|
free(formats);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
XvFreeAdaptorInfo (adaptors);
|
XvFreeAdaptorInfo(adaptors);
|
||||||
|
|
||||||
if (xv_portid < 0)
|
if (xv_portid < 0)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "Could not open Xv output port.\n");
|
fprintf(stderr, "Could not open Xv output port.\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set XV_AUTOPAINT_COLORKEY _only_ if available */
|
/* Set XV_AUTOPAINT_COLORKEY _only_ if available */
|
||||||
port_attr = XvQueryPortAttributes (display, xv_portid, &num_attrs);
|
port_attr = XvQueryPortAttributes(display, xv_portid, &num_attrs);
|
||||||
|
|
||||||
for (int i = 0; i < num_attrs; i++)
|
for (int i = 0; i < num_attrs; i++)
|
||||||
{
|
{
|
||||||
if (!strcmp (port_attr[i].name, "XV_AUTOPAINT_COLORKEY"))
|
if (!strcmp(port_attr[i].name, "XV_AUTOPAINT_COLORKEY"))
|
||||||
{
|
{
|
||||||
Atom colorkey;
|
Atom colorkey;
|
||||||
|
|
||||||
colorkey = XInternAtom (display, "XV_AUTOPAINT_COLORKEY", True);
|
colorkey = XInternAtom(display, "XV_AUTOPAINT_COLORKEY", True);
|
||||||
if (colorkey != None)
|
if (colorkey != None)
|
||||||
XvSetPortAttribute (display, xv_portid, colorkey, 1);
|
XvSetPortAttribute(display, xv_portid, colorkey, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,9 +271,9 @@ S9xXVDisplayDriver::init ()
|
||||||
format = -1;
|
format = -1;
|
||||||
bpp = 100;
|
bpp = 100;
|
||||||
|
|
||||||
formats = XvListImageFormats (display,
|
formats = XvListImageFormats(display,
|
||||||
xv_portid,
|
xv_portid,
|
||||||
&num_formats);
|
&num_formats);
|
||||||
|
|
||||||
for (int i = 0; i < num_formats; i++)
|
for (int i = 0; i < num_formats; i++)
|
||||||
{
|
{
|
||||||
|
@ -316,12 +286,12 @@ S9xXVDisplayDriver::init ()
|
||||||
bytes_per_pixel = (bpp == 15) ? 2 : bpp >> 3;
|
bytes_per_pixel = (bpp == 15) ? 2 : bpp >> 3;
|
||||||
depth = formats[i].depth;
|
depth = formats[i].depth;
|
||||||
|
|
||||||
this->rshift = get_inv_shift (formats[i].red_mask, bpp);
|
this->rshift = get_inv_shift(formats[i].red_mask, bpp);
|
||||||
this->gshift = get_inv_shift (formats[i].green_mask, bpp);
|
this->gshift = get_inv_shift(formats[i].green_mask, bpp);
|
||||||
this->bshift = get_inv_shift (formats[i].blue_mask, bpp);
|
this->bshift = get_inv_shift(formats[i].blue_mask, bpp);
|
||||||
|
|
||||||
/* Check for red-blue inversion on SiliconMotion drivers */
|
/* Check for red-blue inversion on SiliconMotion drivers */
|
||||||
if (formats[i].red_mask == 0x001f &&
|
if (formats[i].red_mask == 0x001f &&
|
||||||
formats[i].blue_mask == 0x7c00)
|
formats[i].blue_mask == 0x7c00)
|
||||||
{
|
{
|
||||||
int copy = this->rshift;
|
int copy = this->rshift;
|
||||||
|
@ -331,9 +301,9 @@ S9xXVDisplayDriver::init ()
|
||||||
|
|
||||||
/* on big-endian Xv still seems to like LSB order */
|
/* on big-endian Xv still seems to like LSB order */
|
||||||
if (config->force_inverted_byte_order)
|
if (config->force_inverted_byte_order)
|
||||||
S9xSetEndianess (ENDIAN_SWAPPED);
|
S9xSetEndianess(ENDIAN_SWAPPED);
|
||||||
else
|
else
|
||||||
S9xSetEndianess (ENDIAN_NORMAL);
|
S9xSetEndianess(ENDIAN_NORMAL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -350,16 +320,16 @@ S9xXVDisplayDriver::init ()
|
||||||
if (formats[i].byte_order == LSBFirst)
|
if (formats[i].byte_order == LSBFirst)
|
||||||
{
|
{
|
||||||
if (config->force_inverted_byte_order)
|
if (config->force_inverted_byte_order)
|
||||||
S9xSetEndianess (ENDIAN_SWAPPED);
|
S9xSetEndianess(ENDIAN_SWAPPED);
|
||||||
else
|
else
|
||||||
S9xSetEndianess (ENDIAN_NORMAL);
|
S9xSetEndianess(ENDIAN_NORMAL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (config->force_inverted_byte_order)
|
if (config->force_inverted_byte_order)
|
||||||
S9xSetEndianess (ENDIAN_NORMAL);
|
S9xSetEndianess(ENDIAN_NORMAL);
|
||||||
else
|
else
|
||||||
S9xSetEndianess (ENDIAN_SWAPPED);
|
S9xSetEndianess(ENDIAN_SWAPPED);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -367,11 +337,11 @@ S9xXVDisplayDriver::init ()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free (formats);
|
free(formats);
|
||||||
|
|
||||||
if (format == -1)
|
if (format == -1)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "No compatible formats found for Xv.\n");
|
fprintf(stderr, "No compatible formats found for Xv.\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -384,19 +354,19 @@ S9xXVDisplayDriver::init ()
|
||||||
int y, u, v;
|
int y, u, v;
|
||||||
|
|
||||||
r = ((color & 0xf800) >> 8) | ((color >> 13) & 0x7);
|
r = ((color & 0xf800) >> 8) | ((color >> 13) & 0x7);
|
||||||
g = ((color & 0x07e0) >> 3) | ((color >> 9 ) & 0x3);
|
g = ((color & 0x07e0) >> 3) | ((color >> 9) & 0x3);
|
||||||
b = ((color & 0x001F) << 3) | ((color >> 3 ) & 0x7);
|
b = ((color & 0x001F) << 3) | ((color >> 3) & 0x7);
|
||||||
|
|
||||||
y = (int) ((0.257 * ((double) r)) + (0.504 * ((double) g)) + (0.098 * ((double) b)) + 16.0);
|
y = (int)((0.257 * ((double)r)) + (0.504 * ((double)g)) + (0.098 * ((double)b)) + 16.0);
|
||||||
u = (int) ((-0.148 * ((double) r)) + (-0.291 * ((double) g)) + (0.439 * ((double) b)) + 128.0);
|
u = (int)((-0.148 * ((double)r)) + (-0.291 * ((double)g)) + (0.439 * ((double)b)) + 128.0);
|
||||||
v = (int) ((0.439 * ((double) r)) + (-0.368 * ((double) g)) + (-0.071 * ((double) b)) + 128.0);
|
v = (int)((0.439 * ((double)r)) + (-0.368 * ((double)g)) + (-0.071 * ((double)b)) + 128.0);
|
||||||
|
|
||||||
y_table[color] = CLAMP (y, 0, 255);
|
y_table[color] = CLAMP(y, 0, 255);
|
||||||
u_table[color] = CLAMP (u, 0, 255);
|
u_table[color] = CLAMP(u, 0, 255);
|
||||||
v_table[color] = CLAMP (v, 0, 255);
|
v_table[color] = CLAMP(v, 0, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
S9xRegisterYUVTables (y_table, u_table, v_table);
|
S9xRegisterYUVTables(y_table, u_table, v_table);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create a sub-window */
|
/* Create a sub-window */
|
||||||
|
@ -406,42 +376,42 @@ S9xXVDisplayDriver::init ()
|
||||||
vi_template.visualid = visualid;
|
vi_template.visualid = visualid;
|
||||||
vi_template.depth = depth;
|
vi_template.depth = depth;
|
||||||
vi_template.visual = NULL;
|
vi_template.visual = NULL;
|
||||||
vi = XGetVisualInfo (display, VisualIDMask | VisualDepthMask, &vi_template, &vi_num_items);
|
vi = XGetVisualInfo(display, VisualIDMask | VisualDepthMask, &vi_template, &vi_num_items);
|
||||||
|
|
||||||
if (!vi)
|
if (!vi)
|
||||||
{
|
{
|
||||||
vi_template.depth = 0;
|
vi_template.depth = 0;
|
||||||
vi = XGetVisualInfo (display, VisualIDMask, &vi_template, &vi_num_items);
|
vi = XGetVisualInfo(display, VisualIDMask, &vi_template, &vi_num_items);
|
||||||
|
|
||||||
if (!vi)
|
if (!vi)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "Couldn't map visual.\n");
|
fprintf(stderr, "Couldn't map visual.\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
xcolormap = XCreateColormap (display,
|
xcolormap = XCreateColormap(display,
|
||||||
gdk_x11_window_get_xid (gtk_widget_get_window (drawing_area)),
|
gdk_x11_window_get_xid(gtk_widget_get_window(drawing_area)),
|
||||||
vi->visual,
|
vi->visual,
|
||||||
AllocNone);
|
AllocNone);
|
||||||
|
|
||||||
create_window (1, 1);
|
create_window(1, 1);
|
||||||
gdk_window_hide (gdk_window);
|
gdk_window_hide(gdk_window);
|
||||||
|
|
||||||
/* Allocate a shared memory image. */
|
/* Allocate a shared memory image. */
|
||||||
xv_image = XvShmCreateImage (display,
|
xv_image = XvShmCreateImage(display,
|
||||||
xv_portid,
|
xv_portid,
|
||||||
format,
|
format,
|
||||||
0,
|
0,
|
||||||
scaled_max_width,
|
512,
|
||||||
scaled_max_width,
|
512,
|
||||||
&shm);
|
&shm);
|
||||||
|
|
||||||
shm.shmid = shmget (IPC_PRIVATE, xv_image->data_size, IPC_CREAT | 0777);
|
shm.shmid = shmget(IPC_PRIVATE, xv_image->data_size, IPC_CREAT | 0777);
|
||||||
shm.shmaddr = (char *) shmat (shm.shmid, 0, 0);
|
shm.shmaddr = (char *)shmat(shm.shmid, 0, 0);
|
||||||
if (shm.shmaddr == (void *) -1)
|
if (shm.shmaddr == (void *)-1)
|
||||||
{
|
{
|
||||||
fprintf (stderr, "Could not attach shared memory segment.\n");
|
fprintf(stderr, "Could not attach shared memory segment.\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -449,60 +419,37 @@ S9xXVDisplayDriver::init ()
|
||||||
|
|
||||||
xv_image->data = shm.shmaddr;
|
xv_image->data = shm.shmaddr;
|
||||||
|
|
||||||
XShmAttach (display, &shm);
|
XShmAttach(display, &shm);
|
||||||
|
|
||||||
desired_width = scaled_max_width;
|
xv_image_width = 512;
|
||||||
desired_height = scaled_max_width;
|
xv_image_height = 512;
|
||||||
|
|
||||||
buffer[0] = new uint8_t[image_padded_size];
|
|
||||||
buffer[1] = new uint8_t[scaled_padded_size];
|
|
||||||
|
|
||||||
padded_buffer[0] = &buffer[0][image_padded_offset];
|
|
||||||
padded_buffer[1] = &buffer[1][scaled_padded_offset];
|
|
||||||
|
|
||||||
memset (buffer[0], 0, image_padded_size);
|
|
||||||
memset (buffer[1], 0, scaled_padded_size);
|
|
||||||
|
|
||||||
clear_buffers ();
|
|
||||||
|
|
||||||
/* Give Snes9x core a pointer to draw on */
|
|
||||||
GFX.Screen = (uint16 *) padded_buffer[0];
|
|
||||||
GFX.Pitch = image_width * image_bpp;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void S9xXVDisplayDriver::deinit()
|
||||||
S9xXVDisplayDriver::deinit ()
|
|
||||||
{
|
{
|
||||||
gdk_window_destroy (gdk_window);
|
gdk_window_destroy(gdk_window);
|
||||||
|
|
||||||
XShmDetach (display, &shm);
|
XShmDetach(display, &shm);
|
||||||
XSync (display, 0);
|
XSync(display, 0);
|
||||||
|
|
||||||
XFreeColormap (display, xcolormap);
|
XFreeColormap(display, xcolormap);
|
||||||
XFree (vi);
|
XFree(vi);
|
||||||
|
|
||||||
delete[] buffer[0];
|
shmctl(shm.shmid, IPC_RMID, 0);
|
||||||
delete[] buffer[1];
|
shmdt(shm.shmaddr);
|
||||||
|
|
||||||
shmctl (shm.shmid, IPC_RMID, 0);
|
|
||||||
shmdt (shm.shmaddr);
|
|
||||||
|
|
||||||
padded_buffer[0] = NULL;
|
|
||||||
padded_buffer[1] = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void S9xXVDisplayDriver::clear()
|
||||||
S9xXVDisplayDriver::clear ()
|
|
||||||
{
|
{
|
||||||
int width, height;
|
int width, height;
|
||||||
GtkAllocation allocation;
|
GtkAllocation allocation;
|
||||||
GC xgc = XDefaultGC (display, XDefaultScreen (display));
|
GC xgc = XDefaultGC(display, XDefaultScreen(display));
|
||||||
|
|
||||||
gtk_widget_get_allocation (drawing_area, &allocation);
|
gtk_widget_get_allocation(drawing_area, &allocation);
|
||||||
#if GTK_CHECK_VERSION(3,10,0)
|
#if GTK_CHECK_VERSION(3, 10, 0)
|
||||||
int gdk_scale_factor = gdk_window_get_scale_factor (gdk_window);
|
int gdk_scale_factor = gdk_window_get_scale_factor(gdk_window);
|
||||||
|
|
||||||
allocation.width *= gdk_scale_factor;
|
allocation.width *= gdk_scale_factor;
|
||||||
allocation.height *= gdk_scale_factor;
|
allocation.height *= gdk_scale_factor;
|
||||||
|
@ -513,7 +460,7 @@ S9xXVDisplayDriver::clear ()
|
||||||
|
|
||||||
if (window->last_width <= 0 || window->last_height <= 0)
|
if (window->last_width <= 0 || window->last_height <= 0)
|
||||||
{
|
{
|
||||||
XDrawRectangle (display, xwindow, xgc, 0, 0, width, height);
|
XDrawRectangle(display, xwindow, xgc, 0, 0, width, height);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -521,107 +468,58 @@ S9xXVDisplayDriver::clear ()
|
||||||
S9xRect dst;
|
S9xRect dst;
|
||||||
dst.w = window->last_width;
|
dst.w = window->last_width;
|
||||||
dst.h = window->last_height;
|
dst.h = window->last_height;
|
||||||
get_filter_scale (dst.w, dst.h);
|
get_filter_scale(dst.w, dst.h);
|
||||||
dst = S9xApplyAspect (dst.w, dst.h, width, height);
|
dst = S9xApplyAspect(dst.w, dst.h, width, height);
|
||||||
|
|
||||||
if (dst.x > 0)
|
if (dst.x > 0)
|
||||||
{
|
{
|
||||||
XFillRectangle (display, xwindow, xgc, 0, dst.y, dst.x, dst.h);
|
XFillRectangle(display, xwindow, xgc, 0, dst.y, dst.x, dst.h);
|
||||||
}
|
}
|
||||||
if (dst.x + dst.w < width)
|
if (dst.x + dst.w < width)
|
||||||
{
|
{
|
||||||
XFillRectangle (display, xwindow, xgc, dst.x + dst.w, dst.y, width - (dst.x + dst.w), dst.h);
|
XFillRectangle(display, xwindow, xgc, dst.x + dst.w, dst.y, width - (dst.x + dst.w), dst.h);
|
||||||
}
|
}
|
||||||
if (dst.y > 0)
|
if (dst.y > 0)
|
||||||
{
|
{
|
||||||
XFillRectangle (display, xwindow, xgc, 0, 0, width, dst.y);
|
XFillRectangle(display, xwindow, xgc, 0, 0, width, dst.y);
|
||||||
}
|
}
|
||||||
if (dst.y + dst.h < height)
|
if (dst.y + dst.h < height)
|
||||||
{
|
{
|
||||||
XFillRectangle (display, xwindow, xgc, 0, dst.y + dst.h, width, height - (dst.y + dst.h));
|
XFillRectangle(display, xwindow, xgc, 0, dst.y + dst.h, width, height - (dst.y + dst.h));
|
||||||
}
|
}
|
||||||
|
|
||||||
XSync (display, False);
|
XSync(display, False);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void S9xXVDisplayDriver::refresh(int width, int height)
|
||||||
S9xXVDisplayDriver::refresh (int width, int height)
|
|
||||||
{
|
{
|
||||||
clear ();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16 *
|
int S9xXVDisplayDriver::query_availability()
|
||||||
S9xXVDisplayDriver::get_next_buffer ()
|
|
||||||
{
|
|
||||||
return (uint16 *) padded_buffer[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16 *
|
|
||||||
S9xXVDisplayDriver::get_current_buffer ()
|
|
||||||
{
|
|
||||||
return get_next_buffer ();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
S9xXVDisplayDriver::push_buffer (uint16 *src)
|
|
||||||
{
|
|
||||||
memmove (GFX.Screen, src, image_size * image_bpp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
S9xXVDisplayDriver::clear_buffers ()
|
|
||||||
{
|
|
||||||
uint32 black;
|
|
||||||
uint8 *color;
|
|
||||||
|
|
||||||
memset (buffer[0], 0, image_padded_size);
|
|
||||||
memset (buffer[1], 0, scaled_padded_size);
|
|
||||||
|
|
||||||
/* Construct value byte-order independently */
|
|
||||||
if (format == FOURCC_YUY2)
|
|
||||||
{
|
|
||||||
color = (uint8 *) &black;
|
|
||||||
*color++ = y_table[0];
|
|
||||||
*color++ = u_table[0];
|
|
||||||
*color++ = y_table[0];
|
|
||||||
*color++ = v_table[0];
|
|
||||||
|
|
||||||
for (int i = 0; i < xv_image->data_size >> 2; i++)
|
|
||||||
{
|
|
||||||
*(((uint32 *) xv_image->data) + i) = black;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
memset (xv_image->data, 0, xv_image->data_size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
S9xXVDisplayDriver::query_availability ()
|
|
||||||
{
|
{
|
||||||
unsigned int p_version,
|
unsigned int p_version,
|
||||||
p_release,
|
p_release,
|
||||||
p_request_base,
|
p_request_base,
|
||||||
p_event_base,
|
p_event_base,
|
||||||
p_error_base;
|
p_error_base;
|
||||||
Display *display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
|
Display *display = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
|
||||||
|
|
||||||
if (!display)
|
if (!display)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Test if XV and SHM are feasible */
|
/* Test if XV and SHM are feasible */
|
||||||
if (!XShmQueryExtension (display))
|
if (!XShmQueryExtension(display))
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (XvQueryExtension (display,
|
if (XvQueryExtension(display,
|
||||||
&p_version,
|
&p_version,
|
||||||
&p_release,
|
&p_release,
|
||||||
&p_request_base,
|
&p_request_base,
|
||||||
&p_event_base,
|
&p_event_base,
|
||||||
&p_error_base) != Success)
|
&p_error_base) != Success)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,51 +19,55 @@ const uint32 FOURCC_YUY2 = 0x32595559;
|
||||||
|
|
||||||
class S9xXVDisplayDriver : public S9xDisplayDriver
|
class S9xXVDisplayDriver : public S9xDisplayDriver
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
S9xXVDisplayDriver (Snes9xWindow *window, Snes9xConfig *config);
|
S9xXVDisplayDriver(Snes9xWindow *window, Snes9xConfig *config);
|
||||||
void refresh (int width, int height);
|
void refresh(int width, int height);
|
||||||
int init ();
|
int init();
|
||||||
void deinit ();
|
void deinit();
|
||||||
void clear_buffers ();
|
void update(uint16_t *buffer, int width, int height, int stride_in_pixels);
|
||||||
void update (int width, int height, int yoffset);
|
void *get_parameters()
|
||||||
uint16 *get_next_buffer ();
|
{
|
||||||
uint16 *get_current_buffer ();
|
return NULL;
|
||||||
void push_buffer (uint16 *src);
|
}
|
||||||
void *get_parameters () { return NULL; }
|
void save(const char *filename)
|
||||||
void save (const char *filename) { }
|
{
|
||||||
static int query_availability ();
|
}
|
||||||
bool is_ready () { return true; }
|
static int query_availability();
|
||||||
|
bool is_ready()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void clear ();
|
void clear();
|
||||||
void update_image_size (int width, int height);
|
void update_image_size(int width, int height);
|
||||||
void resize_window (int width, int height);
|
void resize_window(int width, int height);
|
||||||
void create_window (int width, int height);
|
void create_window(int width, int height);
|
||||||
|
|
||||||
Display *display;
|
Display *display;
|
||||||
Window xwindow;
|
Window xwindow;
|
||||||
Colormap xcolormap;
|
Colormap xcolormap;
|
||||||
XVisualInfo *vi;
|
XVisualInfo *vi;
|
||||||
GdkWindow *gdk_window;
|
GdkWindow *gdk_window;
|
||||||
|
|
||||||
XvImage *xv_image;
|
XvImage *xv_image;
|
||||||
int xv_portid;
|
int xv_portid;
|
||||||
XShmSegmentInfo shm;
|
XShmSegmentInfo shm;
|
||||||
|
|
||||||
int output_window_width;
|
int output_window_width;
|
||||||
int output_window_height;
|
int output_window_height;
|
||||||
int last_known_width;
|
int last_known_width;
|
||||||
int last_known_height;
|
int last_known_height;
|
||||||
int desired_width;
|
int xv_image_width;
|
||||||
int desired_height;
|
int xv_image_height;
|
||||||
int format;
|
int format;
|
||||||
int bpp;
|
int bpp;
|
||||||
int bytes_per_pixel;
|
int bytes_per_pixel;
|
||||||
int rshift, gshift, bshift;
|
int rshift, gshift, bshift;
|
||||||
|
|
||||||
uint8 y_table[65536];
|
uint8 y_table[65536];
|
||||||
uint8 u_table[65536];
|
uint8 u_table[65536];
|
||||||
uint8 v_table[65536];
|
uint8 v_table[65536];
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __GTK_DISPLAY_DRIVER_XV_H */
|
#endif /* __GTK_DISPLAY_DRIVER_XV_H */
|
||||||
|
|
|
@ -255,7 +255,7 @@ void S9xNoROMLoaded ()
|
||||||
{
|
{
|
||||||
S9xSoundStop ();
|
S9xSoundStop ();
|
||||||
gui_config->rom_loaded = false;
|
gui_config->rom_loaded = false;
|
||||||
S9xDisplayRefresh (-1, -1);
|
S9xDisplayRefresh(-1, -1);
|
||||||
top_level->configure_widgets ();
|
top_level->configure_widgets ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1869,8 +1869,6 @@ Snes9xWindow::propagate_pause_state ()
|
||||||
S9xSoundStart ();
|
S9xSoundStart ();
|
||||||
if (config->rom_loaded)
|
if (config->rom_loaded)
|
||||||
enable_widget ("pause_item", true);
|
enable_widget ("pause_item", true);
|
||||||
|
|
||||||
S9xDisplayClearBuffers ();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue