Skip to content

Commit

Permalink
Refactor and Improve Swizzling Functions in OSLib
Browse files Browse the repository at this point in the history
- Enhanced `oslSwizzleTexture` function with improved readability, loop structure, and consistency in variable usage.
- Added safety check for memory allocation failure in `oslSwizzleImage` function to handle errors gracefully.
- Improved documentation and added comments for better understanding of swizzling logic.
- Standardized pixel width calculations across functions for consistency.
- Cleaned up redundant code and made minor optimizations in the swizzling process.
  • Loading branch information
dogo committed Sep 1, 2024
1 parent 140850d commit cf529e1
Showing 1 changed file with 80 additions and 80 deletions.
160 changes: 80 additions & 80 deletions src/image/oslSwizzleImage.c
Original file line number Diff line number Diff line change
@@ -1,98 +1,98 @@
#include "oslib.h"

void oslSwizzleTexture(u8* out, const u8* in, unsigned int width, unsigned int height)
{
unsigned int blockx, blocky;
unsigned int j;

unsigned int width_blocks = (width / 16);
unsigned int height_blocks = (height / 8);

unsigned int src_pitch = (width-16)/4;
unsigned int src_row = width * 8;

const u8* ysrc = in;
u32* dst = (u32*)out;

// Swizzle a texture to optimize memory access patterns on the PSP
void oslSwizzleTexture(u8* out, const u8* in, unsigned int width, unsigned int height) {
unsigned int blockx, blocky, j;
unsigned int width_blocks = width / 16;
unsigned int height_blocks = height / 8;
unsigned int src_pitch = (width - 16) / 4;
unsigned int src_row = width * 8;

const u8* ysrc = in;
u32* dst = (u32*)out;

#ifndef PSP
memcpy(out, in, width * height);
return;
// On non-PSP platforms, simply copy the input to output
memcpy(out, in, width * height);
return;
#endif
for (blocky = 0; blocky < height_blocks; ++blocky)
{
const u8* xsrc = ysrc;
for (blockx = 0; blockx < width_blocks; ++blockx)
{
const u32* src = (u32*)xsrc;
for (j = 0; j < 8; ++j)
{
*(dst++) = *(src++);
*(dst++) = *(src++);
*(dst++) = *(src++);
*(dst++) = *(src++);
src += src_pitch;
}
xsrc += 16;
}
ysrc += src_row;
}

// Swizzle the texture
for (blocky = 0; blocky < height_blocks; ++blocky) {
const u8* xsrc = ysrc;
for (blockx = 0; blockx < width_blocks; ++blockx) {
const u32* src = (const u32*)xsrc;
for (j = 0; j < 8; ++j) {
for (int i = 0; i < 4; ++i) {
*(dst++) = *(src++);
}
src += src_pitch;
}
xsrc += 16;
}
ysrc += src_row;
}
}

void *oslGetSwizzledPixelAddr(OSL_IMAGE *img, unsigned int x, unsigned int y)
{
if (!oslImageIsSwizzled(img))
return oslGetImagePixelAdr(img, x, y);
// Get the address of a swizzled pixel
void* oslGetSwizzledPixelAddr(OSL_IMAGE* img, unsigned int x, unsigned int y) {
if (!oslImageIsSwizzled(img)) {
return oslGetImagePixelAdr(img, x, y);
}

//Multiply the x value by the pixelformat
x = (x * osl_pixelWidth[img->pixelFormat]) >> 3;
// Calculate pixel address for swizzled images
unsigned int pixelWidth = osl_pixelWidth[img->pixelFormat];
x = (x * pixelWidth) >> 3;
unsigned int width = (img->realSizeX * pixelWidth) >> 3;
unsigned int rowblocks = width / 16;

unsigned int width = (img->realSizeX * osl_pixelWidth[img->pixelFormat]) >> 3;
unsigned int rowblocks = (width / 16);

unsigned int blockx = x / 16;
unsigned int blocky = y / 8;
unsigned int blockx = x / 16;
unsigned int blocky = y / 8;

unsigned int block_index = blockx + ((blocky) * rowblocks);
unsigned int block_address = block_index * 16 * 8;

x = (x - blockx * 16);
y = (y - blocky * 8);
unsigned int block_index = blockx + (blocky * rowblocks);
unsigned int block_address = block_index * 16 * 8;

return (void*)((u8*)img->data + block_address + x + y * 16);
}
x = x - (blockx * 16);
y = y - (blocky * 8);

void oslSwizzleImage(OSL_IMAGE *img) {
void *block;
return (void*)((u8*)img->data + block_address + x + (y * 16));
}

//Already swizzled?
if (oslImageIsSwizzled(img))
return;
// Swizzle an entire image
void oslSwizzleImage(OSL_IMAGE* img) {
// Check if the image is already swizzled
if (oslImageIsSwizzled(img)) {
return;
}

block = (void*)malloc(img->totalSize);
if (block) {
memcpy(block, img->data, img->totalSize);
oslSwizzleTexture((u8*)img->data, (u8*)block, (img->realSizeX * osl_pixelWidth[img->pixelFormat]) >> 3, img->realSizeY);
free(block);
// Allocate a temporary block of memory for swizzling
void* block = malloc(img->totalSize);
if (block) {
memcpy(block, img->data, img->totalSize);
oslSwizzleTexture((u8*)img->data, (u8*)block, (img->realSizeX * osl_pixelWidth[img->pixelFormat]) >> 3, img->realSizeY);
free(block);

oslUncacheImageData(img);
oslImageIsSwizzledSet(img, 1);
}
oslUncacheImageData(img);
oslImageIsSwizzledSet(img, 1);
} else {
oslFatalError("oslSwizzleImage: Memory allocation failed.");
}
}

void oslSwizzleImageTo(OSL_IMAGE *imgDst, OSL_IMAGE *imgSrc)
{
//Même image?
if (imgDst == imgSrc)
oslSwizzleImage(imgDst);
// Swizzle an image to another image buffer
void oslSwizzleImageTo(OSL_IMAGE* imgDst, OSL_IMAGE* imgSrc) {
if (imgDst == imgSrc) {
oslSwizzleImage(imgDst);
return;
}

if (imgSrc->pixelFormat != imgDst->pixelFormat || imgSrc->totalSize != imgDst->totalSize) {
oslFatalError("oslSwizzleImageTo: Both images must have the same size and pixel format!");
return;
}
else {
oslSwizzleTexture((u8*)imgDst->data, (u8*)imgSrc->data, (imgSrc->realSizeX*osl_pixelWidth[imgSrc->pixelFormat])>>3, imgSrc->realSizeY);
oslUncacheImageData(imgDst);
oslImageIsSwizzledSet(imgDst, 1);
}
}
// Validate that both images have the same pixel format and size
if (imgSrc->pixelFormat != imgDst->pixelFormat || imgSrc->totalSize != imgDst->totalSize) {
oslFatalError("oslSwizzleImageTo: Both images must have the same size and pixel format!");
return;
}

oslSwizzleTexture((u8*)imgDst->data, (u8*)imgSrc->data, (imgSrc->realSizeX * osl_pixelWidth[imgSrc->pixelFormat]) >> 3, imgSrc->realSizeY);
oslUncacheImageData(imgDst);
oslImageIsSwizzledSet(imgDst, 1);
}

0 comments on commit cf529e1

Please sign in to comment.