diff --git a/src/Drawer2D.c b/src/Drawer2D.c index 3dd40a3b9..ddf95e438 100644 --- a/src/Drawer2D.c +++ b/src/Drawer2D.c @@ -157,8 +157,7 @@ void Context2D_Alloc(struct Context2D* ctx, int width, int height) { width = Math_NextPowOf2(width); height = Math_NextPowOf2(height); } else if (Gfx.NonPowTwoTexturesSupport == GFX_NONPOW2_UPLOAD) { - /* Can upload texture without needing to pad up to power of two height */ - width = Math_NextPowOf2(width); + /* Can upload texture without needing to pad up to power of two */ } if (Gfx.MinTexWidth) { width = max(width, Gfx.MinTexWidth); } @@ -326,16 +325,17 @@ void Context2D_MakeTexture(struct Texture* tex, struct Context2D* ctx) { tex->width = nouv ? ctx->bmp.width : ctx->width; tex->height = nouv ? ctx->bmp.height : ctx->height; - tex->uv.u1 = 0.0f; tex->uv.v1 = 0.0f; - if (Gfx.NonPowTwoTexturesSupport == GFX_NONPOW2_FULL) { - tex->uv.u2 = 1.0f; - tex->uv.v2 = 1.0f; - } else if (Gfx.NonPowTwoTexturesSupport == GFX_NONPOW2_UPLOAD) { - tex->uv.u2 = (float)ctx->width / (float)ctx->bmp.width; - tex->uv.v2 = (float)ctx->height / (float)Math_NextPowOf2(ctx->bmp.height); + tex->uv.u1 = 0.0f; + tex->uv.v1 = 0.0f; + tex->uv.u2 = Context2D_CalcUV(ctx->width, ctx->bmp.width); + tex->uv.v2 = Context2D_CalcUV(ctx->height, ctx->bmp.height); +} + +float Context2D_CalcUV(int pixels, int axisLen) { + if (Gfx.NonPowTwoTexturesSupport == GFX_NONPOW2_UPLOAD) { + return (float)pixels / (float)Math_NextPowOf2(axisLen); } else { - tex->uv.u2 = (float)ctx->width / (float)ctx->bmp.width; - tex->uv.v2 = (float)ctx->height / (float)ctx->bmp.height; + return (float)pixels / (float)axisLen; } } diff --git a/src/Drawer2D.h b/src/Drawer2D.h index 79616881d..0e2f8ec4f 100644 --- a/src/Drawer2D.h +++ b/src/Drawer2D.h @@ -45,6 +45,7 @@ CC_API void Context2D_Wrap(struct Context2D* ctx, struct Bitmap* bmp); CC_API void Context2D_Free(struct Context2D* ctx); /* Creates a texture consisting of the pixels from the backing bitmap of the given 2D context */ CC_API void Context2D_MakeTexture(struct Texture* tex, struct Context2D* ctx); +float Context2D_CalcUV(int pixels, int axisLen); /* Draws text using the given font at the given coordinates */ CC_API void Context2D_DrawText(struct Context2D* ctx, struct DrawTextArgs* args, int x, int y); diff --git a/src/Graphics_NDS.c b/src/Graphics_NDS.c index fdf583579..9c72c4533 100644 --- a/src/Graphics_NDS.c +++ b/src/Graphics_NDS.c @@ -143,6 +143,7 @@ void Gfx_Create(void) { vramSetBankE(VRAM_E_TEX_PALETTE); Gfx_SetFaceCulling(false); + Gfx.NonPowTwoTexturesSupport = GFX_NONPOW2_UPLOAD; } cc_bool Gfx_TryRestoreContext(void) { @@ -349,24 +350,27 @@ GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, CCTexture* tex = Mem_TryAllocCleared(1, sizeof(CCTexture)); if (!tex) return 0; - tex->width = bmp->width; - tex->height = bmp->height; + int dst_w = Math_NextPowOf2(bmp->width); + int dst_h = Math_NextPowOf2(bmp->height); + + tex->width = dst_w; + tex->height = dst_h; BitmapCol palette[256]; int pal_count = CalcPalette(palette, bmp, rowWidth); int tex_size, tex_fmt; if (pal_count <= 4) { - tex_size = bmp->width * bmp->height / 4; // 2 bits per pixel + tex_size = dst_w * dst_h / 4; // 2 bits per pixel tex_fmt = GL_RGB4; } else if (pal_count <= 16) { - tex_size = bmp->width * bmp->height / 2; // 4 bits per pixel + tex_size = dst_w * dst_h / 2; // 4 bits per pixel tex_fmt = GL_RGB16; } else if (pal_count <= 256) { - tex_size = bmp->width * bmp->height; // 8 bits per pixel + tex_size = dst_w * dst_h; // 8 bits per pixel tex_fmt = GL_RGB256; } else { - tex_size = bmp->width * bmp->height * 2; // 16 bits per pixel + tex_size = dst_w * dst_h * 2; // 16 bits per pixel tex_fmt = GL_RGBA; } @@ -384,15 +388,15 @@ GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, u32 banks = vramSetPrimaryBanks(VRAM_A_LCD, VRAM_B_LCD, VRAM_C_LCD, VRAM_D_LCD); int stride; - int width = bmp->width, height = bmp->height; + int src_w = bmp->width, src_h = bmp->height; BitmapCol* row = bmp->scan0; if (tex_fmt == GL_RGB4) { - stride = width >> 3; + stride = dst_w >> 3; - for (int y = 0; y < height; y++, row += rowWidth) + for (int y = 0; y < src_h; y++, row += rowWidth) { - for (int x = 0; x < width; x++) + for (int x = 0; x < src_w; x++) { int idx = FindInPalette(palette, pal_count, row[x]); @@ -405,11 +409,11 @@ GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, CopyHWords(tmp, addr + stride * y, stride); } } else if (tex_fmt == GL_RGB16) { - stride = width >> 2; + stride = dst_w >> 2; - for (int y = 0; y < height; y++, addr += stride, row += rowWidth) + for (int y = 0; y < src_h; y++, addr += stride, row += rowWidth) { - for (int x = 0; x < width; x++) + for (int x = 0; x < src_w; x++) { int idx = FindInPalette(palette, pal_count, row[x]); @@ -422,20 +426,20 @@ GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, CopyHWords(tmp, addr, stride); } } else if (tex_fmt == GL_RGB256) { - stride = width >> 1; + stride = dst_w >> 1; - for (int y = 0; y < height; y++, addr += stride, row += rowWidth) + for (int y = 0; y < src_h; y++, addr += stride, row += rowWidth) { - for (int x = 0; x < width; x++) + for (int x = 0; x < src_w; x++) { tmp[x] = FindInPalette(palette, pal_count, row[x]); } CopyHWords(tmp, addr, stride); } } else { - stride = width; + stride = dst_w; - for (int y = 0; y < height; y++, addr += stride, row += rowWidth) + for (int y = 0; y < src_h; y++, addr += stride, row += rowWidth) { CopyHWords(row, addr, stride); } @@ -443,8 +447,8 @@ GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, vramRestorePrimaryBanks(banks); - int sSize = (Math_ilog2(tex->width) - 3) << 20; - int tSize = (Math_ilog2(tex->height) - 3) << 23; + int sSize = (Math_ilog2(dst_w) - 3) << 20; + int tSize = (Math_ilog2(dst_h) - 3) << 23; tex->texFormat = (offset >> 3) | sSize | tSize | (tex_fmt << 26) | GL_TEXTURE_WRAP_S | GL_TEXTURE_WRAP_T | TEXGEN_TEXCOORD | GL_TEXTURE_COLOR0_TRANSPARENT; diff --git a/src/Graphics_PS3.c b/src/Graphics_PS3.c index 080f92a4f..d3fc05ff6 100644 --- a/src/Graphics_PS3.c +++ b/src/Graphics_PS3.c @@ -260,6 +260,7 @@ void Gfx_Create(void) { Gfx_RestoreState(); gfx_format = -1; + Gfx.NonPowTwoTexturesSupport = GFX_NONPOW2_UPLOAD; } void Gfx_Free(void) { Gfx_FreeState(); } @@ -608,24 +609,27 @@ static CC_INLINE void TwiddleCalcFactors(unsigned w, unsigned h, } 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); + int size = dst_w * dst_h * 4; + CCTexture* tex = (CCTexture*)rsxMemalign(128, 128 + size); - tex->width = bmp->width; - tex->height = bmp->height; + tex->width = dst_w; + tex->height = dst_h; cc_uint32* dst = tex->pixels; - int width = bmp->width, height = bmp->height; + int src_w = bmp->width, src_h = bmp->height; unsigned maskX, maskY; unsigned X = 0, Y = 0; - TwiddleCalcFactors(width, height, &maskX, &maskY); + TwiddleCalcFactors(dst_w, dst_h, &maskX, &maskY); - for (int y = 0; y < height; y++) + for (int y = 0; y < src_h; y++) { cc_uint32* src = bmp->scan0 + y * rowWidth; X = 0; - for (int x = 0; x < width; x++, src++) + for (int x = 0; x < src_w; x++, src++) { dst[X | Y] = *src; X = (X - maskX) & maskX; diff --git a/src/Gui.c b/src/Gui.c index c802c1948..046a24f81 100644 --- a/src/Gui.c +++ b/src/Gui.c @@ -401,7 +401,7 @@ void TextAtlas_Make(struct TextAtlas* atlas, const cc_string* chars, struct Font } Context2D_Free(&ctx); - atlas->uScale = 1.0f / (float)ctx.bmp.width; + atlas->uScale = Context2D_CalcUV(1, ctx.bmp.width); atlas->tex.uv.u2 = atlas->offset * atlas->uScale; atlas->tex.width = atlas->offset; } diff --git a/src/dreamcast/Graphics_Dreamcast.c b/src/dreamcast/Graphics_Dreamcast.c index c4b0914b9..bfddab952 100644 --- a/src/dreamcast/Graphics_Dreamcast.c +++ b/src/dreamcast/Graphics_Dreamcast.c @@ -754,17 +754,20 @@ GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, if (pal_count > 0) ApplyPalette(palette, pal_count, pal_index); } - tex->log2_w = Log2Dimension(bmp->width); - tex->log2_h = Log2Dimension(bmp->height); + int dst_w = Math_NextPowOf2(bmp->width); + int dst_h = Math_NextPowOf2(bmp->height); + + tex->log2_w = Math_ilog2(dst_w); + tex->log2_h = Math_ilog2(dst_h); 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; + tex->size = dst_w * dst_h / 2; } else { tex->format = PVR_TXRFMT_ARGB4444; // 16 bpp = 1 pixel in 2 bytes - tex->size = bmp->width * bmp->height * 2; + tex->size = dst_w * dst_h * 2; } tex->data = texmem_alloc(tex->size); diff --git a/src/psvita/Graphics_PSVita.c b/src/psvita/Graphics_PSVita.c index fffb836a4..0b40def54 100644 --- a/src/psvita/Graphics_PSVita.c +++ b/src/psvita/Graphics_PSVita.c @@ -579,6 +579,7 @@ void Gfx_Create(void) { Gfx_SetDepthTest(true); Gfx_SetVertexFormat(VERTEX_FORMAT_COLOURED); Gfx_RestoreState(); + Gfx.NonPowTwoTexturesSupport = GFX_NONPOW2_UPLOAD; } void Gfx_Free(void) { @@ -703,21 +704,24 @@ static CC_INLINE void TwiddleCalcFactors(unsigned w, unsigned h, *---------------------------------------------------------Textures--------------------------------------------------------* *#########################################################################################################################*/ 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); + int size = dst_w * dst_h * 4; + struct GPUTexture* tex = GPUTexture_Alloc(size); cc_uint32* dst = tex->data; - int width = bmp->width, height = bmp->height; + int src_w = bmp->width, src_h = bmp->height; unsigned maskX, maskY; unsigned X = 0, Y = 0; - TwiddleCalcFactors(width, height, &maskX, &maskY); + TwiddleCalcFactors(dst_w, dst_h, &maskX, &maskY); - for (int y = 0; y < height; y++) + for (int y = 0; y < src_h; y++) { cc_uint32* src = bmp->scan0 + y * rowWidth; X = 0; - for (int x = 0; x < width; x++, src++) + for (int x = 0; x < src_w; x++, src++) { dst[X | Y] = *src; X = (X - maskX) & maskX; @@ -726,7 +730,7 @@ GfxResourceID Gfx_AllocTexture(struct Bitmap* bmp, int rowWidth, cc_uint8 flags, } sceGxmTextureInitSwizzled(&tex->texture, dst, - SCE_GXM_TEXTURE_FORMAT_A8B8G8R8, width, height, 0); + SCE_GXM_TEXTURE_FORMAT_A8B8G8R8, dst_w, dst_h, 0); sceGxmTextureSetUAddrMode(&tex->texture, SCE_GXM_TEXTURE_ADDR_REPEAT); sceGxmTextureSetVAddrMode(&tex->texture, SCE_GXM_TEXTURE_ADDR_REPEAT); diff --git a/src/xbox/Graphics_Xbox.c b/src/xbox/Graphics_Xbox.c index 587e7e5a9..c59d4ac0b 100644 --- a/src/xbox/Graphics_Xbox.c +++ b/src/xbox/Graphics_Xbox.c @@ -118,6 +118,7 @@ void Gfx_Create(void) { SetupShaders(); Gfx_SetVertexFormat(VERTEX_FORMAT_COLOURED); ResetState(); + Gfx.NonPowTwoTexturesSupport = GFX_NONPOW2_UPLOAD; // 1x1 dummy white texture struct Bitmap bmp; @@ -174,25 +175,28 @@ static CC_INLINE void TwiddleCalcFactors(unsigned w, unsigned h, 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) { - int size = bmp->width * bmp->height * 4; + int dst_w = Math_NextPowOf2(bmp->width); + int dst_h = Math_NextPowOf2(bmp->height); + int size = dst_w * dst_h * 4; + CCTexture* tex = Mem_Alloc(1, sizeof(CCTexture), "GPU texture"); tex->pixels = MmAllocateContiguousMemoryEx(size, 0, MAX_RAM_ADDR, 0, PAGE_WRITECOMBINE | PAGE_READWRITE); - tex->log2_w = Log2Dimension(bmp->width); - tex->log2_h = Log2Dimension(bmp->height); + tex->log2_w = Math_ilog2(dst_w); + tex->log2_h = Math_ilog2(dst_h); cc_uint32* dst = tex->pixels; - int width = bmp->width, height = bmp->height; + int src_w = bmp->width, src_h = bmp->height; unsigned maskX, maskY; unsigned X = 0, Y = 0; - TwiddleCalcFactors(width, height, &maskX, &maskY); + TwiddleCalcFactors(dst_w, dst_h, &maskX, &maskY); - for (int y = 0; y < height; y++) + for (int y = 0; y < src_h; y++) { cc_uint32* src = bmp->scan0 + y * rowWidth; X = 0; - for (int x = 0; x < width; x++, src++) + for (int x = 0; x < src_w; x++, src++) { dst[X | Y] = *src; X = (X - maskX) & maskX;