mirror of https://github.com/ClassiCube/ClassiCube
PSP: Use swizzled textures
This commit is contained in:
parent
514b10f662
commit
2e7a5c9897
|
|
@ -119,7 +119,7 @@ static CC_INLINE void TwiddleCalcFactors(unsigned w, unsigned h,
|
||||||
*maskX = 0b00011; // 2 linear X bits, 1 bit until next block
|
*maskX = 0b00011; // 2 linear X bits, 1 bit until next block
|
||||||
*maskY = 0b01100; // 2 linear Y bits, 1 bit until next block
|
*maskY = 0b01100; // 2 linear Y bits, 1 bit until next block
|
||||||
|
|
||||||
// Lower 2 X and Y bits are always linear
|
// Adjust for lower 2 X and 2 Y linear bits
|
||||||
w >>= 3;
|
w >>= 3;
|
||||||
h >>= 3;
|
h >>= 3;
|
||||||
int shift = 5;
|
int shift = 5;
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,7 @@ void Gfx_Create(void) {
|
||||||
|
|
||||||
Gfx.MaxTexWidth = 512;
|
Gfx.MaxTexWidth = 512;
|
||||||
Gfx.MaxTexHeight = 512;
|
Gfx.MaxTexHeight = 512;
|
||||||
|
Gfx.NonPowTwoTexturesSupport = GFX_NONPOW2_UPLOAD;
|
||||||
Gfx.Created = true;
|
Gfx.Created = true;
|
||||||
gfx_vsync = true;
|
gfx_vsync = true;
|
||||||
|
|
||||||
|
|
@ -103,6 +104,79 @@ static void Gfx_FreeState(void) {
|
||||||
|
|
||||||
#define GU_Toggle(cap) if (enabled) { sceGuEnable(cap); } else { sceGuDisable(cap); }
|
#define GU_Toggle(cap) if (enabled) { sceGuEnable(cap); } else { sceGuDisable(cap); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*########################################################################################################################*
|
||||||
|
*---------------------------------------------------------Swizzling-------------------------------------------------------*
|
||||||
|
*#########################################################################################################################*/
|
||||||
|
// PSP swizzled textures are 16 bytes X 8 rows = 4 '32 bit' pixels X 8 rows
|
||||||
|
static CC_INLINE void TwiddleCalcFactors(unsigned w, unsigned h, unsigned* maskX, unsigned* maskY) {
|
||||||
|
*maskX = 0b00011; // 2 linear X bits
|
||||||
|
*maskY = 0b11100; // 3 linear Y bits
|
||||||
|
|
||||||
|
// Adjust for lower 2 X and 2 Y linear bits
|
||||||
|
w >>= 3;
|
||||||
|
h >>= 4;
|
||||||
|
int shift = 5;
|
||||||
|
|
||||||
|
for (; w > 0; w >>= 1) {
|
||||||
|
*maskX += 0x01 << shift;
|
||||||
|
shift += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; h > 0; h >>= 1) {
|
||||||
|
*maskY += 0x01 << shift;
|
||||||
|
shift += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static CC_INLINE void UploadFullTexture(struct Bitmap* bmp, int rowWidth, cc_uint32* dst, int dst_w, int dst_h) {
|
||||||
|
int src_w = bmp->width, src_h = bmp->height;
|
||||||
|
unsigned maskX, maskY;
|
||||||
|
unsigned X = 0, Y = 0;
|
||||||
|
TwiddleCalcFactors(dst_w, dst_h, &maskX, &maskY);
|
||||||
|
|
||||||
|
for (int y = 0; y < src_h; y++)
|
||||||
|
{
|
||||||
|
cc_uint32* src = bmp->scan0 + y * rowWidth;
|
||||||
|
X = 0;
|
||||||
|
|
||||||
|
for (int x = 0; x < src_w; x++, src++)
|
||||||
|
{
|
||||||
|
dst[X | Y] = *src;
|
||||||
|
X = (X - maskX) & maskX;
|
||||||
|
}
|
||||||
|
Y = (Y - maskY) & maskY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static CC_INLINE void UploadPartialTexture(struct Bitmap* part, int rowWidth, cc_uint32* dst, int dst_w, int dst_h,
|
||||||
|
int originX, int originY) {
|
||||||
|
int src_w = part->width, src_h = part->height;
|
||||||
|
unsigned maskX, maskY;
|
||||||
|
unsigned X = 0, Y = 0;
|
||||||
|
TwiddleCalcFactors(dst_w, dst_h, &maskX, &maskY);
|
||||||
|
|
||||||
|
// Calculate start twiddled X and Y values
|
||||||
|
for (int x = 0; x < originX; x++) { X = (X - maskX) & maskX; }
|
||||||
|
for (int y = 0; y < originY; y++) { Y = (Y - maskY) & maskY; }
|
||||||
|
unsigned startX = X;
|
||||||
|
|
||||||
|
for (int y = 0; y < src_h; y++)
|
||||||
|
{
|
||||||
|
cc_uint32* src = part->scan0 + y * rowWidth;
|
||||||
|
X = startX;
|
||||||
|
|
||||||
|
for (int x = 0; x < src_w; x++, src++)
|
||||||
|
{
|
||||||
|
dst[X | Y] = *src;
|
||||||
|
X = (X - maskX) & maskX;
|
||||||
|
}
|
||||||
|
Y = (Y - maskY) & maskY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*########################################################################################################################*
|
/*########################################################################################################################*
|
||||||
*---------------------------------------------------------Textures--------------------------------------------------------*
|
*---------------------------------------------------------Textures--------------------------------------------------------*
|
||||||
*#########################################################################################################################*/
|
*#########################################################################################################################*/
|
||||||
|
|
@ -113,38 +187,28 @@ typedef struct CCTexture_ {
|
||||||
} CCTexture;
|
} CCTexture;
|
||||||
|
|
||||||
GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, cc_bool mipmaps) {
|
GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, cc_bool mipmaps) {
|
||||||
int size = bmp->width * bmp->height * 4;
|
int dst_w = Math_NextPowOf2(bmp->width);
|
||||||
|
int dst_h = Math_NextPowOf2(bmp->height);
|
||||||
|
|
||||||
|
// Swizzled texture assumes at least 16 bytes x 8 rows
|
||||||
|
int size = max(16 * 8, dst_w * dst_h * 4);
|
||||||
CCTexture* tex = (CCTexture*)memalign(16, 16 + size);
|
CCTexture* tex = (CCTexture*)memalign(16, 16 + size);
|
||||||
|
|
||||||
tex->width = bmp->width;
|
tex->width = dst_w;
|
||||||
tex->height = bmp->height;
|
tex->height = dst_h;
|
||||||
|
|
||||||
CopyPixels(tex->pixels, bmp->width * BITMAPCOLOR_SIZE,
|
UploadFullTexture(bmp, rowWidth, tex->pixels, dst_w, dst_h);
|
||||||
bmp->scan0, rowWidth * BITMAPCOLOR_SIZE,
|
|
||||||
bmp->width, bmp->height);
|
|
||||||
return tex;
|
return tex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gfx_UpdateTexture(GfxResourceID texId, int x, int y, struct Bitmap* part, int rowWidth, cc_bool mipmaps) {
|
void Gfx_UpdateTexture(GfxResourceID texId, int x, int y, struct Bitmap* part, int rowWidth, cc_bool mipmaps) {
|
||||||
CCTexture* tex = (CCTexture*)texId;
|
CCTexture* tex = (CCTexture*)texId;
|
||||||
BitmapCol* dst = (tex->pixels + x) + y * tex->width;
|
UploadPartialTexture(part, rowWidth, tex->pixels, tex->width, tex->height, x, y);
|
||||||
|
|
||||||
CopyPixels(dst, tex->width * BITMAPCOLOR_SIZE,
|
|
||||||
part->scan0, rowWidth * BITMAPCOLOR_SIZE,
|
|
||||||
part->width, part->height);
|
|
||||||
// TODO: Do line by line and only invalidate the actually changed parts of lines?
|
// TODO: Do line by line and only invalidate the actually changed parts of lines?
|
||||||
sceKernelDcacheWritebackInvalidateRange(dst, (tex->width * part->height) * 4);
|
sceKernelDcacheWritebackInvalidateRange(tex->pixels, (tex->width * tex->height) * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*void Gfx_UpdateTexture(GfxResourceID texId, int x, int y, struct Bitmap* part, int rowWidth, cc_bool mipmaps) {
|
|
||||||
CCTexture* tex = (CCTexture*)texId;
|
|
||||||
cc_uint32* dst = (tex->pixels + x) + y * tex->width;
|
|
||||||
|
|
||||||
for (int yy = 0; yy < part->height; yy++) {
|
|
||||||
Mem_Copy(dst + (y + yy) * tex->width, part->scan0 + yy * rowWidth, part->width * 4);
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
void Gfx_DeleteTexture(GfxResourceID* texId) {
|
void Gfx_DeleteTexture(GfxResourceID* texId) {
|
||||||
GfxResourceID data = *texId;
|
GfxResourceID data = *texId;
|
||||||
if (data) Mem_Free(data);
|
if (data) Mem_Free(data);
|
||||||
|
|
@ -158,7 +222,7 @@ void Gfx_BindTexture(GfxResourceID texId) {
|
||||||
CCTexture* tex = (CCTexture*)texId;
|
CCTexture* tex = (CCTexture*)texId;
|
||||||
if (!tex) tex = white_square;
|
if (!tex) tex = white_square;
|
||||||
|
|
||||||
sceGuTexMode(GU_PSM_8888, 0, 0, 0);
|
sceGuTexMode(GU_PSM_8888, 0, 0, 1);
|
||||||
sceGuTexImage(0, tex->width, tex->height, tex->width, tex->pixels);
|
sceGuTexImage(0, tex->width, tex->height, tex->width, tex->pixels);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -673,9 +673,12 @@ static void GPUTextures_DeleteUnreferenced(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*########################################################################################################################*
|
||||||
|
*---------------------------------------------------------Swizzling-------------------------------------------------------*
|
||||||
|
*#########################################################################################################################*/
|
||||||
// See Graphics_Dreamcast.c for twiddling explanation
|
// See Graphics_Dreamcast.c for twiddling explanation
|
||||||
static CC_INLINE void TwiddleCalcFactors(unsigned w, unsigned h,
|
static CC_INLINE void TwiddleCalcFactors(unsigned w, unsigned h, unsigned* maskX, unsigned* maskY) {
|
||||||
unsigned* maskX, unsigned* maskY) {
|
|
||||||
*maskX = 0;
|
*maskX = 0;
|
||||||
*maskY = 0;
|
*maskY = 0;
|
||||||
int shift = 0;
|
int shift = 0;
|
||||||
|
|
@ -699,18 +702,7 @@ static CC_INLINE void TwiddleCalcFactors(unsigned w, unsigned h,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static CC_INLINE void UploadFullTexture(struct Bitmap* bmp, int rowWidth, cc_uint32* dst, int dst_w, int dst_h) {
|
||||||
/*########################################################################################################################*
|
|
||||||
*---------------------------------------------------------Textures--------------------------------------------------------*
|
|
||||||
*#########################################################################################################################*/
|
|
||||||
GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, cc_bool mipmaps) {
|
|
||||||
int dst_w = Math_NextPowOf2(bmp->width);
|
|
||||||
int dst_h = Math_NextPowOf2(bmp->height);
|
|
||||||
int size = dst_w * dst_h * 4;
|
|
||||||
|
|
||||||
struct GPUTexture* tex = GPUTexture_Alloc(size);
|
|
||||||
cc_uint32* dst = tex->data;
|
|
||||||
|
|
||||||
int src_w = bmp->width, src_h = bmp->height;
|
int src_w = bmp->width, src_h = bmp->height;
|
||||||
unsigned maskX, maskY;
|
unsigned maskX, maskY;
|
||||||
unsigned X = 0, Y = 0;
|
unsigned X = 0, Y = 0;
|
||||||
|
|
@ -728,6 +720,46 @@ GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags,
|
||||||
}
|
}
|
||||||
Y = (Y - maskY) & maskY;
|
Y = (Y - maskY) & maskY;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static CC_INLINE void UploadPartialTexture(struct Bitmap* part, int rowWidth, cc_uint32* dst, int dst_w, int dst_h,
|
||||||
|
int originX, int originY) {
|
||||||
|
int src_w = part->width, src_h = part->height;
|
||||||
|
unsigned maskX, maskY;
|
||||||
|
unsigned X = 0, Y = 0;
|
||||||
|
TwiddleCalcFactors(dst_w, dst_h, &maskX, &maskY);
|
||||||
|
|
||||||
|
// Calculate start twiddled X and Y values
|
||||||
|
for (int x = 0; x < originX; x++) { X = (X - maskX) & maskX; }
|
||||||
|
for (int y = 0; y < originY; y++) { Y = (Y - maskY) & maskY; }
|
||||||
|
unsigned startX = X;
|
||||||
|
|
||||||
|
for (int y = 0; y < src_h; y++)
|
||||||
|
{
|
||||||
|
cc_uint32* src = part->scan0 + y * rowWidth;
|
||||||
|
X = startX;
|
||||||
|
|
||||||
|
for (int x = 0; x < src_w; x++, src++)
|
||||||
|
{
|
||||||
|
dst[X | Y] = *src;
|
||||||
|
X = (X - maskX) & maskX;
|
||||||
|
}
|
||||||
|
Y = (Y - maskY) & maskY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*########################################################################################################################*
|
||||||
|
*---------------------------------------------------------Textures--------------------------------------------------------*
|
||||||
|
*#########################################################################################################################*/
|
||||||
|
GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, cc_bool mipmaps) {
|
||||||
|
int dst_w = Math_NextPowOf2(bmp->width);
|
||||||
|
int dst_h = Math_NextPowOf2(bmp->height);
|
||||||
|
int size = dst_w * dst_h * 4;
|
||||||
|
|
||||||
|
struct GPUTexture* tex = GPUTexture_Alloc(size);
|
||||||
|
cc_uint32* dst = tex->data;
|
||||||
|
UploadFullTexture(bmp, rowWidth, dst, dst_w, dst_h);
|
||||||
|
|
||||||
sceGxmTextureInitSwizzled(&tex->texture, dst,
|
sceGxmTextureInitSwizzled(&tex->texture, dst,
|
||||||
SCE_GXM_TEXTURE_FORMAT_A8B8G8R8, dst_w, dst_h, 0);
|
SCE_GXM_TEXTURE_FORMAT_A8B8G8R8, dst_w, dst_h, 0);
|
||||||
|
|
@ -741,33 +773,12 @@ void Gfx_UpdateTexture(GfxResourceID texId, int originX, int originY, struct Bit
|
||||||
struct GPUTexture* tex = (struct GPUTexture*)texId;
|
struct GPUTexture* tex = (struct GPUTexture*)texId;
|
||||||
int texWidth = sceGxmTextureGetWidth(&tex->texture);
|
int texWidth = sceGxmTextureGetWidth(&tex->texture);
|
||||||
int texHeight = sceGxmTextureGetHeight(&tex->texture);
|
int texHeight = sceGxmTextureGetHeight(&tex->texture);
|
||||||
cc_uint32* dst = tex->data;
|
|
||||||
|
|
||||||
int width = part->width, height = part->height;
|
|
||||||
unsigned maskX, maskY;
|
|
||||||
unsigned X = 0, Y = 0;
|
|
||||||
TwiddleCalcFactors(texWidth, texHeight, &maskX, &maskY);
|
|
||||||
|
|
||||||
// Calculate start twiddled X and Y values
|
cc_uint32* dst = tex->data;
|
||||||
for (int x = 0; x < originX; x++) { X = (X - maskX) & maskX; }
|
UploadPartialTexture(part, rowWidth, dst, texWidth, texHeight, originX, originY);
|
||||||
for (int y = 0; y < originY; y++) { Y = (Y - maskY) & maskY; }
|
|
||||||
unsigned startX = X;
|
|
||||||
|
|
||||||
for (int y = 0; y < height; y++)
|
|
||||||
{
|
|
||||||
cc_uint32* src = part->scan0 + rowWidth * y;
|
|
||||||
X = startX;
|
|
||||||
|
|
||||||
for (int x = 0; x < width; x++, src++)
|
|
||||||
{
|
|
||||||
dst[X | Y] = *src;
|
|
||||||
X = (X - maskX) & maskX;
|
|
||||||
}
|
|
||||||
Y = (Y - maskY) & maskY;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: is it necessary to invalidate? probably just everything?
|
// TODO: is it necessary to invalidate? probably just everything?
|
||||||
//sceKernelDcacheWritebackInvalidateRange(dst, (tex->width * part->height) * 4);
|
//sceKernelDcacheWritebackInvalidateRange(dst, (tex->width * tex->height) * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gfx_DeleteTexture(GfxResourceID* texId) {
|
void Gfx_DeleteTexture(GfxResourceID* texId) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue