Problem Rendering large image on gu

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

Post Reply
coolkehon
Posts: 355
Joined: Mon Oct 20, 2008 5:44 am

Problem Rendering large image on gu

Post by coolkehon »

it renders images that are of smaller sizes but when i try to render a background image that is 480x272 they image becomes smaller and the framerate slows to about 18 frames per second does anyone have any idea why and how to solve this
User avatar
Jim
Posts: 476
Joined: Sat Jul 02, 2005 10:06 pm
Location: Sydney
Contact:

Post by Jim »

Use swizzled textures, use lower bit-depth textures or palettised textures, don't clear the screen if you're rendering all of it, disable alpha.

Jim
coolkehon
Posts: 355
Joined: Mon Oct 20, 2008 5:44 am

Post by coolkehon »

i think i problem is because of the psp texture width limits is there a workaround for this and if so can someone explain it because i'm new to the gu
rapso
Posts: 140
Joined: Mon Mar 28, 2005 6:35 am

Post by rapso »

maybe it's downscaled to a power of two texture, scale it up to 512x512 (or add border), that might work, and yeah, follow the jim's tips for performance.
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

You'll see in many examples and apps that wide textures are drawn in "slices". The reason is the PSP uses a texture cache that can only hold so much data - if you go too wide on the texture, the cache is reloaded (maybe more than once) on every single line drawn. If you cut a wide texture into vertical pieces that are narrow enough to fit in the cache, it will draw many lines before needing to reload the texture cache. Swizzling the texture also helps because otherwise the PSP will swizzle the texture during load, slowing the loading. Note that compressed textures cannot be swizzled.

Alpha computation also takes time, so if you know you don't need it, don't enable it. A good example is drawing the initial background that fills the screen completely.
coolkehon
Posts: 355
Joined: Mon Oct 20, 2008 5:44 am

Post by coolkehon »

cool thanks could you provide an example and all i'm doing is drawing a background image
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

Look at the ubiquitous graphics.c. Look at any program that draws using the GU. Look at nearly every gu sample in the sdk. The samples are there for a reason.
coolkehon
Posts: 355
Joined: Mon Oct 20, 2008 5:44 am

Post by coolkehon »

yeah i looked at the sdk gu stuff and it doesn't have a sample showing any of this stuff that i'm looking for like spliting the texture and drawing parts of it and i looked at the graphics.c and it just wont load the image if it is < 512 and it seems that this background image is exactly 512x512 but its not greater so why is the gu messing this up here is the load function

Code: Select all

Image * ImageUtil&#58;&#58;loadImageFilePNG&#40;FILE * fp, PixelFormat pixelFormat , bool swizzle, bool in_vram, DrawingCanvas * canvas&#41;
&#123;
	if&#40;fp == NULL || !is_png&#40;fp&#41;&#41; 
		return NULL;
	
	Image * rimg = new Image&#40;canvas&#41;;
	rimg->image = &#40;Image&#58;&#58;ImageData *&#41; malloc&#40;sizeof&#40;Image&#58;&#58;ImageData&#41;&#41;;
	if&#40;rimg->image == NULL&#41;
	&#123;
		rimg->Delete&#40;&#41;;
		return NULL;
	&#125;
	Image&#58;&#58;ImageData * image = rimg->image;
	memset&#40;image,0,sizeof&#40;Image&#58;&#58;ImageData&#41;&#41;;
	image->pixelFormat = pixelFormat;
	image->in_vram = in_vram;
	
	png_structp png_ptr;
	png_infop info_ptr;
