GTK: Refactoring of display output code.

Moves buffer management to single location.
This commit is contained in:
Brandon Wright 2020-06-30 17:28:10 -05:00
parent 38bcabff68
commit 3c3ea985ef
11 changed files with 1183 additions and 1578 deletions

File diff suppressed because it is too large Load Diff

View File

@ -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 ();

View File

@ -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*/

View File

@ -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);
}

View File

@ -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 */

View File

@ -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())
{ {

View File

@ -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
}; };

View File

@ -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;
} }

View File

@ -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 */

View File

@ -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 ();
} }

View File

@ -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
{ {