# HG changeset patch # User Sam Lantinga # Date 996655305 0 # Node ID 717f739d6ec1ed651fd783cc3c64416413583018 # Parent 0bfcf0d2b87474b5573eed404b702dff69c5fd75 Added hardware stretching code to scale 640x480 to TV resolution There's a bug of some kind in the 16bpp code. ?? diff -r 0bfcf0d2b874 -r 717f739d6ec1 src/video/ps2gs/SDL_gsmouse.c --- a/src/video/ps2gs/SDL_gsmouse.c Wed Aug 01 05:01:08 2001 +0000 +++ b/src/video/ps2gs/SDL_gsmouse.c Wed Aug 01 08:41:45 2001 +0000 @@ -79,7 +79,7 @@ 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 @@ 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 */ diff -r 0bfcf0d2b874 -r 717f739d6ec1 src/video/ps2gs/SDL_gsvideo.c --- a/src/video/ps2gs/SDL_gsvideo.c Wed Aug 01 05:01:08 2001 +0000 +++ b/src/video/ps2gs/SDL_gsvideo.c Wed Aug 01 08:41:45 2001 +0000 @@ -235,6 +235,59 @@ 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<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 @@ } 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 @@ /* 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 @@ 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 @@ 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 @@ 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 @@ 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(); diff -r 0bfcf0d2b874 -r 717f739d6ec1 src/video/ps2gs/SDL_gsvideo.h --- a/src/video/ps2gs/SDL_gsvideo.h Wed Aug 01 05:01:08 2001 +0000 +++ b/src/video/ps2gs/SDL_gsvideo.h Wed Aug 01 08:41:45 2001 +0000 @@ -67,6 +67,8 @@ 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 @@ #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 */ diff -r 0bfcf0d2b874 -r 717f739d6ec1 src/video/ps2gs/SDL_gsyuv.c --- a/src/video/ps2gs/SDL_gsyuv.c Wed Aug 01 05:01:08 2001 +0000 +++ b/src/video/ps2gs/SDL_gsyuv.c Wed Aug 01 08:41:45 2001 +0000 @@ -223,7 +223,7 @@ 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 @@ 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 @@ 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;