//	png_uint_32 width, height;
//	int bit_depth, color_type, interlace_type;
	
	png_ptr = png_create_read_struct&#40;PNG_LIBPNG_VER_STRING,NULL,NULL,NULL&#41;;
	if&#40;png_ptr == NULL&#41;
	&#123;
		rimg->Delete&#40;&#41;;
		return NULL;
	&#125;
	info_ptr = png_create_info_struct&#40;png_ptr&#41;;
	if&#40;info_ptr == NULL&#41;
	&#123;
		rimg->Delete&#40;&#41;;
		png_destroy_read_struct&#40;&png_ptr, NULL, NULL&#41;;
		return NULL;
	&#125;
	if &#40;setjmp&#40;png_jmpbuf&#40;png_ptr&#41;&#41;&#41;
	&#123;
		png_destroy_read_struct&#40;&png_ptr, &info_ptr, NULL&#41;;
		rimg->Delete&#40;&#41;;
		return NULL;
	&#125;
	
	png_init_io&#40;png_ptr, fp&#41;;
//	png_set_sig_bytes&#40;png_ptr, 8&#41;;
	
	if&#40;pixelWidths&#91;pixelFormat&#93; <= 8&#41;
	&#123;
		png_read_png&#40;png_ptr,info_ptr,
			PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_BGR, NULL &#41;;
	&#125;
	else
	&#123;
		png_read_png&#40; png_ptr, info_ptr, 
			PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_BGR, NULL &#41;;
	&#125;
	
	png_uint_32 width = info_ptr->width;
	png_uint_32 height = info_ptr->height;
	png_uint_32 depth = info_ptr->bit_depth;
	int color_type = info_ptr->color_type;
	
	png_byte **pRowTable = info_ptr->row_pointers;
	unsigned char r=0, g=0, b=0, a=0;
	int wantedPixelFormat = pixelFormat;
	if &#40;!info_ptr->num_palette && pixelWidths&#91;pixelFormat&#93; <= 8&#41;
	&#123;
		pixelFormat = GU_PSM_8888;
		image->width = width;
		image->height = height;
		image->pixelFormat = pixelFormat;
		image->in_vram = false;
	&#125;
	else
	&#123;
		image->width = width;
		image->height = height;
		image->pixelFormat = pixelFormat;
		image->in_vram = in_vram;
	&#125;
	image->swizzled = false;
	
	if&#40;image->width > 512&#41;
		image->textureWidth = image->width;
	else
		image->textureWidth = getNextPower2&#40;image->width&#41;;
	
	if&#40;image->height > 512&#41;
		image->textureHeight = image->height;
	else
		image->textureHeight = getNextPower2&#40;image->height&#41;;
	
	image->size = &#40;image->textureWidth * image->textureHeight * pixelWidths&#91;image->pixelFormat&#93;&#41; >> 3;
	if&#40;image->in_vram&#41;
		image->data = &#40;uint *&#41;valloc&#40;image->size&#41;;
	else
		image->data = &#40;uint *&#41;memalign&#40;16,image->size&#41;;
	
	if&#40;image->data == NULL&#41;
	&#123;
		png_destroy_read_struct&#40;&png_ptr, &info_ptr, NULL&#41;;
		rimg->Delete&#40;&#41;;
		return NULL;
	&#125;
	
	if&#40;pixelWidths&#91;pixelFormat&#93; <= 8&#41;
	&#123;
		image->palette = Image&#58;&#58;CreatePalette&#40;MIN&#40;info_ptr->num_palette, 1 << paletteSizes&#91;pixelFormat&#93;&#41;, in_vram, GU_PSM_8888&#41;;
		if&#40;image->palette == NULL&#41;
		&#123;
			png_destroy_read_struct&#40;&png_ptr, &info_ptr, NULL&#41;;
			rimg->Delete&#40;&#41;;
			return NULL;
		&#125;
		info_ptr->num_palette = MIN&#40;info_ptr->num_palette, image->palette->nentries&#41;;
		for&#40;int i = 0; i < info_ptr->num_palette; i++&#41;
		&#123;
			int r = info_ptr->palette&#91;i&#93;.red;
			int g = info_ptr->palette&#91;i&#93;.green;
			int b = info_ptr->palette&#91;i&#93;.blue;
			int a = 0xff;
		&#125;
		sceKernelDcacheWritebackInvalidateRange&#40;image->palette->data,image->palette->size&#41;;
	&#125;
	
	u32 *p_dest4 = &#40;u32*&#41;image->data;
	u16 *p_dest2 = &#40;u16*&#41;image->data;
	u8 *p_dest1 = &#40;u8*&#41;image->data;
	u32 x, y;
	int color_per_entry = 8 / depth;
	int color_offset, pixel_value = 0;
	int mask = &#40;1 << depth&#41; - 1;
	
	for &#40; y = 0; y < height; ++y &#41;
	&#123;
		const png_byte * pRow = pRowTable&#91;y&#93;;

		for &#40; x = 0; x < width; ++x &#41;
		&#123;
			switch &#40; color_type &#41;
			&#123;
				case PNG_COLOR_TYPE_GRAY&#58;
					r = g = b = *pRow++;
					if &#40; r == 0 && g == 0 && b == 0 &#41;
						a = 0x00;
					else
						a = 0xff;
					break;
				case PNG_COLOR_TYPE_GRAY_ALPHA&#58;
					r = g = b = *pRow++;
					if &#40; r == 0 && g == 0 && b == 0 &#41;
						a = 0x00;
					else
						a = 0xff;
					pRow++;
					break;
				case PNG_COLOR_TYPE_RGB&#58;
					b = *pRow++;
					g = *pRow++;
					r = *pRow++;
					a = 0xff;
					break;
				case PNG_COLOR_TYPE_RGB_ALPHA&#58;
					b = *pRow++;
					g = *pRow++;
					r = *pRow++;
					a = *pRow++;
					break;
			
				case PNG_COLOR_TYPE_PALETTE&#58;
					color_offset = x % color_per_entry;
					pixel_value = &#40;*pRow >> &#40;8 - depth * &#40;color_offset + 1&#41;&#41;&#41; & mask;
					
					if &#40;x % color_per_entry == color_per_entry - 1&#41;
						pRow++;
					if &#40;image->palette&#41;
					&#123;
						r = &#40;&#40;&#40;u32*&#41;image->palette->data&#41;&#91;pixel_value&#93;&#41; & 0xff;
						g = &#40;&#40;&#40;&#40;u32*&#41;image->palette->data&#41;&#91;pixel_value&#93;&#41; >> 8&#41; & 0xff;
						b = &#40;&#40;&#40;&#40;u32*&#41;image->palette->data&#41;&#91;pixel_value&#93;&#41; >> 16&#41; & 0xff;
						a = &#40;&#40;&#40;&#40;u32*&#41;image->palette->data&#41;&#91;pixel_value&#93;&#41; >> 24&#41; & 0xff;
					&#125;
					else	
					&#123;
						b = info_ptr->palette&#91;pixel_value&#93;.blue;
						g = info_ptr->palette&#91;pixel_value&#93;.green;
						r = info_ptr->palette&#91;pixel_value&#93;.red;
						a = 0xff;
					&#125;
					break;
			&#125;
			if &#40;pixelFormat == GU_PSM_8888&#41;
				p_dest4&#91;x&#93; = RGBA&#40;r,g,b,a&#41;;
			else if &#40;pixelFormat == GU_PSM_5650&#41;
				p_dest2&#91;x&#93; = RGB16&#40;r,g,b&#41;;
			else if &#40;pixelFormat == GU_PSM_5551&#41;
				p_dest2&#91;x&#93; = RGBA15&#40;r,g,b,a&#41;;
			else if &#40;pixelFormat == GU_PSM_4444&#41;
				p_dest2&#91;x&#93; = RGBA12&#40;r,g,b,a&#41;;
			else if &#40;pixelFormat == GU_PSM_T8&#41;
				p_dest1&#91;x&#93; = pixel_value;
			else if &#40;pixelFormat == GU_PSM_T4&#41;				
			&#123;
				p_dest1&#91;x >> 1&#93; &= ~&#40;15 << &#40;&#40;x & 1&#41; << 2&#41;&#41;;
				p_dest1&#91;x >> 1&#93; |= &#40;pixel_value & 15&#41; << &#40;&#40;x & 1&#41; << 2&#41;;
			&#125;
		&#125;

		p_dest1 += &#40; image->textureWidth * pixelWidths&#91;pixelFormat&#93;&#41; >> 3;
		p_dest2 += &#40; image->textureWidth &#41;;
		p_dest4 += &#40; image->textureWidth &#41;;
	&#125;
	
	sceKernelDcacheWritebackInvalidateRange&#40;image->data,image->size&#41;;
	rimg->setStart&#40;Location&#40;0,0&#41;&#41;;
	rimg->setEnd&#40;Location&#40;image->width,image->height&#41;&#41;;
