mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-08 23:10:52 -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->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 */
|
||||
width = Math_NextPowOf2(width);
|
||||
height = Math_NextPowOf2(height);
|
||||
|
@ -66,8 +66,8 @@ CC_VAR extern struct _GfxData {
|
||||
/* Whether graphics context has been created */
|
||||
cc_bool Created;
|
||||
struct Matrix View, Projection;
|
||||
/* Whether the graphics backend supports non power of two textures */
|
||||
cc_bool SupportsNonPowTwoTextures;
|
||||
/* Level of support for non power of two textures */
|
||||
cc_uint8 NonPowTwoTexturesSupport;
|
||||
/* Limitations of the graphics backend, see GFX_LIMIT values */
|
||||
cc_uint8 Limitations;
|
||||
/* Type of the backend (e.g. OpenGL, Direct3D 9, etc)*/
|
||||
@ -85,6 +85,14 @@ CC_VAR extern struct _GfxData {
|
||||
GfxResourceID DefaultIb;
|
||||
} 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 */
|
||||
/* e.g. Saturn, 3D0 systems don't support it */
|
||||
#define GFX_LIMIT_NO_UV_SUPPORT 0x01
|
||||
|
@ -66,15 +66,6 @@ static void CommandsList_Append(struct CommandsList* list, const void* cmd) {
|
||||
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------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
@ -133,12 +124,11 @@ static int texmem_defragment(void) {
|
||||
TextureObject* tex = &TEXTURE_LIST[i];
|
||||
if (!tex->data) continue;
|
||||
|
||||
cc_uint32 size = TextureSize(tex);
|
||||
int moved = texmem_move(tex->data, size);
|
||||
int moved = texmem_move(tex->data, tex->size);
|
||||
if (!moved) continue;
|
||||
|
||||
moved_any = true;
|
||||
memmove(tex->data - moved, tex->data, size);
|
||||
memmove(tex->data - moved, tex->data, tex->size);
|
||||
tex->data -= moved;
|
||||
}
|
||||
return moved_any;
|
||||
@ -660,6 +650,8 @@ static TextureObject* FindFreeTexture(void) {
|
||||
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) {
|
||||
TextureObject* tex = FindFreeTexture();
|
||||
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);
|
||||
}
|
||||
|
||||
tex->width = bmp->width;
|
||||
tex->height = bmp->height;
|
||||
tex->format = pal_count > 0 ? (PVR_TXRFMT_PAL4BPP | PVR_TXRFMT_4BPP_PAL(pal_index)) : PVR_TXRFMT_ARGB4444;
|
||||
tex->log2_width = Log2Dimension(bmp->width);
|
||||
tex->log2_height = Log2Dimension(bmp->height);
|
||||
|
||||
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->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;
|
||||
unsigned maskX, maskY;
|
||||
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
|
||||
for (int x = 0; x < originX; x++) { X = (X - maskX) & maskX; }
|
||||
@ -726,8 +727,7 @@ void Gfx_DeleteTexture(GfxResourceID* texId) {
|
||||
TextureObject* tex = (TextureObject*)(*texId);
|
||||
if (!tex) return;
|
||||
|
||||
cc_uint32 size = TextureSize(tex);
|
||||
texmem_free(tex->data, size);
|
||||
texmem_free(tex->data, tex->size);
|
||||
|
||||
if (tex->format != PVR_TXRFMT_ARGB4444) {
|
||||
int index = (tex->format & PVR_TXRFMT_4BPP_PAL(63)) >> 21;
|
||||
|
@ -45,7 +45,7 @@ void Gfx_Create(void) {
|
||||
Gfx.MaxTexSize = 1024;
|
||||
Gfx.MaxLowResTexSize = 2048;
|
||||
|
||||
Gfx.SupportsNonPowTwoTextures = true;
|
||||
Gfx.NonPowTwoTexturesSupport = GFX_NONPOW2_FULL;
|
||||
Gfx_RestoreState();
|
||||
|
||||
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) {
|
||||
if (Gfx.SupportsNonPowTwoTextures && (flags & TEXTURE_FLAG_NONPOW2)) {
|
||||
if (Gfx.NonPowTwoTexturesSupport && (flags & TEXTURE_FLAG_NONPOW2)) {
|
||||
/* 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)) {
|
||||
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 {
|
||||
uint32_t format;
|
||||
void *data;
|
||||
uint16_t width;
|
||||
uint16_t height;
|
||||
uint32_t log2_width: 4;
|
||||
uint32_t log2_height: 4;
|
||||
uint32_t size: 24;
|
||||
} TextureObject;
|
||||
|
||||
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 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) {
|
||||
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_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 |= (DimensionFlag(tx1->height) << PVR_TA_PM2_VSIZE_SHIFT) & PVR_TA_PM2_VSIZE_MASK;
|
||||
dst->mode2 |= ((tx1->log2_width - 3) << PVR_TA_PM2_USIZE_SHIFT) & PVR_TA_PM2_USIZE_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 |= (tx1->format << PVR_TA_PM3_TXRFMT_SHIFT) & PVR_TA_PM3_TXRFMT_MASK;
|
||||
|
Loading…
x
Reference in New Issue
Block a user