mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-12 17:17:09 -04:00
WIP on non power of two texture upload support
This commit is contained in:
parent
f23afac745
commit
8dd99cb11c
@ -152,7 +152,7 @@ void Context2D_Alloc(struct Context2D* ctx, int width, int height) {
|
|||||||
ctx->height = height;
|
ctx->height = height;
|
||||||
ctx->meta = NULL;
|
ctx->meta = NULL;
|
||||||
|
|
||||||
if (!Gfx.SupportsNonPowTwoTextures) {
|
if (Gfx.NonPowTwoTexturesSupport != GFX_NONPOW2_FULL) {
|
||||||
/* Allocate power-of-2 sized bitmap equal to or greater than the given size */
|
/* Allocate power-of-2 sized bitmap equal to or greater than the given size */
|
||||||
width = Math_NextPowOf2(width);
|
width = Math_NextPowOf2(width);
|
||||||
height = Math_NextPowOf2(height);
|
height = Math_NextPowOf2(height);
|
||||||
|
@ -66,8 +66,8 @@ CC_VAR extern struct _GfxData {
|
|||||||
/* Whether graphics context has been created */
|
/* Whether graphics context has been created */
|
||||||
cc_bool Created;
|
cc_bool Created;
|
||||||
struct Matrix View, Projection;
|
struct Matrix View, Projection;
|
||||||
/* Whether the graphics backend supports non power of two textures */
|
/* Level of support for non power of two textures */
|
||||||
cc_bool SupportsNonPowTwoTextures;
|
cc_uint8 NonPowTwoTexturesSupport;
|
||||||
/* Limitations of the graphics backend, see GFX_LIMIT values */
|
/* Limitations of the graphics backend, see GFX_LIMIT values */
|
||||||
cc_uint8 Limitations;
|
cc_uint8 Limitations;
|
||||||
/* Type of the backend (e.g. OpenGL, Direct3D 9, etc)*/
|
/* Type of the backend (e.g. OpenGL, Direct3D 9, etc)*/
|
||||||
@ -85,6 +85,14 @@ CC_VAR extern struct _GfxData {
|
|||||||
GfxResourceID DefaultIb;
|
GfxResourceID DefaultIb;
|
||||||
} Gfx;
|
} Gfx;
|
||||||
|
|
||||||
|
/* Backend has no support at all for non power of two textures */
|
||||||
|
#define GFX_NONPOW2_NONE 0x00
|
||||||
|
/* Backend only supports uploading non power of two textures */
|
||||||
|
/* E.g. 64x20 texture may only occupy 64x20 in VRAM, but is addressed as if it was 64x32 */
|
||||||
|
#define GFX_NONPOW2_UPLOAD 0x01
|
||||||
|
/* Backend fully supports uploading and addressing non power of two textures */
|
||||||
|
#define GFX_NONPOW2_FULL 0x02
|
||||||
|
|
||||||
/* Whether the graphics backend supports U/V that don't occupy whole texture */
|
/* Whether the graphics backend supports U/V that don't occupy whole texture */
|
||||||
/* e.g. Saturn, 3D0 systems don't support it */
|
/* e.g. Saturn, 3D0 systems don't support it */
|
||||||
#define GFX_LIMIT_NO_UV_SUPPORT 0x01
|
#define GFX_LIMIT_NO_UV_SUPPORT 0x01
|
||||||
|
@ -66,15 +66,6 @@ static void CommandsList_Append(struct CommandsList* list, const void* cmd) {
|
|||||||
list->length++;
|
list->length++;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CC_INLINE cc_uint32 TextureSize(TextureObject* tex) {
|
|
||||||
// 16 bpp = 1 pixel in 2 bytes
|
|
||||||
if (tex->format == PVR_TXRFMT_ARGB4444) return tex->width * tex->height * 2;
|
|
||||||
|
|
||||||
// 4bpp = 2 pixels in 1 byte
|
|
||||||
return tex->width * tex->height / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*########################################################################################################################*
|
/*########################################################################################################################*
|
||||||
*-----------------------------------------------------Texture memory------------------------------------------------------*
|
*-----------------------------------------------------Texture memory------------------------------------------------------*
|
||||||
*#########################################################################################################################*/
|
*#########################################################################################################################*/
|
||||||
@ -133,12 +124,11 @@ static int texmem_defragment(void) {
|
|||||||
TextureObject* tex = &TEXTURE_LIST[i];
|
TextureObject* tex = &TEXTURE_LIST[i];
|
||||||
if (!tex->data) continue;
|
if (!tex->data) continue;
|
||||||
|
|
||||||
cc_uint32 size = TextureSize(tex);
|
int moved = texmem_move(tex->data, tex->size);
|
||||||
int moved = texmem_move(tex->data, size);
|
|
||||||
if (!moved) continue;
|
if (!moved) continue;
|
||||||
|
|
||||||
moved_any = true;
|
moved_any = true;
|
||||||
memmove(tex->data - moved, tex->data, size);
|
memmove(tex->data - moved, tex->data, tex->size);
|
||||||
tex->data -= moved;
|
tex->data -= moved;
|
||||||
}
|
}
|
||||||
return moved_any;
|
return moved_any;
|
||||||
@ -660,6 +650,8 @@ static TextureObject* FindFreeTexture(void) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int Log2Dimension(int len) { return Math_ilog2(Math_NextPowOf2(len)); }
|
||||||
|
|
||||||
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) {
|
||||||
TextureObject* tex = FindFreeTexture();
|
TextureObject* tex = FindFreeTexture();
|
||||||
if (!tex) return NULL;
|
if (!tex) return NULL;
|
||||||
@ -673,11 +665,20 @@ GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags,
|
|||||||
if (pal_count > 0) ApplyPalette(palette, pal_count, pal_index);
|
if (pal_count > 0) ApplyPalette(palette, pal_count, pal_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
tex->width = bmp->width;
|
tex->log2_width = Log2Dimension(bmp->width);
|
||||||
tex->height = bmp->height;
|
tex->log2_height = Log2Dimension(bmp->height);
|
||||||
tex->format = pal_count > 0 ? (PVR_TXRFMT_PAL4BPP | PVR_TXRFMT_4BPP_PAL(pal_index)) : PVR_TXRFMT_ARGB4444;
|
|
||||||
|
|
||||||
tex->data = texmem_alloc(TextureSize(tex));
|
if (pal_count > 0) {
|
||||||
|
tex->format = PVR_TXRFMT_PAL4BPP | PVR_TXRFMT_4BPP_PAL(pal_index);
|
||||||
|
// 4bpp = 2 pixels in 1 byte
|
||||||
|
tex->size = bmp->width * bmp->height / 2;
|
||||||
|
} else {
|
||||||
|
tex->format = PVR_TXRFMT_ARGB4444;
|
||||||
|
// 16 bpp = 1 pixel in 2 bytes
|
||||||
|
tex->size = bmp->width * bmp->height * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
tex->data = texmem_alloc(tex->size);
|
||||||
if (!tex->data) { Platform_LogConst("Out of PVR VRAM!"); return NULL; }
|
if (!tex->data) { Platform_LogConst("Out of PVR VRAM!"); return NULL; }
|
||||||
|
|
||||||
if (tex->format == PVR_TXRFMT_ARGB4444) {
|
if (tex->format == PVR_TXRFMT_ARGB4444) {
|
||||||
@ -694,7 +695,7 @@ void Gfx_UpdateTexture(GfxResourceID texId, int originX, int originY, struct Bit
|
|||||||
int width = part->width, height = part->height;
|
int width = part->width, height = part->height;
|
||||||
unsigned maskX, maskY;
|
unsigned maskX, maskY;
|
||||||
unsigned X = 0, Y = 0;
|
unsigned X = 0, Y = 0;
|
||||||
TwiddleCalcFactors(tex->width, tex->height, &maskX, &maskY);
|
TwiddleCalcFactors(1 << tex->log2_width, 1 << tex->log2_height, &maskX, &maskY);
|
||||||
|
|
||||||
// Calculate start twiddled X and Y values
|
// Calculate start twiddled X and Y values
|
||||||
for (int x = 0; x < originX; x++) { X = (X - maskX) & maskX; }
|
for (int x = 0; x < originX; x++) { X = (X - maskX) & maskX; }
|
||||||
@ -726,8 +727,7 @@ void Gfx_DeleteTexture(GfxResourceID* texId) {
|
|||||||
TextureObject* tex = (TextureObject*)(*texId);
|
TextureObject* tex = (TextureObject*)(*texId);
|
||||||
if (!tex) return;
|
if (!tex) return;
|
||||||
|
|
||||||
cc_uint32 size = TextureSize(tex);
|
texmem_free(tex->data, tex->size);
|
||||||
texmem_free(tex->data, size);
|
|
||||||
|
|
||||||
if (tex->format != PVR_TXRFMT_ARGB4444) {
|
if (tex->format != PVR_TXRFMT_ARGB4444) {
|
||||||
int index = (tex->format & PVR_TXRFMT_4BPP_PAL(63)) >> 21;
|
int index = (tex->format & PVR_TXRFMT_4BPP_PAL(63)) >> 21;
|
||||||
|
@ -45,7 +45,7 @@ void Gfx_Create(void) {
|
|||||||
Gfx.MaxTexSize = 1024;
|
Gfx.MaxTexSize = 1024;
|
||||||
Gfx.MaxLowResTexSize = 2048;
|
Gfx.MaxLowResTexSize = 2048;
|
||||||
|
|
||||||
Gfx.SupportsNonPowTwoTextures = true;
|
Gfx.NonPowTwoTexturesSupport = GFX_NONPOW2_FULL;
|
||||||
Gfx_RestoreState();
|
Gfx_RestoreState();
|
||||||
|
|
||||||
Gfx_SetFaceCulling(false);
|
Gfx_SetFaceCulling(false);
|
||||||
|
@ -429,9 +429,9 @@ GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipm
|
|||||||
}
|
}
|
||||||
|
|
||||||
GfxResourceID Gfx_CreateTexture2(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, cc_bool mipmaps) {
|
GfxResourceID Gfx_CreateTexture2(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, cc_bool mipmaps) {
|
||||||
if (Gfx.SupportsNonPowTwoTextures && (flags & TEXTURE_FLAG_NONPOW2)) {
|
if (Gfx.NonPowTwoTexturesSupport && (flags & TEXTURE_FLAG_NONPOW2)) {
|
||||||
/* Texture is being deliberately created and can be successfully created */
|
/* Texture is being deliberately created and can be successfully created */
|
||||||
/* with non power of two dimensions. Typically used for UI textures */
|
/* with non power of two dimensions. Typically only used for UI textures */
|
||||||
} else if (!Math_IsPowOf2(bmp->width) || !Math_IsPowOf2(bmp->height)) {
|
} else if (!Math_IsPowOf2(bmp->width) || !Math_IsPowOf2(bmp->height)) {
|
||||||
Process_Abort("Textures must have power of two dimensions");
|
Process_Abort("Textures must have power of two dimensions");
|
||||||
}
|
}
|
||||||
|
5
third_party/gldc/gldc.h
vendored
5
third_party/gldc/gldc.h
vendored
@ -17,8 +17,9 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t format;
|
uint32_t format;
|
||||||
void *data;
|
void *data;
|
||||||
uint16_t width;
|
uint32_t log2_width: 4;
|
||||||
uint16_t height;
|
uint32_t log2_height: 4;
|
||||||
|
uint32_t size: 24;
|
||||||
} TextureObject;
|
} TextureObject;
|
||||||
|
|
||||||
void GLDC_NO_INLINE SubmitCommands(Vertex* v3, int n);
|
void GLDC_NO_INLINE SubmitCommands(Vertex* v3, int n);
|
||||||
|
19
third_party/gldc/state.c
vendored
19
third_party/gldc/state.c
vendored
@ -19,21 +19,6 @@ static uint8_t BLEND_ENABLED;
|
|||||||
static uint8_t TEXTURES_ENABLED;
|
static uint8_t TEXTURES_ENABLED;
|
||||||
static uint8_t AUTOSORT_ENABLED;
|
static uint8_t AUTOSORT_ENABLED;
|
||||||
|
|
||||||
static inline int DimensionFlag(int w) {
|
|
||||||
switch(w) {
|
|
||||||
case 16: return 1;
|
|
||||||
case 32: return 2;
|
|
||||||
case 64: return 3;
|
|
||||||
case 128: return 4;
|
|
||||||
case 256: return 5;
|
|
||||||
case 512: return 6;
|
|
||||||
case 1024: return 7;
|
|
||||||
case 8:
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static GLDC_NO_INLINE void apply_poly_header(pvr_poly_hdr_t* dst, int list_type) {
|
static GLDC_NO_INLINE void apply_poly_header(pvr_poly_hdr_t* dst, int list_type) {
|
||||||
TextureObject* tx1 = TEXTURE_ACTIVE;
|
TextureObject* tx1 = TEXTURE_ACTIVE;
|
||||||
|
|
||||||
@ -100,8 +85,8 @@ static GLDC_NO_INLINE void apply_poly_header(pvr_poly_hdr_t* dst, int list_type)
|
|||||||
dst->mode2 |= (PVR_MIPBIAS_NORMAL << PVR_TA_PM2_MIPBIAS_SHIFT) & PVR_TA_PM2_MIPBIAS_MASK;
|
dst->mode2 |= (PVR_MIPBIAS_NORMAL << PVR_TA_PM2_MIPBIAS_SHIFT) & PVR_TA_PM2_MIPBIAS_MASK;
|
||||||
dst->mode2 |= (PVR_TXRENV_MODULATEALPHA << PVR_TA_PM2_TXRENV_SHIFT) & PVR_TA_PM2_TXRENV_MASK;
|
dst->mode2 |= (PVR_TXRENV_MODULATEALPHA << PVR_TA_PM2_TXRENV_SHIFT) & PVR_TA_PM2_TXRENV_MASK;
|
||||||
|
|
||||||
dst->mode2 |= (DimensionFlag(tx1->width) << PVR_TA_PM2_USIZE_SHIFT) & PVR_TA_PM2_USIZE_MASK;
|
dst->mode2 |= ((tx1->log2_width - 3) << PVR_TA_PM2_USIZE_SHIFT) & PVR_TA_PM2_USIZE_MASK;
|
||||||
dst->mode2 |= (DimensionFlag(tx1->height) << PVR_TA_PM2_VSIZE_SHIFT) & PVR_TA_PM2_VSIZE_MASK;
|
dst->mode2 |= ((tx1->log2_height - 3) << PVR_TA_PM2_VSIZE_SHIFT) & PVR_TA_PM2_VSIZE_MASK;
|
||||||
|
|
||||||
dst->mode3 = (0 << PVR_TA_PM3_MIPMAP_SHIFT) & PVR_TA_PM3_MIPMAP_MASK;
|
dst->mode3 = (0 << PVR_TA_PM3_MIPMAP_SHIFT) & PVR_TA_PM3_MIPMAP_MASK;
|
||||||
dst->mode3 |= (tx1->format << PVR_TA_PM3_TXRFMT_SHIFT) & PVR_TA_PM3_TXRFMT_MASK;
|
dst->mode3 |= (tx1->format << PVR_TA_PM3_TXRFMT_SHIFT) & PVR_TA_PM3_TXRFMT_MASK;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user