merge: final merge of custom gldc and upstream current
This commit is contained in:
commit
1ac25e4d79
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -6,3 +6,4 @@
|
|||
*.img
|
||||
dc-build.sh
|
||||
.buildconfig
|
||||
GL/version.h
|
||||
|
|
36
GL/clip.c
36
GL/clip.c
|
@ -26,7 +26,7 @@ void _glEnableClipping(unsigned char v) {
|
|||
|
||||
void _glClipLineToNearZ(const Vertex* v1, const Vertex* v2, Vertex* vout, float* t) __attribute__((optimize("fast-math")));
|
||||
void _glClipLineToNearZ(const Vertex* v1, const Vertex* v2, Vertex* vout, float* t) {
|
||||
const float NEAR_PLANE = 0.2; // FIXME: this needs to be read from the projection matrix.. somehow
|
||||
const float NEAR_PLANE = NEAR_PLANE_DISTANCE + 0.0001f;
|
||||
|
||||
*t = (NEAR_PLANE - v1->w) / (v2->w - v1->w);
|
||||
|
||||
|
@ -87,6 +87,11 @@ void _glClipTriangle(const Triangle* triangle, const uint8_t visible, Submission
|
|||
const Vertex* vertices = triangle->vertex;
|
||||
const VertexExtra* extras = triangle->extra;
|
||||
|
||||
char* bgra = (char*) vertices[2].bgra;
|
||||
|
||||
/* Used when flat shading is enabled */
|
||||
uint32_t finalColour = *((uint32_t*) bgra);
|
||||
|
||||
for(i = 0; i < 4; ++i) {
|
||||
uint8_t thisIndex = (i == 3) ? 0 : i;
|
||||
|
||||
|
@ -116,16 +121,8 @@ void _glClipTriangle(const Triangle* triangle, const uint8_t visible, Submission
|
|||
interpolateVec2(ve1->st, ve2->st, t, veNext.st);
|
||||
|
||||
if(flatShade) {
|
||||
/* Original */
|
||||
//*((uint32_t*) next.bgra) = *((uint32_t*) vertices[2].bgra);
|
||||
|
||||
/* "Correct" memcpy */
|
||||
//memcpy(next.bgra, vertices[2].bgra, 4);
|
||||
|
||||
/* manual aliasing */
|
||||
uint32_t* a = (void*)(&vertices[2].bgra[0]);
|
||||
uint32_t* b = (void*)(&next.bgra[0]);
|
||||
*b = *a;
|
||||
char* next_bgra = (char*) next.bgra;
|
||||
*((uint32_t*) next_bgra) = finalColour;
|
||||
} else {
|
||||
interpolateColour(v1->bgra, v2->bgra, t, next.bgra);
|
||||
}
|
||||
|
@ -184,6 +181,23 @@ void _glClipTriangle(const Triangle* triangle, const uint8_t visible, Submission
|
|||
|
||||
static inline void markDead(Vertex* vert) {
|
||||
vert->flags = VERTEX_CMD_EOL;
|
||||
|
||||
// If we're debugging, wipe out the xyz
|
||||
#ifndef NDEBUG
|
||||
typedef union {
|
||||
float* f;
|
||||
int* i;
|
||||
} cast;
|
||||
|
||||
cast v1, v2, v3;
|
||||
v1.f = &vert->xyz[0];
|
||||
v2.f = &vert->xyz[1];
|
||||
v3.f = &vert->xyz[2];
|
||||
|
||||
*v1.i = 0xDEADBEEF;
|
||||
*v2.i = 0xDEADBEEF;
|
||||
*v3.i = 0xDEADBEEF;
|
||||
#endif
|
||||
}
|
||||
|
||||
#define B000 0
|
||||
|
|
454
GL/draw.c
454
GL/draw.c
|
@ -4,6 +4,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
#include <dc/vec3f.h>
|
||||
|
||||
#include "../include/gl.h"
|
||||
#include "../include/glext.h"
|
||||
|
@ -20,7 +21,7 @@ static AttribPointer DIFFUSE_POINTER;
|
|||
|
||||
static GLuint ENABLED_VERTEX_ATTRIBUTES = 0;
|
||||
static GLubyte ACTIVE_CLIENT_TEXTURE = 0;
|
||||
|
||||
static GLboolean FAST_PATH_ENABLED = GL_FALSE;
|
||||
|
||||
#define ITERATE(count) \
|
||||
GLuint i = count; \
|
||||
|
@ -56,7 +57,45 @@ void _glInitAttributePointers() {
|
|||
NORMAL_POINTER.size = 3;
|
||||
}
|
||||
|
||||
static INLINE_DEBUG GLuint byte_size(GLenum type) {
|
||||
static GLboolean _glIsVertexDataFastPathCompatible() {
|
||||
/*
|
||||
* We provide a "fast path" if vertex data is provided in
|
||||
* exactly the right format that matches what the PVR can handle.
|
||||
* This function returns true if all the requirements are met.
|
||||
*/
|
||||
|
||||
/*
|
||||
* At least these attributes need to be enabled, because we're not going to do any checking
|
||||
* in the loop
|
||||
*/
|
||||
if((ENABLED_VERTEX_ATTRIBUTES & VERTEX_ENABLED_FLAG) != VERTEX_ENABLED_FLAG) return GL_FALSE;
|
||||
if((ENABLED_VERTEX_ATTRIBUTES & UV_ENABLED_FLAG) != UV_ENABLED_FLAG) return GL_FALSE;
|
||||
if((ENABLED_VERTEX_ATTRIBUTES & DIFFUSE_ENABLED_FLAG) != DIFFUSE_ENABLED_FLAG) return GL_FALSE;
|
||||
|
||||
// All 3 attribute types must have a stride of 32
|
||||
if(VERTEX_POINTER.stride != 32) return GL_FALSE;
|
||||
if(UV_POINTER.stride != 32) return GL_FALSE;
|
||||
if(DIFFUSE_POINTER.stride != 32) return GL_FALSE;
|
||||
|
||||
// UV must follow vertex, diffuse must follow UV
|
||||
if((UV_POINTER.ptr - VERTEX_POINTER.ptr) != sizeof(GLfloat) * 3) return GL_FALSE;
|
||||
if((DIFFUSE_POINTER.ptr - UV_POINTER.ptr) != sizeof(GLfloat) * 2) return GL_FALSE;
|
||||
|
||||
if(VERTEX_POINTER.type != GL_FLOAT) return GL_FALSE;
|
||||
if(VERTEX_POINTER.size != 3) return GL_FALSE;
|
||||
|
||||
if(UV_POINTER.type != GL_FLOAT) return GL_FALSE;
|
||||
if(UV_POINTER.size != 2) return GL_FALSE;
|
||||
|
||||
if(DIFFUSE_POINTER.type != GL_UNSIGNED_BYTE) return GL_FALSE;
|
||||
|
||||
/* BGRA is the required color order */
|
||||
if(DIFFUSE_POINTER.size != GL_BGRA) return GL_FALSE;
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
static inline GLuint byte_size(GLenum type) {
|
||||
switch(type) {
|
||||
case GL_BYTE: return sizeof(GLbyte);
|
||||
case GL_UNSIGNED_BYTE: return sizeof(GLubyte);
|
||||
|
@ -65,6 +104,8 @@ static INLINE_DEBUG GLuint byte_size(GLenum type) {
|
|||
case GL_INT: return sizeof(GLint);
|
||||
case GL_UNSIGNED_INT: return sizeof(GLuint);
|
||||
case GL_DOUBLE: return sizeof(GLdouble);
|
||||
case GL_UNSIGNED_INT_2_10_10_10_REV: return sizeof(GLuint);
|
||||
case GL_INT_2_10_10_10_REV: return sizeof(GLint);
|
||||
case GL_FLOAT:
|
||||
default: return sizeof(GLfloat);
|
||||
}
|
||||
|
@ -75,6 +116,11 @@ typedef void (*ByteParseFunc)(GLubyte* out, const GLubyte* in);
|
|||
typedef void (*PolyBuildFunc)(Vertex* first, Vertex* previous, Vertex* vertex, Vertex* next, const GLsizei i);
|
||||
|
||||
|
||||
static inline float clamp(float d, float min, float max) {
|
||||
const float t = d < min ? min : d;
|
||||
return t > max ? max : t;
|
||||
}
|
||||
|
||||
static void _readVertexData3f3f(const float* input, GLuint count, GLubyte stride, float* output) {
|
||||
ITERATE(count) {
|
||||
output[0] = input[0];
|
||||
|
@ -86,6 +132,32 @@ static void _readVertexData3f3f(const float* input, GLuint count, GLubyte stride
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
static inline float conv_i10_to_norm_float(int i10) {
|
||||
struct attr_bits_10 {
|
||||
signed int x:10;
|
||||
} val;
|
||||
|
||||
val.x = i10;
|
||||
|
||||
return (2.0F * (float)val.x + 1.0F) * (1.0F / 1023.0F);
|
||||
}
|
||||
|
||||
// 10:10:10:2REV format
|
||||
static void _readVertexData1i3f(const GLuint* input, GLuint count, GLubyte stride, float* output) {
|
||||
ITERATE(count) {
|
||||
int inp = *input;
|
||||
output[0] = conv_i10_to_norm_float((inp) & 0x3ff);
|
||||
output[1] = conv_i10_to_norm_float(((inp) >> 10) & 0x3ff);
|
||||
output[2] = conv_i10_to_norm_float(((inp) >> 20) & 0x3ff);
|
||||
|
||||
// fprintf(stderr, "%d -> %f %f %f\n", inp, output[0], output[1], output[2]);
|
||||
|
||||
input = (GLuint*) (((GLubyte*) input) + stride);
|
||||
output = (GLfloat*) (((GLubyte*) output) + sizeof(VertexExtra));
|
||||
}
|
||||
}
|
||||
|
||||
/* VE == VertexExtra */
|
||||
static void _readVertexData3f3fVE(const float* input, GLuint count, GLubyte stride, float* output) {
|
||||
ITERATE(count) {
|
||||
|
@ -300,28 +372,28 @@ static void _readVertexData4ubARGB(const GLubyte* input, GLuint count, GLubyte s
|
|||
output[B8IDX] = input[2];
|
||||
output[A8IDX] = input[3];
|
||||
|
||||
input = (GLubyte*) (((GLubyte*) input) + stride);
|
||||
output = (GLubyte*) (((GLubyte*) output) + sizeof(Vertex));
|
||||
input += stride;
|
||||
output += sizeof(Vertex);
|
||||
}
|
||||
}
|
||||
|
||||
static void _readVertexData4fARGB(const float* input, GLuint count, GLubyte stride, GLubyte* output) {
|
||||
ITERATE(count) {
|
||||
output[R8IDX] = (GLubyte) (input[0] * 255.0f);
|
||||
output[G8IDX] = (GLubyte) (input[1] * 255.0f);
|
||||
output[B8IDX] = (GLubyte) (input[2] * 255.0f);
|
||||
output[A8IDX] = (GLubyte) (input[3] * 255.0f);
|
||||
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);
|
||||
|
||||
input = (float*) (((GLubyte*) input) + stride);
|
||||
output = (GLubyte*) (((GLubyte*) output) + sizeof(Vertex));
|
||||
output += sizeof(Vertex);
|
||||
}
|
||||
}
|
||||
|
||||
static void _readVertexData3fARGB(const float* input, GLuint count, GLubyte stride, GLubyte* output) {
|
||||
ITERATE(count) {
|
||||
output[R8IDX] = (GLubyte) (input[0] * 255.0f);
|
||||
output[G8IDX] = (GLubyte) (input[1] * 255.0f);
|
||||
output[B8IDX] = (GLubyte) (input[2] * 255.0f);
|
||||
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] = 1.0f;
|
||||
|
||||
input = (float*) (((GLubyte*) input) + stride);
|
||||
|
@ -341,6 +413,30 @@ static void _readVertexData3ubARGB(const GLubyte* input, GLuint count, GLubyte s
|
|||
}
|
||||
}
|
||||
|
||||
static void _readVertexData4ubRevARGB(const GLubyte* input, GLuint count, GLubyte stride, GLubyte* output) {
|
||||
ITERATE(count) {
|
||||
output[B8IDX] = input[0];
|
||||
output[G8IDX] = input[1];
|
||||
output[R8IDX] = input[2];
|
||||
output[A8IDX] = input[3];
|
||||
|
||||
input += stride;
|
||||
output += sizeof(Vertex);
|
||||
}
|
||||
}
|
||||
|
||||
static void _readVertexData4fRevARGB(const float* input, GLuint count, GLubyte stride, GLubyte* output) {
|
||||
ITERATE(count) {
|
||||
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);
|
||||
|
||||
input = (float*) (((GLubyte*) input) + stride);
|
||||
output += sizeof(Vertex);
|
||||
}
|
||||
}
|
||||
|
||||
static void _fillWithNegZVE(GLuint count, GLfloat* output) {
|
||||
ITERATE(count) {
|
||||
output[0] = output[1] = 0.0f;
|
||||
|
@ -408,6 +504,22 @@ static void _readVertexData4uiARGB(const GLuint* input, GLuint count, GLubyte st
|
|||
assert(0 && "Not Implemented");
|
||||
}
|
||||
|
||||
static void _readVertexData4usRevARGB(const GLushort* input, GLuint count, GLubyte stride, GLubyte* output) {
|
||||
(void)input;
|
||||
(void)count;
|
||||
(void)stride;
|
||||
(void)output;
|
||||
assert(0 && "Not Implemented");
|
||||
}
|
||||
|
||||
static void _readVertexData4uiRevARGB(const GLuint* input, GLuint count, GLubyte stride, GLubyte* output) {
|
||||
(void)input;
|
||||
(void)count;
|
||||
(void)stride;
|
||||
(void)output;
|
||||
assert(0 && "Not Implemented");
|
||||
}
|
||||
|
||||
GLuint* _glGetEnabledAttributes() {
|
||||
return &ENABLED_VERTEX_ATTRIBUTES;
|
||||
}
|
||||
|
@ -523,23 +635,22 @@ Vertex* _glSubmissionTargetEnd(SubmissionTarget* target) {
|
|||
}
|
||||
|
||||
static inline void genTriangles(Vertex* output, GLuint count) {
|
||||
const GLuint tris = count / 3;
|
||||
Vertex* it = output + 2;
|
||||
ITERATE(count / 3) {
|
||||
ITERATE(tris) {
|
||||
it->flags = PVR_CMD_VERTEX_EOL;
|
||||
it += 3;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void genQuads(Vertex* output, GLuint count) {
|
||||
Vertex* this = output + 2;
|
||||
Vertex* next = output + 3;
|
||||
const GLuint quads = count / 4;
|
||||
Vertex* final = output + 3;
|
||||
|
||||
ITERATE(count / 4) {
|
||||
swapVertex(this, next);
|
||||
next->flags = PVR_CMD_VERTEX_EOL;
|
||||
|
||||
this += 4;
|
||||
next += 4;
|
||||
ITERATE(quads) {
|
||||
swapVertex((final - 1), final);
|
||||
final->flags = PVR_CMD_VERTEX_EOL;
|
||||
final += 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -568,6 +679,7 @@ static inline void _readPositionData(const GLuint first, const GLuint count, Ver
|
|||
|
||||
if(VERTEX_POINTER.size == 3) {
|
||||
switch(VERTEX_POINTER.type) {
|
||||
case GL_DOUBLE:
|
||||
case GL_FLOAT:
|
||||
_readVertexData3f3f(vptr, count, vstride, output[0].xyz);
|
||||
break;
|
||||
|
@ -588,6 +700,7 @@ static inline void _readPositionData(const GLuint first, const GLuint count, Ver
|
|||
}
|
||||
} else if(VERTEX_POINTER.size == 2) {
|
||||
switch(VERTEX_POINTER.type) {
|
||||
case GL_DOUBLE:
|
||||
case GL_FLOAT:
|
||||
_readVertexData2f3f(vptr, count, vstride, output[0].xyz);
|
||||
break;
|
||||
|
@ -640,6 +753,7 @@ static inline void _readUVData(const GLuint first, const GLuint count, Vertex* o
|
|||
|
||||
if(UV_POINTER.size == 2) {
|
||||
switch(UV_POINTER.type) {
|
||||
case GL_DOUBLE:
|
||||
case GL_FLOAT:
|
||||
_readVertexData2f2f(uvptr, count, uvstride, output[0].uv);
|
||||
break;
|
||||
|
@ -674,6 +788,7 @@ static inline void _readSTData(const GLuint first, const GLuint count, VertexExt
|
|||
|
||||
if(ST_POINTER.size == 2) {
|
||||
switch(ST_POINTER.type) {
|
||||
case GL_DOUBLE:
|
||||
case GL_FLOAT:
|
||||
_readVertexData2f2fVE(stptr, count, ststride, extra->st);
|
||||
break;
|
||||
|
@ -704,10 +819,12 @@ static inline void _readNormalData(const GLuint first, const GLuint count, Verte
|
|||
}
|
||||
|
||||
const GLuint nstride = (NORMAL_POINTER.stride) ? NORMAL_POINTER.stride : NORMAL_POINTER.size * byte_size(NORMAL_POINTER.type);
|
||||
|
||||
const void* nptr = ((GLubyte*) NORMAL_POINTER.ptr + (first * nstride));
|
||||
|
||||
if(NORMAL_POINTER.size == 3) {
|
||||
if(NORMAL_POINTER.size == 3 || NORMAL_POINTER.type == GL_INT_2_10_10_10_REV) {
|
||||
switch(NORMAL_POINTER.type) {
|
||||
case GL_DOUBLE:
|
||||
case GL_FLOAT:
|
||||
_readVertexData3f3fVE(nptr, count, nstride, extra->nxyz);
|
||||
break;
|
||||
|
@ -723,21 +840,43 @@ static inline void _readNormalData(const GLuint first, const GLuint count, Verte
|
|||
case GL_UNSIGNED_INT:
|
||||
_readVertexData3ui3fVE(nptr, count, nstride, extra->nxyz);
|
||||
break;
|
||||
case GL_INT_2_10_10_10_REV:
|
||||
_readVertexData1i3f(nptr, count, nstride, extra->nxyz);
|
||||
break;
|
||||
default:
|
||||
assert(0 && "Not Implemented");
|
||||
}
|
||||
} else {
|
||||
assert(0 && "Not Implemented");
|
||||
}
|
||||
|
||||
if(_glIsNormalizeEnabled()) {
|
||||
GLubyte* ptr = (GLubyte*) extra->nxyz;
|
||||
GLfloat l;
|
||||
ITERATE(count) {
|
||||
GLfloat* n = (GLfloat*) ptr;
|
||||
|
||||
vec3f_length(n[0], n[1], n[2], l);
|
||||
|
||||
l = 1.0f / l;
|
||||
|
||||
n[0] *= l;
|
||||
n[1] *= l;
|
||||
n[2] *= l;
|
||||
|
||||
ptr += sizeof(VertexExtra);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void _readDiffuseData(const GLuint first, const GLuint count, Vertex* output) {
|
||||
|
||||
const GLubyte cstride = (DIFFUSE_POINTER.stride) ? DIFFUSE_POINTER.stride : DIFFUSE_POINTER.size * byte_size(DIFFUSE_POINTER.type);
|
||||
const void* cptr = ((GLubyte*) DIFFUSE_POINTER.ptr + (first * cstride));
|
||||
const void* cptr = ((GLubyte*) DIFFUSE_POINTER.ptr) + (first * cstride);
|
||||
|
||||
if(DIFFUSE_POINTER.size == 3) {
|
||||
switch(DIFFUSE_POINTER.type) {
|
||||
case GL_DOUBLE:
|
||||
case GL_FLOAT:
|
||||
_readVertexData3fARGB(cptr, count, cstride, output[0].bgra);
|
||||
break;
|
||||
|
@ -758,6 +897,7 @@ static inline void _readDiffuseData(const GLuint first, const GLuint count, Vert
|
|||
}
|
||||
} else if(DIFFUSE_POINTER.size == 4) {
|
||||
switch(DIFFUSE_POINTER.type) {
|
||||
case GL_DOUBLE:
|
||||
case GL_FLOAT:
|
||||
_readVertexData4fARGB(cptr, count, cstride, output[0].bgra);
|
||||
break;
|
||||
|
@ -776,7 +916,28 @@ static inline void _readDiffuseData(const GLuint first, const GLuint count, Vert
|
|||
default:
|
||||
assert(0 && "Not Implemented");
|
||||
}
|
||||
} else {
|
||||
} else if(DIFFUSE_POINTER.size == GL_BGRA) {
|
||||
switch(DIFFUSE_POINTER.type) {
|
||||
case GL_DOUBLE:
|
||||
case GL_FLOAT:
|
||||
_readVertexData4fRevARGB(cptr, count, cstride, output[0].bgra);
|
||||
break;
|
||||
case GL_BYTE:
|
||||
case GL_UNSIGNED_BYTE:
|
||||
_readVertexData4ubRevARGB(cptr, count, cstride, output[0].bgra);
|
||||
break;
|
||||
case GL_SHORT:
|
||||
case GL_UNSIGNED_SHORT:
|
||||
_readVertexData4usRevARGB(cptr, count, cstride, output[0].bgra);
|
||||
break;
|
||||
case GL_INT:
|
||||
case GL_UNSIGNED_INT:
|
||||
_readVertexData4uiRevARGB(cptr, count, cstride, output[0].bgra);
|
||||
break;
|
||||
default:
|
||||
assert(0 && "Not Implemented");
|
||||
}
|
||||
}else {
|
||||
assert(0 && "Not Implemented");
|
||||
}
|
||||
}
|
||||
|
@ -786,6 +947,7 @@ static void generate(SubmissionTarget* target, const GLenum mode, const GLsizei
|
|||
/* Read from the client buffers and generate an array of ClipVertices */
|
||||
TRACE();
|
||||
|
||||
static const uint32_t FAST_PATH_BYTE_SIZE = (sizeof(GLfloat) * 3) + (sizeof(GLfloat) * 2) + (sizeof(GLubyte) * 4);
|
||||
const GLsizei istride = byte_size(type);
|
||||
|
||||
if(!indices) {
|
||||
|
@ -836,18 +998,37 @@ static void generate(SubmissionTarget* target, const GLenum mode, const GLsizei
|
|||
|
||||
Vertex* start = _glSubmissionTargetStart(target);
|
||||
|
||||
_readPositionData(first, count, start);
|
||||
profiler_checkpoint("positions");
|
||||
|
||||
if((ENABLED_VERTEX_ATTRIBUTES & DIFFUSE_ENABLED_FLAG) != DIFFUSE_ENABLED_FLAG) {
|
||||
/* Just fill the whole thing white if the attribute is disabled */
|
||||
_fillWhiteARGB(count, start[0].bgra);
|
||||
if(FAST_PATH_ENABLED) {
|
||||
/* Copy the pos, uv and color directly in one go */
|
||||
const GLubyte* pos = VERTEX_POINTER.ptr;
|
||||
Vertex* it = start;
|
||||
ITERATE(count) {
|
||||
it->flags = PVR_CMD_VERTEX;
|
||||
memcpy(it->xyz, pos, FAST_PATH_BYTE_SIZE);
|
||||
it++;
|
||||
pos += VERTEX_POINTER.stride;
|
||||
}
|
||||
} else {
|
||||
_readDiffuseData(first, count, start);
|
||||
}
|
||||
profiler_checkpoint("diffuse");
|
||||
_readPositionData(first, count, start);
|
||||
profiler_checkpoint("positions");
|
||||
|
||||
if(doTexture) _readUVData(first, count, start);
|
||||
if((ENABLED_VERTEX_ATTRIBUTES & DIFFUSE_ENABLED_FLAG) != DIFFUSE_ENABLED_FLAG) {
|
||||
/* Just fill the whole thing white if the attribute is disabled */
|
||||
_fillWhiteARGB(count, start[0].bgra);
|
||||
} else {
|
||||
_readDiffuseData(first, count, start);
|
||||
}
|
||||
profiler_checkpoint("diffuse");
|
||||
|
||||
if(doTexture) _readUVData(first, count, start);
|
||||
|
||||
Vertex* it = _glSubmissionTargetStart(target);
|
||||
|
||||
ITERATE(count) {
|
||||
it->flags = PVR_CMD_VERTEX;
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
VertexExtra* ve = aligned_vector_at(target->extras, 0);
|
||||
|
||||
|
@ -855,15 +1036,6 @@ static void generate(SubmissionTarget* target, const GLenum mode, const GLsizei
|
|||
if(doTexture && doMultitexture) _readSTData(first, count, ve);
|
||||
profiler_checkpoint("others");
|
||||
|
||||
Vertex* it = _glSubmissionTargetStart(target);
|
||||
|
||||
ITERATE(count) {
|
||||
it->flags = PVR_CMD_VERTEX;
|
||||
++it;
|
||||
}
|
||||
|
||||
profiler_checkpoint("flags");
|
||||
|
||||
// Drawing arrays
|
||||
switch(mode) {
|
||||
case GL_TRIANGLES:
|
||||
|
@ -879,6 +1051,7 @@ static void generate(SubmissionTarget* target, const GLenum mode, const GLsizei
|
|||
genTriangleStrip(_glSubmissionTargetStart(target), count);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unhandled mode %d\n", (int) mode);
|
||||
assert(0 && "Not Implemented");
|
||||
}
|
||||
|
||||
|
@ -893,28 +1066,51 @@ static void generate(SubmissionTarget* target, const GLenum mode, const GLsizei
|
|||
Vertex* vertices = _glSubmissionTargetStart(target);
|
||||
VertexExtra* extras = aligned_vector_at(target->extras, 0);
|
||||
|
||||
ITERATE(count) {
|
||||
j = indexFunc(idx);
|
||||
if(FAST_PATH_ENABLED) {
|
||||
typedef struct FastPath {
|
||||
float xyz[3];
|
||||
float uv[2];
|
||||
uint8_t bgra[4];
|
||||
} FastPath;
|
||||
|
||||
_readPositionData(j, 1, vertices);
|
||||
_readDiffuseData(j, 1, vertices);
|
||||
if(doTexture) _readUVData(j, 1, vertices);
|
||||
if(doLighting) _readNormalData(j, 1, extras);
|
||||
if(doTexture && doMultitexture) _readSTData(j, 1, extras);
|
||||
GLboolean readST = doTexture && doMultitexture;
|
||||
|
||||
++vertices;
|
||||
++extras;
|
||||
ITERATE(count) {
|
||||
j = indexFunc(idx);
|
||||
|
||||
idx += istride;
|
||||
vertices->flags = PVR_CMD_VERTEX;
|
||||
|
||||
FastPath* srcV = (FastPath*) ((uint8_t*) VERTEX_POINTER.ptr + (VERTEX_POINTER.stride * j));
|
||||
FastPath* dst = (FastPath*) vertices->xyz;
|
||||
*dst = *srcV;
|
||||
|
||||
if(doLighting) _readNormalData(j, 1, extras);
|
||||
if(readST) _readSTData(j, 1, extras);
|
||||
|
||||
++vertices;
|
||||
++extras;
|
||||
|
||||
idx += istride;
|
||||
}
|
||||
} else {
|
||||
ITERATE(count) {
|
||||
j = indexFunc(idx);
|
||||
vertices->flags = PVR_CMD_VERTEX;
|
||||
|
||||
_readPositionData(j, 1, vertices);
|
||||
_readDiffuseData(j, 1, vertices);
|
||||
if(doTexture) _readUVData(j, 1, vertices);
|
||||
if(doLighting) _readNormalData(j, 1, extras);
|
||||
if(doTexture && doMultitexture) _readSTData(j, 1, extras);
|
||||
|
||||
++vertices;
|
||||
++extras;
|
||||
|
||||
idx += istride;
|
||||
}
|
||||
}
|
||||
|
||||
Vertex* it = _glSubmissionTargetStart(target);
|
||||
const Vertex* end = _glSubmissionTargetEnd(target);
|
||||
while(it < end) {
|
||||
(it++)->flags = PVR_CMD_VERTEX;
|
||||
}
|
||||
|
||||
it = _glSubmissionTargetStart(target);
|
||||
// Drawing arrays
|
||||
switch(mode) {
|
||||
case GL_TRIANGLES:
|
||||
|
@ -947,7 +1143,7 @@ static void transform(SubmissionTarget* target) {
|
|||
register float __x __asm__("fr12") = (vertex->xyz[0]);
|
||||
register float __y __asm__("fr13") = (vertex->xyz[1]);
|
||||
register float __z __asm__("fr14") = (vertex->xyz[2]);
|
||||
register float __w __asm__("fr15");
|
||||
register float __w __asm__("fr15") = (vertex->w);
|
||||
|
||||
__asm__ __volatile__(
|
||||
"fldi1 fr15\n"
|
||||
|
@ -1006,64 +1202,6 @@ static void mat_transform_normal3(const float* xyz, const float* xyzOut, const u
|
|||
|
||||
static void light(SubmissionTarget* target) {
|
||||
|
||||
#if 0
|
||||
typedef struct {
|
||||
float xyz[3];
|
||||
float n[3];
|
||||
} EyeSpaceData;
|
||||
|
||||
static AlignedVector* eye_space_data = NULL;
|
||||
|
||||
if(!eye_space_data) {
|
||||
eye_space_data = (AlignedVector*) malloc(sizeof(AlignedVector));
|
||||
aligned_vector_init(eye_space_data, sizeof(EyeSpaceData));
|
||||
}
|
||||
|
||||
aligned_vector_resize(eye_space_data, target->count);
|
||||
|
||||
/* Perform lighting calculations and manipulate the colour */
|
||||
Vertex* vertex = _glSubmissionTargetStart(target);
|
||||
VertexExtra* extra = aligned_vector_at(target->extras, 0);
|
||||
EyeSpaceData* eye_space = (EyeSpaceData*) eye_space_data->data;
|
||||
|
||||
_glMatrixLoadModelView();
|
||||
mat_transform3(vertex->xyz, eye_space->xyz, target->count, sizeof(Vertex), sizeof(EyeSpaceData));
|
||||
|
||||
_glMatrixLoadNormal();
|
||||
mat_transform_normal3(extra->nxyz, eye_space->n, target->count, sizeof(VertexExtra), sizeof(EyeSpaceData));
|
||||
|
||||
GLsizei i;
|
||||
EyeSpaceData* ES = aligned_vector_at(eye_space_data, 0);
|
||||
|
||||
for(i = 0; i < target->count; ++i, ++vertex, ++ES) {
|
||||
/* We ignore diffuse colour when lighting is enabled. If GL_COLOR_MATERIAL is enabled
|
||||
* then the lighting calculation should possibly take it into account */
|
||||
|
||||
GLfloat total [] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
GLfloat to_add [] = {0.0f, 0.0f, 0.0f, 0.0f};
|
||||
GLubyte j;
|
||||
for(j = 0; j < MAX_LIGHTS; ++j) {
|
||||
if(_glIsLightEnabled(j)) {
|
||||
_glCalculateLightingContribution(j, ES->xyz, ES->n, vertex->bgra, to_add);
|
||||
|
||||
total[0] += to_add[0];
|
||||
total[1] += to_add[1];
|
||||
total[2] += to_add[2];
|
||||
total[3] += to_add[3];
|
||||
}
|
||||
}
|
||||
|
||||
vertex->bgra[A8IDX] = (GLubyte) (255.0f * fminf(total[3], 1.0f));
|
||||
vertex->bgra[R8IDX] = (GLubyte) (255.0f * fminf(total[0], 1.0f));
|
||||
vertex->bgra[G8IDX] = (GLubyte) (255.0f * fminf(total[1], 1.0f));
|
||||
vertex->bgra[B8IDX] = (GLubyte) (255.0f * fminf(total[2], 1.0f));
|
||||
}
|
||||
#endif
|
||||
|
||||
if(!_glIsLightingEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
static AlignedVector* eye_space_data = NULL;
|
||||
|
||||
if(!eye_space_data) {
|
||||
|
@ -1086,7 +1224,6 @@ static void light(SubmissionTarget* target) {
|
|||
|
||||
EyeSpaceData* ES = aligned_vector_at(eye_space_data, 0);
|
||||
_glPerformLighting(vertex, ES, target->count);
|
||||
|
||||
}
|
||||
|
||||
static void divide(SubmissionTarget* target) {
|
||||
|
@ -1096,17 +1233,16 @@ static void divide(SubmissionTarget* target) {
|
|||
Vertex* vertex = _glSubmissionTargetStart(target);
|
||||
|
||||
ITERATE(target->count) {
|
||||
vertex->xyz[2] = 1.0f / vertex->w;
|
||||
vertex->xyz[0] *= vertex->xyz[2];
|
||||
vertex->xyz[1] *= vertex->xyz[2];
|
||||
float f = 1.0f / vertex->w;
|
||||
vertex->xyz[0] *= f;
|
||||
vertex->xyz[1] *= f;
|
||||
vertex->xyz[2] = 1.0 - ((DEPTH_RANGE_MULTIPLIER_L * vertex->xyz[2] * f) + DEPTH_RANGE_MULTIPLIER_H);
|
||||
++vertex;
|
||||
}
|
||||
}
|
||||
|
||||
static void push(PVRHeader* header, Vertex* output, const GLuint count, PolyList* activePolyList, GLshort textureUnit) {
|
||||
static void push(PVRHeader* header, GLboolean multiTextureHeader, PolyList* activePolyList, GLshort textureUnit) {
|
||||
TRACE();
|
||||
(void)output;
|
||||
(void)count;
|
||||
|
||||
// Compile the header
|
||||
pvr_poly_cxt_t cxt = *_glGetPVRContext();
|
||||
|
@ -1114,6 +1250,16 @@ static void push(PVRHeader* header, Vertex* output, const GLuint count, PolyList
|
|||
|
||||
_glUpdatePVRTextureContext(&cxt, textureUnit);
|
||||
|
||||
if(multiTextureHeader) {
|
||||
assert(cxt.list_type == PVR_LIST_TR_POLY);
|
||||
|
||||
cxt.gen.alpha = PVR_ALPHA_ENABLE;
|
||||
cxt.txr.alpha = PVR_TXRALPHA_ENABLE;
|
||||
cxt.blend.src = PVR_BLEND_ZERO;
|
||||
cxt.blend.dst = PVR_BLEND_DESTCOLOR;
|
||||
cxt.depth.comparison = PVR_DEPTHCMP_EQUAL;
|
||||
}
|
||||
|
||||
pvr_poly_compile(&header->hdr, &cxt);
|
||||
|
||||
/* Post-process the vertex list */
|
||||
|
@ -1146,6 +1292,11 @@ static void submitVertices(GLenum mode, GLsizei first, GLuint count, GLenum type
|
|||
return;
|
||||
}
|
||||
|
||||
if(mode == GL_LINE_STRIP || mode == GL_LINES) {
|
||||
fprintf(stderr, "Line drawing is currently unsupported\n");
|
||||
return;
|
||||
}
|
||||
|
||||
static SubmissionTarget* target = NULL;
|
||||
static AlignedVector extras;
|
||||
|
||||
|
@ -1303,7 +1454,7 @@ static void submitVertices(GLenum mode, GLsizei first, GLuint count, GLenum type
|
|||
|
||||
profiler_checkpoint("divide");
|
||||
|
||||
push(_glSubmissionTargetHeader(target), _glSubmissionTargetStart(target), target->count, target->output, 0);
|
||||
push(_glSubmissionTargetHeader(target), GL_FALSE, target->output, 0);
|
||||
|
||||
profiler_checkpoint("push");
|
||||
/*
|
||||
|
@ -1338,7 +1489,6 @@ static void submitVertices(GLenum mode, GLsizei first, GLuint count, GLenum type
|
|||
assert(vertex);
|
||||
|
||||
PVRHeader* mtHeader = (PVRHeader*) vertex++;
|
||||
Vertex* mtStart = vertex;
|
||||
|
||||
/* Replace the UV coordinates with the ST ones */
|
||||
VertexExtra* ve = aligned_vector_at(target->extras, 0);
|
||||
|
@ -1349,6 +1499,8 @@ static void submitVertices(GLenum mode, GLsizei first, GLuint count, GLenum type
|
|||
++ve;
|
||||
}
|
||||
|
||||
/*@Note: unsure if we still need this */
|
||||
#if 0
|
||||
/* Store state, as we're about to mess around with it */
|
||||
GLint depthFunc, blendSrc, blendDst;
|
||||
glGetIntegerv(GL_DEPTH_FUNC, &depthFunc);
|
||||
|
@ -1363,15 +1515,10 @@ static void submitVertices(GLenum mode, GLsizei first, GLuint count, GLenum type
|
|||
|
||||
/* This is modulation, we need to switch depending on the texture env mode! */
|
||||
//glBlendFunc(GL_DST_COLOR, GL_ZERO);
|
||||
#endif
|
||||
|
||||
/* Send the buffer again to the transparent list */
|
||||
push(mtHeader, mtStart, target->count, _glTransparentPolyList(), 1);
|
||||
|
||||
/* Reset state */
|
||||
glDepthFunc(depthFunc);
|
||||
glBlendFunc(blendSrc, blendDst);
|
||||
(blendEnabled) ? glEnable(GL_BLEND) : glDisable(GL_BLEND);
|
||||
(depthEnabled) ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST);
|
||||
push(mtHeader, GL_TRUE, _glTransparentPolyList(), 1);
|
||||
|
||||
profiler_pop();
|
||||
}
|
||||
|
@ -1423,6 +1570,8 @@ void APIENTRY glEnableClientState(GLenum cap) {
|
|||
default:
|
||||
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
||||
}
|
||||
|
||||
_glRecalcFastPath();
|
||||
}
|
||||
|
||||
void APIENTRY glDisableClientState(GLenum cap) {
|
||||
|
@ -1444,8 +1593,10 @@ void APIENTRY glDisableClientState(GLenum cap) {
|
|||
(ENABLED_VERTEX_ATTRIBUTES &= ~UV_ENABLED_FLAG);
|
||||
break;
|
||||
default:
|
||||
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
||||
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
||||
}
|
||||
|
||||
_glRecalcFastPath();
|
||||
}
|
||||
|
||||
GLuint _glGetActiveClientTexture() {
|
||||
|
@ -1467,33 +1618,62 @@ void APIENTRY glClientActiveTextureARB(GLenum texture) {
|
|||
ACTIVE_CLIENT_TEXTURE = (texture == GL_TEXTURE1_ARB) ? 1 : 0;
|
||||
}
|
||||
|
||||
GLboolean _glRecalcFastPath() {
|
||||
FAST_PATH_ENABLED = _glIsVertexDataFastPathCompatible();
|
||||
return FAST_PATH_ENABLED;
|
||||
}
|
||||
|
||||
void APIENTRY glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid * pointer) {
|
||||
TRACE();
|
||||
|
||||
if(size < 1 || size > 4) {
|
||||
_glKosThrowError(GL_INVALID_VALUE, __func__);
|
||||
_glKosPrintError();
|
||||
return;
|
||||
}
|
||||
|
||||
AttribPointer* tointer = (ACTIVE_CLIENT_TEXTURE == 0) ? &UV_POINTER : &ST_POINTER;
|
||||
|
||||
tointer->ptr = pointer;
|
||||
tointer->stride = stride;
|
||||
tointer->type = type;
|
||||
tointer->size = size;
|
||||
|
||||
_glRecalcFastPath();
|
||||
}
|
||||
|
||||
void APIENTRY glVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid * pointer) {
|
||||
TRACE();
|
||||
|
||||
if(size < 2 || size > 4) {
|
||||
_glKosThrowError(GL_INVALID_VALUE, __func__);
|
||||
_glKosPrintError();
|
||||
return;
|
||||
}
|
||||
|
||||
VERTEX_POINTER.ptr = pointer;
|
||||
VERTEX_POINTER.stride = stride;
|
||||
VERTEX_POINTER.type = type;
|
||||
VERTEX_POINTER.size = size;
|
||||
|
||||
_glRecalcFastPath();
|
||||
}
|
||||
|
||||
void APIENTRY glColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid * pointer) {
|
||||
TRACE();
|
||||
|
||||
if(size != 3 && size != 4 && size != GL_BGRA) {
|
||||
_glKosThrowError(GL_INVALID_VALUE, __func__);
|
||||
_glKosPrintError();
|
||||
return;
|
||||
}
|
||||
|
||||
DIFFUSE_POINTER.ptr = pointer;
|
||||
DIFFUSE_POINTER.stride = stride;
|
||||
DIFFUSE_POINTER.type = type;
|
||||
DIFFUSE_POINTER.size = size;
|
||||
|
||||
_glRecalcFastPath();
|
||||
}
|
||||
|
||||
void APIENTRY glNormalPointer(GLenum type, GLsizei stride, const GLvoid * pointer) {
|
||||
|
@ -1502,5 +1682,7 @@ void APIENTRY glNormalPointer(GLenum type, GLsizei stride, const GLvoid * poin
|
|||
NORMAL_POINTER.ptr = pointer;
|
||||
NORMAL_POINTER.stride = stride;
|
||||
NORMAL_POINTER.type = type;
|
||||
NORMAL_POINTER.size = 3;
|
||||
NORMAL_POINTER.size = (type == GL_INT_2_10_10_10_REV) ? 1 : 3;
|
||||
|
||||
_glRecalcFastPath();
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "../containers/aligned_vector.h"
|
||||
#include "private.h"
|
||||
#include "profiler.h"
|
||||
#include "version.h"
|
||||
|
||||
#define TA_SQ_ADDR (unsigned int *)(void *) \
|
||||
(0xe0000000 | (((unsigned long)0x10000000) & 0x03ffffe0))
|
||||
|
@ -96,6 +97,8 @@ void APIENTRY glKosInitConfig(GLdcConfig* config) {
|
|||
void APIENTRY glKosInitEx(GLdcConfig* config) {
|
||||
TRACE();
|
||||
|
||||
printf("\nWelcome to GLdc! Git revision: %s\n\n", GLDC_VERSION);
|
||||
|
||||
_glInitPVR(config->autosort_enabled);
|
||||
|
||||
_glInitMatrices();
|
||||
|
|
184
GL/framebuffer.c
184
GL/framebuffer.c
|
@ -1,4 +1,6 @@
|
|||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "private.h"
|
||||
#include "config.h"
|
||||
#include "../include/glkos.h"
|
||||
|
@ -97,22 +99,22 @@ void APIENTRY glFramebufferTexture2DEXT(GLenum target, GLenum attachment, GLenum
|
|||
|
||||
static INLINE_DEBUG GLuint A1555(GLuint v) {
|
||||
const GLuint MASK = (1 << 15);
|
||||
return (v & MASK) >> 15;
|
||||
return (v & MASK) >> 8;
|
||||
}
|
||||
|
||||
static INLINE_DEBUG GLuint R1555(GLuint v) {
|
||||
const GLuint MASK = (31 << 10);
|
||||
return (v & MASK) >> 10;
|
||||
return (v & MASK) >> 7;
|
||||
}
|
||||
|
||||
static INLINE_DEBUG GLuint G1555(GLuint v) {
|
||||
const GLuint MASK = (31 << 5);
|
||||
return (v & MASK) >> 5;
|
||||
return (v & MASK) >> 2;
|
||||
}
|
||||
|
||||
static INLINE_DEBUG GLuint B1555(GLuint v) {
|
||||
const GLuint MASK = (31 << 0);
|
||||
return (v & MASK) >> 0;
|
||||
return (v & MASK) << 3;
|
||||
}
|
||||
|
||||
static INLINE_DEBUG GLuint A4444(GLuint v) {
|
||||
|
@ -137,67 +139,122 @@ static INLINE_DEBUG GLuint B4444(GLuint v) {
|
|||
|
||||
static INLINE_DEBUG GLuint R565(GLuint v) {
|
||||
const GLuint MASK = (31 << 11);
|
||||
return (v & MASK) >> 11;
|
||||
return (v & MASK) >> 8;
|
||||
}
|
||||
|
||||
static INLINE_DEBUG GLuint G565(GLuint v) {
|
||||
const GLuint MASK = (63 << 5);
|
||||
return (v & MASK) >> 5;
|
||||
return (v & MASK) >> 3;
|
||||
}
|
||||
|
||||
static INLINE_DEBUG GLuint B565(GLuint v) {
|
||||
const GLuint MASK = (31 << 0);
|
||||
return (v & MASK) >> 0;
|
||||
return (v & MASK) << 3;
|
||||
}
|
||||
|
||||
static NO_INSTRUMENT GLboolean _glCalculateAverageTexel(const GLubyte* src, const GLuint srcWidth, const GLuint pvrFormat, GLubyte* dest) {
|
||||
GLushort* s1 = ((GLushort*) src);
|
||||
GLushort* s2 = ((GLushort*) src) + 1;
|
||||
GLushort* s3 = ((GLushort*) src) + srcWidth;
|
||||
GLushort* s4 = ((GLushort*) src) + srcWidth + 1;
|
||||
GLushort* d1 = ((GLushort*) dest);
|
||||
|
||||
static NO_INSTRUMENT GLboolean _glCalculateAverageTexel(GLuint pvrFormat, const GLubyte* src1, const GLubyte* src2, const GLubyte* src3, const GLubyte* src4, GLubyte* t) {
|
||||
GLuint a, r, g, b;
|
||||
|
||||
if((pvrFormat & PVR_TXRFMT_ARGB1555) == PVR_TXRFMT_ARGB1555) {
|
||||
a = A1555(*s1) + A1555(*s2) + A1555(*s3) + A1555(*s4);
|
||||
r = R1555(*s1) + R1555(*s2) + R1555(*s3) + R1555(*s4);
|
||||
g = G1555(*s1) + R1555(*s2) + R1555(*s3) + R1555(*s4);
|
||||
b = B1555(*s1) + R1555(*s2) + R1555(*s3) + R1555(*s4);
|
||||
GLubyte format = ((pvrFormat & (1 << 27)) | (pvrFormat & (1 << 26))) >> 26;
|
||||
|
||||
const GLubyte ARGB1555 = 0;
|
||||
const GLubyte ARGB4444 = 1;
|
||||
const GLubyte RGB565 = 2;
|
||||
|
||||
if((pvrFormat & PVR_TXRFMT_PAL8BPP) == PVR_TXRFMT_PAL8BPP) {
|
||||
/* Paletted... all we can do really is just pick one of the
|
||||
* 4 texels.. unless we want to change the palette (bad) or
|
||||
* pick the closest available colour (slow, and probably bad)
|
||||
*/
|
||||
*t = *src1;
|
||||
} else if(format == RGB565) {
|
||||
GLushort* s1 = (GLushort*) src1;
|
||||
GLushort* s2 = (GLushort*) src2;
|
||||
GLushort* s3 = (GLushort*) src3;
|
||||
GLushort* s4 = (GLushort*) src4;
|
||||
GLushort* d1 = (GLushort*) t;
|
||||
|
||||
r = R565(*s1) + R565(*s2) + R565(*s3) + R565(*s4);
|
||||
g = G565(*s1) + G565(*s2) + G565(*s3) + G565(*s4);
|
||||
b = B565(*s1) + B565(*s2) + B565(*s3) + B565(*s4);
|
||||
|
||||
a /= 4;
|
||||
r /= 4;
|
||||
g /= 4;
|
||||
b /= 4;
|
||||
|
||||
*d1 = (a << 15 | r << 10 | g << 5 | b);
|
||||
} else if((pvrFormat & PVR_TXRFMT_ARGB4444) == PVR_TXRFMT_ARGB4444) {
|
||||
*d1 = PACK_RGB565(r, g, b);
|
||||
} else if(format == ARGB4444) {
|
||||
GLushort* s1 = (GLushort*) src1;
|
||||
GLushort* s2 = (GLushort*) src2;
|
||||
GLushort* s3 = (GLushort*) src3;
|
||||
GLushort* s4 = (GLushort*) src4;
|
||||
GLushort* d1 = (GLushort*) t;
|
||||
|
||||
a = A4444(*s1) + A4444(*s2) + A4444(*s3) + A4444(*s4);
|
||||
r = R4444(*s1) + R4444(*s2) + R4444(*s3) + R4444(*s4);
|
||||
g = G4444(*s1) + R4444(*s2) + R4444(*s3) + R4444(*s4);
|
||||
b = B4444(*s1) + R4444(*s2) + R4444(*s3) + R4444(*s4);
|
||||
g = G4444(*s1) + G4444(*s2) + G4444(*s3) + G4444(*s4);
|
||||
b = B4444(*s1) + B4444(*s2) + B4444(*s3) + B4444(*s4);
|
||||
|
||||
a /= 4;
|
||||
r /= 4;
|
||||
g /= 4;
|
||||
b /= 4;
|
||||
|
||||
*d1 = (a << 12 | r << 8 | g << 4 | b);
|
||||
} else if((pvrFormat & PVR_TXRFMT_RGB565) == PVR_TXRFMT_ARGB4444) {
|
||||
r = R565(*s1) + R565(*s2) + R565(*s3) + R565(*s4);
|
||||
g = G565(*s1) + R565(*s2) + R565(*s3) + R565(*s4);
|
||||
b = B565(*s1) + R565(*s2) + R565(*s3) + R565(*s4);
|
||||
*d1 = PACK_ARGB4444(a, r, g, b);
|
||||
} else {
|
||||
assert(format == ARGB1555);
|
||||
|
||||
GLushort* s1 = (GLushort*) src1;
|
||||
GLushort* s2 = (GLushort*) src2;
|
||||
GLushort* s3 = (GLushort*) src3;
|
||||
GLushort* s4 = (GLushort*) src4;
|
||||
GLushort* d1 = (GLushort*) t;
|
||||
|
||||
a = A1555(*s1) + A1555(*s2) + A1555(*s3) + A1555(*s4);
|
||||
r = R1555(*s1) + R1555(*s2) + R1555(*s3) + R1555(*s4);
|
||||
g = G1555(*s1) + G1555(*s2) + G1555(*s3) + G1555(*s4);
|
||||
b = B1555(*s1) + B1555(*s2) + B1555(*s3) + B1555(*s4);
|
||||
|
||||
a /= 4;
|
||||
r /= 4;
|
||||
g /= 4;
|
||||
b /= 4;
|
||||
|
||||
*d1 = (r << 11 | g << 5 | b);
|
||||
*d1 = PACK_ARGB1555((GLubyte) a, (GLubyte) r, (GLubyte) g, (GLubyte) b);
|
||||
}
|
||||
|
||||
return GL_TRUE;
|
||||
}
|
||||
|
||||
GLboolean _glGenerateMipmapTwiddled(const GLuint pvrFormat, const GLubyte* prevData, GLuint thisWidth, GLuint thisHeight, GLubyte* thisData) {
|
||||
uint32_t lastWidth = thisWidth * 2;
|
||||
uint32_t lastHeight = thisHeight * 2;
|
||||
|
||||
uint32_t i, j;
|
||||
uint32_t stride = 0;
|
||||
|
||||
if((pvrFormat & PVR_TXRFMT_PAL8BPP) == PVR_TXRFMT_PAL8BPP) {
|
||||
stride = 1;
|
||||
} else {
|
||||
fprintf(stderr, "ERROR: Unsupported PVR format for mipmap generation");
|
||||
_glKosThrowError(GL_INVALID_OPERATION, __func__);
|
||||
_glKosPrintError();
|
||||
return GL_FALSE;
|
||||
stride = 2;
|
||||
}
|
||||
|
||||
for(i = 0, j = 0; i < lastWidth * lastHeight; i += 4, j++) {
|
||||
|
||||
/* In a twiddled texture, the neighbouring texels
|
||||
* are next to each other. By averaging them we just basically shrink
|
||||
* the reverse Ns so each reverse N becomes the next level down... if that makes sense!? */
|
||||
|
||||
const GLubyte* s1 = &prevData[i * stride];
|
||||
const GLubyte* s2 = s1 + stride;
|
||||
const GLubyte* s3 = s2 + stride;
|
||||
const GLubyte* s4 = s3 + stride;
|
||||
GLubyte* t = &thisData[j * stride];
|
||||
|
||||
assert(s4 < prevData + (lastHeight * lastWidth * stride));
|
||||
assert(t < thisData + (thisHeight * thisWidth * stride));
|
||||
|
||||
_glCalculateAverageTexel(pvrFormat, s1, s2, s3, s4, t);
|
||||
}
|
||||
|
||||
return GL_TRUE;
|
||||
|
@ -212,56 +269,65 @@ void APIENTRY glGenerateMipmapEXT(GLenum target) {
|
|||
|
||||
TextureObject* tex = _glGetBoundTexture();
|
||||
|
||||
if(tex->width != tex->height) {
|
||||
fprintf(stderr, "[GL ERROR] Mipmaps cannot be supported on non-square textures\n");
|
||||
_glKosThrowError(GL_INVALID_OPERATION, __func__);
|
||||
_glKosPrintError();
|
||||
return;
|
||||
}
|
||||
|
||||
if(!tex || !tex->data || !tex->mipmapCount) {
|
||||
_glKosThrowError(GL_INVALID_OPERATION, __func__);
|
||||
_glKosPrintError();
|
||||
return;
|
||||
}
|
||||
|
||||
if(_glIsMipmapComplete(tex)) {
|
||||
if((tex->color & PVR_TXRFMT_NONTWIDDLED) == PVR_TXRFMT_NONTWIDDLED) {
|
||||
/* glTexImage2D should twiddle internally textures in nearly all cases
|
||||
* so this error is unlikely */
|
||||
|
||||
fprintf(stderr, "[GL ERROR] Mipmaps are only supported on twiddled textures\n");
|
||||
_glKosThrowError(GL_INVALID_OPERATION, __func__);
|
||||
_glKosPrintError();
|
||||
return;
|
||||
}
|
||||
|
||||
GLboolean complete = _glIsMipmapComplete(tex);
|
||||
if(!complete && tex->isCompressed) {
|
||||
fprintf(stderr, "[GL ERROR] Generating mipmaps for compressed textures is not yet supported\n");
|
||||
_glKosThrowError(GL_INVALID_OPERATION, __func__);
|
||||
_glKosPrintError();
|
||||
return;
|
||||
}
|
||||
|
||||
if(complete) {
|
||||
/* Nothing to do */
|
||||
return;
|
||||
}
|
||||
|
||||
GLuint i = 1;
|
||||
GLuint sx, sy, dx, dy;
|
||||
GLuint i;
|
||||
GLuint prevWidth = tex->width;
|
||||
GLuint prevHeight = tex->height;
|
||||
|
||||
for(; i < _glGetMipmapLevelCount(tex); ++i) {
|
||||
/* Make sure there is room for the mipmap data on the texture object */
|
||||
_glAllocateSpaceForMipmaps(tex);
|
||||
|
||||
for(i = 1; i < _glGetMipmapLevelCount(tex); ++i) {
|
||||
GLubyte* prevData = _glGetMipmapLocation(tex, i - 1);
|
||||
GLubyte* thisData = _glGetMipmapLocation(tex, i);
|
||||
|
||||
GLuint thisWidth = (prevWidth > 1) ? prevWidth / 2 : 1;
|
||||
GLuint thisHeight = (prevHeight > 1) ? prevHeight / 2 : 1;
|
||||
|
||||
/* Do the minification */
|
||||
for(sx = 0, dx = 0; sx < prevWidth; sx += 2, dx += 1) {
|
||||
for(sy = 0, dy = 0; sy < prevHeight; sy += 2, dy += 1) {
|
||||
GLubyte* srcTexel = &prevData[
|
||||
((sy * prevWidth) + sx) * tex->dataStride
|
||||
];
|
||||
|
||||
GLubyte* destTexel = &thisData[
|
||||
((dy * thisWidth) + dx) * tex->dataStride
|
||||
];
|
||||
|
||||
if(!_glCalculateAverageTexel(
|
||||
srcTexel,
|
||||
prevWidth,
|
||||
tex->color,
|
||||
destTexel
|
||||
)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
_glGenerateMipmapTwiddled(tex->color, prevData, thisWidth, thisHeight, thisData);
|
||||
|
||||
tex->mipmap |= (1 << i);
|
||||
|
||||
prevWidth = thisWidth;
|
||||
prevHeight = thisHeight;
|
||||
}
|
||||
|
||||
assert(_glIsMipmapComplete(tex));
|
||||
}
|
||||
|
||||
GLenum APIENTRY glCheckFramebufferStatusEXT(GLenum target) {
|
||||
|
|
10
GL/glu.c
10
GL/glu.c
|
@ -5,14 +5,12 @@
|
|||
/* Set the Perspective */
|
||||
void APIENTRY gluPerspective(GLfloat angle, GLfloat aspect,
|
||||
GLfloat znear, GLfloat zfar) {
|
||||
GLfloat xmin, xmax, ymin, ymax;
|
||||
GLfloat fW, fH;
|
||||
|
||||
ymax = znear * tanf(angle * F_PI / 360.0f);
|
||||
ymin = -ymax;
|
||||
xmin = ymin * aspect;
|
||||
xmax = ymax * aspect;
|
||||
fH = tanf(angle * (F_PI / 360)) * znear;
|
||||
fW = fH * aspect;
|
||||
|
||||
glFrustum(xmin, xmax, ymin, ymax, znear, zfar);
|
||||
glFrustum(-fW, fW, -fH, fH, znear, zfar);
|
||||
}
|
||||
|
||||
void APIENTRY gluOrtho2D(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top) {
|
||||
|
|
116
GL/immediate.c
116
GL/immediate.c
|
@ -7,8 +7,12 @@
|
|||
* 3. This is entirely untested.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../include/gl.h"
|
||||
#include "../include/glext.h"
|
||||
#include "../include/glkos.h"
|
||||
#include "profiler.h"
|
||||
|
||||
#include "private.h"
|
||||
|
@ -17,18 +21,14 @@ static GLboolean IMMEDIATE_MODE_ACTIVE = GL_FALSE;
|
|||
static GLenum ACTIVE_POLYGON_MODE = GL_TRIANGLES;
|
||||
|
||||
static AlignedVector VERTICES;
|
||||
static AlignedVector COLOURS;
|
||||
static AlignedVector UV_COORDS;
|
||||
static AlignedVector ST_COORDS;
|
||||
static AlignedVector NORMALS;
|
||||
|
||||
|
||||
static GLfloat NORMAL[3] = {0.0f, 0.0f, 1.0f};
|
||||
static GLubyte COLOR[4] = {255, 255, 255, 255};
|
||||
static GLfloat UV_COORD[2] = {0.0f, 0.0f};
|
||||
static GLfloat ST_COORD[2] = {0.0f, 0.0f};
|
||||
|
||||
|
||||
static AttribPointer VERTEX_ATTRIB;
|
||||
static AttribPointer DIFFUSE_ATTRIB;
|
||||
static AttribPointer UV_ATTRIB;
|
||||
|
@ -36,42 +36,38 @@ static AttribPointer ST_ATTRIB;
|
|||
static AttribPointer NORMAL_ATTRIB;
|
||||
|
||||
void _glInitImmediateMode(GLuint initial_size) {
|
||||
aligned_vector_init(&VERTICES, sizeof(GLfloat));
|
||||
aligned_vector_init(&COLOURS, sizeof(GLubyte));
|
||||
aligned_vector_init(&UV_COORDS, sizeof(GLfloat));
|
||||
aligned_vector_init(&VERTICES, sizeof(GLVertexKOS));
|
||||
aligned_vector_init(&ST_COORDS, sizeof(GLfloat));
|
||||
aligned_vector_init(&NORMALS, sizeof(GLfloat));
|
||||
aligned_vector_init(&NORMALS, sizeof(GLuint));
|
||||
|
||||
aligned_vector_reserve(&VERTICES, initial_size);
|
||||
aligned_vector_reserve(&COLOURS, initial_size);
|
||||
aligned_vector_reserve(&UV_COORDS, initial_size);
|
||||
aligned_vector_reserve(&ST_COORDS, initial_size);
|
||||
aligned_vector_reserve(&ST_COORDS, initial_size * 2);
|
||||
aligned_vector_reserve(&NORMALS, initial_size);
|
||||
|
||||
VERTEX_ATTRIB.ptr = VERTICES.data;
|
||||
VERTEX_ATTRIB.ptr = VERTICES.data + sizeof(uint32_t);
|
||||
VERTEX_ATTRIB.size = 3;
|
||||
VERTEX_ATTRIB.type = GL_FLOAT;
|
||||
VERTEX_ATTRIB.stride = 0;
|
||||
VERTEX_ATTRIB.stride = 32;
|
||||
|
||||
DIFFUSE_ATTRIB.ptr = COLOURS.data;
|
||||
DIFFUSE_ATTRIB.size = 4;
|
||||
DIFFUSE_ATTRIB.type = GL_UNSIGNED_BYTE;
|
||||
DIFFUSE_ATTRIB.stride = 0;
|
||||
|
||||
UV_ATTRIB.ptr = UV_COORDS.data;
|
||||
UV_ATTRIB.stride = 0;
|
||||
UV_ATTRIB.ptr = VERTEX_ATTRIB.ptr + (sizeof(GLfloat) * 3);
|
||||
UV_ATTRIB.stride = 32;
|
||||
UV_ATTRIB.type = GL_FLOAT;
|
||||
UV_ATTRIB.size = 2;
|
||||
|
||||
DIFFUSE_ATTRIB.ptr = VERTEX_ATTRIB.ptr + (sizeof(GLfloat) * 5);
|
||||
DIFFUSE_ATTRIB.size = GL_BGRA; /* Flipped color order */
|
||||
DIFFUSE_ATTRIB.type = GL_UNSIGNED_BYTE;
|
||||
DIFFUSE_ATTRIB.stride = 32;
|
||||
|
||||
NORMAL_ATTRIB.ptr = NORMALS.data;
|
||||
NORMAL_ATTRIB.stride = 0;
|
||||
NORMAL_ATTRIB.type = GL_INT_2_10_10_10_REV;
|
||||
NORMAL_ATTRIB.size = 1;
|
||||
|
||||
ST_ATTRIB.ptr = ST_COORDS.data;
|
||||
ST_ATTRIB.stride = 0;
|
||||
ST_ATTRIB.type = GL_FLOAT;
|
||||
ST_ATTRIB.size = 2;
|
||||
|
||||
NORMAL_ATTRIB.ptr = NORMALS.data;
|
||||
NORMAL_ATTRIB.stride = 0;
|
||||
NORMAL_ATTRIB.type = GL_FLOAT;
|
||||
NORMAL_ATTRIB.size = 3;
|
||||
}
|
||||
|
||||
GLubyte _glCheckImmediateModeInactive(const char* func) {
|
||||
|
@ -131,6 +127,13 @@ void APIENTRY glColor3ub(GLubyte red, GLubyte green, GLubyte blue) {
|
|||
COLOR[3] = 255;
|
||||
}
|
||||
|
||||
void APIENTRY glColor3ubv(const GLubyte *v) {
|
||||
COLOR[0] = v[0];
|
||||
COLOR[1] = v[1];
|
||||
COLOR[2] = v[2];
|
||||
COLOR[3] = 255;
|
||||
}
|
||||
|
||||
void APIENTRY glColor3fv(const GLfloat* v) {
|
||||
COLOR[0] = (GLubyte)(v[0] * 255);
|
||||
COLOR[1] = (GLubyte)(v[1] * 255);
|
||||
|
@ -138,18 +141,42 @@ void APIENTRY glColor3fv(const GLfloat* v) {
|
|||
COLOR[3] = 255;
|
||||
}
|
||||
|
||||
static inline uint32_t pack_vertex_attribute_vec3_1i(float x, float y, float z) {
|
||||
const float w = 0.0f;
|
||||
|
||||
const uint32_t xs = x < 0;
|
||||
const uint32_t ys = y < 0;
|
||||
const uint32_t zs = z < 0;
|
||||
const uint32_t ws = w < 0;
|
||||
|
||||
uint32_t vi =
|
||||
ws << 31 | ((uint32_t)(w + (ws << 1)) & 1) << 30 |
|
||||
zs << 29 | ((uint32_t)(z * 511 + (zs << 9)) & 511) << 20 |
|
||||
ys << 19 | ((uint32_t)(y * 511 + (ys << 9)) & 511) << 10 |
|
||||
xs << 9 | ((uint32_t)(x * 511 + (xs << 9)) & 511);
|
||||
|
||||
return vi;
|
||||
}
|
||||
|
||||
void APIENTRY glVertex3f(GLfloat x, GLfloat y, GLfloat z) {
|
||||
aligned_vector_reserve(&VERTICES, VERTICES.size + 3);
|
||||
aligned_vector_push_back(&VERTICES, &x, 1);
|
||||
aligned_vector_push_back(&VERTICES, &y, 1);
|
||||
aligned_vector_push_back(&VERTICES, &z, 1);
|
||||
GLVertexKOS* vert = aligned_vector_extend(&VERTICES, 1);
|
||||
GLfloat* st = aligned_vector_extend(&ST_COORDS, 2);
|
||||
GLuint* n = aligned_vector_extend(&NORMALS, 1);
|
||||
|
||||
vert->x = x;
|
||||
vert->y = y;
|
||||
vert->z = z;
|
||||
vert->u = UV_COORD[0];
|
||||
vert->v = UV_COORD[1];
|
||||
|
||||
/* Push back the stashed colour, normal and uv_coordinate */
|
||||
aligned_vector_push_back(&COLOURS, COLOR, 4);
|
||||
aligned_vector_push_back(&UV_COORDS, UV_COORD, 2);
|
||||
aligned_vector_push_back(&ST_COORDS, ST_COORD, 2);
|
||||
aligned_vector_push_back(&NORMALS, NORMAL, 3);
|
||||
vert->bgra[R8IDX] = COLOR[0];
|
||||
vert->bgra[G8IDX] = COLOR[1];
|
||||
vert->bgra[B8IDX] = COLOR[2];
|
||||
vert->bgra[A8IDX] = COLOR[3];
|
||||
|
||||
*n = pack_vertex_attribute_vec3_1i(NORMAL[0], NORMAL[1], NORMAL[2]);
|
||||
|
||||
memcpy(st, ST_COORD, sizeof(GLfloat) * 2);
|
||||
}
|
||||
|
||||
void APIENTRY glVertex3fv(const GLfloat* v) {
|
||||
|
@ -212,11 +239,12 @@ void APIENTRY glEnd() {
|
|||
IMMEDIATE_MODE_ACTIVE = GL_FALSE;
|
||||
|
||||
/* Resizing could have invalidated these pointers */
|
||||
VERTEX_ATTRIB.ptr = VERTICES.data;
|
||||
DIFFUSE_ATTRIB.ptr = COLOURS.data;
|
||||
UV_ATTRIB.ptr = UV_COORDS.data;
|
||||
ST_ATTRIB.ptr = ST_COORDS.data;
|
||||
VERTEX_ATTRIB.ptr = VERTICES.data + sizeof(uint32_t);
|
||||
UV_ATTRIB.ptr = VERTEX_ATTRIB.ptr + (sizeof(GLfloat) * 3);
|
||||
DIFFUSE_ATTRIB.ptr = VERTEX_ATTRIB.ptr + (sizeof(GLfloat) * 5);
|
||||
|
||||
NORMAL_ATTRIB.ptr = NORMALS.data;
|
||||
ST_ATTRIB.ptr = ST_COORDS.data;
|
||||
|
||||
GLuint* attrs = _glGetEnabledAttributes();
|
||||
|
||||
|
@ -244,7 +272,15 @@ void APIENTRY glEnd() {
|
|||
|
||||
*attrs = ~0; // Enable everything
|
||||
|
||||
glDrawArrays(ACTIVE_POLYGON_MODE, 0, VERTICES.size / 3);
|
||||
#ifndef NDEBUG
|
||||
_glRecalcFastPath();
|
||||
#else
|
||||
// Immediate mode should always activate the fast path
|
||||
GLboolean fastPathEnabled = _glRecalcFastPath();
|
||||
assert(fastPathEnabled);
|
||||
#endif
|
||||
|
||||
glDrawArrays(ACTIVE_POLYGON_MODE, 0, VERTICES.size);
|
||||
|
||||
/* Restore everything */
|
||||
*vattr = vptr;
|
||||
|
@ -257,8 +293,6 @@ void APIENTRY glEnd() {
|
|||
|
||||
/* Clear arrays for next polys */
|
||||
aligned_vector_clear(&VERTICES);
|
||||
aligned_vector_clear(&COLOURS);
|
||||
aligned_vector_clear(&UV_COORDS);
|
||||
aligned_vector_clear(&ST_COORDS);
|
||||
aligned_vector_clear(&NORMALS);
|
||||
|
||||
|
|
304
GL/lighting.c
304
GL/lighting.c
|
@ -1,9 +1,14 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
#include <dc/vec3f.h>
|
||||
#include "private.h"
|
||||
|
||||
/* Lighting will not be calculated if the attenuation
|
||||
* multiplier ends up less than this value */
|
||||
#define ATTENUATION_THRESHOLD 0.01f
|
||||
|
||||
static GLfloat SCENE_AMBIENT [] = {0.2, 0.2, 0.2, 1.0};
|
||||
static GLboolean VIEWER_IN_EYE_COORDINATES = GL_TRUE;
|
||||
static GLenum COLOR_CONTROL = GL_SINGLE_COLOR;
|
||||
|
@ -48,8 +53,6 @@ void _glInitLights() {
|
|||
LIGHTS[i].constant_attenuation = 1.0f;
|
||||
LIGHTS[i].linear_attenuation = 0.0f;
|
||||
LIGHTS[i].quadratic_attenuation = 0.0f;
|
||||
|
||||
LIGHTS[i].is_directional = GL_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -112,8 +115,7 @@ void APIENTRY glLightfv(GLenum light, GLenum pname, const GLfloat *params) {
|
|||
_glMatrixLoadModelView();
|
||||
memcpy(LIGHTS[idx].position, params, sizeof(GLfloat) * 4);
|
||||
|
||||
LIGHTS[idx].is_directional = (params[3] == 0.0f) ? GL_TRUE : GL_FALSE;
|
||||
if(LIGHTS[idx].is_directional) {
|
||||
if(params[3] == 0.0f) {
|
||||
//FIXME: Do we need to rotate directional lights?
|
||||
} else {
|
||||
mat_trans_single4(
|
||||
|
@ -209,7 +211,7 @@ void APIENTRY glMaterialfv(GLenum face, GLenum pname, const GLfloat *params) {
|
|||
memcpy(MATERIAL.specular, params, sizeof(GLfloat) * 4);
|
||||
break;
|
||||
case GL_EMISSION:
|
||||
memcpy(MATERIAL.specular, params, sizeof(GLfloat) * 4);
|
||||
memcpy(MATERIAL.emissive, params, sizeof(GLfloat) * 4);
|
||||
break;
|
||||
case GL_AMBIENT_AND_DIFFUSE: {
|
||||
glMaterialfv(face, GL_AMBIENT, params);
|
||||
|
@ -239,19 +241,19 @@ void APIENTRY glColorMaterial(GLenum face, GLenum mode) {
|
|||
COLOR_MATERIAL_MODE = mode;
|
||||
}
|
||||
|
||||
static inline GLboolean isDiffuseColorMaterial() {
|
||||
GL_FORCE_INLINE GLboolean isDiffuseColorMaterial() {
|
||||
return (COLOR_MATERIAL_MODE == GL_DIFFUSE || COLOR_MATERIAL_MODE == GL_AMBIENT_AND_DIFFUSE);
|
||||
}
|
||||
|
||||
static inline GLboolean isAmbientColorMaterial() {
|
||||
GL_FORCE_INLINE GLboolean isAmbientColorMaterial() {
|
||||
return (COLOR_MATERIAL_MODE == GL_AMBIENT || COLOR_MATERIAL_MODE == GL_AMBIENT_AND_DIFFUSE);
|
||||
}
|
||||
|
||||
static inline GLboolean isSpecularColorMaterial() {
|
||||
GL_FORCE_INLINE GLboolean isSpecularColorMaterial() {
|
||||
return (COLOR_MATERIAL_MODE == GL_SPECULAR);
|
||||
}
|
||||
|
||||
static inline void initVec3(struct vec3f* v, const GLfloat* src) {
|
||||
GL_FORCE_INLINE void initVec3(struct vec3f* v, const GLfloat* src) {
|
||||
memcpy(v, src, sizeof(GLfloat) * 3);
|
||||
}
|
||||
|
||||
|
@ -259,7 +261,7 @@ static inline void initVec3(struct vec3f* v, const GLfloat* src) {
|
|||
#define EXP_A 184
|
||||
#define EXP_C 16249
|
||||
|
||||
static inline float FEXP(float y) {
|
||||
GL_FORCE_INLINE float FEXP(float y) {
|
||||
union {
|
||||
float d;
|
||||
struct {
|
||||
|
@ -271,34 +273,56 @@ static inline float FEXP(float y) {
|
|||
return eco.d;
|
||||
}
|
||||
|
||||
static inline float FLOG(float y) {
|
||||
int *nTemp = (int *)&y;
|
||||
y = (*nTemp) >> 16;
|
||||
return (y - EXP_C) / EXP_A;
|
||||
/* Inspired by: https://web.archive.org/web/20180423090243/www.dctsystems.co.uk/Software/power.html */
|
||||
#define SHIFT23 (1 << 23)
|
||||
#define INVSHIFT23 (1.0f / SHIFT23)
|
||||
#define LOGBODGE 0.346607f
|
||||
#define POWBODGE 0.33971f
|
||||
|
||||
static const float FINT_MAX = (float) INT_MAX;
|
||||
|
||||
GL_FORCE_INLINE float FFLOOR(float x) {
|
||||
return (int)(x + FINT_MAX) - INT_MAX;
|
||||
}
|
||||
|
||||
static inline float FPOW(float b, float p) {
|
||||
return FEXP(FLOG(b) * p);
|
||||
GL_FORCE_INLINE float FLOG2(float i) {
|
||||
float y;
|
||||
|
||||
union {
|
||||
float f;
|
||||
int i;
|
||||
} x;
|
||||
|
||||
x.i = i;
|
||||
|
||||
x.f *= INVSHIFT23;
|
||||
x.f = x.f - 127;
|
||||
|
||||
y = x.f - FFLOOR(x.f);
|
||||
y = (y - y * y) * LOGBODGE;
|
||||
|
||||
return x.f + y;
|
||||
}
|
||||
|
||||
#define LIGHT_COMPONENT(C) { \
|
||||
const GLfloat* acm = &MA[C]; \
|
||||
const GLfloat* dcm = &MD[C]; \
|
||||
const GLfloat* scm = &MS[C]; \
|
||||
const GLfloat* scli = &light->specular[C]; \
|
||||
const GLfloat* dcli = &light->diffuse[C]; \
|
||||
const GLfloat* acli = &light->ambient[C]; \
|
||||
const GLfloat* srm = &MATERIAL.exponent; \
|
||||
const GLfloat fi = (LdotN == 0) ? 0 : 1; \
|
||||
GLfloat component = (*acm * *acli); \
|
||||
component += (LdotN * *dcm * *dcli); \
|
||||
component += (FPOW((fi * NdotH), *srm) * *scm * *scli); \
|
||||
component *= att; \
|
||||
component *= spot; \
|
||||
final[C] += component; \
|
||||
GL_FORCE_INLINE float FPOW2(float i) {
|
||||
float y = i - FFLOOR(i);
|
||||
y = (y - y * y) * POWBODGE;
|
||||
|
||||
union {
|
||||
float f;
|
||||
float i;
|
||||
} x;
|
||||
|
||||
x.f = i + 127 - y;
|
||||
x.f *= SHIFT23;
|
||||
return x.i;
|
||||
}
|
||||
|
||||
static inline float vec3_dot_limited(
|
||||
GL_FORCE_INLINE float FPOW(float a, float b) {
|
||||
return FPOW2(b * FLOG2(a));
|
||||
}
|
||||
|
||||
GL_FORCE_INLINE float vec3_dot_limited(
|
||||
const float* x1, const float* y1, const float* z1,
|
||||
const float* x2, const float* y2, const float* z2) {
|
||||
|
||||
|
@ -307,117 +331,149 @@ static inline float vec3_dot_limited(
|
|||
return (ret < 0) ? 0 : ret;
|
||||
}
|
||||
|
||||
#define _MIN(x, y) (x < y) ? x : y
|
||||
|
||||
GL_FORCE_INLINE void _glLightVertexDirectional(uint8_t* final, int8_t lid, float LdotN, float NdotH) {
|
||||
float F;
|
||||
float FI = (LdotN != 0.0f);
|
||||
uint8_t FO;
|
||||
|
||||
#define _PROCESS_COMPONENT(T, X) \
|
||||
F = (MATERIAL.ambient[X] * LIGHTS[lid].ambient[X]); \
|
||||
F += (LdotN * MATERIAL.diffuse[X] * LIGHTS[lid].diffuse[X]); \
|
||||
FI = (MATERIAL.exponent) ? FPOW(FI * NdotH, MATERIAL.exponent) : 1.0f; \
|
||||
F += FI * MATERIAL.specular[X] * LIGHTS[lid].specular[X]; \
|
||||
FO = (uint8_t) (_MIN(F * 255.0f, 255.0f)); \
|
||||
\
|
||||
final[T] += _MIN(FO, 255 - final[T]); \
|
||||
|
||||
_PROCESS_COMPONENT(R8IDX, 0);
|
||||
_PROCESS_COMPONENT(G8IDX, 1);
|
||||
_PROCESS_COMPONENT(B8IDX, 2);
|
||||
|
||||
#undef _PROCESS_COMPONENT
|
||||
}
|
||||
|
||||
GL_FORCE_INLINE void _glLightVertexPoint(uint8_t* final, int8_t lid, float LdotN, float NdotH, float att) {
|
||||
float F;
|
||||
float FI = (LdotN != 0.0f);
|
||||
uint8_t FO;
|
||||
|
||||
#define _PROCESS_COMPONENT(T, X) \
|
||||
F = (MATERIAL.ambient[X] * LIGHTS[lid].ambient[X]); \
|
||||
F += (LdotN * MATERIAL.diffuse[X] * LIGHTS[lid].diffuse[X]); \
|
||||
FI = (MATERIAL.exponent) ? FPOW(FI * NdotH, MATERIAL.exponent) : 1.0f; \
|
||||
F += FI * MATERIAL.specular[X] * LIGHTS[lid].specular[X]; \
|
||||
FO = (uint8_t) (_MIN(F * att * 255.0f, 255.0f)); \
|
||||
\
|
||||
final[T] += _MIN(FO, 255 - final[T]); \
|
||||
|
||||
_PROCESS_COMPONENT(R8IDX, 0);
|
||||
_PROCESS_COMPONENT(G8IDX, 1);
|
||||
_PROCESS_COMPONENT(B8IDX, 2);
|
||||
|
||||
#undef _PROCESS_COMPONENT
|
||||
}
|
||||
|
||||
void _glPerformLighting(Vertex* vertices, const EyeSpaceData* es, const int32_t count) {
|
||||
int8_t i;
|
||||
int32_t j;
|
||||
|
||||
const LightSource* light = NULL;
|
||||
|
||||
const GLboolean colorMaterial = _glIsColorMaterialEnabled();
|
||||
const GLboolean isDiffuseCM = isDiffuseColorMaterial();
|
||||
const GLboolean isAmbientCM = isAmbientColorMaterial();
|
||||
const GLboolean isSpecularCM = isSpecularColorMaterial();
|
||||
|
||||
static GLfloat CM[4];
|
||||
|
||||
/* So the DC has 16 floating point registers, that means
|
||||
* we need to limit the number of floats as much as possible
|
||||
* to give the compiler a good enough chance to do the right
|
||||
* thing */
|
||||
|
||||
Vertex* vertex = vertices;
|
||||
const EyeSpaceData* data = es;
|
||||
|
||||
static const float ONE_OVER_255 = 1.0f / 255.0f;
|
||||
float base;
|
||||
|
||||
for(j = 0; j < count; ++j, ++vertex, ++data) {
|
||||
/* When GL_COLOR_MATERIAL is on, we need to pull out
|
||||
* the passed in diffuse and use it */
|
||||
const GLfloat* MD = MATERIAL.diffuse;
|
||||
const GLfloat* MA = MATERIAL.ambient;
|
||||
const GLfloat* MS = MATERIAL.specular;
|
||||
|
||||
if(colorMaterial) {
|
||||
CM[0] = ((GLfloat) vertex->bgra[R8IDX]) * ONE_OVER_255;
|
||||
CM[1] = ((GLfloat) vertex->bgra[G8IDX]) * ONE_OVER_255;
|
||||
CM[2] = ((GLfloat) vertex->bgra[B8IDX]) * ONE_OVER_255;
|
||||
CM[3] = ((GLfloat) vertex->bgra[A8IDX]) * ONE_OVER_255;
|
||||
|
||||
MD = (isDiffuseCM) ? CM : MATERIAL.diffuse;
|
||||
MA = (isAmbientCM) ? CM : MATERIAL.ambient;
|
||||
MS = (isSpecularCM) ? CM : MATERIAL.specular;
|
||||
}
|
||||
|
||||
float final[4];
|
||||
|
||||
/* Initial, non-light related values */
|
||||
final[0] = (SCENE_AMBIENT[0] * MA[0]) + MATERIAL.emissive[0];
|
||||
final[1] = (SCENE_AMBIENT[1] * MA[1]) + MATERIAL.emissive[1];
|
||||
final[2] = (SCENE_AMBIENT[2] * MA[2]) + MATERIAL.emissive[2];
|
||||
final[3] = MD[3];
|
||||
base = (SCENE_AMBIENT[0] * MATERIAL.ambient[0]) + MATERIAL.emissive[0];
|
||||
vertex->bgra[R8IDX] = (uint8_t)(_MIN(base * 255.0f, 255.0f));
|
||||
|
||||
float Vx, Vy, Vz;
|
||||
Vx = -data->xyz[0];
|
||||
Vy = -data->xyz[1];
|
||||
Vz = -data->xyz[2];
|
||||
base = (SCENE_AMBIENT[1] * MATERIAL.ambient[1]) + MATERIAL.emissive[1];
|
||||
vertex->bgra[G8IDX] = (uint8_t)(_MIN(base * 255.0f, 255.0f));
|
||||
|
||||
base = (SCENE_AMBIENT[2] * MATERIAL.ambient[2]) + MATERIAL.emissive[2];
|
||||
vertex->bgra[B8IDX] = (uint8_t)(_MIN(base * 255.0f, 255.0f));
|
||||
vertex->bgra[A8IDX] = (uint8_t)(_MIN(MATERIAL.diffuse[3] * 255.0f, 255.0f));
|
||||
|
||||
float Vx = -data->xyz[0];
|
||||
float Vy = -data->xyz[1];
|
||||
float Vz = -data->xyz[2];
|
||||
vec3f_normalize(Vx, Vy, Vz);
|
||||
|
||||
const float Nx = data->n[0];
|
||||
const float Ny = data->n[1];
|
||||
const float Nz = data->n[2];
|
||||
|
||||
for(i = 0; i < MAX_LIGHTS; ++i) {
|
||||
if(!_glIsLightEnabled(i)) continue;
|
||||
|
||||
/* Calc light specific parameters */
|
||||
light = &LIGHTS[i];
|
||||
if(LIGHTS[i].position[3] == 0.0f) {
|
||||
float Lx = -LIGHTS[i].position[0];
|
||||
float Ly = -LIGHTS[i].position[1];
|
||||
float Lz = -LIGHTS[i].position[2];
|
||||
float Hx = (Lx + Vx);
|
||||
float Hy = (Ly + Vy);
|
||||
float Hz = (Lz + Vz);
|
||||
|
||||
float Lx, Ly, Lz, D;
|
||||
float Hx, Hy, Hz;
|
||||
const float* Nx = &data->n[0];
|
||||
const float* Ny = &data->n[1];
|
||||
const float* Nz = &data->n[2];
|
||||
vec3f_normalize(Lx, Ly, Lz);
|
||||
vec3f_normalize(Hx, Hy, Hz);
|
||||
|
||||
Lx = light->position[0] - data->xyz[0];
|
||||
Ly = light->position[1] - data->xyz[1];
|
||||
Lz = light->position[2] - data->xyz[2];
|
||||
vec3f_length(Lx, Ly, Lz, D);
|
||||
const float LdotN = vec3_dot_limited(
|
||||
&Nx, &Ny, &Nz,
|
||||
&Lx, &Ly, &Lz
|
||||
);
|
||||
|
||||
{
|
||||
/* Normalize L - scoping ensures Llen is temporary */
|
||||
const float Llen = 1.0f / D;
|
||||
Lx *= Llen;
|
||||
Ly *= Llen;
|
||||
Lz *= Llen;
|
||||
const float NdotH = vec3_dot_limited(
|
||||
&Nx, &Ny, &Nz,
|
||||
&Hx, &Hy, &Hz
|
||||
);
|
||||
|
||||
_glLightVertexDirectional(
|
||||
vertex->bgra,
|
||||
i, LdotN, NdotH
|
||||
);
|
||||
} else {
|
||||
float Lx = LIGHTS[i].position[0] - data->xyz[0];
|
||||
float Ly = LIGHTS[i].position[1] - data->xyz[1];
|
||||
float Lz = LIGHTS[i].position[2] - data->xyz[2];
|
||||
float D;
|
||||
|
||||
vec3f_length(Lx, Ly, Lz, D);
|
||||
|
||||
float att = (
|
||||
LIGHTS[i].constant_attenuation + (
|
||||
LIGHTS[i].linear_attenuation * D
|
||||
) + (LIGHTS[i].quadratic_attenuation * D * D)
|
||||
);
|
||||
|
||||
att = MATH_fsrra(att * att);
|
||||
|
||||
if(att >= ATTENUATION_THRESHOLD) {
|
||||
float Hx = (Lx + Vx);
|
||||
float Hy = (Ly + Vy);
|
||||
float Hz = (Lz + Vz);
|
||||
|
||||
vec3f_normalize(Lx, Ly, Lz);
|
||||
vec3f_normalize(Hx, Hy, Hz);
|
||||
|
||||
const float LdotN = vec3_dot_limited(
|
||||
&Nx, &Ny, &Nz,
|
||||
&Lx, &Ly, &Lz
|
||||
);
|
||||
|
||||
const float NdotH = vec3_dot_limited(
|
||||
&Nx, &Ny, &Nz,
|
||||
&Hx, &Hy, &Hz
|
||||
);
|
||||
|
||||
_glLightVertexPoint(
|
||||
vertex->bgra,
|
||||
i, LdotN, NdotH, att
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Hx = (Lx + Vx);
|
||||
Hy = (Ly + Vy);
|
||||
Hz = (Lz + Vz);
|
||||
vec3f_normalize(Hx, Hy, Hz);
|
||||
|
||||
const float LdotN = vec3_dot_limited(
|
||||
&Lx, &Ly, &Lz,
|
||||
Nx, Ny, Nz
|
||||
);
|
||||
|
||||
const float NdotH = vec3_dot_limited(
|
||||
Nx, Ny, Nz,
|
||||
&Hx, &Hy, &Hz
|
||||
);
|
||||
|
||||
const float att = (
|
||||
light->position[3] == 0.0f) ? 1.0f :
|
||||
1.0f / (light->constant_attenuation + (light->linear_attenuation * D) + (light->quadratic_attenuation * D * D)
|
||||
);
|
||||
|
||||
const float spot = 1.0f;
|
||||
|
||||
LIGHT_COMPONENT(0);
|
||||
LIGHT_COMPONENT(1);
|
||||
LIGHT_COMPONENT(2);
|
||||
}
|
||||
|
||||
vertex->bgra[R8IDX] = (GLubyte)(fminf(final[0] * 255.0f, 255.0f));
|
||||
vertex->bgra[G8IDX] = (GLubyte)(fminf(final[1] * 255.0f, 255.0f));
|
||||
vertex->bgra[B8IDX] = (GLubyte)(fminf(final[2] * 255.0f, 255.0f));
|
||||
vertex->bgra[A8IDX] = (GLubyte)(fminf(final[3] * 255.0f, 255.0f));
|
||||
}
|
||||
}
|
||||
|
||||
#undef LIGHT_COMPONENT
|
||||
|
|
|
@ -299,7 +299,7 @@ void APIENTRY glFrustum(GLfloat left, GLfloat right,
|
|||
/* Frustum Matrix */
|
||||
static Matrix4x4 FrustumMatrix __attribute__((aligned(32)));
|
||||
|
||||
memset4(FrustumMatrix, 0, sizeof(float) * 16);
|
||||
memset(FrustumMatrix, 0, sizeof(float) * 16);
|
||||
|
||||
const float near2 = 2.0f * znear;
|
||||
const float A = (right + left) / (right - left);
|
||||
|
@ -522,6 +522,7 @@ void gluLookAt(GLfloat eyex, GLfloat eyey, GLfloat eyez, GLfloat centerx,
|
|||
m[2] = -f[0]; m[6] = -f[1]; m[10] = -f[2]; m[14] = 0.0f;
|
||||
m[3] = 0.0f; m[7] = 0.0f; m[11] = 0.0f; m[15] = 1.0f;
|
||||
|
||||
/*
|
||||
static Matrix4x4 trn __attribute__((aligned(32))) = {
|
||||
1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
|
@ -538,6 +539,9 @@ void gluLookAt(GLfloat eyex, GLfloat eyey, GLfloat eyez, GLfloat centerx,
|
|||
multiply_matrix(&trn);
|
||||
multiply_matrix(stack_top(MATRIX_STACKS + (GL_MODELVIEW & 0xF)));
|
||||
download_matrix(stack_top(MATRIX_STACKS + (GL_MODELVIEW & 0xF)));
|
||||
*/
|
||||
glMultMatrixf(m);
|
||||
glTranslatef(-eyex, -eyey, -eyez);
|
||||
}
|
||||
|
||||
void _glApplyRenderMatrix() {
|
||||
|
|
68
GL/private.h
68
GL/private.h
|
@ -2,6 +2,11 @@
|
|||
#define PRIVATE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <dc/matrix.h>
|
||||
#include <dc/pvr.h>
|
||||
#include <dc/vec3f.h>
|
||||
#include <dc/fmath.h>
|
||||
#include <dc/matrix3d.h>
|
||||
|
||||
#include "../include/gl.h"
|
||||
#include "../containers/aligned_vector.h"
|
||||
|
@ -11,6 +16,20 @@
|
|||
|
||||
extern void* memcpy4 (void *dest, const void *src, size_t count);
|
||||
|
||||
#define GL_FORCE_INLINE __attribute__((always_inline)) static __inline__
|
||||
|
||||
#define FASTCPY(dst, src, bytes) \
|
||||
(bytes % 32 == 0) ? sq_cpy(dst, src, bytes) : memcpy(dst, src, bytes);
|
||||
|
||||
#define _PACK4(v) ((v * 0xF) / 0xFF)
|
||||
#define PACK_ARGB4444(a,r,g,b) (_PACK4(a) << 12) | (_PACK4(r) << 8) | (_PACK4(g) << 4) | (_PACK4(b))
|
||||
#define PACK_ARGB8888(a,r,g,b) ( ((a & 0xFF) << 24) | ((r & 0xFF) << 16) | ((g & 0xFF) << 8) | (b & 0xFF) )
|
||||
#define PACK_ARGB1555(a,r,g,b) \
|
||||
(((GLushort)(a > 0) << 15) | (((GLushort) r >> 3) << 10) | (((GLushort)g >> 3) << 5) | ((GLushort)b >> 3))
|
||||
|
||||
#define PACK_RGB565(r,g,b) \
|
||||
((((GLushort)r & 0xf8) << 8) | (((GLushort) g & 0xfc) << 3) | ((GLushort) b >> 3))
|
||||
|
||||
#define TRACE_ENABLED 0
|
||||
#define TRACE() if(TRACE_ENABLED) {fprintf(stderr, "%s\n", __func__);}
|
||||
|
||||
|
@ -68,7 +87,6 @@ typedef float Matrix4x4[16];
|
|||
#define M15 15
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct {
|
||||
pvr_poly_hdr_t hdr;
|
||||
} PVRHeader;
|
||||
|
@ -125,6 +143,16 @@ typedef struct {
|
|||
GLboolean isCompressed;
|
||||
GLboolean isPaletted;
|
||||
//44
|
||||
|
||||
/* Mipmap textures have a different
|
||||
* offset for the base level when supplying the data, this
|
||||
* keeps track of that. baseDataOffset == 0
|
||||
* means that the texture has no mipmaps
|
||||
*/
|
||||
GLuint baseDataOffset;
|
||||
//48
|
||||
GLuint baseDataSize; /* The data size of mipmap level 0 */
|
||||
//52
|
||||
} TextureObject;
|
||||
|
||||
typedef struct {
|
||||
|
@ -132,6 +160,8 @@ typedef struct {
|
|||
GLfloat ambient[4];
|
||||
GLfloat diffuse[4];
|
||||
GLfloat specular[4];
|
||||
|
||||
/* Valid values are 0-128 */
|
||||
GLfloat exponent;
|
||||
} Material;
|
||||
|
||||
|
@ -146,7 +176,6 @@ typedef struct {
|
|||
GLfloat diffuse[4];
|
||||
GLfloat specular[4];
|
||||
GLfloat ambient[4];
|
||||
GLboolean is_directional;
|
||||
} LightSource;
|
||||
|
||||
typedef struct {
|
||||
|
@ -163,11 +192,10 @@ typedef struct {
|
|||
} Vertex;
|
||||
|
||||
#define swapVertex(a, b) \
|
||||
do { \
|
||||
Vertex temp __attribute__((aligned(32))); \
|
||||
memcpy4(&temp, &b, 32); \
|
||||
memcpy4(&b, &a, 32); \
|
||||
memcpy4(&b, &temp, 32); \
|
||||
do { \
|
||||
Vertex c = *a; \
|
||||
*a = *b; \
|
||||
*b = c; \
|
||||
} while(0)
|
||||
|
||||
/* ClipVertex doesn't have room for these, so we need to parse them
|
||||
|
@ -244,6 +272,10 @@ GLubyte _glInitTextures();
|
|||
void _glUpdatePVRTextureContext(pvr_poly_cxt_t* context, GLshort textureUnit);
|
||||
void _glAllocateSpaceForMipmaps(TextureObject* active);
|
||||
|
||||
extern GLfloat NEAR_PLANE_DISTANCE;
|
||||
|
||||
GLfloat _glGetNearPlane();
|
||||
|
||||
typedef struct {
|
||||
const void* ptr;
|
||||
GLenum type;
|
||||
|
@ -251,11 +283,6 @@ typedef struct {
|
|||
GLint size;
|
||||
} AttribPointer;
|
||||
|
||||
typedef struct {
|
||||
float xyz[3];
|
||||
float n[3];
|
||||
} EyeSpaceData;
|
||||
|
||||
GLboolean _glCheckValidEnum(GLint param, GLint* values, const char* func);
|
||||
|
||||
GLuint* _glGetEnabledAttributes();
|
||||
|
@ -281,13 +308,24 @@ GLboolean _glIsBlendingEnabled();
|
|||
GLboolean _glIsAlphaTestEnabled();
|
||||
|
||||
GLboolean _glIsMipmapComplete(const TextureObject* obj);
|
||||
GLubyte* _glGetMipmapLocation(TextureObject* obj, GLuint level);
|
||||
GLuint _glGetMipmapLevelCount(TextureObject* obj);
|
||||
GLuint _glGetMipmapDataOffset(const TextureObject* obj, GLuint level);
|
||||
GLubyte* _glGetMipmapLocation(const TextureObject* obj, GLuint level);
|
||||
GLuint _glGetMipmapLevelCount(const TextureObject* obj);
|
||||
|
||||
GLboolean _glIsLightingEnabled();
|
||||
GLboolean _glIsLightEnabled(GLubyte light);
|
||||
GLboolean _glIsColorMaterialEnabled();
|
||||
void _glPerformLighting(Vertex* vertices, const EyeSpaceData* es, const int32_t count);
|
||||
|
||||
GLboolean _glIsNormalizeEnabled();
|
||||
|
||||
GLboolean _glRecalcFastPath();
|
||||
|
||||
typedef struct {
|
||||
float xyz[3];
|
||||
float n[3];
|
||||
} EyeSpaceData;
|
||||
|
||||
extern void _glPerformLighting(Vertex* vertices, const EyeSpaceData* es, const int32_t count);
|
||||
|
||||
unsigned char _glIsClippingEnabled();
|
||||
void _glEnableClipping(unsigned char v);
|
||||
|
|
74
GL/state.c
74
GL/state.c
|
@ -33,6 +33,8 @@ static GLboolean ALPHA_TEST_ENABLED = GL_FALSE;
|
|||
|
||||
static GLboolean POLYGON_OFFSET_ENABLED = GL_FALSE;
|
||||
|
||||
static GLboolean NORMALIZE_ENABLED = GL_FALSE;
|
||||
|
||||
GLboolean _glIsSharedTexturePaletteEnabled() {
|
||||
return SHARED_PALETTE_ENABLED;
|
||||
}
|
||||
|
@ -61,17 +63,17 @@ static int _calc_pvr_depth_test() {
|
|||
case GL_NEVER:
|
||||
return PVR_DEPTHCMP_NEVER;
|
||||
case GL_LESS:
|
||||
return PVR_DEPTHCMP_GREATER;
|
||||
return PVR_DEPTHCMP_GEQUAL;
|
||||
case GL_EQUAL:
|
||||
return PVR_DEPTHCMP_EQUAL;
|
||||
case GL_LEQUAL:
|
||||
return PVR_DEPTHCMP_GEQUAL;
|
||||
return PVR_DEPTHCMP_GREATER;
|
||||
case GL_GREATER:
|
||||
return PVR_DEPTHCMP_LESS;
|
||||
return PVR_DEPTHCMP_LEQUAL;
|
||||
case GL_NOTEQUAL:
|
||||
return PVR_DEPTHCMP_NOTEQUAL;
|
||||
case GL_GEQUAL:
|
||||
return PVR_DEPTHCMP_LEQUAL;
|
||||
return PVR_DEPTHCMP_LESS;
|
||||
break;
|
||||
case GL_ALWAYS:
|
||||
default:
|
||||
|
@ -86,6 +88,10 @@ static GLboolean BLEND_ENABLED = GL_FALSE;
|
|||
static GLfloat OFFSET_FACTOR = 0.0f;
|
||||
static GLfloat OFFSET_UNITS = 0.0f;
|
||||
|
||||
GLboolean _glIsNormalizeEnabled() {
|
||||
return NORMALIZE_ENABLED;
|
||||
}
|
||||
|
||||
GLboolean _glIsBlendingEnabled() {
|
||||
return BLEND_ENABLED;
|
||||
}
|
||||
|
@ -121,17 +127,12 @@ static int _calcPVRBlendFactor(GLenum factor) {
|
|||
static void _updatePVRBlend(pvr_poly_cxt_t* context) {
|
||||
if(BLEND_ENABLED) {
|
||||
context->gen.alpha = PVR_ALPHA_ENABLE;
|
||||
context->blend.src = _calcPVRBlendFactor(BLEND_SFACTOR);
|
||||
context->blend.dst = _calcPVRBlendFactor(BLEND_DFACTOR);
|
||||
context->blend.src_enable = PVR_BLEND_DISABLE;
|
||||
context->blend.dst_enable = PVR_BLEND_DISABLE;
|
||||
} else {
|
||||
context->gen.alpha = PVR_ALPHA_DISABLE;
|
||||
context->blend.src = PVR_BLEND_ONE;
|
||||
context->blend.dst = PVR_BLEND_ZERO;
|
||||
context->blend.src_enable = PVR_BLEND_DISABLE;
|
||||
context->blend.dst_enable = PVR_BLEND_DISABLE;
|
||||
}
|
||||
|
||||
context->blend.src = _calcPVRBlendFactor(BLEND_SFACTOR);
|
||||
context->blend.dst = _calcPVRBlendFactor(BLEND_DFACTOR);
|
||||
}
|
||||
|
||||
GLboolean _glCheckValidEnum(GLint param, GLint* values, const char* func) {
|
||||
|
@ -158,15 +159,16 @@ GLboolean TEXTURES_ENABLED [] = {GL_FALSE, GL_FALSE};
|
|||
void _glUpdatePVRTextureContext(pvr_poly_cxt_t* context, GLshort textureUnit) {
|
||||
const TextureObject *tx1 = (textureUnit == 0) ? _glGetTexture0() : _glGetTexture1();
|
||||
|
||||
/* Disable all texturing to start with */
|
||||
context->txr.enable = PVR_TEXTURE_DISABLE;
|
||||
context->txr2.enable = PVR_TEXTURE_DISABLE;
|
||||
context->txr2.alpha = PVR_TXRALPHA_DISABLE;
|
||||
|
||||
if(!TEXTURES_ENABLED[textureUnit] || !tx1) {
|
||||
context->txr.enable = PVR_TEXTURE_DISABLE;
|
||||
context->txr.base = 0;
|
||||
context->txr.format = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
context->txr2.enable = PVR_TEXTURE_DISABLE;
|
||||
context->txr2.alpha = PVR_TXRALPHA_DISABLE;
|
||||
context->txr.alpha = (BLEND_ENABLED) ? PVR_TXRALPHA_ENABLE : PVR_TXRALPHA_DISABLE;
|
||||
|
||||
GLuint filter = PVR_FILTER_NEAREST;
|
||||
GLboolean enableMipmaps = GL_FALSE;
|
||||
|
@ -223,29 +225,25 @@ void _glUpdatePVRTextureContext(pvr_poly_cxt_t* context, GLshort textureUnit) {
|
|||
if(tx1->data) {
|
||||
context->txr.enable = PVR_TEXTURE_ENABLE;
|
||||
context->txr.filter = filter;
|
||||
context->txr.mipmap = enableMipmaps;
|
||||
context->txr.mipmap_bias = tx1->mipmap_bias;
|
||||
context->txr.width = tx1->width;
|
||||
context->txr.height = tx1->height;
|
||||
if(enableMipmaps){
|
||||
|
||||
if(enableMipmaps) {
|
||||
context->txr.base = tx1->data;
|
||||
context->txr.mipmap = PVR_MIPMAP_ENABLE;
|
||||
context->txr.mipmap_bias = PVR_MIPBIAS_NORMAL;
|
||||
} else {
|
||||
if(tx1->mipmap > 1)
|
||||
context->txr.base = _glGetMipmapLocation((TextureObject*)tx1,0);
|
||||
/* We should need this? */
|
||||
else
|
||||
context->txr.base = tx1->data;
|
||||
context->txr.base = tx1->data + tx1->baseDataOffset;
|
||||
context->txr.mipmap = PVR_MIPMAP_DISABLE;
|
||||
context->txr.mipmap_bias = PVR_MIPBIAS_NORMAL;
|
||||
}
|
||||
|
||||
context->txr.format = tx1->color;
|
||||
|
||||
if(tx1->isPaletted) {
|
||||
if(_glIsSharedTexturePaletteEnabled()) {
|
||||
//TexturePalette* palette = _glGetSharedPalette(tx1->shared_bank);
|
||||
context->txr.format |= PVR_TXRFMT_8BPP_PAL(tx1->shared_bank);
|
||||
if(tx1->shared_bank != 0){
|
||||
//printf("%s chose bank %d!\n",__func__,tx1->shared_bank);
|
||||
}
|
||||
TexturePalette* palette = _glGetSharedPalette(tx1->shared_bank);
|
||||
context->txr.format |= PVR_TXRFMT_8BPP_PAL(palette->bank);
|
||||
} else {
|
||||
context->txr.format |= PVR_TXRFMT_8BPP_PAL((tx1->palette) ? tx1->palette->bank : 0);
|
||||
}
|
||||
|
@ -254,9 +252,6 @@ void _glUpdatePVRTextureContext(pvr_poly_cxt_t* context, GLshort textureUnit) {
|
|||
context->txr.env = tx1->env;
|
||||
context->txr.uv_flip = PVR_UVFLIP_NONE;
|
||||
context->txr.uv_clamp = tx1->uv_clamp;
|
||||
context->txr.alpha = PVR_TXRALPHA_ENABLE;
|
||||
} else {
|
||||
context->txr.enable = PVR_TEXTURE_DISABLE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -359,7 +354,10 @@ GLAPI void APIENTRY glEnable(GLenum cap) {
|
|||
case GL_POLYGON_OFFSET_LINE:
|
||||
case GL_POLYGON_OFFSET_FILL:
|
||||
POLYGON_OFFSET_ENABLED = GL_TRUE;
|
||||
break;
|
||||
break;
|
||||
case GL_NORMALIZE:
|
||||
NORMALIZE_ENABLED = GL_TRUE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -418,7 +416,10 @@ GLAPI void APIENTRY glDisable(GLenum cap) {
|
|||
case GL_POLYGON_OFFSET_LINE:
|
||||
case GL_POLYGON_OFFSET_FILL:
|
||||
POLYGON_OFFSET_ENABLED = GL_FALSE;
|
||||
break;
|
||||
break;
|
||||
case GL_NORMALIZE:
|
||||
NORMALIZE_ENABLED = GL_FALSE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -465,7 +466,6 @@ GLAPI void APIENTRY glReadBuffer(GLenum mode) {
|
|||
|
||||
GLAPI void APIENTRY glDepthMask(GLboolean flag) {
|
||||
GL_CONTEXT.depth.write = (flag == GL_TRUE) ? PVR_DEPTHWRITE_ENABLE : PVR_DEPTHWRITE_DISABLE;
|
||||
GL_CONTEXT.depth.comparison = _calc_pvr_depth_test();
|
||||
}
|
||||
|
||||
GLAPI void APIENTRY glDepthFunc(GLenum func) {
|
||||
|
@ -731,7 +731,7 @@ const GLubyte *glGetString(GLenum name) {
|
|||
return (const GLubyte*) "1.2 (partial) - GLdc 1.1";
|
||||
|
||||
case GL_EXTENSIONS:
|
||||
return (const GLubyte*) "GL_ARB_framebuffer_object, GL_ARB_multitexture, GL_ARB_texture_rg, GL_EXT_paletted_texture, GL_EXT_shared_texture_palette, GL_KOS_multiple_shared_palette";
|
||||
return (const GLubyte*) "GL_ARB_framebuffer_object, GL_ARB_multitexture, GL_ARB_texture_rg, GL_EXT_paletted_texture, GL_EXT_shared_texture_palette, GL_KOS_multiple_shared_palette, GL_ARB_vertex_array_bgra, GL_ARB_vertex_type_2_10_10_10_rev";
|
||||
}
|
||||
|
||||
return (const GLubyte*) "GL_KOS_ERROR: ENUM Unsupported\n";
|
||||
|
|
254
GL/texture.c
254
GL/texture.c
|
@ -9,6 +9,7 @@
|
|||
#include "config.h"
|
||||
#include "../include/glext.h"
|
||||
#include "../include/glkos.h"
|
||||
#include <kos/string.h>
|
||||
|
||||
#define CLAMP_U (1<<1)
|
||||
#define CLAMP_V (1<<0)
|
||||
|
@ -21,12 +22,6 @@ static TexturePalette* SHARED_PALETTES[4] = {NULL, NULL, NULL, NULL};
|
|||
|
||||
GLuint _determinePVRFormat(GLint internalFormat, GLenum type);
|
||||
|
||||
#define PACK_ARGB8888(a,r,g,b) ( ((a & 0xFF) << 24) | ((r & 0xFF) << 16) | ((g & 0xFF) << 8) | (b & 0xFF) )
|
||||
|
||||
|
||||
#define _PACK4(v) ((v * 0xF) / 0xFF)
|
||||
#define PACK_ARGB4444(a,r,g,b) (_PACK4(a) << 12) | (_PACK4(r) << 8) | (_PACK4(g) << 4) | (_PACK4(b))
|
||||
|
||||
static GLboolean BANKS_USED[4]; // Each time a 256 colour bank is used, this is set to true
|
||||
static GLboolean SUBBANKS_USED[4][16]; // 4 counts of the used 16 colour banks within the 256 ones
|
||||
static GLenum INTERNAL_PALETTE_FORMAT = GL_RGBA4;
|
||||
|
@ -141,9 +136,9 @@ GLubyte _glGetActiveTexture() {
|
|||
switch(type) {
|
||||
case GL_BYTE:
|
||||
case GL_UNSIGNED_BYTE:
|
||||
return (format == GL_RED) ? 1 : (format == GL_RGB) ? 3 : 4;
|
||||
return (format == GL_RED || format == GL_ALPHA) ? 1 : (format == GL_RGB) ? 3 : 4;
|
||||
case GL_UNSIGNED_SHORT:
|
||||
return (format == GL_RED) ? 2 : (format == GL_RGB) ? 6 : 8;
|
||||
return (format == GL_RED || format == GL_ALPHA) ? 2 : (format == GL_RGB) ? 6 : 8;
|
||||
case GL_UNSIGNED_SHORT_5_6_5:
|
||||
case GL_UNSIGNED_SHORT_5_6_5_REV:
|
||||
case GL_UNSIGNED_SHORT_5_6_5_TWID_KOS:
|
||||
|
@ -159,12 +154,16 @@ GLubyte _glGetActiveTexture() {
|
|||
return -1;
|
||||
}
|
||||
|
||||
GLubyte* _glGetMipmapLocation(TextureObject* obj, GLuint level) {
|
||||
GLuint _glGetMipmapDataOffset(const TextureObject* obj, GLuint level) {
|
||||
GLuint offset = 0;
|
||||
GLuint size = obj->height;
|
||||
if(obj->width == size){
|
||||
if(obj->isPaletted){
|
||||
|
||||
if(obj->width != obj->height) {
|
||||
fprintf(stderr, "ERROR: Accessing memory location of mipmaps on non-square texture\n");
|
||||
return offset;
|
||||
}
|
||||
|
||||
if(obj->isPaletted){
|
||||
switch(size >> level){
|
||||
case 1024:
|
||||
offset = 0x55558;
|
||||
|
@ -274,14 +273,16 @@ GLubyte* _glGetMipmapLocation(TextureObject* obj, GLuint level) {
|
|||
offset = 0x00006;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return ((GLubyte*) obj->data) + offset;
|
||||
return offset;
|
||||
}
|
||||
|
||||
GLuint _glGetMipmapLevelCount(TextureObject* obj) {
|
||||
GLubyte* _glGetMipmapLocation(const TextureObject* obj, GLuint level) {
|
||||
return ((GLubyte*) obj->data) + _glGetMipmapDataOffset(obj, level);
|
||||
}
|
||||
|
||||
GLuint _glGetMipmapLevelCount(const TextureObject* obj) {
|
||||
return 1 + floorf(log2f(MAX(obj->width, obj->height)));
|
||||
}
|
||||
|
||||
|
@ -358,7 +359,7 @@ static void _glInitializeTextureObject(TextureObject* txr, unsigned int id) {
|
|||
txr->width = txr->height = 0;
|
||||
txr->mipmap = 0;
|
||||
txr->uv_clamp = 0;
|
||||
txr->env = PVR_TXRENV_MODULATEALPHA;
|
||||
txr->env = PVR_TXRENV_MODULATE;
|
||||
txr->data = NULL;
|
||||
txr->mipmapCount = 0;
|
||||
txr->minFilter = GL_NEAREST;
|
||||
|
@ -367,6 +368,9 @@ static void _glInitializeTextureObject(TextureObject* txr, unsigned int id) {
|
|||
txr->isCompressed = GL_FALSE;
|
||||
txr->isPaletted = GL_FALSE;
|
||||
|
||||
/* Not mipmapped by default */
|
||||
txr->baseDataOffset = 0;
|
||||
|
||||
/* Always default to the first shared bank */
|
||||
txr->shared_bank = 0;
|
||||
}
|
||||
|
@ -484,7 +488,7 @@ void APIENTRY glTexEnvi(GLenum target, GLenum pname, GLint param) {
|
|||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -802,10 +806,17 @@ static INLINE_DEBUG void _i8_to_i8(const GLubyte* source, GLubyte* dest) {
|
|||
*dst = *source;
|
||||
}
|
||||
|
||||
static inline void _alpha8_to_argb4444(const GLubyte* source, GLubyte* dest) {
|
||||
*((GLushort*) dest) = (*source & 0xF0) << 8 | (0xFF & 0xF0) << 4 | (0xFF & 0xF0) | (0xFF & 0xF0) >> 4;
|
||||
}
|
||||
|
||||
static TextureConversionFunc _determineConversion(GLint internalFormat, GLenum format, GLenum type) {
|
||||
switch(internalFormat) {
|
||||
case GL_ALPHA: {
|
||||
if(type == GL_UNSIGNED_BYTE && format == GL_RGBA) {
|
||||
if(format == GL_ALPHA) {
|
||||
/* Dreamcast doesn't really support GL_ALPHA internally, so store as argb with each rgb value as white */
|
||||
return _alpha8_to_argb4444;
|
||||
} else if(type == GL_UNSIGNED_BYTE && format == GL_RGBA) {
|
||||
return _rgba8888_to_a000;
|
||||
} else if(type == GL_BYTE && format == GL_RGBA) {
|
||||
return _rgba8888_to_a000;
|
||||
|
@ -870,6 +881,7 @@ static TextureConversionFunc _determineConversion(GLint internalFormat, GLenum f
|
|||
|
||||
static GLboolean _isSupportedFormat(GLenum format) {
|
||||
switch(format) {
|
||||
case GL_ALPHA:
|
||||
case GL_RED:
|
||||
case GL_RGB:
|
||||
case GL_RGBA:
|
||||
|
@ -882,6 +894,12 @@ static GLboolean _isSupportedFormat(GLenum format) {
|
|||
}
|
||||
|
||||
GLboolean _glIsMipmapComplete(const TextureObject* obj) {
|
||||
|
||||
// Non-square textures can't have mipmaps
|
||||
if(obj->width != obj->height) {
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
if(!obj->mipmap || !obj->mipmapCount) {
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
@ -896,34 +914,38 @@ GLboolean _glIsMipmapComplete(const TextureObject* obj) {
|
|||
return GL_TRUE;
|
||||
}
|
||||
|
||||
#define TWIDTAB(x) ( (x&1)|((x&2)<<1)|((x&4)<<2)|((x&8)<<3)|((x&16)<<4)| \
|
||||
((x&32)<<5)|((x&64)<<6)|((x&128)<<7)|((x&256)<<8)|((x&512)<<9) )
|
||||
|
||||
#define TWIDOUT(x, y) ( TWIDTAB((y)) | (TWIDTAB((x)) << 1) )
|
||||
|
||||
void _glAllocateSpaceForMipmaps(TextureObject* active) {
|
||||
if(!active->data){
|
||||
if(active->data && active->baseDataOffset > 0) {
|
||||
/* Already done - mipmaps have a dataOffset */
|
||||
return;
|
||||
}
|
||||
if(active->data && active->mipmap > 1) {
|
||||
/* Already done */
|
||||
return;
|
||||
}
|
||||
|
||||
int size = active->height*active->width*active->dataStride;
|
||||
|
||||
/* We've allocated level 0 before, but now we're allocating
|
||||
* a level beyond that, we need to reallocate the data, copy level 0
|
||||
* then free the original
|
||||
*/
|
||||
GLubyte* temp = malloc(size);
|
||||
memcpy4(temp, active->data, size);
|
||||
|
||||
GLuint size = active->baseDataSize;
|
||||
|
||||
/* Copy the data out of the pvr and back to ram */
|
||||
GLubyte* temp = (GLubyte*) malloc(size);
|
||||
memcpy(temp, active->data, size);
|
||||
|
||||
/* Free the PVR data */
|
||||
pvr_mem_free(active->data);
|
||||
active->data = pvr_mem_malloc(_glGetMipmapDataSize(active));
|
||||
active->data = NULL;
|
||||
|
||||
/* Figure out how much room to allocate for mipmaps */
|
||||
GLuint bytes = _glGetMipmapDataSize(active);
|
||||
|
||||
active->data = pvr_mem_malloc(bytes);
|
||||
|
||||
/* If there was existing data, then copy it where it should go */
|
||||
memcpy4(_glGetMipmapLocation(active,0), temp, size);
|
||||
free(temp);
|
||||
memcpy(_glGetMipmapLocation(active, 0), temp, size);
|
||||
|
||||
/* Set the data offset depending on whether or not this is a
|
||||
* paletted texure */
|
||||
active->baseDataOffset = _glGetMipmapDataOffset(active, 0);
|
||||
}
|
||||
|
||||
void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
||||
|
@ -931,32 +953,28 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
|||
GLenum format, GLenum type, const GLvoid *data) {
|
||||
|
||||
TRACE();
|
||||
if(!data) {
|
||||
/* No data? Do nothing! */
|
||||
return;
|
||||
}
|
||||
|
||||
if(target != GL_TEXTURE_2D) {
|
||||
_glKosThrowError(GL_INVALID_ENUM, "glTexImage2D");
|
||||
_glKosThrowError(GL_INVALID_ENUM, "glTexImage2D1");
|
||||
}
|
||||
|
||||
if(format != GL_COLOR_INDEX) {
|
||||
if(!_isSupportedFormat(format)) {
|
||||
_glKosThrowError(GL_INVALID_ENUM, "glTexImage2D");
|
||||
_glKosThrowError(GL_INVALID_ENUM, "glTexImage2D2");
|
||||
}
|
||||
|
||||
/* Abuse determineStride to see if type is valid */
|
||||
if(_determineStride(GL_RGBA, type) == -1) {
|
||||
_glKosThrowError(GL_INVALID_ENUM, "glTexImage2D");
|
||||
_glKosThrowError(GL_INVALID_ENUM, "glTexImage2D3");
|
||||
}
|
||||
|
||||
internalFormat = _cleanInternalFormat(internalFormat);
|
||||
if(internalFormat == -1) {
|
||||
_glKosThrowError(GL_INVALID_VALUE, "glTexImage2D");
|
||||
_glKosThrowError(GL_INVALID_VALUE, "glTexImage2D4");
|
||||
}
|
||||
} else {
|
||||
if(internalFormat != GL_COLOR_INDEX8_EXT) {
|
||||
_glKosThrowError(GL_INVALID_ENUM, __func__);
|
||||
_glKosThrowError(GL_INVALID_ENUM, "glTexImage2D5");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -965,26 +983,31 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
|||
if(level == 0){
|
||||
if((w < 8 || (w & -w) != w)) {
|
||||
/* Width is not a power of two. Must be!*/
|
||||
_glKosThrowError(GL_INVALID_VALUE, "glTexImage2D");
|
||||
_glKosThrowError(GL_INVALID_VALUE, "glTexImage2D6");
|
||||
}
|
||||
|
||||
|
||||
if((h < 8 || (h & -h) != h)) {
|
||||
/* height is not a power of two. Must be!*/
|
||||
_glKosThrowError(GL_INVALID_VALUE, "glTexImage2D");
|
||||
_glKosThrowError(GL_INVALID_VALUE, "glTexImage2D7");
|
||||
}
|
||||
}
|
||||
|
||||
if(level < 0) {
|
||||
_glKosThrowError(GL_INVALID_VALUE, "glTexImage2D");
|
||||
_glKosThrowError(GL_INVALID_VALUE, "glTexImage2D8");
|
||||
}
|
||||
|
||||
if(level > 0 && width != height) {
|
||||
fprintf(stderr, "[GL ERROR] Mipmaps cannot be supported on non-square textures\n");
|
||||
_glKosThrowError(GL_INVALID_OPERATION, "glTexImage2D9");
|
||||
}
|
||||
|
||||
if(border) {
|
||||
_glKosThrowError(GL_INVALID_VALUE, "glTexImage2D");
|
||||
_glKosThrowError(GL_INVALID_VALUE, "glTexImage2D10");
|
||||
}
|
||||
|
||||
if(!TEXTURE_UNITS[ACTIVE_TEXTURE]) {
|
||||
_glKosThrowError(GL_INVALID_OPERATION, __func__);
|
||||
_glKosThrowError(GL_INVALID_OPERATION, "glTexImage2D11");
|
||||
}
|
||||
|
||||
GLboolean isPaletted = (internalFormat == GL_COLOR_INDEX8_EXT) ? GL_TRUE : GL_FALSE;
|
||||
|
@ -1001,7 +1024,7 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
|||
|
||||
assert(active);
|
||||
|
||||
if(active->data && (level == 0) ) {
|
||||
if(active->data && level == 0) {
|
||||
/* pre-existing texture - check if changed */
|
||||
if(active->width != width ||
|
||||
active->height != height ||
|
||||
|
@ -1011,8 +1034,9 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
|||
active->data = NULL;
|
||||
active->mipmap = 0;
|
||||
active->mipmapCount = 0;
|
||||
active->mipmap_bias = GL_KOS_INTERNAL_DEFAULT_MIPMAP_LOD_BIAS; // in the scale of -8 - 8 moved to 1-15, -4 = 4
|
||||
active->dataStride = 0;
|
||||
active->baseDataOffset = 0;
|
||||
active->baseDataSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1022,7 +1046,7 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
|||
GLint destStride = isPaletted ? 1 : 2;
|
||||
GLuint bytes = (width * height * destStride);
|
||||
|
||||
if(!active->data && (level == 0)) {
|
||||
if(!active->data) {
|
||||
assert(active);
|
||||
assert(width);
|
||||
assert(height);
|
||||
|
@ -1034,24 +1058,27 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
|||
active->color = pvr_format;
|
||||
/* Set the required mipmap count */
|
||||
active->mipmapCount = _glGetMipmapLevelCount(active);
|
||||
active->mipmap_bias = GL_KOS_INTERNAL_DEFAULT_MIPMAP_LOD_BIAS; // in the scale of -8 - 8 moved to 1-15, -4 = 4
|
||||
|
||||
active->dataStride = destStride;
|
||||
active->baseDataSize = bytes;
|
||||
|
||||
assert(bytes);
|
||||
|
||||
if(level > 0) {
|
||||
/* If we're uploading a mipmap level, we need to allocate the full amount of space */
|
||||
_glAllocateSpaceForMipmaps(active);
|
||||
} else {
|
||||
active->data = pvr_mem_malloc(active->baseDataSize);
|
||||
}
|
||||
|
||||
active->data = pvr_mem_malloc(destStride*width*height);
|
||||
assert(active->data);
|
||||
|
||||
active->isCompressed = GL_FALSE;
|
||||
active->isPaletted = isPaletted;
|
||||
} else if(!active->data && (level != 0)){
|
||||
printf("Spooky!\n");
|
||||
assert(0 && "GLdc broken, sorry! @neo");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check if we need to re-alloc and move texture data */
|
||||
if(level > 0){
|
||||
_glAllocateSpaceForMipmaps(active);
|
||||
/* We're supplying a mipmap level, but previously we only had
|
||||
* data for the first level (level 0) */
|
||||
if(level > 0 && active->baseDataOffset == 0) {
|
||||
_glAllocateSpaceForMipmaps(active);
|
||||
}
|
||||
|
||||
/* Mark this level as set in the mipmap bitmask */
|
||||
|
@ -1059,7 +1086,9 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
|||
|
||||
/* Let's assume we need to convert */
|
||||
GLboolean needsConversion = GL_TRUE;
|
||||
GLboolean needsTwiddling = GL_FALSE;
|
||||
|
||||
/* Let's assume we need twiddling - we always store things twiddled! */
|
||||
GLboolean needsTwiddling = GL_TRUE;
|
||||
|
||||
/*
|
||||
* These are the only formats where the source format passed in matches the pvr format.
|
||||
|
@ -1068,7 +1097,10 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
|||
if(format == GL_COLOR_INDEX) {
|
||||
/* Don't convert color indexes */
|
||||
needsConversion = GL_FALSE;
|
||||
needsTwiddling = type == GL_UNSIGNED_BYTE;
|
||||
|
||||
if(type == GL_UNSIGNED_BYTE_TWID_KOS) {
|
||||
needsTwiddling = GL_FALSE;
|
||||
}
|
||||
} else if(format == GL_BGRA && type == GL_UNSIGNED_SHORT_4_4_4_4_REV && internalFormat == GL_RGBA) {
|
||||
needsConversion = GL_FALSE;
|
||||
} else if(format == GL_BGRA && type == GL_UNSIGNED_SHORT_1_5_5_5_REV && internalFormat == GL_RGBA) {
|
||||
|
@ -1077,56 +1109,32 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
|||
needsConversion = GL_FALSE;
|
||||
} else if(format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5_TWID_KOS && internalFormat == GL_RGB) {
|
||||
needsConversion = GL_FALSE;
|
||||
needsTwiddling = GL_FALSE;
|
||||
} else if(format == GL_BGRA && type == GL_UNSIGNED_SHORT_1_5_5_5_REV_TWID_KOS && internalFormat == GL_RGBA) {
|
||||
needsConversion = GL_FALSE;
|
||||
needsTwiddling = GL_FALSE;
|
||||
} else if(format == GL_BGRA && type == GL_UNSIGNED_SHORT_4_4_4_4_REV_TWID_KOS && internalFormat == GL_RGBA) {
|
||||
needsConversion = GL_FALSE;
|
||||
needsTwiddling = GL_FALSE;
|
||||
}
|
||||
|
||||
GLubyte* targetData = NULL;
|
||||
|
||||
if(active->mipmap == 1 && level==0){
|
||||
targetData = active->data;
|
||||
} else {
|
||||
targetData = _glGetMipmapLocation(active, level);
|
||||
}
|
||||
|
||||
GLubyte* targetData = (active->baseDataOffset == 0) ? active->data : _glGetMipmapLocation(active, level);
|
||||
assert(targetData);
|
||||
|
||||
if(!needsConversion) {
|
||||
GLubyte* conversionBuffer = NULL;
|
||||
|
||||
if(!data) {
|
||||
/* No data? Do nothing! */
|
||||
return;
|
||||
} else if(!needsConversion && !needsTwiddling) {
|
||||
assert(targetData);
|
||||
assert(data);
|
||||
assert(bytes);
|
||||
|
||||
if(needsTwiddling) {
|
||||
assert(type == GL_UNSIGNED_BYTE); // Anything else needs this loop adjusting
|
||||
GLuint x, y, min, mask;
|
||||
|
||||
GLubyte *pixels = (GLubyte*) data;
|
||||
GLushort *vtex = (GLushort*) targetData;
|
||||
|
||||
min = MIN(w, h);
|
||||
mask = min - 1;
|
||||
|
||||
if(height == 1 || width == 1){
|
||||
targetData[0] = ((GLubyte*)data)[0];
|
||||
targetData[1] = ((GLubyte*)data)[0];
|
||||
targetData[2] = ((GLubyte*)data)[0];
|
||||
targetData[3] = ((GLubyte*)data)[0];
|
||||
} else {
|
||||
for(y = 0; y < h; y += 2) {
|
||||
for(x = 0; x < w; x++) {
|
||||
vtex[TWIDOUT((y & mask) / 2, x & mask) + (x / min + y / min)*min * min / 2] = pixels[y * w + x] | (pixels[(y + 1) * w + x] << 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* No conversion? Just copy the data, and the pvr_format is correct */
|
||||
FASTCPY(targetData, data, bytes);
|
||||
}
|
||||
|
||||
/* No conversion? Just copy the data, and the pvr_format is correct */
|
||||
FASTCPY(targetData, data, bytes);
|
||||
return;
|
||||
} else {
|
||||
} else if(needsConversion) {
|
||||
TextureConversionFunc convert = _determineConversion(
|
||||
internalFormat,
|
||||
format,
|
||||
|
@ -1138,12 +1146,6 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
|||
return;
|
||||
}
|
||||
|
||||
GLubyte* dest = (GLubyte*) targetData;
|
||||
const GLubyte* source = data;
|
||||
|
||||
assert(dest);
|
||||
assert(source);
|
||||
|
||||
GLint stride = _determineStride(format, type);
|
||||
assert(stride > -1);
|
||||
|
||||
|
@ -1152,6 +1154,14 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
|||
return;
|
||||
}
|
||||
|
||||
conversionBuffer = malloc(bytes);
|
||||
|
||||
GLubyte* dest = conversionBuffer;
|
||||
const GLubyte* source = data;
|
||||
|
||||
assert(conversionBuffer);
|
||||
assert(source);
|
||||
|
||||
/* Perform the conversion */
|
||||
GLuint i;
|
||||
for(i = 0; i < bytes; i += destStride) {
|
||||
|
@ -1161,8 +1171,36 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat,
|
|||
source += stride;
|
||||
}
|
||||
}
|
||||
|
||||
if(needsTwiddling) {
|
||||
const GLubyte *pixels = (GLubyte*) (conversionBuffer) ? conversionBuffer : data;
|
||||
|
||||
if(internalFormat == GL_COLOR_INDEX8_EXT) {
|
||||
pvr_txr_load_ex((void*) pixels, targetData, width, height, PVR_TXRLOAD_8BPP);
|
||||
} else {
|
||||
pvr_txr_load_ex((void*) pixels, targetData, width, height, PVR_TXRLOAD_16BPP);
|
||||
}
|
||||
|
||||
/* We make sure we remove nontwiddled and add twiddled. We could always
|
||||
* make it twiddled when determining the format but I worry that would make the
|
||||
* code less flexible to change in the future */
|
||||
active->color &= ~(1 << 26);
|
||||
} else {
|
||||
/* We should only get here if we converted twiddled data... which is never currently */
|
||||
assert(conversionBuffer);
|
||||
|
||||
// We've already converted the data and we
|
||||
// don't need to twiddle it!
|
||||
FASTCPY(targetData, conversionBuffer, bytes);
|
||||
}
|
||||
|
||||
if(conversionBuffer) {
|
||||
free(conversionBuffer);
|
||||
conversionBuffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param) {
|
||||
TRACE();
|
||||
|
||||
|
|
15
GL/util.c
Normal file
15
GL/util.c
Normal file
|
@ -0,0 +1,15 @@
|
|||
#include "../include/glkos.h"
|
||||
|
||||
void APIENTRY glVertexPackColor3fKOS(GLVertexKOS* vertex, float r, float g, float b) {
|
||||
vertex->bgra[3] = 255;
|
||||
vertex->bgra[2] = (r * 255.0f);
|
||||
vertex->bgra[1] = (g * 255.0f);
|
||||
vertex->bgra[0] = (b * 255.0f);
|
||||
}
|
||||
|
||||
void APIENTRY glVertexPackColor4fKOS(GLVertexKOS* vertex, float r, float g, float b, float a) {
|
||||
vertex->bgra[3] = (a * 255.0f);
|
||||
vertex->bgra[2] = (r * 255.0f);
|
||||
vertex->bgra[1] = (g * 255.0f);
|
||||
vertex->bgra[0] = (b * 255.0f);
|
||||
}
|
8
Makefile
8
Makefile
|
@ -3,7 +3,7 @@
|
|||
# kos-ports/libgl Makefile
|
||||
# Copyright (C) 2013, 2014 Josh Pearson
|
||||
# Copyright (C) 2014 Lawrence Sebald
|
||||
# Copyright (C) 2018 Luke Benstead
|
||||
# Copyright (C) 2020 Luke Benstead
|
||||
|
||||
TARGET = libGLdc.a
|
||||
OBJS = GL/gldc.o
|
||||
|
@ -40,7 +40,11 @@ export OBJEXTRA := $(LIB_DIR)/libGLdc.a
|
|||
link: | $(OBJS) ;
|
||||
$(KOS_AR) rcs $(TARGET) $(OBJS)
|
||||
|
||||
build: $(OBJS)
|
||||
GL/version.h:
|
||||
rm -f $@
|
||||
@echo -e '#pragma once\n#define GLDC_VERSION "$(shell git describe --abbrev=4 --dirty --always --tags)"\n' > $@
|
||||
|
||||
build: GL/version.h $(OBJS)
|
||||
|
||||
samples: build
|
||||
$(KOS_MAKE) -C samples all
|
||||
|
|
|
@ -26,7 +26,6 @@ void aligned_vector_init(AlignedVector* vector, unsigned int element_size) {
|
|||
aligned_vector_reserve(vector, ALIGNED_VECTOR_CHUNK_SIZE);
|
||||
}
|
||||
|
||||
|
||||
static INLINE_DEBUG unsigned int round_to_chunk_size(unsigned int val) {
|
||||
const unsigned int n = val;
|
||||
const unsigned int m = ALIGNED_VECTOR_CHUNK_SIZE;
|
||||
|
@ -34,7 +33,6 @@ static INLINE_DEBUG unsigned int round_to_chunk_size(unsigned int val) {
|
|||
return ((n + m - 1) / m) * m;
|
||||
}
|
||||
|
||||
|
||||
void aligned_vector_reserve(AlignedVector* vector, unsigned int element_count) {
|
||||
if(element_count == 0) {
|
||||
return;
|
||||
|
|
39
include/gl.h
39
include/gl.h
|
@ -19,25 +19,18 @@ __BEGIN_DECLS
|
|||
|
||||
#include <math.h>
|
||||
|
||||
#include <dc/fmath.h>
|
||||
#include <dc/matrix.h>
|
||||
#include <dc/matrix3d.h>
|
||||
#include <dc/pvr.h>
|
||||
#include <dc/vec3f.h>
|
||||
#include <dc/video.h>
|
||||
|
||||
/* Primitive Types taken from GL for compatability */
|
||||
/* Not all types are implemented in Open GL DC V.1.0 */
|
||||
#define GL_POINTS 0x01
|
||||
#define GL_LINES 0x02
|
||||
#define GL_LINE_LOOP 0x03
|
||||
#define GL_LINE_STRIP 0x04
|
||||
#define GL_TRIANGLES 0x05
|
||||
#define GL_TRIANGLE_STRIP 0x06
|
||||
#define GL_TRIANGLE_FAN 0x07
|
||||
#define GL_QUADS 0x08
|
||||
#define GL_QUAD_STRIP 0x09
|
||||
#define GL_POLYGON 0x0A
|
||||
#define GL_POINTS 0x0000
|
||||
#define GL_LINES 0x0001
|
||||
#define GL_LINE_LOOP 0x0002
|
||||
#define GL_LINE_STRIP 0x0003
|
||||
#define GL_TRIANGLES 0x0004
|
||||
#define GL_TRIANGLE_STRIP 0x0005
|
||||
#define GL_TRIANGLE_FAN 0x0006
|
||||
#define GL_QUADS 0x0007
|
||||
#define GL_QUAD_STRIP 0x0008
|
||||
#define GL_POLYGON 0x0009
|
||||
|
||||
/* FrontFaceDirection */
|
||||
#define GL_CW 0x0900
|
||||
|
@ -232,6 +225,13 @@ __BEGIN_DECLS
|
|||
#define GL_SINGLE_COLOR 0x81F9
|
||||
#define GL_SEPARATE_SPECULAR_COLOR 0x81FA
|
||||
|
||||
/* glPolygonOffset */
|
||||
#define GL_POLYGON_OFFSET_FACTOR 0x8038
|
||||
#define GL_POLYGON_OFFSET_UNITS 0x2A00
|
||||
#define GL_POLYGON_OFFSET_POINT 0x2A01
|
||||
#define GL_POLYGON_OFFSET_LINE 0x2A02
|
||||
#define GL_POLYGON_OFFSET_FILL 0x8037
|
||||
|
||||
/* Client state caps */
|
||||
#define GL_VERTEX_ARRAY 0x8074
|
||||
#define GL_NORMAL_ARRAY 0x8075
|
||||
|
@ -335,6 +335,9 @@ __BEGIN_DECLS
|
|||
#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365
|
||||
#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
|
||||
|
||||
#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
|
||||
#define GL_INT_2_10_10_10_REV 0x8D9F
|
||||
|
||||
#define GL_COLOR_INDEX 0x1900
|
||||
#define GL_RED 0x1903
|
||||
#define GL_GREEN 0x1904
|
||||
|
@ -431,6 +434,7 @@ GLAPI void APIENTRY glColor1ui(GLuint argb);
|
|||
GLAPI void APIENTRY glColor4ub(GLubyte r, GLubyte g, GLubyte b, GLubyte a);
|
||||
GLAPI void APIENTRY glColor3f(GLfloat r, GLfloat g, GLfloat b);
|
||||
GLAPI void APIENTRY glColor3ub(GLubyte r, GLubyte g, GLubyte b);
|
||||
GLAPI void APIENTRY glColor3ubv(const GLubyte *v);
|
||||
GLAPI void APIENTRY glColor3fv(const GLfloat *rgb);
|
||||
GLAPI void APIENTRY glColor4f(GLfloat r, GLfloat g, GLfloat b, GLfloat a);
|
||||
GLAPI void APIENTRY glColor4fv(const GLfloat *rgba);
|
||||
|
@ -488,6 +492,7 @@ GLAPI void APIENTRY glClearDepth(GLfloat depth);
|
|||
GLAPI void APIENTRY glClearDepthf(GLfloat depth);
|
||||
GLAPI void APIENTRY glDepthMask(GLboolean flag);
|
||||
GLAPI void APIENTRY glDepthFunc(GLenum func);
|
||||
GLAPI void APIENTRY glDepthRange(GLclampf n, GLclampf f);
|
||||
|
||||
/* Hints */
|
||||
/* Currently Supported Capabilities:
|
||||
|
|
|
@ -53,6 +53,20 @@ typedef struct {
|
|||
} GLdcConfig;
|
||||
|
||||
|
||||
typedef struct {
|
||||
GLuint padding0;
|
||||
GLfloat x;
|
||||
GLfloat y;
|
||||
GLfloat z;
|
||||
GLfloat u;
|
||||
GLfloat v;
|
||||
GLubyte bgra[4];
|
||||
GLuint padding1;
|
||||
} GLVertexKOS;
|
||||
|
||||
GLAPI void APIENTRY glVertexPackColor3fKOS(GLVertexKOS* vertex, float r, float g, float b);
|
||||
GLAPI void APIENTRY glVertexPackColor4fKOS(GLVertexKOS* vertex, float r, float g, float b, float a);
|
||||
|
||||
GLAPI void APIENTRY glKosInitConfig(GLdcConfig* config);
|
||||
|
||||
/* Usage:
|
||||
|
|
|
@ -26,3 +26,7 @@ all:
|
|||
$(KOS_MAKE) -C paletted_pcx all
|
||||
$(KOS_MAKE) -C depth_funcs all
|
||||
$(KOS_MAKE) -C polymark all
|
||||
$(KOS_MAKE) -C polygon_offset all
|
||||
$(KOS_MAKE) -C blend_test all
|
||||
$(KOS_MAKE) -C mipmap all
|
||||
$(KOS_MAKE) -C lights all
|
||||
|
|
29
samples/blend_test/Makefile
Normal file
29
samples/blend_test/Makefile
Normal file
|
@ -0,0 +1,29 @@
|
|||
TARGET = blend_test.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)
|
100
samples/blend_test/main.c
Normal file
100
samples/blend_test/main.c
Normal file
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* This sample is to demonstrate a bug where rendering an unblended
|
||||
* polygon, before a series of blended ones would result in no blended
|
||||
* output and incorrect depth testing
|
||||
*/
|
||||
|
||||
#include "gl.h"
|
||||
#include "glu.h"
|
||||
#include "glkos.h"
|
||||
|
||||
/* 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.
|
||||
{
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // This Will Clear The Background Color To Black
|
||||
glClearDepth(1.0); // Enables Clearing Of The Depth Buffer
|
||||
glDepthFunc(GL_LEQUAL); // The Type Of Depth Test To Do
|
||||
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
void DrawQuad(const float* colour) {
|
||||
glBegin(GL_QUADS);
|
||||
glColor4fv(colour);
|
||||
glVertex3f(-1.0,-1.0, 0.0);
|
||||
glVertex3f( 1.0,-1.0, 0.0);
|
||||
glVertex3f( 1.0, 1.0, 0.0);
|
||||
glVertex3f(-1.0, 1.0, 0.0);
|
||||
glEnd();
|
||||
}
|
||||
|
||||
/* The main drawing function. */
|
||||
void DrawGLScene()
|
||||
{
|
||||
const float RED [] = {1.0, 0, 0, 0.5};
|
||||
const float BLUE [] = {0.0, 0, 1, 0.5};
|
||||
const float NONE [] = {0, 0, 0, 0};
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
|
||||
glLoadIdentity(); // Reset The View
|
||||
|
||||
glTranslatef(0, 0, -10.0f); // Move Left 1.5 Units And Into The Screen 6.0
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(-4.0, 0, -10);
|
||||
DrawQuad(RED);
|
||||
glPopMatrix();
|
||||
|
||||
glTranslatef(4.0, 0, 0);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
/* Draw 3 overlapping quads, 2 of which should be totally transparent so the
|
||||
* output should be the third */
|
||||
DrawQuad(NONE);
|
||||
DrawQuad(NONE);
|
||||
DrawQuad(BLUE);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
glKosSwapBuffers();
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
glKosInit();
|
||||
|
||||
InitGL(640, 480);
|
||||
ReSizeGLScene(640, 480);
|
||||
|
||||
while(1) {
|
||||
DrawGLScene();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
0
samples/blend_test/romdisk/PLACEHOLDER
Normal file
0
samples/blend_test/romdisk/PLACEHOLDER
Normal file
29
samples/lights/Makefile
Normal file
29
samples/lights/Makefile
Normal file
|
@ -0,0 +1,29 @@
|
|||
TARGET = lights.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)
|
296
samples/lights/main.c
Normal file
296
samples/lights/main.c
Normal file
|
@ -0,0 +1,296 @@
|
|||
#include <stdio.h>
|
||||
|
||||
#include "gl.h"
|
||||
#include "glu.h"
|
||||
#include "glkos.h"
|
||||
|
||||
extern uint8 romdisk[];
|
||||
KOS_INIT_ROMDISK(romdisk);
|
||||
|
||||
|
||||
float xrot, yrot, zrot;
|
||||
|
||||
|
||||
int texture[1];
|
||||
|
||||
|
||||
struct Image {
|
||||
unsigned long sizeX;
|
||||
unsigned long sizeY;
|
||||
char *data;
|
||||
};
|
||||
typedef struct Image Image;
|
||||
|
||||
|
||||
|
||||
int ImageLoad(char *filename, Image *image) {
|
||||
FILE *file;
|
||||
unsigned long size;
|
||||
unsigned long i;
|
||||
unsigned short int planes;
|
||||
unsigned short int bpp;
|
||||
char temp;
|
||||
|
||||
|
||||
if ((file = fopen(filename, "rb"))==NULL)
|
||||
{
|
||||
printf("File Not Found : %s\n",filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
fseek(file, 18, SEEK_CUR);
|
||||
|
||||
|
||||
if ((i = fread(&image->sizeX, 4, 1, file)) != 1) {
|
||||
printf("Error reading width from %s.\n", filename);
|
||||
return 0;
|
||||
}
|
||||
printf("Width of %s: %lu\n", filename, image->sizeX);
|
||||
|
||||
|
||||
if ((i = fread(&image->sizeY, 4, 1, file)) != 1) {
|
||||
printf("Error reading height from %s.\n", filename);
|
||||
return 0;
|
||||
}
|
||||
printf("Height of %s: %lu\n", filename, image->sizeY);
|
||||
|
||||
|
||||
size = image->sizeX * image->sizeY * 3;
|
||||
|
||||
|
||||
if ((fread(&planes, 2, 1, file)) != 1) {
|
||||
printf("Error reading planes from %s.\n", filename);
|
||||
return 0;
|
||||
}
|
||||
if (planes != 1) {
|
||||
printf("Planes from %s is not 1: %u\n", filename, planes);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
if ((i = fread(&bpp, 2, 1, file)) != 1) {
|
||||
printf("Error reading bpp from %s.\n", filename);
|
||||
return 0;
|
||||
}
|
||||
if (bpp != 24) {
|
||||
printf("Bpp from %s is not 24: %u\n", filename, bpp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
fseek(file, 24, SEEK_CUR);
|
||||
|
||||
|
||||
image->data = (char *) malloc(size);
|
||||
if (image->data == NULL) {
|
||||
printf("Error allocating memory for color-corrected image data");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((i = fread(image->data, size, 1, file)) != 1) {
|
||||
printf(stderr, "Error reading image data from %s.\n", filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i=0;i<size;i+=3) {
|
||||
temp = image->data[i];
|
||||
image->data[i] = image->data[i+2];
|
||||
image->data[i+2] = temp;
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void LoadGLTextures() {
|
||||
|
||||
Image *image1;
|
||||
|
||||
|
||||
image1 = (Image *) malloc(sizeof(Image));
|
||||
if (image1 == NULL) {
|
||||
printf("Error allocating space for image");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!ImageLoad("/rd/NeHe.bmp", image1)) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
glGenTextures(1, &texture[0]);
|
||||
glBindTexture(GL_TEXTURE_2D, texture[0]);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
|
||||
|
||||
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, 3, image1->sizeX, image1->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image1->data);
|
||||
|
||||
glGenerateMipmapEXT(GL_TEXTURE_2D);
|
||||
};
|
||||
|
||||
|
||||
void InitGL(int Width, int Height)
|
||||
{
|
||||
LoadGLTextures();
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
glClearDepth(1.0);
|
||||
glDepthFunc(GL_LESS);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glShadeModel(GL_SMOOTH);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
|
||||
gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
|
||||
glEnable(GL_COLOR_MATERIAL);
|
||||
glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
|
||||
|
||||
glClearColor(0.5, 0.5, 0.5, 0.5);
|
||||
|
||||
glEnable(GL_LIGHTING);
|
||||
glEnable(GL_LIGHT0);
|
||||
|
||||
// Create light components
|
||||
GLfloat ambientLight[] = { 0.2f, 0.2f, 0.2f, 1.0f };
|
||||
GLfloat diffuseLight[] = { 1.0f, 0.0f, 0.0, 1.0f };
|
||||
GLfloat specularLight[] = { 0.5f, 0.5f, 0.5f, 1.0f };
|
||||
GLfloat position[] = { -1.5f, -1.0f, 0.0f, 0.0f };
|
||||
|
||||
// Assign created components to GL_LIGHT0
|
||||
glLightfv(GL_LIGHT0, GL_AMBIENT, ambientLight);
|
||||
glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuseLight);
|
||||
glLightfv(GL_LIGHT0, GL_SPECULAR, specularLight);
|
||||
glLightfv(GL_LIGHT0, GL_POSITION, position);
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
diffuseLight[1] = 1.0f;
|
||||
|
||||
glEnable(GL_LIGHT1);
|
||||
glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuseLight);
|
||||
glLightfv(GL_LIGHT1, GL_SPECULAR, specularLight);
|
||||
|
||||
glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, 1.0);
|
||||
glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, 4.5 / 100);
|
||||
glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, 75.0f / (100 * 100));
|
||||
|
||||
glEnable(GL_NORMALIZE);
|
||||
}
|
||||
|
||||
|
||||
void ReSizeGLScene(int Width, int Height)
|
||||
{
|
||||
if (Height == 0)
|
||||
Height = 1;
|
||||
|
||||
glViewport(0, 0, Width, Height);
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
|
||||
gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
}
|
||||
|
||||
void DrawCube(float x, float z) {
|
||||
static float pos = 0.0f;
|
||||
const static float radius = 30.0f;
|
||||
|
||||
pos += 0.001f;
|
||||
|
||||
GLfloat position[] = { cos(pos) * radius, 15.0f, sin(pos) * radius, 1.0f };
|
||||
glLightfv(GL_LIGHT1, GL_POSITION, position);
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(x, 0, z);
|
||||
glColor4f(1, 1, 1, 1);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
|
||||
|
||||
glNormal3f(0, 0, -1);
|
||||
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);
|
||||
|
||||
|
||||
glNormal3f(0, 0, 1);
|
||||
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);
|
||||
|
||||
|
||||
glNormal3f(0, 1, 0);
|
||||
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);
|
||||
|
||||
glNormal3f(0, -1, 0);
|
||||
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);
|
||||
|
||||
glNormal3f(1, 0, 0);
|
||||
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);
|
||||
|
||||
glNormal3f(-1, 0, 0);
|
||||
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();
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
void DrawGLScene()
|
||||
{
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
glLoadIdentity();
|
||||
|
||||
|
||||
glTranslatef(0.0f, 0.0f, -55.0f);
|
||||
glRotatef(45, 1, 0, 0);
|
||||
glTranslatef(0, 0, -30);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture[0]);
|
||||
|
||||
int x, z;
|
||||
for(z = -100; z < 100; z += 10) {
|
||||
for(x = -100; x < 100; x += 10) {
|
||||
DrawCube(x, z);
|
||||
}
|
||||
}
|
||||
|
||||
glKosSwapBuffers();
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
glKosInit();
|
||||
|
||||
InitGL(640, 480);
|
||||
ReSizeGLScene(640, 480);
|
||||
|
||||
while(1) {
|
||||
DrawGLScene();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
BIN
samples/lights/romdisk/NeHe.bmp
Normal file
BIN
samples/lights/romdisk/NeHe.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 192 KiB |
0
samples/lights/romdisk/PLACEHOLDER
Normal file
0
samples/lights/romdisk/PLACEHOLDER
Normal file
|
@ -13,8 +13,7 @@ KOS_INIT_ROMDISK(romdisk);
|
|||
int texture[1];
|
||||
|
||||
/* Image type - contains height, width, and data */
|
||||
struct Image
|
||||
{
|
||||
struct Image {
|
||||
unsigned long sizeX;
|
||||
unsigned long sizeY;
|
||||
char *data;
|
||||
|
@ -23,19 +22,18 @@ typedef struct Image Image;
|
|||
|
||||
// quick and dirty bitmap loader...for 24 bit bitmaps with 1 plane only.
|
||||
// See http://www.dcs.ed.ac.uk/~mxr/gfx/2d/BMP.txt for more info.
|
||||
int ImageLoad(char *filename, Image *image)
|
||||
{
|
||||
int ImageLoad(char *filename, Image *image) {
|
||||
FILE *file;
|
||||
unsigned long size; // size of the image in bytes.
|
||||
unsigned long i; // standard counter.
|
||||
unsigned short int planes; // number of planes in image (must be 1)
|
||||
unsigned short int bpp; // number of bits per pixel (must be 24)
|
||||
char temp; // temporary color storage for bgr-rgb conversion.
|
||||
unsigned long size; // size of the image in bytes.
|
||||
unsigned long i; // standard counter.
|
||||
unsigned short int planes; // number of planes in image (must be 1)
|
||||
unsigned short int bpp; // number of bits per pixel (must be 24)
|
||||
char temp; // temporary color storage for bgr-rgb conversion.
|
||||
|
||||
// make sure the file is there.
|
||||
if ((file = fopen(filename, "rb")) == NULL)
|
||||
if ((file = fopen(filename, "rb"))==NULL)
|
||||
{
|
||||
printf("File Not Found : %s\n", filename);
|
||||
printf("File Not Found : %s\n",filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -43,16 +41,14 @@ int ImageLoad(char *filename, Image *image)
|
|||
fseek(file, 18, SEEK_CUR);
|
||||
|
||||
// read the width
|
||||
if ((i = fread(&image->sizeX, 4, 1, file)) != 1)
|
||||
{
|
||||
if ((i = fread(&image->sizeX, 4, 1, file)) != 1) {
|
||||
printf("Error reading width from %s.\n", filename);
|
||||
return 0;
|
||||
}
|
||||
printf("Width of %s: %lu\n", filename, image->sizeX);
|
||||
|
||||
// read the height
|
||||
if ((i = fread(&image->sizeY, 4, 1, file)) != 1)
|
||||
{
|
||||
if ((i = fread(&image->sizeY, 4, 1, file)) != 1) {
|
||||
printf("Error reading height from %s.\n", filename);
|
||||
return 0;
|
||||
}
|
||||
|
@ -62,25 +58,21 @@ int ImageLoad(char *filename, Image *image)
|
|||
size = image->sizeX * image->sizeY * 3;
|
||||
|
||||
// read the planes
|
||||
if ((fread(&planes, 2, 1, file)) != 1)
|
||||
{
|
||||
if ((fread(&planes, 2, 1, file)) != 1) {
|
||||
printf("Error reading planes from %s.\n", filename);
|
||||
return 0;
|
||||
}
|
||||
if (planes != 1)
|
||||
{
|
||||
if (planes != 1) {
|
||||
printf("Planes from %s is not 1: %u\n", filename, planes);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// read the bpp
|
||||
if ((i = fread(&bpp, 2, 1, file)) != 1)
|
||||
{
|
||||
if ((i = fread(&bpp, 2, 1, file)) != 1) {
|
||||
printf("Error reading bpp from %s.\n", filename);
|
||||
return 0;
|
||||
}
|
||||
if (bpp != 24)
|
||||
{
|
||||
if (bpp != 24) {
|
||||
printf("Bpp from %s is not 24: %u\n", filename, bpp);
|
||||
return 0;
|
||||
}
|
||||
|
@ -89,24 +81,21 @@ int ImageLoad(char *filename, Image *image)
|
|||
fseek(file, 24, SEEK_CUR);
|
||||
|
||||
// read the data.
|
||||
image->data = (char *)malloc(size);
|
||||
if (image->data == NULL)
|
||||
{
|
||||
image->data = (char *) malloc(size);
|
||||
if (image->data == NULL) {
|
||||
printf("Error allocating memory for color-corrected image data");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((i = fread(image->data, size, 1, file)) != 1)
|
||||
{
|
||||
if ((i = fread(image->data, size, 1, file)) != 1) {
|
||||
printf(stderr, "Error reading image data from %s.\n", filename);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < size; i += 3)
|
||||
{ // reverse all of the colors. (bgr -> rgb)
|
||||
for (i=0;i<size;i+=3) { // reverse all of the colors. (bgr -> rgb)
|
||||
temp = image->data[i];
|
||||
image->data[i] = image->data[i + 2];
|
||||
image->data[i + 2] = temp;
|
||||
image->data[i] = image->data[i+2];
|
||||
image->data[i+2] = temp;
|
||||
}
|
||||
|
||||
// we're done.
|
||||
|
@ -149,15 +138,13 @@ void LoadGLTextures()
|
|||
Image *image1;
|
||||
|
||||
// allocate space for texture
|
||||
image1 = (Image *)malloc(sizeof(Image));
|
||||
if (image1 == NULL)
|
||||
{
|
||||
image1 = (Image *) malloc(sizeof(Image));
|
||||
if (image1 == NULL) {
|
||||
printf("Error allocating space for image");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!ImageLoad("/rd/NeHe.bmp", image1))
|
||||
{
|
||||
if (!ImageLoad("/rd/NeHe.bmp", image1)) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
@ -204,30 +191,25 @@ void InitGL(int Width, int Height) // We call this right after our OpenGL window
|
|||
/* 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
|
||||
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
|
||||
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);
|
||||
gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
}
|
||||
|
||||
void DrawQuad()
|
||||
{
|
||||
void DrawQuad() {
|
||||
glBegin(GL_QUADS);
|
||||
glTexCoord2f(0.0f, 0.0f);
|
||||
glVertex3f(-1.0f, -1.0f, 0.0f); // Bottom Left Of The Texture and Quad
|
||||
glTexCoord2f(1.0f, 0.0f);
|
||||
glVertex3f(1.0f, -1.0f, 0.0f); // Bottom Right Of The Texture and Quad
|
||||
glTexCoord2f(1.0f, 1.0f);
|
||||
glVertex3f(1.0f, 1.0f, 0.0f); // Top Right Of The Texture and Quad
|
||||
glTexCoord2f(0.0f, 1.0f);
|
||||
glVertex3f(-1.0f, 1.0f, 0.0f); // Top Left Of The Texture and Quad
|
||||
glEnd(); // done with the polygon.
|
||||
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 0.0f); // Bottom Left Of The Texture and Quad
|
||||
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 0.0f); // Bottom Right Of The Texture and Quad
|
||||
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 0.0f); // Top Right Of The Texture and Quad
|
||||
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 0.0f); // Top Left Of The Texture and Quad
|
||||
glEnd(); // done with the polygon.
|
||||
}
|
||||
|
||||
static GLboolean mipmap_enabled = GL_FALSE;
|
||||
|
@ -245,23 +227,18 @@ void movebias(void) {
|
|||
void DrawGLScene()
|
||||
{
|
||||
timer++;
|
||||
if (timer > 60)
|
||||
{
|
||||
if(timer > 60) {
|
||||
timer = 0;
|
||||
mipmap_enabled = !mipmap_enabled;
|
||||
|
||||
if (mipmap_enabled)
|
||||
{
|
||||
if(mipmap_enabled) {
|
||||
printf("Enabling mipmaps!\n");
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
movebias();
|
||||
}
|
||||
else
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
|
||||
} else {
|
||||
printf("Disabling mipmaps!\n");
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -297,8 +274,7 @@ int main(int argc, char **argv)
|
|||
InitGL(640, 480);
|
||||
ReSizeGLScene(640, 480);
|
||||
|
||||
while (1)
|
||||
{
|
||||
while(1) {
|
||||
DrawGLScene();
|
||||
}
|
||||
|
||||
|
|
BIN
samples/mipmap/romdisk/NeHe.bmp
Normal file
BIN
samples/mipmap/romdisk/NeHe.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 192 KiB |
0
samples/mipmap/romdisk/PLACEHOLDER
Normal file
0
samples/mipmap/romdisk/PLACEHOLDER
Normal file
|
@ -67,7 +67,7 @@ void RenderCallback(GLuint texID0, GLuint texID1) {
|
|||
glClientActiveTextureARB(GL_TEXTURE0_ARB);
|
||||
|
||||
/* Bind the Color Array */
|
||||
glColorPointer(1, GL_UNSIGNED_INT, 0, ARGB_ARRAY);
|
||||
glColorPointer(GL_BGRA, GL_UNSIGNED_BYTE, 0, ARGB_ARRAY);
|
||||
|
||||
/* Bind the Vertex Array */
|
||||
glVertexPointer(3, GL_FLOAT, 0, VERTEX_ARRAY);
|
||||
|
|
|
@ -117,12 +117,13 @@ void LoadGLTextures() {
|
|||
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
|
||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR_MIPMAP_LINEAR);
|
||||
|
||||
// 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_TWID_KOS, image1->data);
|
||||
glGenerateMipmapEXT(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
/* A general OpenGL initialization function. Sets all of the initial parameters. */
|
||||
|
@ -130,7 +131,7 @@ void InitGL(int Width, int Height) // We call this right after our OpenG
|
|||
{
|
||||
LoadGLTextures();
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // This Will Clear The Background Color To Black
|
||||
glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
|
||||
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
|
||||
|
|
|
@ -182,14 +182,14 @@ void DrawGLScene()
|
|||
}
|
||||
|
||||
|
||||
glColor3f(0.0f, 0.0f, 0.0f);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
drawBox();
|
||||
glColor3f(0.0f, 0.0f, 0.0f);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
drawBox();
|
||||
|
||||
if (offset)
|
||||
glDisable(GL_POLYGON_OFFSET_LINE);
|
||||
if (offset)
|
||||
glDisable(GL_POLYGON_OFFSET_LINE);
|
||||
|
||||
glFlush();
|
||||
glFlush();
|
||||
#endif
|
||||
// swap buffers to display, since we're double buffered.
|
||||
glKosSwapBuffers();
|
||||
|
|
Loading…
Reference in New Issue
Block a user