diff --git a/src/Drawer2D.c b/src/Drawer2D.c index d3ca2b933..243aaf386 100644 --- a/src/Drawer2D.c +++ b/src/Drawer2D.c @@ -152,9 +152,11 @@ void Context2D_Alloc(struct Context2D* ctx, int width, int height) { ctx->height = height; ctx->meta = NULL; - /* Allocates a power-of-2 sized bitmap equal to or greater than the given size, and clears it to 0 */ - width = Math_NextPowOf2(width); - height = Math_NextPowOf2(height); + if (!Gfx.SupportsNonPowTwoTextures) { + /* Allocate power-of-2 sized bitmap equal to or greater than the given size */ + width = Math_NextPowOf2(width); + height = Math_NextPowOf2(height); + } ctx->bmp.width = width; ctx->bmp.height = height; @@ -299,7 +301,7 @@ void Drawer2D_MakeTextTexture(struct Texture* tex, struct DrawTextArgs* args) { } void Context2D_MakeTexture(struct Texture* tex, struct Context2D* ctx) { - Gfx_RecreateTexture(&tex->ID, &ctx->bmp, 0, false); + Gfx_RecreateTexture(&tex->ID, &ctx->bmp, TEXTURE_FLAG_NONPOW2, false); tex->Width = ctx->width; tex->Height = ctx->height; diff --git a/src/Entity.c b/src/Entity.c index f25f88f05..c00e54d7c 100644 --- a/src/Entity.c +++ b/src/Entity.c @@ -332,7 +332,7 @@ static cc_result ApplySkin(struct Entity* e, struct Bitmap* bmp, struct Stream* if (e->Model->flags & MODEL_FLAG_CLEAR_HAT) Entity_ClearHat(bmp, e->SkinType); - Gfx_RecreateTexture(&e->TextureId, bmp, TEXTURE_FLAG_MANAGED, false); + e->TextureId = Gfx_CreateTexture(bmp, TEXTURE_FLAG_MANAGED, false); Entity_SetSkinAll(e, false); } return 0; diff --git a/src/Graphics.h b/src/Graphics.h index 922d6e83d..3a72859d1 100644 --- a/src/Graphics.h +++ b/src/Graphics.h @@ -40,9 +40,12 @@ void Gfx_Create(void); void Gfx_Free(void); CC_VAR extern struct _GfxData { - /* Maximum dimensions textures can be created up to. (usually 1024 to 16384) */ + /* Maximum dimensions in pixels that a texture can be created up to */ + /* NOTE: usually 1024 to 16384 */ int MaxTexWidth, MaxTexHeight; - float _unused; + /* Maximum total size in pixels a texture can consist of */ + /* NOTE: Not all graphics backends specify a value for this */ + int MaxTexSize; /* Whether context graphics has been lost (all creation/render calls fail) */ cc_bool LostContext; /* Whether some textures are created with mipmaps */ @@ -53,9 +56,8 @@ CC_VAR extern struct _GfxData { /* Whether graphics context has been created */ cc_bool Created; struct Matrix View, Projection; - /* Maximum size in pixels a texture can consist of */ - /* NOTE: Not all graphics backends specify a value for this */ - int MaxTexSize; + /* Whether the graphics backend supports non power of two textures */ + cc_bool SupportsNonPowTwoTextures; } Gfx; extern GfxResourceID Gfx_defaultIb; @@ -69,6 +71,8 @@ extern const cc_string Gfx_LowPerfMessage; #define TEXTURE_FLAG_MANAGED 0x01 /* Texture should allow updating via Gfx_UpdateTexture */ #define TEXTURE_FLAG_DYNAMIC 0x02 +/* Texture is deliberately (and not accidentally) being created with non power of two dimensions */ +#define TEXTURE_FLAG_NONPOW2 0x04 #define LOWPERF_EXIT_MESSAGE "&eExited reduced performance mode" @@ -77,7 +81,7 @@ void* Gfx_RecreateAndLockVb(GfxResourceID* vb, VertexFormat fmt, int count); cc_bool Gfx_CheckTextureSize(int width, int height); /* Creates a new texture. (and also generates mipmaps if mipmaps) */ -/* Supported flags: TEXTURE_FLAG_MANAGED, TEXTURE_FLAG_DYNAMIC */ +/* See TEXTURE_FLAG values for supported flags */ /* NOTE: Only set mipmaps to true if Gfx_Mipmaps is also true, because whether textures use mipmapping may be either a per-texture or global state depending on the backend */ CC_API GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps); diff --git a/src/Graphics_N64.c b/src/Graphics_N64.c index 995bc8525..86f15a59f 100644 --- a/src/Graphics_N64.c +++ b/src/Graphics_N64.c @@ -33,6 +33,7 @@ void Gfx_Create(void) { Gfx.MaxTexSize = 1024; // TMEM only has 4 KB in it Gfx.Created = true; + Gfx.SupportsNonPowTwoTextures = true; Gfx_RestoreState(); GL_UpdateVsync(); } @@ -137,9 +138,10 @@ static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, cc_uint8 flags, cc_boo bmp->width * 4); } - rdpq_texparms_t params = (rdpq_texparms_t){ - .s.repeats = REPEAT_INFINITE, - .t.repeats = REPEAT_INFINITE, + rdpq_texparms_t params = + { + .s.repeats = (flags & TEXTURE_FLAG_NONPOW2) ? 1 : REPEAT_INFINITE, + .t.repeats = (flags & TEXTURE_FLAG_NONPOW2) ? 1 : REPEAT_INFINITE, }; // rdpq_tex_upload(TILE0, &tex->surface, ¶ms); diff --git a/src/Window_N64.c b/src/Window_N64.c index ead413380..282ad5469 100644 --- a/src/Window_N64.c +++ b/src/Window_N64.c @@ -36,6 +36,8 @@ void Window_Init(void) { WindowInfo.Exists = true; Input.Sources = INPUT_SOURCE_GAMEPAD; + DisplayInfo.ContentOffsetX = 10; + DisplayInfo.ContentOffsetY = 10; joypad_init(); } diff --git a/src/_GraphicsBase.h b/src/_GraphicsBase.h index f08b55a23..c461470f2 100644 --- a/src/_GraphicsBase.h +++ b/src/_GraphicsBase.h @@ -362,9 +362,13 @@ cc_bool Gfx_CheckTextureSize(int width, int height) { static GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps); GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) { - if (!Math_IsPowOf2(bmp->width) || !Math_IsPowOf2(bmp->height)) { + if (Gfx.SupportsNonPowTwoTextures && (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 */ + } else if (!Math_IsPowOf2(bmp->width) || !Math_IsPowOf2(bmp->height)) { Logger_Abort("Textures must have power of two dimensions"); } + if (Gfx.LostContext) return 0; if (!Gfx_CheckTextureSize(bmp->width, bmp->height)) return 0;