Use cairo for scaling in software driver.

This commit is contained in:
Brandon Wright 2010-11-18 05:28:48 -06:00
parent c052e66ae0
commit a37db4c09d
3 changed files with 24 additions and 426 deletions

View File

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

View File

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

View File

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