forums.ps2dev.org Forum Index forums.ps2dev.org
Homebrew PS2, PSP & PS3 Development Discussions
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Problem Rendering large image on gu

 
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PSP Development
View previous topic :: View next topic  
Author Message
coolkehon



Joined: 20 Oct 2008
Posts: 355

PostPosted: Fri Jul 17, 2009 3:18 pm    Post subject: Problem Rendering large image on gu Reply with quote

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
Back to top
View user's profile Send private message MSN Messenger
Jim



Joined: 02 Jul 2005
Posts: 487
Location: Sydney

PostPosted: Fri Jul 17, 2009 10:38 pm    Post subject: Reply with quote

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
_________________
http://www.dbfinteractive.com
Back to top
View user's profile Send private message Visit poster's website
coolkehon



Joined: 20 Oct 2008
Posts: 355

PostPosted: Fri Jul 17, 2009 10:46 pm    Post subject: Reply with quote

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
Back to top
View user's profile Send private message MSN Messenger
rapso



Joined: 28 Mar 2005
Posts: 147

PostPosted: Sat Jul 18, 2009 12:50 am    Post subject: Reply with quote

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.
Back to top
View user's profile Send private message
J.F.



Joined: 22 Feb 2004
Posts: 2906

PostPosted: Sat Jul 18, 2009 1:05 am    Post subject: Reply with quote

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.
Back to top
View user's profile Send private message AIM Address
coolkehon



Joined: 20 Oct 2008
Posts: 355

PostPosted: Sat Jul 18, 2009 1:56 am    Post subject: Reply with quote

cool thanks could you provide an example and all i'm doing is drawing a background image
Back to top
View user's profile Send private message MSN Messenger
J.F.



Joined: 22 Feb 2004
Posts: 2906

PostPosted: Sat Jul 18, 2009 4:21 am    Post subject: Reply with quote

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.
Back to top
View user's profile Send private message AIM Address
coolkehon



Joined: 20 Oct 2008
Posts: 355

PostPosted: Sat Jul 18, 2009 6:46 am    Post subject: Reply with quote

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:
Image * ImageUtil::loadImageFilePNG(FILE * fp, PixelFormat pixelFormat , bool swizzle, bool in_vram, DrawingCanvas * canvas)
{
   if(fp == NULL || !is_png(fp))
      return NULL;
   
   Image * rimg = new Image(canvas);
   rimg->image = (Image::ImageData *) malloc(sizeof(Image::ImageData));
   if(rimg->image == NULL)
   {
      rimg->Delete();
      return NULL;
   }
   Image::ImageData * image = rimg->image;
   memset(image,0,sizeof(Image::ImageData));
   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(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL);
   if(png_ptr == NULL)
   {
      rimg->Delete();
      return NULL;
   }
   info_ptr = png_create_info_struct(png_ptr);
   if(info_ptr == NULL)
   {
      rimg->Delete();
      png_destroy_read_struct(&png_ptr, NULL, NULL);
      return NULL;
   }
   if (setjmp(png_jmpbuf(png_ptr)))
   {
      png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
      rimg->Delete();
      return NULL;
   }
   
   png_init_io(png_ptr, fp);
//   png_set_sig_bytes(png_ptr, 8);
   
   if(pixelWidths[pixelFormat] <= 8)
   {
      png_read_png(png_ptr,info_ptr,
         PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_BGR, NULL );
   }
   else
   {
      png_read_png( png_ptr, info_ptr,
         PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND | PNG_TRANSFORM_BGR, NULL );
   }
   
   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 (!info_ptr->num_palette && pixelWidths[pixelFormat] <= 8)
   {
      pixelFormat = GU_PSM_8888;
      image->width = width;
      image->height = height;
      image->pixelFormat = pixelFormat;
      image->in_vram = false;
   }
   else
   {
      image->width = width;
      image->height = height;
      image->pixelFormat = pixelFormat;
      image->in_vram = in_vram;
   }
   image->swizzled = false;
   
   if(image->width > 512)
      image->textureWidth = image->width;
   else
      image->textureWidth = getNextPower2(image->width);
   
   if(image->height > 512)
      image->textureHeight = image->height;
   else
      image->textureHeight = getNextPower2(image->height);
   
   image->size = (image->textureWidth * image->textureHeight * pixelWidths[image->pixelFormat]) >> 3;
   if(image->in_vram)
      image->data = (uint *)valloc(image->size);
   else
      image->data = (uint *)memalign(16,image->size);
   
   if(image->data == NULL)
   {
      png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
      rimg->Delete();
      return NULL;
   }
   
   if(pixelWidths[pixelFormat] <= 8)
   {
      image->palette = Image::CreatePalette(MIN(info_ptr->num_palette, 1 << paletteSizes[pixelFormat]), in_vram, GU_PSM_8888);
      if(image->palette == NULL)
      {
         png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
         rimg->Delete();
         return NULL;
      }
      info_ptr->num_palette = MIN(info_ptr->num_palette, image->palette->nentries);
      for(int i = 0; i < info_ptr->num_palette; i++)
      {
         int r = info_ptr->palette[i].red;
         int g = info_ptr->palette[i].green;
         int b = info_ptr->palette[i].blue;
         int a = 0xff;
      }
      sceKernelDcacheWritebackInvalidateRange(image->palette->data,image->palette->size);
   }
   
   u32 *p_dest4 = (u32*)image->data;
   u16 *p_dest2 = (u16*)image->data;
   u8 *p_dest1 = (u8*)image->data;
   u32 x, y;
   int color_per_entry = 8 / depth;
   int color_offset, pixel_value = 0;
   int mask = (1 << depth) - 1;
   
   for ( y = 0; y < height; ++y )
   {
      const png_byte * pRow = pRowTable[y];

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

      p_dest1 += ( image->textureWidth * pixelWidths[pixelFormat]) >> 3;
      p_dest2 += ( image->textureWidth );
      p_dest4 += ( image->textureWidth );
   }
   
   sceKernelDcacheWritebackInvalidateRange(image->data,image->size);
   rimg->setStart(Location(0,0));
   rimg->setEnd(Location(image->width,image->height));
//   TODO swizzle images and convert pixel formats
   png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
   return rimg;
}


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
Back to top
View user's profile Send private message MSN Messenger
J.F.



