Added hardware stretching code to scale 640x480 to TV resolution
There's a bug of some kind in the 16bpp code. ?? --HG-- extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%40137
This commit is contained in:
parent
76c9127515
commit
3d9ea4a0ee
4 changed files with 171 additions and 55 deletions
|
@ -79,7 +79,7 @@ static void GS_MoveCursor(_THIS, SDL_Cursor *cursor, int x, int y)
|
||||||
screen->pixels = mapped_mem + screen->offset;
|
screen->pixels = mapped_mem + screen->offset;
|
||||||
screen_updated = 0;
|
screen_updated = 0;
|
||||||
if ( cursor_drawn ) {
|
if ( cursor_drawn ) {
|
||||||
SDL_EraseCursorNoLock(this->screen);
|
SDL_EraseCursorNoLock(screen);
|
||||||
cursor_drawn = 0;
|
cursor_drawn = 0;
|
||||||
screen_updated = 1;
|
screen_updated = 1;
|
||||||
}
|
}
|
||||||
|
@ -114,10 +114,17 @@ static void GS_MoveCursor(_THIS, SDL_Cursor *cursor, int x, int y)
|
||||||
mouse_y2 = area.y+area.h;
|
mouse_y2 = area.y+area.h;
|
||||||
}
|
}
|
||||||
image = screen_image;
|
image = screen_image;
|
||||||
image.y = screen->offset / screen->pitch + mouse_y1;
|
image.y += screen->offset / screen->pitch + mouse_y1;
|
||||||
image.h = mouse_y2 - mouse_y1;
|
image.h = mouse_y2 - mouse_y1;
|
||||||
image.ptr = mapped_mem + image.y * screen->pitch;
|
image.ptr = mapped_mem +
|
||||||
|
(image.y - screen_image.y) * screen->pitch;
|
||||||
ioctl(console_fd, PS2IOC_LOADIMAGE, &image);
|
ioctl(console_fd, PS2IOC_LOADIMAGE, &image);
|
||||||
|
|
||||||
|
/* Need to scale offscreen image to TV output */
|
||||||
|
if ( image.y > 0 ) {
|
||||||
|
scaleimage_nonblock(console_fd,
|
||||||
|
tex_tags_mem, scale_tags_mem);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We're finished */
|
/* We're finished */
|
||||||
|
|
|
@ -235,6 +235,59 @@ static inline int loadimage_nonblock(int fd, struct ps2_image *image, int size,
|
||||||
return ioctl(fd, PS2IOC_SENDL, &plist);
|
return ioctl(fd, PS2IOC_SENDL, &plist);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned long long tex_tags[] __attribute__((aligned(16))) = {
|
||||||
|
3 | (1LL << 60), /* GIFtag */
|
||||||
|
0x0e, /* A+D */
|
||||||
|
0, /* 2 */
|
||||||
|
PS2_GS_TEX0_1,
|
||||||
|
(1 << 5) + (1 << 6),
|
||||||
|
PS2_GS_TEX1_1,
|
||||||
|
0,
|
||||||
|
PS2_GS_TEXFLUSH
|
||||||
|
};
|
||||||
|
static unsigned long long scale_tags[] __attribute__((aligned(16))) = {
|
||||||
|
5 | (1LL << 60), /* GIFtag */
|
||||||
|
0x0e, /* A+D */
|
||||||
|
6 + (1 << 4) + (1 << 8),
|
||||||
|
PS2_GS_PRIM,
|
||||||
|
((unsigned long long)0 * 16) + (((unsigned long long)0 * 16) << 16),
|
||||||
|
PS2_GS_UV,
|
||||||
|
((unsigned long long)0 * 16) + (((unsigned long long)0 * 16) << 16),
|
||||||
|
PS2_GS_XYZ2,
|
||||||
|
0, /* 8 */
|
||||||
|
PS2_GS_UV,
|
||||||
|
0, /* 10 */
|
||||||
|
PS2_GS_XYZ2
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int scaleimage_nonblock(int fd, unsigned long long *tm, unsigned long long *sm)
|
||||||
|
{
|
||||||
|
struct ps2_plist plist;
|
||||||
|
struct ps2_packet packet[2];
|
||||||
|
|
||||||
|
/* initialize the variables */
|
||||||
|
plist.num = 2;
|
||||||
|
plist.packet = packet;
|
||||||
|
|
||||||
|
packet[0].ptr = tm;
|
||||||
|
packet[0].len = sizeof(tex_tags);
|
||||||
|
packet[1].ptr = sm;
|
||||||
|
packet[1].len = sizeof(scale_tags);
|
||||||
|
|
||||||
|
return ioctl(fd, PS2IOC_SENDL, &plist);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int power_of_2(int value)
|
||||||
|
{
|
||||||
|
int shift;
|
||||||
|
|
||||||
|
for ( shift = 0; (1<<shift) < value; ++shift ) {
|
||||||
|
/* Keep looking */ ;
|
||||||
|
}
|
||||||
|
return(shift);
|
||||||
|
}
|
||||||
|
|
||||||
static int GS_VideoInit(_THIS, SDL_PixelFormat *vformat)
|
static int GS_VideoInit(_THIS, SDL_PixelFormat *vformat)
|
||||||
{
|
{
|
||||||
struct ps2_screeninfo vinfo;
|
struct ps2_screeninfo vinfo;
|
||||||
|
@ -261,13 +314,6 @@ static int GS_VideoInit(_THIS, SDL_PixelFormat *vformat)
|
||||||
SDL_SetError("Couldn't get console pixel format");
|
SDL_SetError("Couldn't get console pixel format");
|
||||||
return(-1);
|
return(-1);
|
||||||
}
|
}
|
||||||
#if 0
|
|
||||||
if ( vinfo.mode != PS2_GS_VESA ) {
|
|
||||||
GS_VideoQuit(this);
|
|
||||||
SDL_SetError("Console must be in VESA video mode");
|
|
||||||
return(-1);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
switch (vinfo.psm) {
|
switch (vinfo.psm) {
|
||||||
/* Supported pixel formats */
|
/* Supported pixel formats */
|
||||||
case PS2_GS_PSMCT32:
|
case PS2_GS_PSMCT32:
|
||||||
|
@ -308,11 +354,6 @@ static int GS_VideoInit(_THIS, SDL_PixelFormat *vformat)
|
||||||
|
|
||||||
static SDL_Rect **GS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
|
static SDL_Rect **GS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
|
||||||
{
|
{
|
||||||
static SDL_Rect GS_tvout_mode;
|
|
||||||
static SDL_Rect *GS_tvout_modes[] = {
|
|
||||||
&GS_tvout_mode,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
static SDL_Rect GS_vesa_mode_list[] = {
|
static SDL_Rect GS_vesa_mode_list[] = {
|
||||||
{ 0, 0, 1280, 1024 },
|
{ 0, 0, 1280, 1024 },
|
||||||
{ 0, 0, 1024, 768 },
|
{ 0, 0, 1024, 768 },
|
||||||
|
@ -326,24 +367,44 @@ static SDL_Rect **GS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
|
||||||
&GS_vesa_mode_list[3],
|
&GS_vesa_mode_list[3],
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
static SDL_Rect GS_tvout_stretch;
|
||||||
|
static SDL_Rect GS_tvout_mode;
|
||||||
|
static SDL_Rect *GS_tvout_modes[3];
|
||||||
SDL_Rect **modes = NULL;
|
SDL_Rect **modes = NULL;
|
||||||
|
|
||||||
if ( saved_vinfo.mode == PS2_GS_VESA ) {
|
switch (format->BitsPerPixel) {
|
||||||
switch (format->BitsPerPixel) {
|
case 16:
|
||||||
case 16:
|
case 24:
|
||||||
case 24:
|
case 32:
|
||||||
case 32:
|
if ( saved_vinfo.mode == PS2_GS_VESA ) {
|
||||||
modes = GS_vesa_modes;
|
modes = GS_vesa_modes;
|
||||||
break;
|
} else {
|
||||||
default:
|
int i, j = 0;
|
||||||
break;
|
|
||||||
}
|
// FIXME - what's wrong with the stretch code at 16 bpp?
|
||||||
} else {
|
if ( format->BitsPerPixel != 32 ) break;
|
||||||
if ( GS_formatmap[format->BitsPerPixel/8] == saved_vinfo.psm ) {
|
/* Add a mode that we could possibly stretch to */
|
||||||
|
for ( i=0; GS_vesa_modes[i]; ++i ) {
|
||||||
|
if ( (GS_vesa_modes[i]->w == saved_vinfo.w) &&
|
||||||
|
(GS_vesa_modes[i]->h != saved_vinfo.h) ) {
|
||||||
|
GS_tvout_stretch.w=GS_vesa_modes[i]->w;
|
||||||
|
GS_tvout_stretch.h=GS_vesa_modes[i]->h;
|
||||||
|
GS_tvout_modes[j++] = &GS_tvout_stretch;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Add the current TV video mode */
|
||||||
GS_tvout_mode.w = saved_vinfo.w;
|
GS_tvout_mode.w = saved_vinfo.w;
|
||||||
GS_tvout_mode.h = saved_vinfo.h;
|
GS_tvout_mode.h = saved_vinfo.h;
|
||||||
|
GS_tvout_modes[j++] = &GS_tvout_mode;
|
||||||
|
GS_tvout_modes[j++] = NULL;
|
||||||
|
|
||||||
|
/* Return the created list of modes */
|
||||||
modes = GS_tvout_modes;
|
modes = GS_tvout_modes;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return(modes);
|
return(modes);
|
||||||
}
|
}
|
||||||
|
@ -368,27 +429,30 @@ static SDL_Surface *GS_SetVideoMode(_THIS, SDL_Surface *current,
|
||||||
}
|
}
|
||||||
if ( (vinfo.w != width) || (vinfo.h != height) ||
|
if ( (vinfo.w != width) || (vinfo.h != height) ||
|
||||||
(GS_pixelmasks[vinfo.psm].bpp != bpp) ) {
|
(GS_pixelmasks[vinfo.psm].bpp != bpp) ) {
|
||||||
switch (width) {
|
/* If we're not in VESA mode, we have to scale resolution */
|
||||||
case 640:
|
if ( saved_vinfo.mode == PS2_GS_VESA ) {
|
||||||
vinfo.res = PS2_GS_640x480;
|
switch (width) {
|
||||||
break;
|
case 640:
|
||||||
case 800:
|
vinfo.res = PS2_GS_640x480;
|
||||||
vinfo.res = PS2_GS_800x600;
|
break;
|
||||||
break;
|
case 800:
|
||||||
case 1024:
|
vinfo.res = PS2_GS_800x600;
|
||||||
vinfo.res = PS2_GS_1024x768;
|
break;
|
||||||
break;
|
case 1024:
|
||||||
case 1280:
|
vinfo.res = PS2_GS_1024x768;
|
||||||
vinfo.res = PS2_GS_1280x1024;
|
break;
|
||||||
break;
|
case 1280:
|
||||||
default:
|
vinfo.res = PS2_GS_1280x1024;
|
||||||
SDL_SetError("Unsupported resolution: %dx%d\n",
|
break;
|
||||||
width, height);
|
default:
|
||||||
return(NULL);
|
SDL_SetError("Unsupported resolution: %dx%d\n",
|
||||||
|
width, height);
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
vinfo.res |= (PS2_GS_75Hz << 8);
|
||||||
|
vinfo.w = width;
|
||||||
|
vinfo.h = height;
|
||||||
}
|
}
|
||||||
vinfo.res |= (PS2_GS_75Hz << 8);
|
|
||||||
vinfo.w = width;
|
|
||||||
vinfo.h = height;
|
|
||||||
vinfo.fbp = 0;
|
vinfo.fbp = 0;
|
||||||
vinfo.psm = GS_formatmap[bpp/8];
|
vinfo.psm = GS_formatmap[bpp/8];
|
||||||
if ( vinfo.psm < 0 ) {
|
if ( vinfo.psm < 0 ) {
|
||||||
|
@ -415,8 +479,8 @@ static SDL_Surface *GS_SetVideoMode(_THIS, SDL_Surface *current,
|
||||||
|
|
||||||
/* Set up the new mode framebuffer */
|
/* Set up the new mode framebuffer */
|
||||||
current->flags = SDL_FULLSCREEN;
|
current->flags = SDL_FULLSCREEN;
|
||||||
current->w = vinfo.w;
|
current->w = width;
|
||||||
current->h = vinfo.h;
|
current->h = height;
|
||||||
current->pitch = SDL_CalculatePitch(current);
|
current->pitch = SDL_CalculatePitch(current);
|
||||||
|
|
||||||
/* Memory map the DMA area for block memory transfer */
|
/* Memory map the DMA area for block memory transfer */
|
||||||
|
@ -425,6 +489,9 @@ static SDL_Surface *GS_SetVideoMode(_THIS, SDL_Surface *current,
|
||||||
mapped_len = pixels_len +
|
mapped_len = pixels_len +
|
||||||
/* Screen update DMA command area */
|
/* Screen update DMA command area */
|
||||||
sizeof(head_tags) + ((2 * MAXTAGS) * 16);
|
sizeof(head_tags) + ((2 * MAXTAGS) * 16);
|
||||||
|
if ( saved_vinfo.mode != PS2_GS_VESA ) {
|
||||||
|
mapped_len += sizeof(tex_tags) + sizeof(scale_tags);
|
||||||
|
}
|
||||||
mapped_mem = mmap(0, mapped_len, PROT_READ|PROT_WRITE,
|
mapped_mem = mmap(0, mapped_len, PROT_READ|PROT_WRITE,
|
||||||
MAP_SHARED, memory_fd, 0);
|
MAP_SHARED, memory_fd, 0);
|
||||||
if ( mapped_mem == MAP_FAILED ) {
|
if ( mapped_mem == MAP_FAILED ) {
|
||||||
|
@ -440,12 +507,17 @@ static SDL_Surface *GS_SetVideoMode(_THIS, SDL_Surface *current,
|
||||||
screen_image.fbw = (vinfo.w + 63) / 64;
|
screen_image.fbw = (vinfo.w + 63) / 64;
|
||||||
screen_image.psm = vinfo.psm;
|
screen_image.psm = vinfo.psm;
|
||||||
screen_image.x = 0;
|
screen_image.x = 0;
|
||||||
screen_image.y = 0;
|
if ( vinfo.h == height ) {
|
||||||
screen_image.w = vinfo.w;
|
screen_image.y = 0;
|
||||||
screen_image.h = vinfo.h;
|
} else {
|
||||||
|
/* Put image offscreen and scale to screen height */
|
||||||
|
screen_image.y = vinfo.h;
|
||||||
|
}
|
||||||
|
screen_image.w = current->w;
|
||||||
|
screen_image.h = current->h;
|
||||||
|
|
||||||
/* get screen image data size (qword aligned) */
|
/* get screen image data size (qword aligned) */
|
||||||
screen_image_size = (vinfo.w * vinfo.h);
|
screen_image_size = (screen_image.w * screen_image.h);
|
||||||
switch (screen_image.psm) {
|
switch (screen_image.psm) {
|
||||||
case PS2_GS_PSMCT32:
|
case PS2_GS_PSMCT32:
|
||||||
screen_image_size *= 4;
|
screen_image_size *= 4;
|
||||||
|
@ -465,6 +537,28 @@ static SDL_Surface *GS_SetVideoMode(_THIS, SDL_Surface *current,
|
||||||
image_tags_mem = (unsigned long long *)
|
image_tags_mem = (unsigned long long *)
|
||||||
((caddr_t)head_tags_mem + sizeof(head_tags));
|
((caddr_t)head_tags_mem + sizeof(head_tags));
|
||||||
memcpy(head_tags_mem, head_tags, sizeof(head_tags));
|
memcpy(head_tags_mem, head_tags, sizeof(head_tags));
|
||||||
|
if ( saved_vinfo.mode != PS2_GS_VESA ) {
|
||||||
|
tex_tags_mem = (unsigned long long *)
|
||||||
|
((caddr_t)image_tags_mem + ((2*MAXTAGS)*16));
|
||||||
|
scale_tags_mem = (unsigned long long *)
|
||||||
|
((caddr_t)tex_tags_mem + sizeof(tex_tags));
|
||||||
|
memcpy(tex_tags_mem, tex_tags, sizeof(tex_tags));
|
||||||
|
tex_tags_mem[2] =
|
||||||
|
(vinfo.h * vinfo.w) / 64 +
|
||||||
|
((unsigned long long)screen_image.fbw << 14) +
|
||||||
|
((unsigned long long)screen_image.psm << 20) +
|
||||||
|
((unsigned long long)power_of_2(screen_image.w) << 26) +
|
||||||
|
((unsigned long long)power_of_2(screen_image.h) << 30) +
|
||||||
|
((unsigned long long)1 << 34) +
|
||||||
|
((unsigned long long)1 << 35);
|
||||||
|
memcpy(scale_tags_mem, scale_tags, sizeof(scale_tags));
|
||||||
|
scale_tags_mem[8] =
|
||||||
|
((unsigned long long)screen_image.w * 16) +
|
||||||
|
(((unsigned long long)screen_image.h * 16) << 16);
|
||||||
|
scale_tags_mem[10] =
|
||||||
|
((unsigned long long)vinfo.w * 16) +
|
||||||
|
(((unsigned long long)vinfo.h * 16) << 16);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
current->pixels = NULL;
|
current->pixels = NULL;
|
||||||
if ( getenv("SDL_FULLSCREEN_UPDATE") ) {
|
if ( getenv("SDL_FULLSCREEN_UPDATE") ) {
|
||||||
|
@ -554,7 +648,14 @@ static void GS_DMAFullUpdate(_THIS, int numrects, SDL_Rect *rects)
|
||||||
loadimage_nonblock(console_fd,
|
loadimage_nonblock(console_fd,
|
||||||
&screen_image, screen_image_size,
|
&screen_image, screen_image_size,
|
||||||
head_tags_mem, image_tags_mem);
|
head_tags_mem, image_tags_mem);
|
||||||
dma_pending = 1;
|
if ( screen_image.y > 0 ) {
|
||||||
|
/* Need to scale offscreen image to TV output */
|
||||||
|
ioctl(console_fd, PS2IOC_SENDQCT, 1);
|
||||||
|
dma_pending = 0;
|
||||||
|
scaleimage_nonblock(console_fd, tex_tags_mem, scale_tags_mem);
|
||||||
|
} else {
|
||||||
|
dma_pending = 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* We're finished! */
|
/* We're finished! */
|
||||||
SDL_UnlockCursor();
|
SDL_UnlockCursor();
|
||||||
|
|
|
@ -67,6 +67,8 @@ struct SDL_PrivateVideoData {
|
||||||
int screen_image_size;
|
int screen_image_size;
|
||||||
unsigned long long *head_tags_mem;
|
unsigned long long *head_tags_mem;
|
||||||
unsigned long long *image_tags_mem;
|
unsigned long long *image_tags_mem;
|
||||||
|
unsigned long long *tex_tags_mem;
|
||||||
|
unsigned long long *scale_tags_mem;
|
||||||
int dma_pending;
|
int dma_pending;
|
||||||
};
|
};
|
||||||
/* Old variable names */
|
/* Old variable names */
|
||||||
|
@ -87,6 +89,11 @@ struct SDL_PrivateVideoData {
|
||||||
#define screen_image_size (this->hidden->screen_image_size)
|
#define screen_image_size (this->hidden->screen_image_size)
|
||||||
#define head_tags_mem (this->hidden->head_tags_mem)
|
#define head_tags_mem (this->hidden->head_tags_mem)
|
||||||
#define image_tags_mem (this->hidden->image_tags_mem)
|
#define image_tags_mem (this->hidden->image_tags_mem)
|
||||||
|
#define tex_tags_mem (this->hidden->tex_tags_mem)
|
||||||
|
#define scale_tags_mem (this->hidden->scale_tags_mem)
|
||||||
#define dma_pending (this->hidden->dma_pending)
|
#define dma_pending (this->hidden->dma_pending)
|
||||||
|
|
||||||
|
/* Shared between the mouse and video code for screen update scaling */
|
||||||
|
extern int scaleimage_nonblock(int fd,
|
||||||
|
unsigned long long *tm, unsigned long long *sm);
|
||||||
#endif /* _SDL_gsvideo_h */
|
#endif /* _SDL_gsvideo_h */
|
||||||
|
|
|
@ -223,7 +223,7 @@ SDL_Overlay *GS_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SD
|
||||||
fbp = screen_image.fbp;
|
fbp = screen_image.fbp;
|
||||||
fbw = screen_image.fbw;
|
fbw = screen_image.fbw;
|
||||||
psm = screen_image.psm;
|
psm = screen_image.psm;
|
||||||
y = screen_image.h; /* Offscreen video memory */
|
y = screen_image.y + screen_image.h; /* Offscreen video memory */
|
||||||
for ( h=height/16; h; --h ) {
|
for ( h=height/16; h; --h ) {
|
||||||
x = 0; /* Visible video memory */
|
x = 0; /* Visible video memory */
|
||||||
for ( w=width/16; w; --w ) {
|
for ( w=width/16; w; --w ) {
|
||||||
|
@ -273,7 +273,7 @@ SDL_Overlay *GS_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SD
|
||||||
tex_packet.len = 8 * sizeof(*tags);
|
tex_packet.len = 8 * sizeof(*tags);
|
||||||
tags[0] = 3 | (1LL << 60); /* GIFtag */
|
tags[0] = 3 | (1LL << 60); /* GIFtag */
|
||||||
tags[1] = 0x0e; /* A+D */
|
tags[1] = 0x0e; /* A+D */
|
||||||
tags[2] = (screen_image.h * screen_image.w) / 64 +
|
tags[2] = ((screen_image.y + screen_image.h) * screen_image.w) / 64 +
|
||||||
((unsigned long long)fbw << 14) +
|
((unsigned long long)fbw << 14) +
|
||||||
((unsigned long long)psm << 20) +
|
((unsigned long long)psm << 20) +
|
||||||
((unsigned long long)power_of_2(width) << 26) +
|
((unsigned long long)power_of_2(width) << 26) +
|
||||||
|
@ -437,6 +437,7 @@ int GS_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *dstrect)
|
||||||
screen->format->BytesPerPixel;
|
screen->format->BytesPerPixel;
|
||||||
y += (screen->offset / screen->pitch);
|
y += (screen->offset / screen->pitch);
|
||||||
}
|
}
|
||||||
|
y += screen_image.y;
|
||||||
*hwdata->stretch_x1y1 = (x * 16) + ((y * 16) << 16);
|
*hwdata->stretch_x1y1 = (x * 16) + ((y * 16) << 16);
|
||||||
x += (unsigned int)dstrect->w;
|
x += (unsigned int)dstrect->w;
|
||||||
y += (unsigned int)dstrect->h;
|
y += (unsigned int)dstrect->h;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue