Skip to content
Permalink
Browse files
Added hardware stretching code to scale 640x480 to TV resolution
There's a bug of some kind in the 16bpp code. ??
  • Loading branch information
slouken committed Aug 1, 2001
1 parent 961284e commit 38b893d6171fa839e4f54cb0175777b8f788ae3a
Showing with 171 additions and 55 deletions.
  1. +10 −3 src/video/ps2gs/SDL_gsmouse.c
  2. +151 −50 src/video/ps2gs/SDL_gsvideo.c
  3. +7 −0 src/video/ps2gs/SDL_gsvideo.h
  4. +3 −2 src/video/ps2gs/SDL_gsyuv.c
@@ -79,7 +79,7 @@ static void GS_MoveCursor(_THIS, SDL_Cursor *cursor, int x, int y)
screen->pixels = mapped_mem + screen->offset;
screen_updated = 0;
if ( cursor_drawn ) {
SDL_EraseCursorNoLock(this->screen);
SDL_EraseCursorNoLock(screen);
cursor_drawn = 0;
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;
}
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.ptr = mapped_mem + image.y * screen->pitch;
image.ptr = mapped_mem +
(image.y - screen_image.y) * screen->pitch;
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 */
@@ -235,6 +235,59 @@ static inline int loadimage_nonblock(int fd, struct ps2_image *image, int size,
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)
{
struct ps2_screeninfo vinfo;
@@ -261,13 +314,6 @@ static int GS_VideoInit(_THIS, SDL_PixelFormat *vformat)
SDL_SetError("Couldn't get console pixel format");
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) {
/* Supported pixel formats */
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_tvout_mode;
static SDL_Rect *GS_tvout_modes[] = {
&GS_tvout_mode,
NULL
};
static SDL_Rect GS_vesa_mode_list[] = {
{ 0, 0, 1280, 1024 },
{ 0, 0, 1024, 768 },
@@ -326,24 +367,44 @@ static SDL_Rect **GS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
&GS_vesa_mode_list[3],
NULL
};
static SDL_Rect GS_tvout_stretch;
static SDL_Rect GS_tvout_mode;
static SDL_Rect *GS_tvout_modes[3];
SDL_Rect **modes = NULL;

if ( saved_vinfo.mode == PS2_GS_VESA ) {
switch (format->BitsPerPixel) {
case 16:
case 24:
case 32:
switch (format->BitsPerPixel) {
case 16:
case 24:
case 32:
if ( saved_vinfo.mode == PS2_GS_VESA ) {
modes = GS_vesa_modes;
break;
default:
break;
}
} else {
if ( GS_formatmap[format->BitsPerPixel/8] == saved_vinfo.psm ) {
} else {
int i, j = 0;

// FIXME - what's wrong with the stretch code at 16 bpp?
if ( format->BitsPerPixel != 32 ) break;
/* 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.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;
}
break;
default:
break;
}
return(modes);
}
@@ -368,27 +429,30 @@ static SDL_Surface *GS_SetVideoMode(_THIS, SDL_Surface *current,
}
if ( (vinfo.w != width) || (vinfo.h != height) ||
(GS_pixelmasks[vinfo.psm].bpp != bpp) ) {
switch (width) {
case 640:
vinfo.res = PS2_GS_640x480;
break;
case 800:
vinfo.res = PS2_GS_800x600;
break;
case 1024:
vinfo.res = PS2_GS_1024x768;
break;
case 1280:
vinfo.res = PS2_GS_1280x1024;
break;
default:
SDL_SetError("Unsupported resolution: %dx%d\n",
width, height);
return(NULL);
/* If we're not in VESA mode, we have to scale resolution */
if ( saved_vinfo.mode == PS2_GS_VESA ) {
switch (width) {
case 640:
vinfo.res = PS2_GS_640x480;
break;
case 800:
vinfo.res = PS2_GS_800x600;
break;
case 1024:
vinfo.res = PS2_GS_1024x768;
break;
case 1280:
vinfo.res = PS2_GS_1280x1024;
break;
default:
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.psm = GS_formatmap[bpp/8];
if ( vinfo.psm < 0 ) {
@@ -415,8 +479,8 @@ static SDL_Surface *GS_SetVideoMode(_THIS, SDL_Surface *current,

/* Set up the new mode framebuffer */
current->flags = SDL_FULLSCREEN;
current->w = vinfo.w;
current->h = vinfo.h;
current->w = width;
current->h = height;
current->pitch = SDL_CalculatePitch(current);

/* 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 +
/* Screen update DMA command area */
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,
MAP_SHARED, memory_fd, 0);
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.psm = vinfo.psm;
screen_image.x = 0;
screen_image.y = 0;
screen_image.w = vinfo.w;
screen_image.h = vinfo.h;
if ( vinfo.h == height ) {
screen_image.y = 0;
} 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) */
screen_image_size = (vinfo.w * vinfo.h);
screen_image_size = (screen_image.w * screen_image.h);
switch (screen_image.psm) {
case PS2_GS_PSMCT32:
screen_image_size *= 4;
@@ -465,6 +537,28 @@ static SDL_Surface *GS_SetVideoMode(_THIS, SDL_Surface *current,
image_tags_mem = (unsigned long long *)
((caddr_t)head_tags_mem + 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;
if ( getenv("SDL_FULLSCREEN_UPDATE") ) {
@@ -554,7 +648,14 @@ static void GS_DMAFullUpdate(_THIS, int numrects, SDL_Rect *rects)
loadimage_nonblock(console_fd,
&screen_image, screen_image_size,
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! */
SDL_UnlockCursor();
@@ -67,6 +67,8 @@ struct SDL_PrivateVideoData {
int screen_image_size;
unsigned long long *head_tags_mem;
unsigned long long *image_tags_mem;
unsigned long long *tex_tags_mem;
unsigned long long *scale_tags_mem;
int dma_pending;
};
/* Old variable names */
@@ -87,6 +89,11 @@ struct SDL_PrivateVideoData {
#define screen_image_size (this->hidden->screen_image_size)
#define head_tags_mem (this->hidden->head_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)

/* 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 */
@@ -223,7 +223,7 @@ SDL_Overlay *GS_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SD
fbp = screen_image.fbp;
fbw = screen_image.fbw;
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 ) {
x = 0; /* Visible video memory */
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);
tags[0] = 3 | (1LL << 60); /* GIFtag */
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)psm << 20) +
((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;
y += (screen->offset / screen->pitch);
}
y += screen_image.y;
*hwdata->stretch_x1y1 = (x * 16) + ((y * 16) << 16);
x += (unsigned int)dstrect->w;
y += (unsigned int)dstrect->h;

0 comments on commit 38b893d

Please sign in to comment.