Joined: 22 Feb 2004
Posts: 2906

PostPosted: Sat Jul 18, 2009 8:56 am    Post subject: Reply with quote

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).
Back to top
View user's profile Send private message AIM Address
coolkehon



Joined: 20 Oct 2008
Posts: 355

PostPosted: Sat Jul 18, 2009 9:46 am    Post subject: Reply with quote

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/index.php/topic,4393.0.html

Code:
void blitAlphaImageToScreen(int sx, int sy, int width, int height, Image* source, int dx, int dy)
{
   if (!initialized) return;

   sceKernelDcacheWritebackInvalidateAll();
   guStart();
   float u = 1.0f / ((float)source->textureWidth);
   float v = 1.0f / ((float)source->textureHeight);
   sceGuTexScale(u, v);
   
   int j = 0;
   while (j < width) {
      Vertex* vertices = (Vertex*) sceGuGetMemory(2 * sizeof(Vertex));
      int sliceWidth = 64;
      if (j + sliceWidth > width) sliceWidth = width - j;
      vertices[0].u = sx + j;
      vertices[0].v = sy;
      vertices[0].x = dx + j;
      vertices[0].y = dy;
      vertices[0].z = 0;
      vertices[1].u = sx + j + sliceWidth;
      vertices[1].v = sy + height;
      vertices[1].x = dx + j + sliceWidth;
      vertices[1].y = dy + height;
      vertices[1].z = 0;
      sceGuDrawArray(GU_SPRITES, GU_TEXTURE_16BIT | GU_VERTEX_16BIT | GU_TRANSFORM_2D, 2, 0, vertices);
      j += sliceWidth;
   }
   
   sceGuFinish();
   sceGuSync(0, 0);
}
Back to top
View user's profile Send private message MSN Messenger
J.F.



Joined: 22 Feb 2004
Posts: 2906

PostPosted: Sat Jul 18, 2009 1:38 pm    Post subject: Reply with quote

Set up the proper matrices, then use sceGumDrawArray instead of sceGuDrawArray. Look at the sprites sample.
Back to top
View user's profile Send private message AIM Address
Display posts from previous:   
Post new topic   Reply to topic    forums.ps2dev.org Forum Index -> PSP Development All times are GMT + 10 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group