Code: Select all
/*
===============
GL_Upload32
===============
*/
void GL_Upload32 (gltexture_t *destination, unsigned *data, int width, int height, qboolean mipmap, qboolean alpha, qboolean flipRGBA)
{
int s;
int scaled_width, scaled_height;
int sw, sh;
u32 texbuffs;
u32 texbuffs_mip;
int max_mip_level;
//heap_iblock info;
for (scaled_width = 1 << 5 ; scaled_width < width ; scaled_width<<=1)
;
for (scaled_height = 1 << 5 ; scaled_height < height ; scaled_height<<=1)
;
if (scaled_width > gl_max_size.value)
scaled_width = gl_max_size.value;
if (scaled_height > gl_max_size.value)
scaled_height = gl_max_size.value;
if (scaled_width * scaled_height > sizeof(scaled)/4)
Sys_Error ("GL_Upload32: too big");
if (scaled_width != width || scaled_height != height)
{
GL_ResampleTexture (data, width, height, scaled, scaled_width, scaled_height);
} else {
memcpy(scaled, data, scaled_width * scaled_height * 4);
}
// start at mip level 0
// gets max allowable mipmap level for texture
max_mip_level = 0;
if (mipmap) {
sw = scaled_width;
sh = scaled_height;
while (sw > 4 && sh > 4)
{
sw >>= 1;
sh >>= 1;
max_mip_level++;
};
if (max_mip_level != 0) {
// account for memory offset
max_mip_level += 1;
}
}
//get exact buffer size of memory aligned on a 32byte boundery
texbuffs = GX_GetTexBufferSize (scaled_width, scaled_height, GX_TF_RGB5A3, mipmap ? GX_TRUE : GX_FALSE, max_mip_level);
destination->data = __lwp_heap_allocate(&texture_heap, texbuffs/*scaled_width * scaled_height * 2*/);
//__lwp_heap_getinfo(&texture_heap, &info);
//Con_Printf ("tex buff size %d\n", texbuffs);
//Con_Printf("Used Heap: %dM\n", info.used_size / (1024*1024));
if (!destination->data)
Sys_Error("GL_Upload32: Out of memory.");
s = scaled_width * scaled_height;
if (s & 31)
Sys_Error ("GL_Upload32: s&31");
if ((int)destination->data & 31)
Sys_Error ("GL_Upload32: destination->data&31");
destination->scaled_width = scaled_width;
destination->scaled_height = scaled_height;
//
// sBTODO finish mipmap implementation
//
if (mipmap == true) {
int mip_level;
int sw, sh;
unsigned mipmaptex[640*480];
texbuffs_mip = GX_GetTexBufferSize (scaled_width, scaled_height, GX_TF_RGB5A3, GX_TRUE, max_mip_level);
// this should never happen currently however,
// I plan on circumventing reloading textures
// which are already loaded, and this check will be neccesary
// once that happens
if (texbuffs < texbuffs_mip) {
// copy the texture mem to a temporary buffer
unsigned char * tempbuf = malloc(texbuffs);
memcpy(tempbuf,destination->data,texbuffs);
// free the used heap memory
if (!__lwp_heap_free(&texture_heap, destination->data))
Sys_Error ("Failed to free texture mem for mipmap");
// reallocate in a section of memory big enough for mipmaps and copy in the OG texture buffer
destination->data = __lwp_heap_allocate (&texture_heap, texbuffs_mip);
memcpy(destination->data,tempbuf,texbuffs);
free (tempbuf);
}
// copy texture to dst addr and convert to RGB5A3
GX_CopyRGBA8_To_RGB5A3((u16 *)destination->data, scaled, 0, 0, scaled_width, scaled_height, scaled_width, flipRGBA);
// copy texture to new buffer
memcpy((void *)mipmaptex, scaled, scaled_width * scaled_height * 4);
sw = scaled_width;
sh = scaled_height;
mip_level = 1;
//Con_Printf ("mip max: %i\n", mip_level);
//Con_Printf ("texbuffs: %d\n", texbuffs);
//Con_Printf ("texbuffs_mip: %d\n", texbuffs_mip);
while (sw > 4 && sh > 4 && mip_level < 10) {
// Operates in place, quartering the size of the texture
GX_MipMap ((byte *)mipmaptex, sw, sh);
sw >>= 1;
sh >>= 1;
if (sw < 4)
sw = 4;
if (sh < 4)
sh = 4;
//Con_Printf ("gen mipmaps: %i\n", mip_level);
// Calculate the offset and address of the mipmap
// taken from SDL2 Wii port :)
int offset = _calc_mipmap_offset(mip_level, scaled_width, scaled_height, 2);
unsigned char* dst_addr = (unsigned char*)destination->data;
dst_addr += offset;
//Con_Printf ("mipmap mem offset: %i\n", offset);
mip_level++;
GX_CopyRGBA8_To_RGB5A3((u16 *)dst_addr, (u32 *)mipmaptex, 0, 0, sw, sh, sw, flipRGBA);
DCFlushRange(dst_addr, sw * sh * 2);
GX_InitTexObj(&destination->gx_tex, dst_addr, sw, sh, GX_TF_RGB5A3, GX_REPEAT, GX_REPEAT, GX_TRUE);
if (destination->type != 1) {
GX_InitTexObjLOD(&destination->gx_tex, GX_LIN_MIP_LIN, GX_LIN_MIP_LIN, mip_level, max_mip_level, 0, GX_ENABLE, GX_ENABLE, GX_ANISO_2);
}
}
DCFlushRange(destination->data, texbuffs_mip/*scaled_width * scaled_height * 2*/);
GX_InvalidateTexAll();
GX_InitTexObj(&destination->gx_tex, destination->data, scaled_width, scaled_height, GX_TF_RGB5A3, GX_REPEAT, GX_REPEAT, GX_TRUE);
GX_InitTexObjLOD(&destination->gx_tex, GX_LIN_MIP_LIN, GX_LIN_MIP_LIN, 0, max_mip_level, 0, GX_ENABLE, GX_ENABLE, GX_ANISO_2);
//GX_LoadTexObj((&destination->gx_tex), GX_TEXMAP0);
if (vid_retromode.value == 1) {
GX_InitTexObjFilterMode(&destination->gx_tex, GX_NEAR_MIP_NEAR, GX_NEAR_MIP_NEAR);
} else {
GX_InitTexObjFilterMode(&destination->gx_tex, GX_LIN_MIP_LIN, GX_LIN_MIP_LIN);
}
} else {
GX_CopyRGBA8_To_RGB5A3((u16 *)destination->data, scaled, 0, 0, scaled_width, scaled_height, scaled_width, flipRGBA);
DCFlushRange(destination->data, texbuffs/*scaled_width * scaled_height * 2*/);
GX_InvalidateTexAll();
GX_InitTexObj(&destination->gx_tex, destination->data, scaled_width, scaled_height, GX_TF_RGB5A3, GX_REPEAT, GX_REPEAT, /*mipmap ? GX_TRUE :*/ GX_FALSE);
// do not init mipmaps for lightmaps
if (destination->type != 1) {
GX_InitTexObjLOD(&destination->gx_tex, GX_LIN_MIP_LIN, GX_LIN_MIP_LIN, 0, max_mip_level, 0, GX_ENABLE, GX_ENABLE, GX_ANISO_2);
}
}
}
This does load and display the textures properly, however I do not notice a difference visually at all.
Also, I apologize for any formatting errors, I did my best to make it look OK while embedded!