//	TODO swizzle images and convert pixel formats
	png_destroy_read_struct&#40;&png_ptr, &info_ptr, NULL&#41;;
	return rimg;
&#125;
as you can see i copied this from oslib/oslibmod and modified it a little well a lot because i would basically be doing the same thing and i used it to learn about how to do it smaller images less than 512 are ok but this isnt so why is that
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

The blit gu sample does slices. Slices are for two reasons: speed (makes better use of the texture cache), and size (anything bigger than 512 can't be done in one operation regardless of speed).
coolkehon
Posts: 355
Joined: Mon Oct 20, 2008 5:44 am

Post by coolkehon »

J.F. wrote:The blit gu sample does slices. Slices are for two reasons: speed (makes better use of the texture cache), and size (anything bigger than 512 can't be done in one operation regardless of speed).
haven't tried that yet but how do i do this if the image is rotated

and thanks i because it looks like it will work but i used this from psp-programming because it was less complex

http://www.psp-programming.com/forums/i ... 393.0.html

Code: Select all

void blitAlphaImageToScreen&#40;int sx, int sy, int width, int height, Image* source, int dx, int dy&#41;
&#123;
   if &#40;!initialized&#41; return;

   sceKernelDcacheWritebackInvalidateAll&#40;&#41;;
   guStart&#40;&#41;;
   float u = 1.0f / &#40;&#40;float&#41;source->textureWidth&#41;;
   float v = 1.0f / &#40;&#40;float&#41;source->textureHeight&#41;;
   sceGuTexScale&#40;u, v&#41;;
   
   int j = 0;
   while &#40;j < width&#41; &#123;
      Vertex* vertices = &#40;Vertex*&#41; sceGuGetMemory&#40;2 * sizeof&#40;Vertex&#41;&#41;;
      int sliceWidth = 64;
      if &#40;j + sliceWidth > width&#41; sliceWidth = width - j;
      vertices&#91;0&#93;.u = sx + j;
      vertices&#91;0&#93;.v = sy;
      vertices&#91;0&#93;.x = dx + j;
      vertices&#91;0&#93;.y = dy;
      vertices&#91;0&#93;.z = 0;
      vertices&#91;1&#93;.u = sx + j + sliceWidth;
      vertices&#91;1&#93;.v = sy + height;
      vertices&#91;1&#93;.x = dx + j + sliceWidth;
      vertices&#91;1&#93;.y = dy + height;
      vertices&#91;1&#93;.z = 0;
      sceGuDrawArray&#40;GU_SPRITES, GU_TEXTURE_16BIT | GU_VERTEX_16BIT | GU_TRANSFORM_2D, 2, 0, vertices&#41;;
      j += sliceWidth;
   &#125;
   
   sceGuFinish&#40;&#41;;
   sceGuSync&#40;0, 0&#41;;
&#125;
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

Set up the proper matrices, then use sceGumDrawArray instead of sceGuDrawArray. Look at the sprites sample.
Post Reply