Automatically twiddle non-twiddled palette data

This commit is contained in:
Luke Benstead 2019-03-07 21:21:30 +00:00
parent 3e1ed8a5f7
commit d7342fa0c0
10 changed files with 349 additions and 7 deletions

View File

@ -3,6 +3,7 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <math.h> #include <math.h>
#include <assert.h>
#include "../include/gl.h" #include "../include/gl.h"
#include "../include/glext.h" #include "../include/glext.h"
@ -481,6 +482,13 @@ static inline void genElementsCommon(
const IndexParseFunc indexFunc = _calcParseIndexFunc(type); const IndexParseFunc indexFunc = _calcParseIndexFunc(type);
assert(vertexFunc);
assert(diffuseFunc);
assert(uvFunc);
assert(stFunc);
assert(normalFunc);
assert(indexFunc);
GLsizei i = 0; GLsizei i = 0;
const GLubyte* idx = iptr; const GLubyte* idx = iptr;
ClipVertex* vertex = output; ClipVertex* vertex = output;
@ -622,6 +630,12 @@ static inline void genArraysCommon(
const FloatParseFunc stFunc = _calcSTParseFunc(); const FloatParseFunc stFunc = _calcSTParseFunc();
const FloatParseFunc normalFunc = _calcNormalParseFunc(); const FloatParseFunc normalFunc = _calcNormalParseFunc();
assert(vertexFunc);
assert(diffuseFunc);
assert(uvFunc);
assert(stFunc);
assert(normalFunc);
GLsizei i = count; GLsizei i = count;
ClipVertex* vertex = output; ClipVertex* vertex = output;

View File

@ -547,11 +547,7 @@ static GLuint _determinePVRFormat(GLint internalFormat, GLenum type) {
case GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_TWID_KOS: case GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_TWID_KOS:
return PVR_TXRFMT_ARGB1555 | PVR_TXRFMT_TWIDDLED | PVR_TXRFMT_VQ_ENABLE; return PVR_TXRFMT_ARGB1555 | PVR_TXRFMT_TWIDDLED | PVR_TXRFMT_VQ_ENABLE;
case GL_COLOR_INDEX8_EXT: case GL_COLOR_INDEX8_EXT:
if(type == GL_UNSIGNED_BYTE_TWID_KOS) { return PVR_TXRFMT_PAL8BPP | PVR_TXRFMT_TWIDDLED;
return PVR_TXRFMT_PAL8BPP | PVR_TXRFMT_TWIDDLED;
} else {
return PVR_TXRFMT_PAL8BPP | PVR_TXRFMT_NONTWIDDLED;
}
default: default:
return 0; return 0;
} }
@ -713,6 +709,20 @@ GLboolean _glIsMipmapComplete(const TextureObject* obj) {
return GL_TRUE; return GL_TRUE;
} }
static inline GLuint morton_1by1(GLuint x) {
x &= 0x0000ffff; // x = ---- ---- ---- ---- fedc ba98 7654 3210
x = (x ^ (x << 8)) & 0x00ff00ff; // x = ---- ---- fedc ba98 ---- ---- 7654 3210
x = (x ^ (x << 4)) & 0x0f0f0f0f; // x = ---- fedc ---- ba98 ---- 7654 ---- 3210
x = (x ^ (x << 2)) & 0x33333333; // x = --fe --dc --ba --98 --76 --54 --32 --10
x = (x ^ (x << 1)) & 0x55555555; // x = -f-e -d-c -b-a -9-8 -7-6 -5-4 -3-2 -1-0
return x;
}
static inline GLuint morton_index(GLuint x, GLuint y) {
return (morton_1by1(y) << 1) + morton_1by1(x);
}
void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat, void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
GLsizei width, GLsizei height, GLint border, GLsizei width, GLsizei height, GLint border,
GLenum format, GLenum type, const GLvoid *data) { GLenum format, GLenum type, const GLvoid *data) {
@ -835,6 +845,7 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
/* Let's assume we need to convert */ /* Let's assume we need to convert */
GLboolean needsConversion = GL_TRUE; GLboolean needsConversion = GL_TRUE;
GLboolean needsTwiddling = GL_FALSE;
/* /*
* These are the only formats where the source format passed in matches the pvr format. * These are the only formats where the source format passed in matches the pvr format.
@ -843,6 +854,7 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
if(format == GL_COLOR_INDEX) { if(format == GL_COLOR_INDEX) {
/* Don't convert color indexes */ /* Don't convert color indexes */
needsConversion = GL_FALSE; needsConversion = GL_FALSE;
needsTwiddling = type == GL_UNSIGNED_BYTE;
} else if(format == GL_BGRA && type == GL_UNSIGNED_SHORT_4_4_4_4_REV && internalFormat == GL_RGBA) { } else if(format == GL_BGRA && type == GL_UNSIGNED_SHORT_4_4_4_4_REV && internalFormat == GL_RGBA) {
needsConversion = GL_FALSE; needsConversion = GL_FALSE;
} else if(format == GL_BGRA && type == GL_UNSIGNED_SHORT_1_5_5_5_REV && internalFormat == GL_RGBA) { } else if(format == GL_BGRA && type == GL_UNSIGNED_SHORT_1_5_5_5_REV && internalFormat == GL_RGBA) {
@ -868,8 +880,23 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
assert(data); assert(data);
assert(bytes); assert(bytes);
/* No conversion? Just copy the data, and the pvr_format is correct */ if(needsTwiddling) {
sq_cpy(targetData, data, bytes); assert(type == GL_UNSIGNED_BYTE); // Anything else needs this loop adjusting
GLuint x, y;
for(y = 0; y < height; ++y) {
for(x = 0; x < width; ++x) {
GLuint src = (y * width) + x;
GLuint dest = morton_index(x, y);
targetData[dest] = ((GLubyte*) data)[src];
}
}
} else {
/* No conversion? Just copy the data, and the pvr_format is correct */
sq_cpy(targetData, data, bytes);
}
return; return;
} else { } else {
TextureConversionFunc convert = _determineConversion( TextureConversionFunc convert = _determineConversion(

View File

@ -23,4 +23,5 @@ all:
$(KOS_MAKE) -C trimark all $(KOS_MAKE) -C trimark all
$(KOS_MAKE) -C multitexture_arrays all $(KOS_MAKE) -C multitexture_arrays all
$(KOS_MAKE) -C paletted all $(KOS_MAKE) -C paletted all
$(KOS_MAKE) -C paletted_pcx all
$(KOS_MAKE) -C depth_funcs all $(KOS_MAKE) -C depth_funcs all

View File

@ -0,0 +1,29 @@
TARGET = paletted_pcx.elf
OBJS = main.o
all: rm-elf $(TARGET)
include $(KOS_BASE)/Makefile.rules
clean:
-rm -f $(TARGET) $(OBJS) romdisk.*
rm-elf:
-rm -f $(TARGET) romdisk.*
$(TARGET): $(OBJS) romdisk.o
$(KOS_CC) $(KOS_CFLAGS) $(KOS_LDFLAGS) -o $(TARGET) $(KOS_START) \
$(OBJS) romdisk.o $(OBJEXTRA) -lm -lkosutils $(KOS_LIBS)
romdisk.img:
$(KOS_GENROMFS) -f romdisk.img -d romdisk -v
romdisk.o: romdisk.img
$(KOS_BASE)/utils/bin2o/bin2o romdisk.img romdisk romdisk.o
run: $(TARGET)
$(KOS_LOADER) $(TARGET)
dist:
rm -f $(OBJS) romdisk.o romdisk.img
$(KOS_STRIP) $(TARGET)

271
samples/paletted_pcx/main.c Normal file
View File

@ -0,0 +1,271 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <assert.h>
#include "gl.h"
#include "glext.h"
#include "glu.h"
#include "glkos.h"
extern uint8 romdisk[];
KOS_INIT_ROMDISK(romdisk);
/* floats for x rotation, y rotation, z rotation */
float xrot, yrot, zrot;
/* storage for one texture */
int texture[1];
typedef struct {
unsigned int height;
unsigned int width;
unsigned int palette_width;
char* palette;
char* data;
} Image;
#pragma pack(push)
#pragma pack(1)
/* PCX header */
typedef struct {
uint8_t manufacturer;
uint8_t version;
uint8_t encoding;
uint8_t bits_per_pixel;
uint16_t xmin, ymin;
uint16_t xmax, ymax;
uint16_t horz_res, vert_res;
uint8_t palette[48];
uint8_t reserved;
uint8_t num_color_planes;
uint16_t bytes_per_scan_line;
uint16_t palette_type;
uint16_t horz_size, vert_size;
uint8_t padding[54];
} Header;
#pragma pack(pop)
int LoadPalettedPCX(const char* filename, Image* image) {
FILE* filein = NULL;
filein = fopen(filename, "rb");
if(!filein) {
printf("Unable to open file\n");
return 0;
}
Header header;
fread(&header, sizeof(header), 1, filein);
if(header.manufacturer != 0x0a) {
printf("Invalid file\n");
return 0;
}
/* Read the rest of the file */
long pos = ftell(filein);
fseek(filein, 0, SEEK_END);
long end = ftell(filein);
fseek(filein, pos, SEEK_SET);
long size = end - pos;
uint8_t* buffer = (uint8_t*) malloc(size);
fread(buffer, 1, size, filein);
image->width = header.xmax - header.xmin + 1;
image->height = header.ymax - header.ymin + 1;
image->data = (char*) malloc(sizeof(char) * image->width * image->height);
int bitcount = header.bits_per_pixel * header.num_color_planes;
if(bitcount != 8) {
printf("Wrong bitcount\n");
return 0;
}
uint8_t palette_marker = buffer[size - 769];
const uint8_t* palette = (palette_marker == 12) ? &buffer[size - 768] : header.palette;
image->palette_width = (palette_marker == 12) ? 256 : 16;
image->palette = (char*) malloc(sizeof(char) * 3 * image->palette_width);
memcpy(image->palette, palette, sizeof(char) * 3 * image->palette_width);
int32_t rle_count = 0;
int32_t rle_value = 0;
const uint8_t* image_data = buffer;
uint32_t idx;
for(idx = 0; idx < (image->width * image->height); idx++) {
if(rle_count == 0) {
rle_value = *image_data;
++image_data;
if((rle_value & 0xc0) == 0xc0) {
rle_count = rle_value & 0x3f;
rle_value = *image_data;
++image_data;
} else {
rle_count = 1;
}
}
rle_count--;
assert(rle_value < 256);
image->data[idx] = rle_value;
}
free(buffer);
return 1;
}
// Load Bitmaps And Convert To Textures
void LoadGLTextures() {
// Load Texture
Image *image1;
// allocate space for texture
image1 = (Image *) malloc(sizeof(Image));
if (image1 == NULL) {
printf("Error allocating space for image");
exit(0);
}
if (!LoadPalettedPCX("/rd/NeHe.pcx", image1)) {
exit(1);
}
glEnable(GL_SHARED_TEXTURE_PALETTE_EXT);
glColorTableEXT(GL_SHARED_TEXTURE_PALETTE_EXT, GL_RGBA8, image1->palette_width, GL_RGB, GL_UNSIGNED_BYTE, image1->palette);
// Create Texture
glGenTextures(1, &texture[0]);
glBindTexture(GL_TEXTURE_2D, texture[0]); // 2d texture (x and y size)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR); // scale linearly when image bigger than texture
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR); // scale linearly when image smalled than texture
// 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.
glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, image1->width, image1->height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, image1->data);
}
/* A general OpenGL initialization function. Sets all of the initial parameters. */
void InitGL(int Width, int Height) // We call this right after our OpenGL window is created.
{
LoadGLTextures();
glEnable(GL_TEXTURE_2D);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // This Will Clear The Background Color To Black
glClearDepth(1.0); // Enables Clearing Of The Depth Buffer
glDepthFunc(GL_LESS); // The Type Of Depth Test To Do
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); // Reset The Projection Matrix
gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f); // Calculate The Aspect Ratio Of The Window
glMatrixMode(GL_MODELVIEW);
}
/* The function called when our window is resized (which shouldn't happen, because we're fullscreen) */
void ReSizeGLScene(int Width, int Height)
{
if (Height == 0) // Prevent A Divide By Zero If The Window Is Too Small
Height = 1;
glViewport(0, 0, Width, Height); // Reset The Current Viewport And Perspective Transformation
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);
glMatrixMode(GL_MODELVIEW);
}
/* The main drawing function. */
void DrawGLScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
glLoadIdentity(); // Reset The View
glTranslatef(0.0f,0.0f,-5.0f); // move 5 units into the screen.
glRotatef(xrot,1.0f,0.0f,0.0f); // Rotate On The X Axis
glRotatef(yrot,0.0f,1.0f,0.0f); // Rotate On The Y Axis
glRotatef(zrot,0.0f,0.0f,1.0f); // Rotate On The Z Axis
glBindTexture(GL_TEXTURE_2D, texture[0]); // choose the texture to use.
glBegin(GL_QUADS); // begin drawing a cube
// Front Face (note that the texture's corners have to match the quad's corners)
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Left Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); // Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); // Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // Top Left Of The Texture and Quad
// Back Face
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); // Top Left Of The Texture and Quad
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); // Bottom Left Of The Texture and Quad
// Top Face
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // Top Left Of The Texture and Quad
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // Bottom Left Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 1.0f); // Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); // Top Right Of The Texture and Quad
// Bottom Face
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f); // Top Left Of The Texture and Quad
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); // Bottom Left Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Right Of The Texture and Quad
// Right face
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); // Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); // Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); // Top Left Of The Texture and Quad
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); // Bottom Left Of The Texture and Quad
// Left Face
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom Left Of The Texture and Quad
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Right Of The Texture and Quad
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // Top Right Of The Texture and Quad
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // Top Left Of The Texture and Quad
glEnd(); // done with the polygon.
xrot+=1.5f; // X Axis Rotation
yrot+=1.5f; // Y Axis Rotation
zrot+=1.5f; // Z Axis Rotation
//
// swap buffers to display, since we're double buffered.
glKosSwapBuffers();
}
int main(int argc, char **argv)
{
glKosInit();
InitGL(640, 480);
ReSizeGLScene(640, 480);
while(1) {
DrawGLScene();
}
return 0;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File