mirror of https://github.com/snes9xgit/snes9x.git
Use cairo for scaling in software driver.
This commit is contained in:
parent
084d459635
commit
6880eacd5e
|
@ -628,284 +628,6 @@ internal_convert (void *src_buffer,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
internal_convert_scale (void *src_buffer,
|
|
||||||
void *dst_buffer,
|
|
||||||
int src_pitch,
|
|
||||||
int dst_pitch,
|
|
||||||
int width,
|
|
||||||
int height,
|
|
||||||
int dest_width,
|
|
||||||
int dest_height,
|
|
||||||
int line_start,
|
|
||||||
int line_end,
|
|
||||||
int bpp)
|
|
||||||
{
|
|
||||||
register uint32 x_fraction, y_fraction;
|
|
||||||
|
|
||||||
x_fraction = (width * 0x10000) / dest_width;
|
|
||||||
y_fraction = (height * 0x10000) / dest_height;
|
|
||||||
|
|
||||||
if (endianess == ENDIAN_MSB)
|
|
||||||
{
|
|
||||||
if (bpp == 15)
|
|
||||||
{
|
|
||||||
/* Format in fourcc is xrrrrrgg gggbbbbb */
|
|
||||||
for (register int y = line_start; y < line_end; y++)
|
|
||||||
{
|
|
||||||
register uint8 *data =
|
|
||||||
(uint8 *) dst_buffer + y * dst_pitch;
|
|
||||||
register uint16 *snes =
|
|
||||||
(uint16 *) (((uint8 *) src_buffer) + ((y_fraction * y) >> 16) * src_pitch);
|
|
||||||
|
|
||||||
register uint32 x_error = 0;
|
|
||||||
for (register int x = 0; x < dest_width; x++)
|
|
||||||
{
|
|
||||||
uint32 pixel = *snes;
|
|
||||||
*data++ = (pixel & 0x7c00) >> 8 |
|
|
||||||
(pixel & 0x0300) >> 8; /* Top 2 green, 5 red */
|
|
||||||
*data++ = (pixel & 0x00c0) |
|
|
||||||
(pixel & 0x001f); /* Top 3 of last 4 green 5 blue */
|
|
||||||
|
|
||||||
x_error += x_fraction;
|
|
||||||
|
|
||||||
while (x_error >= 0x10000)
|
|
||||||
{
|
|
||||||
snes++;
|
|
||||||
x_error -= 0x10000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (bpp == 16)
|
|
||||||
{
|
|
||||||
/* Format in fourcc is rrrrrggg gggbbbbb */
|
|
||||||
for (register int y = line_start; y < line_end; y++)
|
|
||||||
{
|
|
||||||
register uint8 *data =
|
|
||||||
(uint8 *) dst_buffer + y * dst_pitch;
|
|
||||||
register uint16 *snes =
|
|
||||||
(uint16 *) (((uint8 *) src_buffer) + ((y_fraction * y) >> 16) * src_pitch);
|
|
||||||
|
|
||||||
register uint32 x_error = 0;
|
|
||||||
for (register int x = 0; x < dest_width; x++)
|
|
||||||
{
|
|
||||||
uint32 pixel = *snes;
|
|
||||||
|
|
||||||
*data++ = (pixel & 0x7c00) >> 7 |
|
|
||||||
(pixel & 0x0300) >> 7; /* 5 red, first 3 green */
|
|
||||||
*data++ = (pixel & 0x00c0) |
|
|
||||||
(pixel & 0x001f); /* last 3 green, 5 blue */
|
|
||||||
|
|
||||||
x_error += x_fraction;
|
|
||||||
|
|
||||||
while (x_error >= 0x10000)
|
|
||||||
{
|
|
||||||
snes++;
|
|
||||||
x_error -= 0x10000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (bpp == 24)
|
|
||||||
{
|
|
||||||
/* Format in fourcc is rrrrrrrr gggggggg bbbbbbbb */
|
|
||||||
for (register int y = line_start; y < line_end; y++)
|
|
||||||
{
|
|
||||||
register uint8 *data =
|
|
||||||
(uint8 *) dst_buffer + y * dst_pitch;
|
|
||||||
|
|
||||||
register uint16 *snes =
|
|
||||||
(uint16 *) (((uint8 *) src_buffer) + ((y_fraction * y) >> 16) * src_pitch);
|
|
||||||
|
|
||||||
register uint32 x_error = 0;
|
|
||||||
for (register int x = 0; x < dest_width; x++)
|
|
||||||
{
|
|
||||||
uint32 pixel = *snes;
|
|
||||||
|
|
||||||
*data++ = (pixel & 0x7c00) >> 7; /* Red */
|
|
||||||
*data++ = (pixel & 0x03e0) >> 2; /* Green */
|
|
||||||
*data++ = (pixel & 0x001f) << 3; /* Blue */
|
|
||||||
|
|
||||||
x_error += x_fraction;
|
|
||||||
|
|
||||||
while (x_error >= 0x10000)
|
|
||||||
{
|
|
||||||
snes++;
|
|
||||||
x_error -= 0x10000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (bpp == 32)
|
|
||||||
{
|
|
||||||
/* Format in fourcc is xxxxxxxx rrrrrrrr gggggggg bbbbbbbb */
|
|
||||||
for (register int y = line_start; y < line_end; y++)
|
|
||||||
{
|
|
||||||
register uint8 *data =
|
|
||||||
(uint8 *) dst_buffer + y * dst_pitch;
|
|
||||||
|
|
||||||
register uint16 *snes =
|
|
||||||
(uint16 *) (((uint8 *) src_buffer) + ((y_fraction * y) >> 16) * src_pitch);
|
|
||||||
|
|
||||||
register uint32 x_error = 0;
|
|
||||||
for (register int x = 0; x < dest_width; x++)
|
|
||||||
{
|
|
||||||
uint32 pixel = *snes;
|
|
||||||
|
|
||||||
*data++ = 0xff; /* Null */
|
|
||||||
*data++ = (pixel & 0x7c00) >> 7; /* Red */
|
|
||||||
*data++ = (pixel & 0x03e0) >> 2; /* Green */
|
|
||||||
*data++ = (pixel & 0x001f) << 3; /* Blue */
|
|
||||||
|
|
||||||
x_error += x_fraction;
|
|
||||||
|
|
||||||
while (x_error >= 0x10000)
|
|
||||||
{
|
|
||||||
snes++;
|
|
||||||
x_error -= 0x10000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else /* Least significant byte first :-P */
|
|
||||||
{
|
|
||||||
if (bpp == 15)
|
|
||||||
{
|
|
||||||
/* Format in fourcc is xrrrrrgg gggbbbbb */
|
|
||||||
|
|
||||||
for (register int y = line_start; y < line_end; y++)
|
|
||||||
{
|
|
||||||
register uint8 *data =
|
|
||||||
(uint8 *) dst_buffer + y * dst_pitch;
|
|
||||||
|
|
||||||
register uint16 *snes =
|
|
||||||
(uint16 *) (((uint8 *) src_buffer) + ((y_fraction * y) >> 16) * src_pitch);
|
|
||||||
|
|
||||||
register uint32 x_error = 0;
|
|
||||||
for (register int x = 0; x < dest_width; x++)
|
|
||||||
{
|
|
||||||
uint32 pixel = *snes;
|
|
||||||
*data++ = (pixel & 0x00c0) |
|
|
||||||
(pixel & 0x001f); /* Top 3 of last 4 green 5 blue */
|
|
||||||
*data++ = (pixel & 0x7c00) >> 8 |
|
|
||||||
(pixel & 0x0300) >> 8; /* Top 2 green, 5 red */
|
|
||||||
|
|
||||||
x_error += x_fraction;
|
|
||||||
|
|
||||||
while (x_error >= 0x10000)
|
|
||||||
{
|
|
||||||
snes++;
|
|
||||||
x_error -= 0x10000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (bpp == 16)
|
|
||||||
{
|
|
||||||
/* Format in fourcc is rrrrrggg gggbbbbb */
|
|
||||||
for (register int y = line_start; y < line_end; y++)
|
|
||||||
{
|
|
||||||
register uint8 *data =
|
|
||||||
(uint8 *) dst_buffer + y * dst_pitch;
|
|
||||||
|
|
||||||
register uint16 *snes =
|
|
||||||
(uint16 *) (((uint8 *) src_buffer) + ((y_fraction * y) >> 16) * src_pitch);
|
|
||||||
|
|
||||||
register uint32 x_error = 0;
|
|
||||||
for (register int x = 0; x < dest_width; x++)
|
|
||||||
{
|
|
||||||
uint32 pixel = *snes;
|
|
||||||
|
|
||||||
*data++ = (pixel & 0x00c0) |
|
|
||||||
(pixel & 0x001f); /* last 3 green, 5 blue */
|
|
||||||
*data++ = (pixel & 0x7c00) >> 7 |
|
|
||||||
(pixel & 0x0300) >> 7; /* 5 red, first 3 green */
|
|
||||||
|
|
||||||
x_error += x_fraction;
|
|
||||||
|
|
||||||
while (x_error >= 0x10000)
|
|
||||||
{
|
|
||||||
snes++;
|
|
||||||
x_error -= 0x10000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (bpp == 24)
|
|
||||||
{
|
|
||||||
/* Format in fourcc is rrrrrrrr gggggggg bbbbbbbb */
|
|
||||||
for (register int y = line_start; y < line_end; y++)
|
|
||||||
{
|
|
||||||
register uint8 *data =
|
|
||||||
(uint8 *) dst_buffer + y * dst_pitch;
|
|
||||||
|
|
||||||
register uint16 *snes =
|
|
||||||
(uint16 *) (((uint8 *) src_buffer) + ((y_fraction * y) >> 16) * src_pitch);
|
|
||||||
|
|
||||||
register uint32 x_error = 0;
|
|
||||||
for (register int x = 0; x < dest_width; x++)
|
|
||||||
{
|
|
||||||
uint32 pixel = *snes;
|
|
||||||
|
|
||||||
*data++ = (pixel & 0x001f) << 3; /* Blue */
|
|
||||||
*data++ = (pixel & 0x03e0) >> 2; /* Green */
|
|
||||||
*data++ = (pixel & 0x7c00) >> 7; /* Red */
|
|
||||||
|
|
||||||
x_error += x_fraction;
|
|
||||||
|
|
||||||
while (x_error >= 0x10000)
|
|
||||||
{
|
|
||||||
snes++;
|
|
||||||
x_error -= 0x10000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (bpp == 32)
|
|
||||||
{
|
|
||||||
/* Format in fourcc is xxxxxxxx rrrrrrrr gggggggg bbbbbbbb */
|
|
||||||
for (register int y = line_start; y < line_end; y++)
|
|
||||||
{
|
|
||||||
register uint8 *data =
|
|
||||||
(uint8 *) dst_buffer + y * dst_pitch;
|
|
||||||
|
|
||||||
register uint16 *snes =
|
|
||||||
(uint16 *) (((uint8 *) src_buffer) + ((y_fraction * y) >> 16) * src_pitch);
|
|
||||||
|
|
||||||
register uint32 x_error = 0;
|
|
||||||
for (register int x = 0; x < dest_width; x++)
|
|
||||||
{
|
|
||||||
uint32 pixel = *snes;
|
|
||||||
|
|
||||||
*data++ = (pixel & 0x001f) << 3; /* Blue */
|
|
||||||
*data++ = (pixel & 0x03e0) >> 2; /* Green */
|
|
||||||
*data++ = (pixel & 0x7c00) >> 7; /* Red */
|
|
||||||
*data++ = 0xff; /* Null */
|
|
||||||
|
|
||||||
x_error += x_fraction;
|
|
||||||
|
|
||||||
while (x_error >= 0x10000)
|
|
||||||
{
|
|
||||||
snes++;
|
|
||||||
x_error -= 0x10000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
S9xForceHires (void *buffer,
|
S9xForceHires (void *buffer,
|
||||||
int pitch,
|
int pitch,
|
||||||
|
@ -1454,19 +1176,6 @@ thread_worker (gpointer data,
|
||||||
job->inv_bmask,
|
job->inv_bmask,
|
||||||
job->inv_gmask,
|
job->inv_gmask,
|
||||||
job->bpp);
|
job->bpp);
|
||||||
|
|
||||||
case JOB_SCALE_AND_CONVERT:
|
|
||||||
internal_convert_scale (job->src_buffer,
|
|
||||||
job->dst_buffer,
|
|
||||||
job->src_pitch,
|
|
||||||
job->dst_pitch,
|
|
||||||
job->width,
|
|
||||||
job->height,
|
|
||||||
job->dst_width,
|
|
||||||
job->dst_height,
|
|
||||||
job->line_start,
|
|
||||||
job->line_end,
|
|
||||||
job->bpp);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1490,71 +1199,6 @@ create_thread_pool (void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
internal_threaded_convert_scale (void *src_buffer,
|
|
||||||
void *dst_buffer,
|
|
||||||
int src_pitch,
|
|
||||||
int dst_pitch,
|
|
||||||
int width,
|
|
||||||
int height,
|
|
||||||
int dst_width,
|
|
||||||
int dst_height,
|
|
||||||
int bpp)
|
|
||||||
{
|
|
||||||
int i, flag;
|
|
||||||
|
|
||||||
/* If the threadpool doesn't exist, create it */
|
|
||||||
create_thread_pool ();
|
|
||||||
|
|
||||||
for (i = 0; i < gui_config->num_threads - 1; i++)
|
|
||||||
{
|
|
||||||
job[i].operation_type = JOB_SCALE_AND_CONVERT;
|
|
||||||
job[i].src_buffer = (uint8 *) src_buffer;
|
|
||||||
job[i].src_pitch = src_pitch;
|
|
||||||
job[i].dst_buffer = (uint8 *) dst_buffer;
|
|
||||||
job[i].dst_pitch = dst_pitch;
|
|
||||||
job[i].width = width;
|
|
||||||
job[i].height = height;
|
|
||||||
job[i].dst_width = dst_width;
|
|
||||||
job[i].dst_height = dst_height;
|
|
||||||
job[i].line_start = i * (dst_height / gui_config->num_threads);
|
|
||||||
job[i].line_end = (i + 1) * (dst_height / gui_config->num_threads);
|
|
||||||
job[i].bpp = bpp;
|
|
||||||
job[i].complete = 0;
|
|
||||||
|
|
||||||
g_thread_pool_push (pool, (gpointer) &(job[i]), NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
job[i].operation_type = JOB_SCALE_AND_CONVERT;
|
|
||||||
job[i].src_buffer = (uint8 *) src_buffer;
|
|
||||||
job[i].src_pitch = src_pitch;
|
|
||||||
job[i].dst_buffer = (uint8 *) dst_buffer;
|
|
||||||
job[i].dst_pitch = dst_pitch;
|
|
||||||
job[i].width = width;
|
|
||||||
job[i].height = height;
|
|
||||||
job[i].dst_width = dst_width;
|
|
||||||
job[i].dst_height = dst_height;
|
|
||||||
job[i].line_start = i * (height / gui_config->num_threads);
|
|
||||||
job[i].line_end = dst_height;
|
|
||||||
job[i].bpp = bpp;
|
|
||||||
|
|
||||||
thread_worker ((gpointer) &(job[i]), NULL);
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
flag = 1;
|
|
||||||
for (i = 0; i < gui_config->num_threads - 1; i++)
|
|
||||||
flag = flag && job[i].complete;
|
|
||||||
|
|
||||||
if (flag)
|
|
||||||
break;
|
|
||||||
|
|
||||||
sched_yield ();
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
internal_threaded_convert (void *src_buffer,
|
internal_threaded_convert (void *src_buffer,
|
||||||
void *dst_buffer,
|
void *dst_buffer,
|
||||||
|
@ -1863,42 +1507,6 @@ S9xConvertMask (void *src,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
S9xConvertScale (void *src,
|
|
||||||
void *dst,
|
|
||||||
int src_pitch,
|
|
||||||
int dst_pitch,
|
|
||||||
int width,
|
|
||||||
int height,
|
|
||||||
int dest_width,
|
|
||||||
int dest_height,
|
|
||||||
int bpp)
|
|
||||||
{
|
|
||||||
if (gui_config->multithreading)
|
|
||||||
internal_threaded_convert_scale (src,
|
|
||||||
dst,
|
|
||||||
src_pitch,
|
|
||||||
dst_pitch,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
dest_width,
|
|
||||||
dest_height,
|
|
||||||
bpp);
|
|
||||||
else
|
|
||||||
internal_convert_scale (src,
|
|
||||||
dst,
|
|
||||||
src_pitch,
|
|
||||||
dst_pitch,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
dest_width,
|
|
||||||
dest_height,
|
|
||||||
0,
|
|
||||||
dest_height,
|
|
||||||
bpp);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
S9xDisplayRefresh (int width, int height)
|
S9xDisplayRefresh (int width, int height)
|
||||||
{
|
{
|
||||||
|
|
|
@ -80,16 +80,6 @@ void S9xConvert (void *src,
|
||||||
int height,
|
int height,
|
||||||
int bpp);
|
int bpp);
|
||||||
|
|
||||||
void S9xConvertScale (void *src,
|
|
||||||
void *dst,
|
|
||||||
int src_pitch,
|
|
||||||
int dst_pitch,
|
|
||||||
int width,
|
|
||||||
int height,
|
|
||||||
int dest_width,
|
|
||||||
int dest_height,
|
|
||||||
int bpp);
|
|
||||||
|
|
||||||
void S9xConvertMask (void *src,
|
void S9xConvertMask (void *src,
|
||||||
void *dst,
|
void *dst,
|
||||||
int src_pitch,
|
int src_pitch,
|
||||||
|
|
|
@ -77,10 +77,10 @@ S9xGTKDisplayDriver::output (void *src,
|
||||||
int dst_width,
|
int dst_width,
|
||||||
int dst_height)
|
int dst_height)
|
||||||
{
|
{
|
||||||
if (dst_width > gdk_buffer_width || dst_height > gdk_buffer_height)
|
if (width > gdk_buffer_width || height > gdk_buffer_height)
|
||||||
{
|
{
|
||||||
gdk_buffer_width = dst_width;
|
gdk_buffer_width = width;
|
||||||
gdk_buffer_height = dst_height;
|
gdk_buffer_height = height;
|
||||||
|
|
||||||
gdk_pixbuf_unref (pixbuf);
|
gdk_pixbuf_unref (pixbuf);
|
||||||
|
|
||||||
|
@ -97,19 +97,6 @@ S9xGTKDisplayDriver::output (void *src,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (width != dst_width || height != dst_height)
|
|
||||||
{
|
|
||||||
S9xConvertScale (src,
|
|
||||||
padded_buffer[2],
|
|
||||||
src_pitch,
|
|
||||||
gdk_buffer_width * 3,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
dst_width, dst_height,
|
|
||||||
24);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
S9xConvert (src,
|
S9xConvert (src,
|
||||||
padded_buffer[2],
|
padded_buffer[2],
|
||||||
src_pitch,
|
src_pitch,
|
||||||
|
@ -117,12 +104,25 @@ S9xGTKDisplayDriver::output (void *src,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
24);
|
24);
|
||||||
}
|
|
||||||
|
|
||||||
cairo_t *cr = gdk_cairo_create (gtk_widget_get_window (drawing_area));
|
cairo_t *cr = gdk_cairo_create (gtk_widget_get_window (drawing_area));
|
||||||
|
|
||||||
gdk_cairo_set_source_pixbuf (cr, pixbuf, x, y);
|
gdk_cairo_set_source_pixbuf (cr, pixbuf, x, y);
|
||||||
|
|
||||||
|
if (width != dst_width || height != dst_height)
|
||||||
|
{
|
||||||
|
cairo_matrix_t matrix;
|
||||||
|
cairo_pattern_t *pattern = cairo_get_source (cr);;
|
||||||
|
|
||||||
|
cairo_matrix_init_identity (&matrix);
|
||||||
|
cairo_matrix_scale (&matrix,
|
||||||
|
(double) width / (double) dst_width,
|
||||||
|
(double) height / (double) dst_height);
|
||||||
|
cairo_matrix_translate (&matrix, -x, -y);
|
||||||
|
cairo_pattern_set_matrix (pattern, &matrix);
|
||||||
|
cairo_pattern_set_filter (pattern, 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_destroy (cr);
|
cairo_destroy (cr);
|
||||||
|
|
Loading…
Reference in New Issue