Merge branch 'master' into tnl_effects

This commit is contained in:
UnknownShadow200 2025-02-22 22:35:41 +11:00
commit 0e112ffb3c
11 changed files with 728 additions and 122 deletions

View File

@ -198,6 +198,7 @@ gen_sample(nehe06_vq samples/nehe06_vq/main.c)
gen_sample(nehe06_4444twid samples/nehe06_4444twid/main.c)
gen_sample(nehe08 samples/nehe08/main.c samples/nehe08/pvr-texture.c)
gen_sample(nehe10 samples/nehe10/main.c samples/loadbmp.c)
gen_sample(nehe16 samples/nehe16/main.c samples/nehe16/pvr-texture.c)
gen_sample(nehe20 samples/nehe20/main.c samples/loadbmp.c)
gen_sample(ortho2d samples/ortho2d/main.c)
gen_sample(paletted samples/paletted/main.c)

View File

@ -31,11 +31,10 @@ GL_FORCE_INLINE GLboolean _glStateUnchanged(AttribPointer* p, GLint size, GLenum
return (p->size == size && p->type == type && p->stride == stride);
}
GLuint* _glGetEnabledAttributes() {
GLuint* _glGetEnabledAttributes(void) {
return &ATTRIB_LIST.enabled;
}
static void _readPosition3f3f(const GLubyte* __restrict__ in, GLubyte* __restrict__ out) {
const float* input = (const float*) in;
Vertex* it = (Vertex*) out;
@ -47,6 +46,17 @@ static void _readPosition3f3f(const GLubyte* __restrict__ in, GLubyte* __restric
TransformVertex(x, y, z, w, it->xyz, &it->w);
}
static void _readPosition3d3f(const GLubyte* __restrict__ in, GLubyte* __restrict__ out) {
const double* input = (const double*) in;
Vertex* it = (Vertex*) out;
float x = input[0];
float y = input[1];
float z = input[2];
float w = 1.0f;
TransformVertex(x, y, z, w, it->xyz, &it->w);
}
static void _readPosition3ub3f(const GLubyte* input, GLubyte* out) {
Vertex* it = (Vertex*)out;
@ -90,6 +100,17 @@ static void _readPosition2f3f(const GLubyte* in, GLubyte* out) {
TransformVertex(x, y, z, w, it->xyz, &it->w);
}
static void _readPosition2d3f(const GLubyte* in, GLubyte* out) {
const double* input = (const double*) in;
Vertex* it = (Vertex*) out;
float x = input[0];
float y = input[1];
float z = 0.0f;
float w = 1.0f;
TransformVertex(x, y, z, w, it->xyz, &it->w);
}
static void _readPosition2ub3f(const GLubyte* input, GLubyte* out) {
Vertex* it = (Vertex*) out;
@ -122,10 +143,12 @@ static void _readPosition2ui3f(const GLubyte* in, GLubyte* out) {
TransformVertex(x, y, z, w, it->xyz, &it->w);
}
static ReadAttributeFunc calcReadPositionFunc() {
static ReadAttributeFunc calcReadPositionFunc(void) {
switch(ATTRIB_LIST.vertex.type) {
default:
case GL_DOUBLE:
return (ATTRIB_LIST.vertex.size == 3) ? _readPosition3d3f:
_readPosition2d3f;
default:
case GL_FLOAT:
return (ATTRIB_LIST.vertex.size == 3) ? _readPosition3f3f:
_readPosition2f3f;
@ -144,7 +167,6 @@ static ReadAttributeFunc calcReadPositionFunc() {
}
}
static void _fillWhiteARGB(const GLubyte* __restrict__ input, GLubyte* __restrict__ output) {
_GL_UNUSED(input);
*((uint32_t*) output) = ~0;
@ -157,24 +179,6 @@ static void _readColour4ubARGB(const GLubyte* input, GLubyte* output) {
output[A8IDX] = input[3];
}
static void _readColour4fARGB(const GLubyte* in, GLubyte* output) {
const float* input = (const float*) in;
output[R8IDX] = (GLubyte) clamp(input[0] * 255.0f, 0, 255);
output[G8IDX] = (GLubyte) clamp(input[1] * 255.0f, 0, 255);
output[B8IDX] = (GLubyte) clamp(input[2] * 255.0f, 0, 255);
output[A8IDX] = (GLubyte) clamp(input[3] * 255.0f, 0, 255);
}
static void _readColour3fARGB(const GLubyte* in, GLubyte* output) {
const float* input = (const float*) in;
output[R8IDX] = (GLubyte) clamp(input[0] * 255.0f, 0, 255);
output[G8IDX] = (GLubyte) clamp(input[1] * 255.0f, 0, 255);
output[B8IDX] = (GLubyte) clamp(input[2] * 255.0f, 0, 255);
output[A8IDX] = 255;
}
static void _readColour3ubARGB(const GLubyte* __restrict__ input, GLubyte* __restrict__ output) {
output[R8IDX] = input[0];
output[G8IDX] = input[1];
@ -182,6 +186,30 @@ static void _readColour3ubARGB(const GLubyte* __restrict__ input, GLubyte* __res
output[A8IDX] = 255;
}
#define DEF_READ_COLOUR_4_ARGB_FP(prefix, intype) \
static void _readColour##prefix##ARGB(const GLubyte* __restrict in, GLubyte* __restrict out) { \
const intype* input = (const intype*) in; \
out[R8IDX] = (GLubyte) clamp(input[0] * 255.0f, 0, 255); \
out[G8IDX] = (GLubyte) clamp(input[1] * 255.0f, 0, 255); \
out[B8IDX] = (GLubyte) clamp(input[2] * 255.0f, 0, 255); \
out[A8IDX] = (GLubyte) clamp(input[3] * 255.0f, 0, 255); \
}
#define DEF_READ_COLOUR_3_ARGB_FP(prefix, intype) \
static void _readColour##prefix##ARGB(const GLubyte* __restrict in, GLubyte* __restrict out) { \
const intype* input = (const intype*) in; \
out[R8IDX] = (GLubyte) clamp(input[0] * 255.0f, 0, 255); \
out[G8IDX] = (GLubyte) clamp(input[1] * 255.0f, 0, 255); \
out[B8IDX] = (GLubyte) clamp(input[2] * 255.0f, 0, 255); \
out[A8IDX] = 255; \
}
DEF_READ_COLOUR_4_ARGB_FP(4f, float)
DEF_READ_COLOUR_4_ARGB_FP(4d, double)
DEF_READ_COLOUR_3_ARGB_FP(3f, float)
DEF_READ_COLOUR_3_ARGB_FP(3d, double)
static void _readColour4ubRevARGB(const GLubyte* __restrict__ input, GLubyte* __restrict__ output) {
argbcpy(output, input);
}
@ -195,51 +223,58 @@ static void _readColour4fRevARGB(const GLubyte* __restrict__ in, GLubyte* __rest
output[3] = (GLubyte) clamp(input[3] * 255.0f, 0, 255);
}
static void _readColour3usARGB(const GLubyte* input, GLubyte* output) {
_GL_UNUSED(input);
_GL_UNUSED(output);
gl_assert(0 && "Not Implemented");
static void _readColour4dRevARGB(const GLubyte* __restrict__ in, GLubyte* __restrict__ output) {
const double* input = (const double*) in;
output[0] = (GLubyte) clamp(input[0] * 255.0f, 0, 255);
output[1] = (GLubyte) clamp(input[1] * 255.0f, 0, 255);
output[2] = (GLubyte) clamp(input[2] * 255.0f, 0, 255);
output[3] = (GLubyte) clamp(input[3] * 255.0f, 0, 255);
}
static void _readColour3uiARGB(const GLubyte* input, GLubyte* output) {
_GL_UNUSED(input);
_GL_UNUSED(output);
gl_assert(0 && "Not Implemented");
}
#define DEF_READ_COLOUR_N_ARGB_INT(prefix, intype, max, alpha, i0, i1, i2, i3) \
static void _readColour##prefix##ARGB(const GLubyte* __restrict in, GLubyte* __restrict out) { \
const intype* input = (const intype*) in; \
out[i0] = (GLubyte) clamp((float)input[0] / (float)max * 255.0f, 0, 255); \
out[i1] = (GLubyte) clamp((float)input[1] / (float)max * 255.0f, 0, 255); \
out[i2] = (GLubyte) clamp((float)input[2] / (float)max * 255.0f, 0, 255); \
out[i3] = alpha; \
}
static void _readColour4usARGB(const GLubyte* input, GLubyte* output) {
_GL_UNUSED(input);
_GL_UNUSED(output);
gl_assert(0 && "Not Implemented");
}
#define DEF_READ_COLOUR_3_ARGB_INT(prefix, intype, max) \
DEF_READ_COLOUR_N_ARGB_INT(prefix, intype, max, 255, R8IDX, G8IDX, B8IDX, A8IDX)
static void _readColour4uiARGB(const GLubyte* input, GLubyte* output) {
_GL_UNUSED(input);
_GL_UNUSED(output);
gl_assert(0 && "Not Implemented");
}
#define DEF_READ_COLOUR_4_ARGB_INT(prefix, intype, max) \
DEF_READ_COLOUR_N_ARGB_INT(prefix, intype, max, \
((GLubyte)clamp((float)input[3] / (float)max * 255.0f, 0, 255)), \
R8IDX, G8IDX, B8IDX, A8IDX)
static void _readColour4usRevARGB(const GLubyte* input, GLubyte* output) {
_GL_UNUSED(input);
_GL_UNUSED(output);
gl_assert(0 && "Not Implemented");
}
#define DEF_READ_COLOUR_4_REV_ARGB_INT(prefix, intype, max) \
DEF_READ_COLOUR_N_ARGB_INT(prefix##Rev, intype, max, \
((GLubyte)clamp((float)input[3] / (float)max * 255.0f, 0, 255)), \
0, 1, 2, 3)
static void _readColour4uiRevARGB(const GLubyte* input, GLubyte* output) {
_GL_UNUSED(input);
_GL_UNUSED(output);
gl_assert(0 && "Not Implemented");
}
DEF_READ_COLOUR_3_ARGB_INT(3us, GLushort, UINT16_MAX)
DEF_READ_COLOUR_3_ARGB_INT(3ui, GLuint, UINT32_MAX)
static ReadAttributeFunc calcReadDiffuseFunc() {
DEF_READ_COLOUR_4_ARGB_INT(4us, GLushort, UINT16_MAX)
DEF_READ_COLOUR_4_ARGB_INT(4ui, GLuint, UINT32_MAX)
DEF_READ_COLOUR_4_REV_ARGB_INT(4us, GLushort, UINT16_MAX)
DEF_READ_COLOUR_4_REV_ARGB_INT(4ui, GLuint, UINT32_MAX)
static ReadAttributeFunc calcReadDiffuseFunc(void) {
if((ATTRIB_LIST.enabled & DIFFUSE_ENABLED_FLAG) != DIFFUSE_ENABLED_FLAG) {
/* Just fill the whole thing white if the attribute is disabled */
return _fillWhiteARGB;
}
switch(ATTRIB_LIST.colour.type) {
default:
case GL_DOUBLE:
return (ATTRIB_LIST.colour.size == 3) ? _readColour3dARGB:
(ATTRIB_LIST.colour.size == 4) ? _readColour4dARGB:
_readColour4dRevARGB;
default:
case GL_FLOAT:
return (ATTRIB_LIST.colour.size == 3) ? _readColour3fARGB:
(ATTRIB_LIST.colour.size == 4) ? _readColour4fARGB:
@ -276,6 +311,11 @@ static void _readTexcoord2f2f(const GLubyte* in, GLubyte* out) {
vec2cpy(out, in);
}
static void _readTexcoord2d2f(const GLubyte* in, GLubyte* out) {
((float*)out)[0] = ((const double*)in)[0];
((float*)out)[1] = ((const double*)in)[1];
}
static void _readTexcoord2ub2f(const GLubyte* input, GLubyte* out) {
float* output = (float*) out;
@ -299,14 +339,15 @@ static void _readTexcoord2ui2f(const GLubyte* in, GLubyte* out) {
output[1] = input[1];
}
static ReadAttributeFunc calcReadUVFunc() {
static ReadAttributeFunc calcReadUVFunc(void) {
if((ATTRIB_LIST.enabled & UV_ENABLED_FLAG) != UV_ENABLED_FLAG) {
return _fillZero2f;
}
switch(ATTRIB_LIST.uv.type) {
default:
case GL_DOUBLE:
return _readTexcoord2d2f;
default:
case GL_FLOAT:
return _readTexcoord2f2f;
case GL_BYTE:
@ -321,14 +362,15 @@ static ReadAttributeFunc calcReadUVFunc() {
}
}
static ReadAttributeFunc calcReadSTFunc() {
static ReadAttributeFunc calcReadSTFunc(void) {
if((ATTRIB_LIST.enabled & ST_ENABLED_FLAG) != ST_ENABLED_FLAG) {
return _fillZero2f;
}
switch(ATTRIB_LIST.st.type) {
default:
case GL_DOUBLE:
return _readTexcoord2d2f;
default:
case GL_FLOAT:
return _readTexcoord2f2f;
case GL_BYTE:
@ -357,6 +399,12 @@ static void _readNormal3f3f(const GLubyte* __restrict__ in, GLubyte* __restrict_
vec3cpy(out, in);
}
static void _readNormal3d3f(const GLubyte* __restrict__ in, GLubyte* __restrict__ out) {
((float*)out)[0] = ((const double*)in)[0];
((float*)out)[1] = ((const double*)in)[1];
((float*)out)[2] = ((const double*)in)[2];
}
static void _readNormal3ub3f(const GLubyte* input, GLubyte* out) {
float* output = (float*) out;
@ -406,15 +454,16 @@ static void _readNormal1i3f(const GLubyte* in, GLubyte* out) {
output[2] = (2.0f * (float) input.bits.z + 1.0f) * MULTIPLIER;
}
static ReadAttributeFunc calcReadNormalFunc() {
static ReadAttributeFunc calcReadNormalFunc(void) {
if((ATTRIB_LIST.enabled & NORMAL_ENABLED_FLAG) != NORMAL_ENABLED_FLAG) {
return _fillWithNegZVE;
}
switch(ATTRIB_LIST.normal.type) {
default:
case GL_DOUBLE:
return _readNormal3d3f;
case GL_FLOAT:
default:
return _readNormal3f3f;
break;
case GL_BYTE:
@ -497,7 +546,7 @@ void APIENTRY glDisableClientState(GLenum cap) {
}
void APIENTRY glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid * pointer) {
void APIENTRY glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) {
TRACE();
stride = (stride) ? stride : size * byte_size(type);
@ -591,7 +640,7 @@ void APIENTRY glNormalPointer(GLenum type, GLsizei stride, const GLvoid * poin
}
void _glInitAttributePointers() {
void _glInitAttributePointers(void) {
TRACE();
ATTRIB_LIST.dirty = ~0; // all attributes dirty
@ -601,7 +650,7 @@ void _glInitAttributePointers() {
glNormalPointer(GL_FLOAT, 0, NULL);
}
GL_FORCE_INLINE GLuint _glIsVertexDataFastPathCompatible() {
GL_FORCE_INLINE GLuint _glIsVertexDataFastPathCompatible(void) {
/* The fast path is enabled when all enabled elements of the vertex
* match the output format. This means:
*
@ -649,7 +698,7 @@ GL_FORCE_INLINE GLuint _glIsVertexDataFastPathCompatible() {
return GL_TRUE;
}
void _glUpdateAttributes() {
void _glUpdateAttributes(void) {
if(ATTRIB_LIST.dirty & VERTEX_ENABLED_FLAG) {
ATTRIB_LIST.vertex_func = calcReadPositionFunc();
}

175
GL/fog.c
View File

@ -1,73 +1,138 @@
/*
TODO: glGetX() fog values
*/
#include <limits.h>
#include "private.h"
static GLfloat FOG_START = 0.0f;
static GLfloat FOG_END = 1.0f;
static GLfloat FOG_DENSITY = 1.0f;
static GLenum FOG_MODE = GL_EXP;
static GLfloat FOG_COLOR [] = {0.0f, 0.0f, 0.0f, 0.0f};
static struct {
GLfloat START;
GLfloat END;
GLfloat DENSITY;
GLenum MODE;
GLfloat COLOR[4];
} FOG = {
0.0f, 1.0f, 1.0f, GL_EXP, { 0.0f, 0.0f, 0.0f, 0.0f }
};
static void updatePVRFog() {
if(FOG_MODE == GL_LINEAR) {
GPUSetFogLinear(FOG_START, FOG_END);
} else if(FOG_MODE == GL_EXP) {
GPUSetFogExp(FOG_DENSITY);
} else if(FOG_MODE == GL_EXP2) {
GPUSetFogExp2(FOG_DENSITY);
static void updatePVRFog(void) {
switch(FOG.MODE) {
case GL_LINEAR:
GPUSetFogLinear(FOG.START, FOG.END);
break;
case GL_EXP:
GPUSetFogExp(FOG.DENSITY);
break;
case GL_EXP2:
GPUSetFogExp2(FOG.DENSITY);
break;
}
GPUSetFogColor(FOG_COLOR[3], FOG_COLOR[0], FOG_COLOR[1], FOG_COLOR[2]);
GPUSetFogColor(FOG.COLOR[3], FOG.COLOR[0], FOG.COLOR[1], FOG.COLOR[2]);
}
void APIENTRY glFogf(GLenum pname, GLfloat param) {
void APIENTRY glFogf(GLenum pname, GLfloat param) {
switch(pname) {
case GL_FOG_MODE: {
FOG_MODE = (GLenum) param;
updatePVRFog();
} break;
case GL_FOG_DENSITY: {
FOG_DENSITY = param;
updatePVRFog();
} break;
case GL_FOG_START: {
FOG_START = param;
updatePVRFog();
} break;
case GL_FOG_END: {
FOG_END = param;
updatePVRFog();
} break;
case GL_FOG_INDEX:
default: {
_glKosThrowError(GL_INVALID_ENUM, __func__);
}
case GL_FOG_DENSITY:
if(FOG.DENSITY != param) {
if(param < 0.0f)
_glKosThrowError(GL_INVALID_VALUE, __func__);
else {
FOG.DENSITY = param;
updatePVRFog();
}
}
break;
case GL_FOG_START:
if(FOG.START != param) {
FOG.START = param;
updatePVRFog();
}
break;
case GL_FOG_END:
if(FOG.END != param) {
FOG.END = param;
updatePVRFog();
}
break;
default:
_glKosThrowError(GL_INVALID_ENUM, __func__);
}
}
void APIENTRY glFogi(GLenum pname, GLint param) {
glFogf(pname, (GLfloat) param);
}
void APIENTRY glFogi(GLenum pname, GLint param) {
switch(pname) {
case GL_FOG_DENSITY:
case GL_FOG_START:
case GL_FOG_END:
glFogf(pname, (GLfloat)param);
break;
void APIENTRY glFogfv(GLenum pname, const GLfloat* params) {
if(pname == GL_FOG_COLOR) {
FOG_COLOR[0] = params[0];
FOG_COLOR[1] = params[1];
FOG_COLOR[2] = params[2];
FOG_COLOR[3] = params[3];
updatePVRFog();
} else {
glFogf(pname, *params);
case GL_FOG_MODE:
if(FOG.MODE != param) {
switch(param) {
case GL_LINEAR:
case GL_EXP:
case GL_EXP2:
FOG.MODE = param;
updatePVRFog();
break;
default:
_glKosThrowError(GL_INVALID_ENUM, __func__);
}
}
break;
case GL_FOG_INDEX:
default:
_glKosThrowError(GL_INVALID_ENUM, __func__);
}
}
void APIENTRY glFogiv(GLenum pname, const GLint* params) {
if(pname == GL_FOG_COLOR) {
FOG_COLOR[0] = ((GLfloat) params[0]) / (GLfloat) INT_MAX;
FOG_COLOR[1] = ((GLfloat) params[1]) / (GLfloat) INT_MAX;
FOG_COLOR[2] = ((GLfloat) params[2]) / (GLfloat) INT_MAX;
FOG_COLOR[3] = ((GLfloat) params[3]) / (GLfloat) INT_MAX;
updatePVRFog();
} else {
glFogi(pname, *params);
void APIENTRY glFogfv(GLenum pname, const GLfloat* params) {
switch(pname) {
case GL_FOG_COLOR: {
GLfloat color[] = {
CLAMP(params[0], 0.0f, 1.0f),
CLAMP(params[1], 0.0f, 1.0f),
CLAMP(params[2], 0.0f, 1.0f),
CLAMP(params[3], 0.0f, 1.0f)
};
if(memcmp(color, FOG.COLOR, sizeof(float) * 4)) {
memcpy(FOG.COLOR, color, sizeof(float) * 4);
updatePVRFog();
}
break;
}
default:
glFogf(pname, *params);
}
}
void APIENTRY glFogiv(GLenum pname, const GLint* params) {
switch(pname) {
case GL_FOG_COLOR: {
GLfloat color[] = {
(GLfloat)params[0] / (GLfloat)INT_MAX,
(GLfloat)params[1] / (GLfloat)INT_MAX,
(GLfloat)params[2] / (GLfloat)INT_MAX,
(GLfloat)params[3] / (GLfloat)INT_MAX,
};
glFogfv(pname, color);
break;
}
default:
glFogi(pname, *params);
}
}

View File

@ -209,11 +209,11 @@ void APIENTRY glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) {
0.0f, 0.0f, 0.0f, 1.0f
};
float r = DEG2RAD * angle;
#ifdef __DREAMCAST__
float s, c;
fsincos(r, &s, &c);
fsincos(angle, &s, &c);
#else
float r = DEG2RAD * angle;
float c = cosf(r);
float s = sinf(r);
#endif

View File

@ -5,6 +5,8 @@
#include "../types.h"
#define __restrict
#define PREFETCH(addr) do {} while(0)
#define MATH_fsrra(x) (1.0f / sqrtf((x)))

View File

@ -906,6 +906,55 @@ void APIENTRY glCompressedTexImage2DARB(GLenum target,
_glGPUStateMarkDirty();
}
void APIENTRY glCompressedTexSubImage2DARB(GLenum target,
GLint level,
GLint xoffset,
GLint yoffset,
GLsizei width,
GLsizei height,
GLenum format,
GLsizei imageSize,
const GLvoid *data) {
TRACE();
if (target != GL_TEXTURE_2D) {
_glKosThrowError(GL_INVALID_ENUM, __func__);
return;
}
if (xoffset < 0 || yoffset < 0 || width <= 0 || height <= 0) {
_glKosThrowError(GL_INVALID_VALUE, __func__);
return;
}
gl_assert(ACTIVE_TEXTURE < MAX_GLDC_TEXTURE_UNITS);
TextureObject* active = TEXTURE_UNITS[ACTIVE_TEXTURE];
if (!active) {
_glKosThrowError(GL_INVALID_OPERATION, __func__);
return;
}
GLuint original_id = active->index;
// Ensure that we're modifying the correct texture
if (active->index != original_id) {
_glKosThrowError(GL_INVALID_OPERATION, __func__);
return;
}
// Copy raw compressed texture data into the texture buffer.
GLubyte* targetData = active->data;
GLubyte* src = (GLubyte*)data;
// Copy the compressed data directly to the texture
if (data) {
FASTCPY(targetData + (yoffset * active->width + xoffset), src, imageSize);
}
_glGPUStateMarkDirty();
}
/**
* Takes an internal format, and returns a GL format matching how we'd store
* it internally, so it'll return one of the following:

View File

@ -185,6 +185,15 @@ GLAPI void APIENTRY glCompressedTexImage2DARB(GLenum target,
GLsizei imageSize,
const GLvoid *data);
GLAPI void APIENTRY glCompressedTexSubImage2DARB(GLenum target,
GLint level,
GLint xoffset,
GLint yoffset,
GLsizei width,
GLsizei height,
GLenum format,
GLsizei imageSize,
const GLvoid *data);
/* Core aliases */
#define GL_INVALID_FRAMEBUFFER_OPERATION GL_INVALID_FRAMEBUFFER_OPERATION_EXT
@ -195,6 +204,7 @@ GLAPI void APIENTRY glCompressedTexImage2DARB(GLenum target,
#define glGenerateMipmapEXT glGenerateMipmap
#define glCompressedTexImage2D glCompressedTexImage2DARB
#define glCompressedTexSubImage2D glCompressedTexSubImage2DARB
#ifndef GL_VERSION_1_4
#define GL_VERSION_1_4 1

View File

@ -165,9 +165,16 @@ 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.
// Allocate texture memory (but don't upload compressed data yet)
glCompressedTexImage2DARB(
GL_TEXTURE_2D, 0, image1->internalFormat, image1->sizeX, image1->sizeY, 0,
image1->dataSize, image1->data
image1->dataSize, NULL // NULL here means we are not uploading data yet
);
// Now use glCompressedTexSubImage2DARB to upload the compressed data to the texture
glCompressedTexSubImage2DARB(
GL_TEXTURE_2D, 0, 0, 0, image1->sizeX, image1->sizeY,
image1->internalFormat, image1->dataSize, image1->data
);
free(image1);

247
samples/nehe16/main.c Normal file
View File

@ -0,0 +1,247 @@
/*
KallistiOS 2.0.0
nehe16.c
(c)2025 Falco Girgis
(c)2014 Josh Pearson
(c)2001 Benoit Miller
(c)2000 Jeff Molofee
*/
#include <stdio.h>
#include <GL/glkos.h>
#include <GL/gl.h>
#include <GL/glu.h>
#ifdef __DREAMCAST__
#include <kos.h>
extern uint8 romdisk[];
KOS_INIT_ROMDISK(romdisk);
#define IMG_PATH "/rd/glass.pvr"
#else
#define IMG_PATH "../samples/nehe08/romdisk/glass.pvr"
#endif
/* Simple GL example to demonstrate fog (PVR table fog).
Essentially the same thing as NeHe's lesson16 code.
To learn more, go to http://nehe.gamedev.net/.
DPAD controls the cube rotation, button A & B control the depth
of the cube, button X toggles fog on/off, and button Y toggles fog type.
*/
static GLfloat xrot; /* X Rotation */
static GLfloat yrot; /* Y Rotation */
static GLfloat xspeed; /* X Rotation Speed */
static GLfloat yspeed; /* Y Rotation Speed */
static GLfloat z = -5.0f; /* Depth Into The Screen */
static GLuint texture; /* Storage For Texture */
/* Storage For Three Types Of Fog */
GLuint fogType = 0; /* use GL_EXP initially */
GLuint fogMode[] = { GL_EXP, GL_EXP2, GL_LINEAR };
char cfogMode[3][10] = {"GL_EXP ", "GL_EXP2 ", "GL_LINEAR" };
GLfloat fogColor[4] = { 0.5f, 0.5f, 0.5f, 1.0f }; /* Fog Color */
int fog = GL_TRUE;
/* Load a PVR texture - located in pvr-texture.c */
extern GLuint glTextureLoadPVR(char *fname, unsigned char isMipMapped, unsigned char glMipMap);
void draw_gl(void) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f, 0.0f, z);
glRotatef(xrot, 1.0f, 0.0f, 0.0f);
glRotatef(yrot, 0.0f, 1.0f, 0.0f);
glBindTexture(GL_TEXTURE_2D, texture);
glBegin(GL_QUADS);
/* Front Face */
glNormal3f(0.0f, 0.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
/* Back Face */
glNormal3f(0.0f, 0.0f, -1.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(1.0f, -1.0f, -1.0f);
/* Top Face */
glNormal3f(0.0f, 1.0f, 0.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(1.0f, 1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(1.0f, 1.0f, -1.0f);
/* Bottom Face */
glNormal3f(0.0f, -1.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(1.0f, -1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
/* Right face */
glNormal3f(1.0f, 0.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(1.0f, 1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(1.0f, -1.0f, 1.0f);
/* Left Face */
glNormal3f(-1.0f, 0.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 0.0f);
glVertex3f(-1.0f, -1.0f, 1.0f);
glTexCoord2f(1.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f);
glVertex3f(-1.0f, 1.0f, -1.0f);
glEnd();
xrot += xspeed;
yrot += yspeed;
}
int main(int argc, char **argv) {
GLboolean xp = GL_FALSE;
GLboolean yp = GL_FALSE;
printf("nehe16 beginning\n");
/* Get basic stuff initialized */
glKosInit();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, 640.0f / 480.0f, 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_TEXTURE_2D);
glShadeModel(GL_SMOOTH);
glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glColor4f(1.0f, 1.0f, 1.0f, 0.5);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
/* Enable Lighting and GL_LIGHT0 */
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
/* Set up the fog */
glFogi(GL_FOG_MODE, fogMode[fogType]); /* Fog Mode */
glFogfv(GL_FOG_COLOR, fogColor); /* Set Fog Color */
glFogf(GL_FOG_DENSITY, 0.35f); /* How Dense The Fog is */
glHint(GL_FOG_HINT, GL_DONT_CARE); /* Fog Hint Value */
glFogf(GL_FOG_START, 0.0f); /* Fog Start Depth */
glFogf(GL_FOG_END, 5.0f); /* Fog End Depth */
glEnable(GL_FOG); /* Enables GL_FOG */
/* Set up the textures */
texture = glTextureLoadPVR(IMG_PATH, 0, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
while(1) {
#ifdef __DREAMCAST__
maple_device_t *cont;
cont_state_t *state;
cont = maple_enum_type(0, MAPLE_FUNC_CONTROLLER);
/* Check key status */
state = (cont_state_t *)maple_dev_status(cont);
if(!state) {
printf("Error reading controller\n");
break;
}
if(state->start)
break;
if(state->a) {
if(z >= -15.0f) z -= 0.02f;
}
if(state->b) {
if(z <= 0.0f) z += 0.02f;
}
if(state->x && !xp) {
xp = GL_TRUE;
fogType = (fogType + 1) % 3;
glFogi(GL_FOG_MODE, fogMode[fogType]);
printf("%s\n", cfogMode[fogType]);
}
if(!state->x)
xp = GL_FALSE;
if(state->y && !yp) {
yp = GL_TRUE;
fog = !fog;
}
if(!state->y)
yp = GL_FALSE;
if(state->dpad_up)
xspeed -= 0.1f;
if(state->dpad_down)
xspeed += 0.1f;
if(state->dpad_left)
yspeed -= 0.1f;
if(state->dpad_right)
yspeed += 0.1f;
#endif
/* Switch fog off/on */
if(fog) {
glEnable(GL_FOG);
}
else {
glDisable(GL_FOG);
}
/* Draw the GL "scene" */
draw_gl();
/* Finish the frame */
glKosSwapBuffers();
}
return 0;
}

View File

@ -0,0 +1,176 @@
/*
KallistiOS 2.0.0
pvr-texture.c
(c)2014 Josh PH3NOM Pearson
Load A PVR Texture to the PVR using Open GL
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include "GL/gl.h"
#include "GL/glu.h"
#include "GL/glkos.h"
#include "GL/glext.h"
#define PVR_HDR_SIZE 0x20
#define MAX(x, y) ((x > y) ? x : y)
static GLuint PVR_TextureHeight(unsigned char *HDR);
static GLuint PVR_TextureWidth(unsigned char *HDR);
static GLuint PVR_TextureFormat(unsigned char *HDR);
static GLuint _glGetMipmapLevelCount(GLuint width, GLuint height) {
return 1 + floor(log2(MAX(width, height)));
}
static GLuint _glGetMipmapDataSize(GLuint width, GLuint height) {
GLuint size = 0;
GLuint i = 0;
for(; i < _glGetMipmapLevelCount(width, height); ++i) {
size += (width * height * 2);
if(width > 1) {
width /= 2;
}
if(height > 1) {
height /= 2;
}
}
return size;
}
/* Load a PVR texture file into memory, and then bind the texture to Open GL.
fname is the name of the PVR texture file to be opened and read.
isMipMapped should be passed as 1 if the texture contains MipMap levels, 0 otherwise.
glMipMap should be passed as 1 if Open GL should calculate the Mipmap levels, 0 otherwise */
GLuint glTextureLoadPVR(char *fname, unsigned char isMipMapped, unsigned char glMipMap) {
FILE *tex = NULL;
uint16_t *TEX0 = NULL;
uint8_t HDR[PVR_HDR_SIZE];
GLuint texID, texSize, texW, texH, texFormat;
/* Open the PVR texture file, and get its file size */
tex = fopen(fname, "rb");
if(tex == NULL) {
printf("FILE READ ERROR: %s\n", fname);
while(1);
}
fseek(tex, 0, SEEK_END);
texSize = ftell(tex) - PVR_HDR_SIZE;
fseek(tex, 0, SEEK_SET);
/* Read in the PVR texture file header */
fread(HDR, 1, PVR_HDR_SIZE, tex);
/* Extract some information from the PVR texture file header */
texW = PVR_TextureWidth(HDR);
texH = PVR_TextureHeight(HDR);
texFormat = PVR_TextureFormat(HDR);
/* Allocate Some Memory for the texture. If we are using Open GL to build the MipMap,
we need to allocate enough space to hold the MipMap texture levels. */
if(!isMipMapped && glMipMap)
TEX0 = malloc(_glGetMipmapDataSize(texW, texH));
else
TEX0 = malloc(texSize);
fread(TEX0, 1, texSize, tex); /* Read in the PVR texture data */
/* Generate and bind a texture as normal for Open GL */
glGenTextures(1, &texID);
glBindTexture(GL_TEXTURE_2D, texID);
if(texFormat != GL_UNSIGNED_SHORT_5_6_5)
glCompressedTexImage2DARB(GL_TEXTURE_2D,
0,
texFormat,
texW,
texH,
0,
texSize,
TEX0);
else {
fprintf(stderr, "%x\n", texFormat);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_RGB,
texW, texH,
0,
GL_RGB,
texFormat,
TEX0);
if(!isMipMapped && glMipMap)
glGenerateMipmapEXT(GL_TEXTURE_2D);
}
free(TEX0);
return texID;
}
static GLuint PVR_TextureFormat(unsigned char *HDR) {
GLuint color = (GLuint)HDR[PVR_HDR_SIZE - 8];
GLuint format = (GLuint)HDR[PVR_HDR_SIZE - 7];
GLboolean twiddled = format == 0x01;
GLboolean compressed = (format == 0x10 || format == 0x03);
if(compressed) {
if(twiddled) {
switch(color) {
case 0x0: {
return GL_COMPRESSED_ARGB_1555_VQ_TWID_KOS;
} break;
case 0x01: {
return GL_COMPRESSED_RGB_565_VQ_TWID_KOS;
} break;
case 0x02: {
return GL_COMPRESSED_ARGB_4444_VQ_TWID_KOS;
}
break;
default:
fprintf(stderr, "Invalid texture format");
return 0;
}
} else {
switch(color) {
case 0: {
return GL_COMPRESSED_ARGB_1555_VQ_KOS;
} break;
case 1: {
return GL_COMPRESSED_RGB_565_VQ_KOS;
} break;
case 2: {
return GL_COMPRESSED_ARGB_4444_VQ_KOS;
}
break;
default:
fprintf(stderr, "Invalid texture format");
return 0;
}
}
} else {
if(color == 1) {
return GL_UNSIGNED_SHORT_5_6_5;
}
return 0;
}
}
static GLuint PVR_TextureWidth(unsigned char *HDR) {
return (GLuint)HDR[PVR_HDR_SIZE - 4] | HDR[PVR_HDR_SIZE - 3] << 8;
}
static GLuint PVR_TextureHeight(unsigned char *HDR) {
return (GLuint)HDR[PVR_HDR_SIZE - 2] | HDR[PVR_HDR_SIZE - 1] << 8;
}

Binary file not shown.