mirror of https://github.com/snes9xgit/snes9x.git
Use cairo for scaling in software driver.
This commit is contained in:
parent
c052e66ae0
commit
a37db4c09d
|
@ -628,284 +628,6 @@ internal_convert (void *src_buffer,
|
|||
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
|
||||
S9xForceHires (void *buffer,
|
||||
int pitch,
|
||||
|
@ -1454,19 +1176,6 @@ thread_worker (gpointer data,
|
|||
job->inv_bmask,
|
||||
job->inv_gmask,
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1490,71 +1199,6 @@ create_thread_pool (void)
|
|||
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
|
||||
internal_threaded_convert (void *src_buffer,
|
||||
void *dst_buffer,
|
||||
|
@ -1863,42 +1507,6 @@ S9xConvertMask (void *src,
|
|||
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
|
||||
S9xDisplayRefresh (int width, int height)
|
||||
{
|
||||
|
|
|
@ -80,16 +80,6 @@ void S9xConvert (void *src,
|
|||
int height,
|
||||
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 *dst,
|
||||
int src_pitch,
|
||||
|
|
|
@ -77,10 +77,10 @@ S9xGTKDisplayDriver::output (void *src,
|
|||
int dst_width,
|
||||
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_height = dst_height;
|
||||
gdk_buffer_width = width;
|
||||
gdk_buffer_height = height;
|
||||
|
||||
gdk_pixbuf_unref (pixbuf);
|
||||
|
||||
|
@ -97,32 +97,32 @@ S9xGTKDisplayDriver::output (void *src,
|
|||
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,
|
||||
padded_buffer[2],
|
||||
src_pitch,
|
||||
gdk_buffer_width * 3,
|
||||
width,
|
||||
height,
|
||||
24);
|
||||
}
|
||||
S9xConvert (src,
|
||||
padded_buffer[2],
|
||||
src_pitch,
|
||||
gdk_buffer_width * 3,
|
||||
width,
|
||||
height,
|
||||
24);
|
||||
|
||||
cairo_t *cr = gdk_cairo_create (gtk_widget_get_window (drawing_area));
|
||||
|
||||
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_fill (cr);
|
||||
cairo_destroy (cr);
|
||||
|
|
Loading…
Reference in New Issue