Added hardware stretching code to scale 640x480 to TV resolution
authorSam Lantinga <slouken@libsdl.org>
Wed, 01 Aug 2001 08:41:45 +0000
changeset 136717f739d6ec1
parent 135 0bfcf0d2b874
child 137 4738ea544d7a
Added hardware stretching code to scale 640x480 to TV resolution
There's a bug of some kind in the 16bpp code. ??
src/video/ps2gs/SDL_gsmouse.c
src/video/ps2gs/SDL_gsvideo.c
src/video/ps2gs/SDL_gsvideo.h
src/video/ps2gs/SDL_gsyuv.c
     1.1 --- a/src/video/ps2gs/SDL_gsmouse.c	Wed Aug 01 05:01:08 2001 +0000
     1.2 +++ b/src/video/ps2gs/SDL_gsmouse.c	Wed Aug 01 08:41:45 2001 +0000
     1.3 @@ -79,7 +79,7 @@
     1.4  	screen->pixels = mapped_mem + screen->offset;
     1.5  	screen_updated = 0;
     1.6  	if ( cursor_drawn ) {
     1.7 -		SDL_EraseCursorNoLock(this->screen);
     1.8 +		SDL_EraseCursorNoLock(screen);
     1.9  		cursor_drawn = 0;
    1.10  		screen_updated = 1;
    1.11  	}
    1.12 @@ -114,10 +114,17 @@
    1.13  			mouse_y2 = area.y+area.h;
    1.14  		}
    1.15  		image = screen_image;
    1.16 -		image.y = screen->offset / screen->pitch + mouse_y1;
    1.17 +		image.y += screen->offset / screen->pitch + mouse_y1;
    1.18  		image.h = mouse_y2 - mouse_y1;
    1.19 -		image.ptr = mapped_mem + image.y * screen->pitch;
    1.20 +		image.ptr = mapped_mem +
    1.21 +		            (image.y - screen_image.y) * screen->pitch;
    1.22  		ioctl(console_fd, PS2IOC_LOADIMAGE, &image);
    1.23 +
    1.24 +		/* Need to scale offscreen image to TV output */
    1.25 +		if ( image.y > 0 ) {
    1.26 +			scaleimage_nonblock(console_fd,
    1.27 +			                    tex_tags_mem, scale_tags_mem);
    1.28 +		}
    1.29  	}
    1.30  
    1.31  	/* We're finished */
     2.1 --- a/src/video/ps2gs/SDL_gsvideo.c	Wed Aug 01 05:01:08 2001 +0000
     2.2 +++ b/src/video/ps2gs/SDL_gsvideo.c	Wed Aug 01 08:41:45 2001 +0000
     2.3 @@ -235,6 +235,59 @@
     2.4  	return ioctl(fd, PS2IOC_SENDL, &plist);
     2.5  }
     2.6  
     2.7 +static unsigned long long tex_tags[] __attribute__((aligned(16))) = {
     2.8 +	3 | (1LL << 60),	/* GIFtag */
     2.9 +	0x0e,			/* A+D */
    2.10 +	0,			/* 2 */
    2.11 +	PS2_GS_TEX0_1,
    2.12 +	(1 << 5) + (1 << 6),
    2.13 +	PS2_GS_TEX1_1,
    2.14 +	0,
    2.15 +	PS2_GS_TEXFLUSH
    2.16 +};
    2.17 +static unsigned long long scale_tags[] __attribute__((aligned(16))) = {
    2.18 +	5 | (1LL << 60),	/* GIFtag */
    2.19 +	0x0e,			/* A+D */
    2.20 +	6 + (1 << 4) + (1 << 8),
    2.21 +	PS2_GS_PRIM,
    2.22 +	((unsigned long long)0 * 16) + (((unsigned long long)0 * 16) << 16),
    2.23 +	PS2_GS_UV,
    2.24 +	((unsigned long long)0 * 16) + (((unsigned long long)0 * 16) << 16),
    2.25 +	PS2_GS_XYZ2,
    2.26 +	0,			/* 8 */
    2.27 +	PS2_GS_UV,
    2.28 +	0,			/* 10 */
    2.29 +	PS2_GS_XYZ2
    2.30 +};
    2.31 +
    2.32 +
    2.33 +int scaleimage_nonblock(int fd, unsigned long long *tm, unsigned long long *sm)
    2.34 +{
    2.35 +	struct ps2_plist plist;
    2.36 +	struct ps2_packet packet[2];
    2.37 +
    2.38 +	/* initialize the variables */
    2.39 +	plist.num = 2;
    2.40 +	plist.packet = packet;
    2.41 +
    2.42 +	packet[0].ptr = tm;
    2.43 +	packet[0].len = sizeof(tex_tags);
    2.44 +	packet[1].ptr = sm;
    2.45 +	packet[1].len = sizeof(scale_tags);
    2.46 +
    2.47 +	return ioctl(fd, PS2IOC_SENDL, &plist);
    2.48 +}
    2.49 +
    2.50 +static int power_of_2(int value)
    2.51 +{
    2.52 +	int shift;
    2.53 +
    2.54 +	for ( shift = 0; (1<<shift) < value; ++shift ) {
    2.55 +		/* Keep looking */ ;
    2.56 +	}
    2.57 +	return(shift);
    2.58 +}
    2.59 +
    2.60  static int GS_VideoInit(_THIS, SDL_PixelFormat *vformat)
    2.61  {
    2.62  	struct ps2_screeninfo vinfo;
    2.63 @@ -261,13 +314,6 @@
    2.64  		SDL_SetError("Couldn't get console pixel format");
    2.65  		return(-1);
    2.66  	}
    2.67 -#if 0
    2.68 -	if ( vinfo.mode != PS2_GS_VESA ) {
    2.69 -		GS_VideoQuit(this);
    2.70 -		SDL_SetError("Console must be in VESA video mode");
    2.71 -		return(-1);
    2.72 -	}
    2.73 -#endif
    2.74  	switch (vinfo.psm) {
    2.75  	    /* Supported pixel formats */
    2.76  	    case PS2_GS_PSMCT32:
    2.77 @@ -308,11 +354,6 @@
    2.78  
    2.79  static SDL_Rect **GS_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
    2.80  {
    2.81 -	static SDL_Rect GS_tvout_mode;
    2.82 -	static SDL_Rect *GS_tvout_modes[] = {
    2.83 -		&GS_tvout_mode,
    2.84 -		NULL
    2.85 -	};
    2.86  	static SDL_Rect GS_vesa_mode_list[] = {
    2.87  		{ 0, 0, 1280, 1024 },
    2.88  		{ 0, 0, 1024, 768 },
    2.89 @@ -326,24 +367,44 @@
    2.90  		&GS_vesa_mode_list[3],
    2.91  		NULL
    2.92  	};
    2.93 +	static SDL_Rect GS_tvout_stretch;
    2.94 +	static SDL_Rect GS_tvout_mode;
    2.95 +	static SDL_Rect *GS_tvout_modes[3];
    2.96  	SDL_Rect **modes = NULL;
    2.97  
    2.98 -	if ( saved_vinfo.mode == PS2_GS_VESA ) {
    2.99 -		switch (format->BitsPerPixel) {
   2.100 -		    case 16:
   2.101 -		    case 24:
   2.102 -		    case 32:
   2.103 +	switch (format->BitsPerPixel) {
   2.104 +	    case 16:
   2.105 +	    case 24:
   2.106 +	    case 32:
   2.107 +		if ( saved_vinfo.mode == PS2_GS_VESA ) {
   2.108  			modes = GS_vesa_modes;
   2.109 -			break;
   2.110 -		    default:
   2.111 -			break;
   2.112 -		}
   2.113 -	} else {
   2.114 -		if ( GS_formatmap[format->BitsPerPixel/8] == saved_vinfo.psm ) {
   2.115 +		} else {
   2.116 +			int i, j = 0;
   2.117 +
   2.118 +// FIXME - what's wrong with the stretch code at 16 bpp?
   2.119 +if ( format->BitsPerPixel != 32 ) break;
   2.120 +			/* Add a mode that we could possibly stretch to */
   2.121 +			for ( i=0; GS_vesa_modes[i]; ++i ) {
   2.122 +				if ( (GS_vesa_modes[i]->w == saved_vinfo.w) &&
   2.123 +				     (GS_vesa_modes[i]->h != saved_vinfo.h) ) {
   2.124 +					GS_tvout_stretch.w=GS_vesa_modes[i]->w;
   2.125 +					GS_tvout_stretch.h=GS_vesa_modes[i]->h;
   2.126 +					GS_tvout_modes[j++] = &GS_tvout_stretch;
   2.127 +					break;
   2.128 +				}
   2.129 +			}
   2.130 +			/* Add the current TV video mode */
   2.131  			GS_tvout_mode.w = saved_vinfo.w;
   2.132  			GS_tvout_mode.h = saved_vinfo.h;
   2.133 +			GS_tvout_modes[j++] = &GS_tvout_mode;
   2.134 +			GS_tvout_modes[j++] = NULL;
   2.135 +
   2.136 +			/* Return the created list of modes */
   2.137  			modes = GS_tvout_modes;
   2.138  		}
   2.139 +		break;
   2.140 +	    default:
   2.141 +		break;
   2.142  	}
   2.143  	return(modes);
   2.144  }
   2.145 @@ -368,27 +429,30 @@
   2.146  	}
   2.147  	if ( (vinfo.w != width) || (vinfo.h != height) ||
   2.148  	     (GS_pixelmasks[vinfo.psm].bpp != bpp) ) {
   2.149 -		switch (width) {
   2.150 -		    case 640:
   2.151 -			vinfo.res = PS2_GS_640x480;
   2.152 -			break;
   2.153 -		    case 800:
   2.154 -			vinfo.res = PS2_GS_800x600;
   2.155 -			break;
   2.156 -		    case 1024:
   2.157 -			vinfo.res = PS2_GS_1024x768;
   2.158 -			break;
   2.159 -		    case 1280:
   2.160 -			vinfo.res = PS2_GS_1280x1024;
   2.161 -			break;
   2.162 -		    default:
   2.163 -			SDL_SetError("Unsupported resolution: %dx%d\n",
   2.164 -			             width, height);
   2.165 -			return(NULL);
   2.166 +		/* If we're not in VESA mode, we have to scale resolution */
   2.167 +		if ( saved_vinfo.mode == PS2_GS_VESA ) {
   2.168 +			switch (width) {
   2.169 +			    case 640:
   2.170 +				vinfo.res = PS2_GS_640x480;
   2.171 +				break;
   2.172 +			    case 800:
   2.173 +				vinfo.res = PS2_GS_800x600;
   2.174 +				break;
   2.175 +			    case 1024:
   2.176 +				vinfo.res = PS2_GS_1024x768;
   2.177 +				break;
   2.178 +			    case 1280:
   2.179 +				vinfo.res = PS2_GS_1280x1024;
   2.180 +				break;
   2.181 +			    default:
   2.182 +				SDL_SetError("Unsupported resolution: %dx%d\n",
   2.183 +					     width, height);
   2.184 +				return(NULL);
   2.185 +			}
   2.186 +			vinfo.res |= (PS2_GS_75Hz << 8);
   2.187 +			vinfo.w = width;
   2.188 +			vinfo.h = height;
   2.189  		}
   2.190 -		vinfo.res |= (PS2_GS_75Hz << 8);
   2.191 -		vinfo.w = width;
   2.192 -		vinfo.h = height;
   2.193  		vinfo.fbp = 0;
   2.194  		vinfo.psm = GS_formatmap[bpp/8];
   2.195  		if ( vinfo.psm < 0 ) {
   2.196 @@ -415,8 +479,8 @@
   2.197  
   2.198  	/* Set up the new mode framebuffer */
   2.199  	current->flags = SDL_FULLSCREEN;
   2.200 -	current->w = vinfo.w;
   2.201 -	current->h = vinfo.h;
   2.202 +	current->w = width;
   2.203 +	current->h = height;
   2.204  	current->pitch = SDL_CalculatePitch(current);
   2.205  
   2.206  	/* Memory map the DMA area for block memory transfer */
   2.207 @@ -425,6 +489,9 @@
   2.208  		mapped_len = pixels_len +
   2.209  		             /* Screen update DMA command area */
   2.210  		             sizeof(head_tags) + ((2 * MAXTAGS) * 16);
   2.211 +		if ( saved_vinfo.mode != PS2_GS_VESA ) {
   2.212 +			mapped_len += sizeof(tex_tags) + sizeof(scale_tags);
   2.213 +		}
   2.214  		mapped_mem = mmap(0, mapped_len, PROT_READ|PROT_WRITE,
   2.215  		                  MAP_SHARED, memory_fd, 0);
   2.216  		if ( mapped_mem == MAP_FAILED ) {
   2.217 @@ -440,12 +507,17 @@
   2.218  		screen_image.fbw = (vinfo.w + 63) / 64;
   2.219  		screen_image.psm = vinfo.psm;
   2.220  		screen_image.x = 0;
   2.221 -		screen_image.y = 0;
   2.222 -		screen_image.w = vinfo.w;
   2.223 -		screen_image.h = vinfo.h;
   2.224 +		if ( vinfo.h == height ) {
   2.225 +			screen_image.y = 0;
   2.226 +		} else {
   2.227 +			/* Put image offscreen and scale to screen height */
   2.228 +			screen_image.y = vinfo.h;
   2.229 +		}
   2.230 +		screen_image.w = current->w;
   2.231 +		screen_image.h = current->h;
   2.232  
   2.233  		/* get screen image data size (qword aligned) */
   2.234 -		screen_image_size = (vinfo.w * vinfo.h);
   2.235 +		screen_image_size = (screen_image.w * screen_image.h);
   2.236  		switch (screen_image.psm) {
   2.237  		    case PS2_GS_PSMCT32:
   2.238  			screen_image_size *= 4;
   2.239 @@ -465,6 +537,28 @@
   2.240  		image_tags_mem = (unsigned long long *)
   2.241  		                 ((caddr_t)head_tags_mem + sizeof(head_tags));
   2.242  		memcpy(head_tags_mem, head_tags, sizeof(head_tags));
   2.243 +		if ( saved_vinfo.mode != PS2_GS_VESA ) {
   2.244 +			tex_tags_mem = (unsigned long long *)
   2.245 +		                 ((caddr_t)image_tags_mem + ((2*MAXTAGS)*16));
   2.246 +			scale_tags_mem = (unsigned long long *)
   2.247 +		                 ((caddr_t)tex_tags_mem + sizeof(tex_tags));
   2.248 +			memcpy(tex_tags_mem, tex_tags, sizeof(tex_tags));
   2.249 +			tex_tags_mem[2] = 
   2.250 +				(vinfo.h * vinfo.w) / 64 +
   2.251 +	          		((unsigned long long)screen_image.fbw << 14) +
   2.252 +	          		((unsigned long long)screen_image.psm << 20) +
   2.253 +	          		((unsigned long long)power_of_2(screen_image.w) << 26) +
   2.254 +	          		((unsigned long long)power_of_2(screen_image.h) << 30) +
   2.255 +	          		((unsigned long long)1 << 34) +
   2.256 +	          		((unsigned long long)1 << 35);
   2.257 +			memcpy(scale_tags_mem, scale_tags, sizeof(scale_tags));
   2.258 +			scale_tags_mem[8] =
   2.259 +				((unsigned long long)screen_image.w * 16) +
   2.260 +			         (((unsigned long long)screen_image.h * 16) << 16);
   2.261 +			scale_tags_mem[10] =
   2.262 +				((unsigned long long)vinfo.w * 16) +
   2.263 +			         (((unsigned long long)vinfo.h * 16) << 16);
   2.264 +		}
   2.265  	}
   2.266  	current->pixels = NULL;
   2.267  	if ( getenv("SDL_FULLSCREEN_UPDATE") ) {
   2.268 @@ -554,7 +648,14 @@
   2.269  	loadimage_nonblock(console_fd,
   2.270  	                   &screen_image, screen_image_size,
   2.271  	                   head_tags_mem, image_tags_mem);
   2.272 -	dma_pending = 1;
   2.273 +	if ( screen_image.y > 0 ) {
   2.274 +		/* Need to scale offscreen image to TV output */
   2.275 +		ioctl(console_fd, PS2IOC_SENDQCT, 1);
   2.276 +		dma_pending = 0;
   2.277 +		scaleimage_nonblock(console_fd, tex_tags_mem, scale_tags_mem);
   2.278 +	} else {
   2.279 +		dma_pending = 1;
   2.280 +	}
   2.281  
   2.282  	/* We're finished! */
   2.283  	SDL_UnlockCursor();
     3.1 --- a/src/video/ps2gs/SDL_gsvideo.h	Wed Aug 01 05:01:08 2001 +0000
     3.2 +++ b/src/video/ps2gs/SDL_gsvideo.h	Wed Aug 01 08:41:45 2001 +0000
     3.3 @@ -67,6 +67,8 @@
     3.4  	int screen_image_size;
     3.5  	unsigned long long *head_tags_mem;
     3.6  	unsigned long long *image_tags_mem;
     3.7 +	unsigned long long *tex_tags_mem;
     3.8 +	unsigned long long *scale_tags_mem;
     3.9  	int dma_pending;
    3.10  };
    3.11  /* Old variable names */
    3.12 @@ -87,6 +89,11 @@
    3.13  #define screen_image_size	(this->hidden->screen_image_size)
    3.14  #define head_tags_mem		(this->hidden->head_tags_mem)
    3.15  #define image_tags_mem		(this->hidden->image_tags_mem)
    3.16 +#define tex_tags_mem		(this->hidden->tex_tags_mem)
    3.17 +#define scale_tags_mem		(this->hidden->scale_tags_mem)
    3.18  #define dma_pending		(this->hidden->dma_pending)
    3.19  
    3.20 +/* Shared between the mouse and video code for screen update scaling */
    3.21 +extern int scaleimage_nonblock(int fd,
    3.22 +                               unsigned long long *tm, unsigned long long *sm);
    3.23  #endif /* _SDL_gsvideo_h */
     4.1 --- a/src/video/ps2gs/SDL_gsyuv.c	Wed Aug 01 05:01:08 2001 +0000
     4.2 +++ b/src/video/ps2gs/SDL_gsyuv.c	Wed Aug 01 08:41:45 2001 +0000
     4.3 @@ -223,7 +223,7 @@
     4.4  	fbp = screen_image.fbp;
     4.5  	fbw = screen_image.fbw;
     4.6  	psm = screen_image.psm;
     4.7 -	y = screen_image.h;	/* Offscreen video memory */
     4.8 +	y = screen_image.y + screen_image.h;	/* Offscreen video memory */
     4.9  	for ( h=height/16; h; --h ) {
    4.10  		x = 0;			/* Visible video memory */
    4.11  		for ( w=width/16; w; --w ) {
    4.12 @@ -273,7 +273,7 @@
    4.13  	tex_packet.len = 8 * sizeof(*tags);
    4.14  	tags[0] = 3 | (1LL << 60);	/* GIFtag */
    4.15  	tags[1] = 0x0e;			/* A+D */
    4.16 -	tags[2] = (screen_image.h * screen_image.w) / 64 +
    4.17 +	tags[2] = ((screen_image.y + screen_image.h) * screen_image.w) / 64 +
    4.18  	          ((unsigned long long)fbw << 14) +
    4.19  	          ((unsigned long long)psm << 20) +
    4.20  	          ((unsigned long long)power_of_2(width) << 26) +
    4.21 @@ -437,6 +437,7 @@
    4.22  		     screen->format->BytesPerPixel;
    4.23  		y += (screen->offset / screen->pitch);
    4.24  	}
    4.25 +	y += screen_image.y;
    4.26  	*hwdata->stretch_x1y1 = (x * 16) + ((y * 16) << 16);
    4.27  	x += (unsigned int)dstrect->w;
    4.28  	y += (unsigned int)dstrect->h;