Problem Rendering large image on gu
Problem Rendering large image on gu
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
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.
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.
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
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
Code: Select all
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;
}
haven't tried that yet but how do i do this if the image is rotatedJ.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).
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(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);
}