4bpp texture palette support, modified paletted_pcx sampled (USE_16C_PALETTE)
This commit is contained in:
parent
37110ba47f
commit
148962254a
|
@ -238,7 +238,12 @@ void _glUpdatePVRTextureContext(PolyContext *context, GLshort textureUnit) {
|
|||
TexturePalette* palette = _glGetSharedPalette(tx1->shared_bank);
|
||||
context->txr.format |= GPUPaletteSelect8BPP(palette->bank);
|
||||
} else {
|
||||
context->txr.format |= GPUPaletteSelect8BPP((tx1->palette) ? tx1->palette->bank : 0);
|
||||
if (tx1->palette->size != 16){
|
||||
context->txr.format |= GPUPaletteSelect8BPP((tx1->palette) ? tx1->palette->bank : 0);
|
||||
}
|
||||
else{
|
||||
context->txr.format |= GPUPaletteSelect4BPP((tx1->palette) ? tx1->palette->bank : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
58
GL/texture.c
58
GL/texture.c
|
@ -139,6 +139,41 @@ static void GPUTextureTwiddle8PPP(void* src, void* dst, uint32_t w, uint32_t h)
|
|||
}
|
||||
}
|
||||
|
||||
static void GPUTextureTwiddle4PPP(void* src, void* dst, uint32_t w, uint32_t h) {
|
||||
uint32_t x, y, yout, min, mask;
|
||||
|
||||
min = MIN(w, h);
|
||||
mask = min - 1;
|
||||
|
||||
uint8 * pixels;
|
||||
uint16 * vtex;
|
||||
pixels = (uint8 *) src;
|
||||
vtex = (uint16*)dst;
|
||||
|
||||
for (y=0; y<h; y += 2) {
|
||||
yout = y;
|
||||
for (x=0; x<w; x += 2) {
|
||||
|
||||
//Ozzy note: if x alignment is wrong just use version commented instead (possible error)
|
||||
#if 1
|
||||
vtex[TWIDOUT((x&mask)/2, (yout&mask)/2) +
|
||||
(x/min + yout/min)*min*min/4] =
|
||||
vtex[TWIDOUT((x&mask)/2, (yout&mask)/2) +
|
||||
(x/min + yout/min)*min*min/4] =
|
||||
((pixels[(x+y*w) >>1]&15)<<8) | ((pixels[(x+(y+1)*w) >>1]&15)<<12) |
|
||||
((pixels[(x+y*w) >>1]>>4)<<0) | ((pixels[(x+(y+1)*w) >>1]>>4)<<4);
|
||||
|
||||
#else
|
||||
vtex[TWIDOUT((x&mask)/2, (yout&mask)/2) +
|
||||
(x/min + yout/min)*min*min/4] =
|
||||
(pixels[(x+y*w) >>1]&15) | ((pixels[(x+(y+1)*w) >>1]&15)<<4) |
|
||||
((pixels[(x+y*w) >>1]>>4)<<8) | ((pixels[(x+(y+1)*w) >>1]>>4)<<12);
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void GPUTextureTwiddle16BPP(void * src, void* dst, uint32_t w, uint32_t h) {
|
||||
uint32_t x, y, yout, min, mask;
|
||||
|
||||
|
@ -188,6 +223,7 @@ void _glApplyColorTable(TexturePalette* src) {
|
|||
|
||||
GLushort i;
|
||||
GLushort offset = src->size * src->bank;
|
||||
|
||||
for(i = 0; i < src->width; ++i) {
|
||||
GLubyte* entry = &src->data[i * 4];
|
||||
if(INTERNAL_PALETTE_FORMAT == GL_RGBA8) {
|
||||
|
@ -925,6 +961,7 @@ static TextureConversionFunc _determineConversion(GLint internalFormat, GLenum f
|
|||
}
|
||||
} break;
|
||||
case GL_RGBA8: {
|
||||
|
||||
if(type == GL_UNSIGNED_BYTE && format == GL_RGBA) {
|
||||
return _rgba8888_to_rgba8888;
|
||||
} else if (type == GL_BYTE && format == GL_RGBA) {
|
||||
|
@ -1071,7 +1108,7 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
|||
return;
|
||||
}
|
||||
} else {
|
||||
if(internalFormat != GL_COLOR_INDEX8_EXT) {
|
||||
if(internalFormat != GL_COLOR_INDEX8_EXT && internalFormat != GL_COLOR_INDEX4_EXT) {
|
||||
INFO_MSG("");
|
||||
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
||||
return;
|
||||
|
@ -1129,7 +1166,7 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
|||
return;
|
||||
}
|
||||
|
||||
GLboolean isPaletted = (internalFormat == GL_COLOR_INDEX8_EXT) ? GL_TRUE : GL_FALSE;
|
||||
GLboolean isPaletted = (internalFormat == GL_COLOR_INDEX8_EXT || internalFormat == GL_COLOR_INDEX4_EXT) ? GL_TRUE : GL_FALSE;
|
||||
|
||||
/* Calculate the format that we need to convert the data to */
|
||||
GLuint pvr_format = _determinePVRFormat(internalFormat, type);
|
||||
|
@ -1161,6 +1198,11 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
|||
GLint destStride = isPaletted ? 1 : 2;
|
||||
GLuint bytes = (width * height * destStride);
|
||||
|
||||
//special case 4bpp
|
||||
if(internalFormat == GL_COLOR_INDEX4_EXT){
|
||||
bytes >>= 1;
|
||||
}
|
||||
|
||||
if(!active->data) {
|
||||
assert(active);
|
||||
assert(width);
|
||||
|
@ -1302,8 +1344,14 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
|||
|
||||
if(internalFormat == GL_COLOR_INDEX8_EXT) {
|
||||
GPUTextureTwiddle8PPP((void*) pixels, targetData, width, height);
|
||||
} else {
|
||||
GPUTextureTwiddle16BPP((void*) pixels, targetData, width, height);
|
||||
}
|
||||
else{
|
||||
if(internalFormat == GL_COLOR_INDEX4_EXT) {
|
||||
GPUTextureTwiddle4PPP((void*) pixels, targetData, width, height);
|
||||
}
|
||||
else {
|
||||
GPUTextureTwiddle16BPP((void*) pixels, targetData, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
/* We make sure we remove nontwiddled and add twiddled. We could always
|
||||
|
@ -1487,7 +1535,7 @@ GLAPI void APIENTRY glColorTableEXT(GLenum target, GLenum internalFormat, GLsize
|
|||
}
|
||||
|
||||
palette->data = (GLubyte*) malloc(width * 4);
|
||||
palette->format = format;
|
||||
palette->format = format; //Ozzy:was previously forcing to GL_RGBA for testing.
|
||||
palette->width = width;
|
||||
palette->size = (width > 16) ? 256 : 16;
|
||||
assert(palette->size == 16 || palette->size == 256);
|
||||
|
|
|
@ -19,19 +19,24 @@
|
|||
KOS_INIT_ROMDISK(romdisk);
|
||||
#endif
|
||||
|
||||
/* using 4bpp textures from BMP files instead of 8bpp from PCX files */
|
||||
#define USE_16C_PALETTE
|
||||
|
||||
/* floats for x rotation, y rotation, z rotation */
|
||||
float xrot, yrot, zrot;
|
||||
|
||||
int textures[3];
|
||||
|
||||
typedef struct {
|
||||
unsigned int height;
|
||||
unsigned int width;
|
||||
unsigned int palette_width;
|
||||
uint32_t height;
|
||||
uint32_t width;
|
||||
uint32_t palette_width;
|
||||
char* palette;
|
||||
char* data;
|
||||
} Image;
|
||||
|
||||
#ifndef USE_16C_PALETTE
|
||||
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
|
||||
|
@ -135,11 +140,234 @@ int LoadPalettedPCX(const char* filename, Image* image) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define BMP_BI_RGB 0L
|
||||
#define BMP_BI_UNCOMPRESSED 0L
|
||||
#define BMP_BI_RLE8 1L
|
||||
#define BMP_BI_RLE4 2L
|
||||
#define BMP_BI_BITFIELDS 3L
|
||||
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
|
||||
typedef struct BITMAP_FILE_HEADER
|
||||
{
|
||||
uint16_t Type;
|
||||
uint32_t Size;
|
||||
uint16_t Reserved1;
|
||||
uint16_t Reserved2;
|
||||
uint32_t OffBits;
|
||||
} BITMAP_FILE_HEADER;
|
||||
|
||||
typedef struct BITMAP_INFO_HEADER
|
||||
{
|
||||
uint32_t Size;
|
||||
int32_t Width;
|
||||
int32_t Height;
|
||||
uint16_t Planes;
|
||||
uint16_t BitCount;
|
||||
uint32_t Compression;
|
||||
uint32_t SizeImage;
|
||||
int32_t XPelsPerMeter;
|
||||
int32_t YPelsPerMeter;
|
||||
uint32_t ClrUsed;
|
||||
uint32_t ClrImportant;
|
||||
} BITMAP_INFO_HEADER;
|
||||
|
||||
typedef struct RGB_QUAD
|
||||
{
|
||||
uint8_t Blue;
|
||||
uint8_t Green;
|
||||
uint8_t Red;
|
||||
uint8_t Reserved;
|
||||
} RGB_QUAD;
|
||||
|
||||
typedef struct BITMAP_INFO
|
||||
{
|
||||
BITMAP_INFO_HEADER Header;
|
||||
RGB_QUAD Colors[1];
|
||||
} BITMAP_INFO;
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
/* some global variables used to load a 4bpp BMP file */
|
||||
static BITMAP_FILE_HEADER BmpFileHeader;
|
||||
static BITMAP_INFO_HEADER BmpInfoHeader;
|
||||
static RGB_QUAD BmpRgbQuad[256];
|
||||
static uint8_t BmpPal[256 * 3];
|
||||
|
||||
int BMP_Infos(FILE *pFile, uint32_t *width, uint32_t *height)
|
||||
{
|
||||
if (!pFile)
|
||||
return 0;
|
||||
|
||||
if (fread(&BmpFileHeader.Type, 1, 2, pFile) != 2)
|
||||
return 0;
|
||||
if (fread(&BmpFileHeader.Size, 1, 4, pFile) != 4)
|
||||
return 0;
|
||||
if (fread(&BmpFileHeader.Reserved1, 1, 2, pFile) != 2)
|
||||
return 0;
|
||||
if (fread(&BmpFileHeader.Reserved2, 1, 2, pFile) != 2)
|
||||
return 0;
|
||||
if (fread(&BmpFileHeader.OffBits, 1, 4, pFile) != 4)
|
||||
return 0;
|
||||
if (fread(&BmpInfoHeader.Size, 1, 4, pFile) != 4)
|
||||
return 0;
|
||||
if (fread(&BmpInfoHeader.Width, 1, 4, pFile) != 4)
|
||||
return 0;
|
||||
if (fread(&BmpInfoHeader.Height, 1, 4, pFile) != 4)
|
||||
return 0;
|
||||
if (fread(&BmpInfoHeader.Planes, 1, 2, pFile) != 2)
|
||||
return 0;
|
||||
if (fread(&BmpInfoHeader.BitCount, 1, 2, pFile) != 2)
|
||||
return 0;
|
||||
if (fread(&BmpInfoHeader.Compression, 1, 4, pFile) != 4)
|
||||
return 0;
|
||||
if (fread(&BmpInfoHeader.SizeImage, 1, 4, pFile) != 4)
|
||||
return 0;
|
||||
if (fread(&BmpInfoHeader.XPelsPerMeter, 1, 4, pFile) != 4)
|
||||
return 0;
|
||||
if (fread(&BmpInfoHeader.YPelsPerMeter, 1, 4, pFile) != 4)
|
||||
return 0;
|
||||
if (fread(&BmpInfoHeader.ClrUsed, 1, 4, pFile) != 4)
|
||||
return 0;
|
||||
if (fread(&BmpInfoHeader.ClrImportant, 1, 4, pFile) != 4)
|
||||
return 0;
|
||||
|
||||
*width = (uint32_t)BmpInfoHeader.Width;
|
||||
*height = (uint32_t)BmpInfoHeader.Height;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int BMP_GetPalette(FILE *pFile)
|
||||
{
|
||||
int32_t i,bitCount;
|
||||
|
||||
if (BmpInfoHeader.BitCount == 4) {
|
||||
|
||||
if (!BmpInfoHeader.ClrImportant) {
|
||||
BmpInfoHeader.ClrImportant = 16;
|
||||
}
|
||||
bitCount = BmpInfoHeader.ClrImportant * sizeof(RGB_QUAD);
|
||||
|
||||
if (fread(BmpRgbQuad, 1, bitCount, pFile) != bitCount){
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < BmpInfoHeader.ClrImportant; i++) {
|
||||
|
||||
BmpPal[i * 3] = (uint8_t)BmpRgbQuad[i].Red;
|
||||
BmpPal[i * 3 + 1] = (uint8_t)BmpRgbQuad[i].Green;
|
||||
BmpPal[i * 3 + 2] = (uint8_t)BmpRgbQuad[i].Blue;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* maybe not the best BMP loader... */
|
||||
int BMP_Depack(FILE *pFile,char *pZone)
|
||||
{
|
||||
char PadRead[4];
|
||||
int32_t i, j, Offset, PadSize, pix, c;
|
||||
|
||||
if (BmpInfoHeader.Compression != BMP_BI_RGB)
|
||||
return 0;
|
||||
|
||||
PadSize = (BmpInfoHeader.Width & 3);
|
||||
|
||||
PadSize = (4 - (BmpInfoHeader.Width & 3)) & 3;
|
||||
|
||||
for (i = BmpInfoHeader.Height - 1; (i > -1); i--) {
|
||||
Offset = i * BmpInfoHeader.Width / 2;
|
||||
|
||||
if (PadSize < 4) {
|
||||
for (j = 0; (j < BmpInfoHeader.Width / 2); j++) {
|
||||
if (!fread(&c, 1, 1, pFile)) {
|
||||
return 0;
|
||||
}
|
||||
pZone[Offset + j] = c;
|
||||
}
|
||||
}
|
||||
|
||||
if (PadSize) {
|
||||
if (fread(PadRead, PadSize, 1, pFile) != PadSize) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i != -1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int LoadPalettedBMP(const char* filename, Image* image)
|
||||
{
|
||||
FILE *fp;
|
||||
uint32_t bytes;
|
||||
|
||||
if (filename == NULL || image == NULL) {
|
||||
printf("Invalid NULL argument\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
fp = fopen(filename, "rb");
|
||||
if (fp == NULL) {
|
||||
printf("Unable to open file\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!BMP_Infos(fp, &image->width, &image->height)) {
|
||||
printf("Error reading BMP:%s header\n",filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!BMP_GetPalette(fp)) {
|
||||
printf("Only 16c BMP are supported for this sample");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* store palette information */
|
||||
image->palette = BmpPal;
|
||||
image->palette_width = 16;
|
||||
|
||||
|
||||
bytes = sizeof(char) * image->width * image->height;
|
||||
/* 4bpp is half byte size*/
|
||||
bytes >>= 1;
|
||||
|
||||
image->data = (char*)malloc(bytes);
|
||||
if (image->data == NULL) {
|
||||
printf("Error allocating image data");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!BMP_Depack(fp, image->data)) {
|
||||
printf("Error depacking BMP:%s",filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
// Load Bitmaps And Convert To Textures
|
||||
void LoadGLTextures() {
|
||||
// Load Texture
|
||||
Image image1, image2;
|
||||
|
||||
#ifndef USE_16C_PALETTE
|
||||
if(!LoadPalettedPCX("/rd/NeHe.pcx", &image1)) {
|
||||
exit(1);
|
||||
}
|
||||
|
@ -147,6 +375,15 @@ void LoadGLTextures() {
|
|||
if(!LoadPalettedPCX("/rd/NeHe-Alpha.pcx", &image2)) {
|
||||
exit(1);
|
||||
}
|
||||
#else
|
||||
if (!LoadPalettedBMP("/rd/NeHe.bmp", &image1)) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!LoadPalettedBMP("/rd/NeHe-Alpha.bmp", &image2)) {
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
glEnable(GL_SHARED_TEXTURE_PALETTE_EXT);
|
||||
|
||||
|
@ -173,7 +410,11 @@ void LoadGLTextures() {
|
|||
|
||||
// 2d texture, level of detail 0 (normal), 3 components (red, green, blue), x size from image, y size from image,
|
||||
// border 0 (normal), rgb color data, unsigned byte data, and finally the data itself.
|
||||
#ifndef USE_16C_PALETTE
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, image1.width, image1.height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, image1.data);
|
||||
#else
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX4_EXT, image1.width, image1.height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, image1.data);
|
||||
#endif
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, textures[1]); // 2d texture (x and y size)
|
||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR); // scale linearly when image bigger than texture
|
||||
|
@ -184,7 +425,11 @@ void LoadGLTextures() {
|
|||
|
||||
// 2d texture, level of detail 0 (normal), 3 components (red, green, blue), x size from image, y size from image,
|
||||
// border 0 (normal), rgb color data, unsigned byte data, and finally the data itself.
|
||||
#ifndef USE_16C_PALETTE
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, image1.width, image1.height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, image1.data);
|
||||
#else
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX4_EXT, image1.width, image1.height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, image1.data);
|
||||
#endif
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, textures[2]);
|
||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
@ -199,8 +444,11 @@ void LoadGLTextures() {
|
|||
}
|
||||
|
||||
glColorTableEXT(GL_TEXTURE_2D, GL_RGBA8, image2.palette_width, GL_RGBA, GL_UNSIGNED_BYTE, new_palette);
|
||||
|
||||
#ifndef USE_16C_PALETTE
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, image2.width, image2.height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, image2.data);
|
||||
#else
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX4_EXT, image2.width, image2.height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, image2.data);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* A general OpenGL initialization function. Sets all of the initial parameters. */
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 192 KiB After Width: | Height: | Size: 64 KiB |
Loading…
Reference in New Issue
Block a user