mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-01-22 17:12:25 -05:00
Dreamcast: Texture animations
This commit is contained in:
parent
1db63e3e19
commit
b1c9e4bd5e
1 changed files with 148 additions and 44 deletions
|
@ -219,55 +219,13 @@ void Gfx_SetDynamicVbData(GfxResourceID vb, void* vertices, int vCount) {
|
|||
*---------------------------------------------------------Textures--------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
void Gfx_BindTexture(GfxResourceID texId) {
|
||||
int tex = texId;
|
||||
glBindTexture(GL_TEXTURE_2D, (GLuint)texId);
|
||||
}
|
||||
|
||||
static void ConvertTexture(cc_uint16* dst, struct Bitmap* bmp) {
|
||||
cc_uint8* src = (cc_uint8*)bmp->scan0;
|
||||
|
||||
for (int y = 0; y < bmp->height; y++)
|
||||
{
|
||||
for (int x = 0; x < bmp->width; x++, dst++, src += 4)
|
||||
{
|
||||
// B8 G8 R8 A8 > B4 G4 R4 A4
|
||||
*dst = ((src[0] & 0xF0) >> 4) | (src[1] & 0xF0) | ((src[2] & 0xF0) << 4) | ((src[3] & 0xF0) << 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) {
|
||||
GLuint texId;
|
||||
glGenTextures(1, &texId);
|
||||
glBindTexture(GL_TEXTURE_2D, texId);
|
||||
|
||||
if (!Math_IsPowOf2(bmp->width) || !Math_IsPowOf2(bmp->height)) {
|
||||
Logger_Abort("Textures must have power of two dimensions");
|
||||
}
|
||||
|
||||
void* temp = Mem_Alloc(bmp->width * bmp->height, 2, "texture conversion buffer");
|
||||
ConvertTexture(temp, bmp);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bmp->width, bmp->height, 0, GL_BGRA,
|
||||
GL_UNSIGNED_SHORT_4_4_4_4_REV, temp);
|
||||
|
||||
Mem_Free(temp);
|
||||
return texId;
|
||||
}
|
||||
|
||||
void Gfx_UpdateTexture(GfxResourceID texId, int x, int y, struct Bitmap* part, int rowWidth, cc_bool mipmaps) {
|
||||
// TODO: Doesn't work and triggers assertion failure
|
||||
// https://github.com/Kazade/GLdc/blob/master/GL/texture.c#L1895
|
||||
}
|
||||
|
||||
void Gfx_UpdateTexturePart(GfxResourceID texId, int x, int y, struct Bitmap* part, cc_bool mipmaps) {
|
||||
Gfx_UpdateTexture(texId, x, y, part, part->width, mipmaps);
|
||||
gldcBindTexture((GLuint)texId);
|
||||
}
|
||||
|
||||
void Gfx_DeleteTexture(GfxResourceID* texId) {
|
||||
GLuint id = (GLuint)(*texId);
|
||||
if (!id) return;
|
||||
glDeleteTextures(1, &id);
|
||||
gldcDeleteTexture(id);
|
||||
*texId = 0;
|
||||
}
|
||||
|
||||
|
@ -275,6 +233,152 @@ void Gfx_EnableMipmaps(void) { }
|
|||
void Gfx_DisableMipmaps(void) { }
|
||||
|
||||
|
||||
static unsigned Interleave(unsigned x) {
|
||||
// Simplified "Interleave bits by Binary Magic Numbers" from
|
||||
// http://graphics.stanford.edu/~seander/bithacks.html#InterleaveBMN
|
||||
|
||||
x = (x | (x << 8)) & 0x00FF00FF;
|
||||
x = (x | (x << 4)) & 0x0F0F0F0F;
|
||||
x = (x | (x << 2)) & 0x33333333;
|
||||
x = (x | (x << 1)) & 0x55555555;
|
||||
return x;
|
||||
}
|
||||
|
||||
/*static int CalcTwiddledIndex(int x, int y, int w, int h) {
|
||||
// Twiddled index looks like this (starting from lowest numbered bits):
|
||||
// e.g. w > h: yx_yx_xx_xx
|
||||
// e.g. h > w: yx_yx_yy_yy
|
||||
// And can therefore be broken down into two components:
|
||||
// 1) interleaved lower bits
|
||||
// 2) masked and then shifted higher bits
|
||||
|
||||
int min_dimension = Math.Min(w, h);
|
||||
|
||||
int interleave_mask = min_dimension - 1;
|
||||
int interleaved_bits = Math_Log2(min_dimension);
|
||||
|
||||
int shifted_mask = (~0) & ~interleave_mask;
|
||||
// as lower interleaved bits contain both X and Y, need to adjust the
|
||||
// higher bit shift by number of interleaved bits used by other axis
|
||||
int shift_bits = interleaved_bits;
|
||||
|
||||
// For example, in the case of W=4 and H=8
|
||||
// the bit pattern is yx_yx_yx_Y
|
||||
// - lower 3 Y bits are interleaved
|
||||
// - upper 1 Y bit must be shifted right 3 bits
|
||||
|
||||
int lo_Y = Interleave(y & interleave_mask);
|
||||
int hi_Y = (y & shifted_mask) << shift_bits;
|
||||
int Y = lo_Y | hi_Y;
|
||||
|
||||
int lo_X = Interleave(x & interleave_mask) << 1;
|
||||
int hi_X = (x & shifted_mask) << shift_bits;
|
||||
int X = lo_X | hi_X;
|
||||
|
||||
return X | Y;
|
||||
}*/
|
||||
|
||||
#define Twiddle_CalcFactors(w, h) \
|
||||
min_dimension = min(w, h); \
|
||||
interleave_mask = min_dimension - 1; \
|
||||
interleaved_bits = Math_Log2(min_dimension); \
|
||||
shifted_mask = 0xFFFFFFFFU & ~interleave_mask; \
|
||||
shift_bits = interleaved_bits;
|
||||
|
||||
#define Twiddle_CalcY(y) \
|
||||
lo_Y = Interleave(y & interleave_mask); \
|
||||
hi_Y = (y & shifted_mask) << shift_bits; \
|
||||
Y = lo_Y | hi_Y;
|
||||
|
||||
#define Twiddle_CalcX(x) \
|
||||
lo_X = Interleave(x & interleave_mask) << 1; \
|
||||
hi_X = (x & shifted_mask) << shift_bits; \
|
||||
X = lo_X | hi_X;
|
||||
|
||||
|
||||
// B8 G8 R8 A8 > B4 G4 R4 A4
|
||||
#define BGRA8_to_BGRA4(src) \
|
||||
((src[0] & 0xF0) >> 4) | (src[1] & 0xF0) | ((src[2] & 0xF0) << 4) | ((src[3] & 0xF0) << 8);
|
||||
|
||||
static void ConvertTexture(cc_uint16* dst, struct Bitmap* bmp) {
|
||||
unsigned min_dimension;
|
||||
unsigned interleave_mask, interleaved_bits;
|
||||
unsigned shifted_mask, shift_bits;
|
||||
unsigned lo_Y, hi_Y, Y;
|
||||
unsigned lo_X, hi_X, X;
|
||||
Twiddle_CalcFactors(bmp->width, bmp->height);
|
||||
|
||||
cc_uint8* src = (cc_uint8*)bmp->scan0;
|
||||
for (int y = 0; y < bmp->height; y++)
|
||||
{
|
||||
Twiddle_CalcY(y);
|
||||
for (int x = 0; x < bmp->width; x++, src += 4)
|
||||
{
|
||||
Twiddle_CalcX(x);
|
||||
dst[X | Y] = BGRA8_to_BGRA4(src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GfxResourceID Gfx_CreateTexture(struct Bitmap* bmp, cc_uint8 flags, cc_bool mipmaps) {
|
||||
GLuint texId = gldcGenTexture();
|
||||
gldcBindTexture(texId);
|
||||
if (!Math_IsPowOf2(bmp->width) || !Math_IsPowOf2(bmp->height)) {
|
||||
Logger_Abort("Textures must have power of two dimensions");
|
||||
}
|
||||
|
||||
gldcAllocTexture(bmp->width, bmp->height, GL_RGBA,
|
||||
GL_UNSIGNED_SHORT_4_4_4_4_REV_TWID_KOS);
|
||||
|
||||
void* pixels;
|
||||
GLsizei width, height;
|
||||
gldcGetTexture(&pixels, &width, &height);
|
||||
ConvertTexture(pixels, bmp);
|
||||
return texId;
|
||||
}
|
||||
// TODO: struct GPUTexture ??
|
||||
static void ConvertSubTexture(cc_uint16* dst, int texWidth, int texHeight,
|
||||
int originX, int originY,
|
||||
struct Bitmap* bmp, int rowWidth) {
|
||||
unsigned min_dimension;
|
||||
unsigned interleave_mask, interleaved_bits;
|
||||
unsigned shifted_mask, shift_bits;
|
||||
unsigned lo_Y, hi_Y, Y;
|
||||
unsigned lo_X, hi_X, X;
|
||||
Twiddle_CalcFactors(texWidth, texHeight);
|
||||
|
||||
for (int y = 0; y < bmp->height; y++)
|
||||
{
|
||||
int dstY = y + originY;
|
||||
Twiddle_CalcY(dstY);
|
||||
cc_uint8* src = (cc_uint8*)(bmp->scan0 + rowWidth * y);
|
||||
|
||||
for (int x = 0; x < bmp->width; x++, src += 4)
|
||||
{
|
||||
int dstX = x + originX;
|
||||
Twiddle_CalcX(dstX);
|
||||
dst[X | Y] = BGRA8_to_BGRA4(src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Gfx_UpdateTexture(GfxResourceID texId, int x, int y, struct Bitmap* part, int rowWidth, cc_bool mipmaps) {
|
||||
gldcBindTexture(texId);
|
||||
|
||||
void* pixels;
|
||||
GLsizei width, height;
|
||||
gldcGetTexture(&pixels, &width, &height);
|
||||
|
||||
ConvertSubTexture(pixels, width, height,
|
||||
x, y, part, rowWidth);
|
||||
// TODO: Do we need to flush VRAM?
|
||||
}
|
||||
|
||||
void Gfx_UpdateTexturePart(GfxResourceID texId, int x, int y, struct Bitmap* part, cc_bool mipmaps) {
|
||||
Gfx_UpdateTexture(texId, x, y, part, part->width, mipmaps);
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*-----------------------------------------------------State management----------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
|
|
Loading…
Reference in a new issue