337 lines
8.9 KiB
C
337 lines
8.9 KiB
C
#include <string.h>
|
|
|
|
#include "log.h"
|
|
|
|
#include "state.h"
|
|
#include "passthrough.h"
|
|
|
|
// GL State
|
|
#define init_array_pointer \
|
|
{ \
|
|
.enabled = 0 \
|
|
}
|
|
#define init_light_source \
|
|
.enabled = 0, \
|
|
.position = { \
|
|
.x = 0, \
|
|
.y = 0, \
|
|
.z = 1 \
|
|
}
|
|
static gl_state_t init_gl_state = {
|
|
.color = {
|
|
.red = 1,
|
|
.green = 1,
|
|
.blue = 1,
|
|
.alpha = 1
|
|
},
|
|
.normal = {
|
|
.x = 0,
|
|
.y = 0,
|
|
.z = 1
|
|
},
|
|
.rescale_normal = 0,
|
|
.array_pointers = {
|
|
.vertex = init_array_pointer,
|
|
.color = init_array_pointer,
|
|
.tex_coord = init_array_pointer,
|
|
.normal = init_array_pointer
|
|
},
|
|
.matrix_stacks = {
|
|
.mode = GL_MODELVIEW
|
|
},
|
|
.alpha_test = 0,
|
|
.texture_2d = 0,
|
|
.fog = {
|
|
.enabled = 0,
|
|
.mode = GL_LINEAR,
|
|
.color = {
|
|
.red = 0,
|
|
.green = 0,
|
|
.blue = 0,
|
|
.alpha = 0
|
|
},
|
|
.start = 0,
|
|
.end = 1
|
|
},
|
|
.lighting = {
|
|
.enabled = 0,
|
|
.light_sources = {
|
|
{
|
|
init_light_source,
|
|
.diffuse = {
|
|
.red = 1,
|
|
.green = 1,
|
|
.blue = 1,
|
|
.alpha = 1
|
|
}
|
|
},
|
|
{
|
|
init_light_source,
|
|
.diffuse = {
|
|
.red = 0,
|
|
.green = 0,
|
|
.blue = 0,
|
|
.alpha = 0
|
|
}
|
|
}
|
|
},
|
|
.ambient = {
|
|
.red = 0.2f,
|
|
.green = 0.2f,
|
|
.blue = 0.2f,
|
|
.alpha = 0.2f
|
|
}
|
|
},
|
|
.highlight_mode = {
|
|
.enabled = 0
|
|
}
|
|
};
|
|
gl_state_t gl_state;
|
|
void _init_gles_compatibility_layer_state() {
|
|
gl_state = init_gl_state;
|
|
_init_gles_compatibility_matrix_stacks();
|
|
}
|
|
|
|
// Change Color
|
|
void glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
|
|
gl_state.color.red = red;
|
|
gl_state.color.green = green;
|
|
gl_state.color.blue = blue;
|
|
gl_state.color.alpha = alpha;
|
|
}
|
|
|
|
// Change Normal
|
|
void glNormal3f(GLfloat nx, GLfloat ny, GLfloat nz) {
|
|
gl_state.normal.x = nx;
|
|
gl_state.normal.y = ny;
|
|
gl_state.normal.z = nz;
|
|
}
|
|
|
|
// Array Pointer Storage
|
|
#define ARRAY_POINTER_FUNC(func, name) \
|
|
void func(GLint size, GLenum type, GLsizei stride, const void *pointer) { \
|
|
gl_state.array_pointers.name.size = size; \
|
|
gl_state.array_pointers.name.type = type; \
|
|
gl_state.array_pointers.name.stride = stride; \
|
|
gl_state.array_pointers.name.pointer = pointer; \
|
|
}
|
|
ARRAY_POINTER_FUNC(glVertexPointer, vertex)
|
|
ARRAY_POINTER_FUNC(glColorPointer, color)
|
|
ARRAY_POINTER_FUNC(glTexCoordPointer, tex_coord)
|
|
static ARRAY_POINTER_FUNC(fake_glNormalPointer, normal)
|
|
void glNormalPointer(GLenum type, GLsizei stride, const void *pointer) {
|
|
fake_glNormalPointer(0, type, stride, pointer);
|
|
}
|
|
static array_pointer_t *get_array_pointer(GLenum array) {
|
|
switch (array) {
|
|
case GL_VERTEX_ARRAY: {
|
|
return &gl_state.array_pointers.vertex;
|
|
}
|
|
case GL_COLOR_ARRAY: {
|
|
return &gl_state.array_pointers.color;
|
|
}
|
|
case GL_TEXTURE_COORD_ARRAY: {
|
|
return &gl_state.array_pointers.tex_coord;
|
|
}
|
|
case GL_NORMAL_ARRAY: {
|
|
return &gl_state.array_pointers.normal;
|
|
}
|
|
default: {
|
|
ERR("Unsupported Array Pointer: %i", array);
|
|
}
|
|
}
|
|
}
|
|
void glEnableClientState(GLenum array) {
|
|
get_array_pointer(array)->enabled = 1;
|
|
}
|
|
void glDisableClientState(GLenum array) {
|
|
get_array_pointer(array)->enabled = 0;
|
|
}
|
|
|
|
// Enable/Disable State
|
|
GL_FUNC(glEnable, void, (GLenum cap));
|
|
void glEnable(GLenum cap) {
|
|
switch (cap) {
|
|
case GL_ALPHA_TEST: {
|
|
gl_state.alpha_test = 1;
|
|
break;
|
|
}
|
|
case GL_TEXTURE_2D: {
|
|
gl_state.texture_2d = 1;
|
|
break;
|
|
}
|
|
case GL_RESCALE_NORMAL: {
|
|
gl_state.rescale_normal = 1;
|
|
break;
|
|
}
|
|
case GL_COLOR_MATERIAL: {
|
|
// Ignore
|
|
break;
|
|
}
|
|
case GL_FOG: {
|
|
gl_state.fog.enabled = 1;
|
|
break;
|
|
}
|
|
case GL_LIGHTING: {
|
|
gl_state.lighting.enabled = 1;
|
|
break;
|
|
}
|
|
case GL_LIGHT0:
|
|
case GL_LIGHT1: {
|
|
gl_state.lighting.light_sources[cap - GL_LIGHT0].enabled = 1;
|
|
break;
|
|
}
|
|
default: {
|
|
real_glEnable()(cap);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
GL_FUNC(glDisable, void, (GLenum cap));
|
|
void glDisable(GLenum cap) {
|
|
switch (cap) {
|
|
case GL_ALPHA_TEST: {
|
|
gl_state.alpha_test = 0;
|
|
break;
|
|
}
|
|
case GL_TEXTURE_2D: {
|
|
gl_state.texture_2d = 0;
|
|
break;
|
|
}
|
|
case GL_RESCALE_NORMAL: {
|
|
gl_state.rescale_normal = 0;
|
|
break;
|
|
}
|
|
case GL_COLOR_MATERIAL: {
|
|
// Ignore
|
|
break;
|
|
}
|
|
case GL_FOG: {
|
|
gl_state.fog.enabled = 0;
|
|
break;
|
|
}
|
|
case GL_LIGHTING: {
|
|
gl_state.lighting.enabled = 0;
|
|
break;
|
|
}
|
|
case GL_LIGHT0:
|
|
case GL_LIGHT1: {
|
|
gl_state.lighting.light_sources[cap - GL_LIGHT0].enabled = 0;
|
|
break;
|
|
}
|
|
default: {
|
|
real_glDisable()(cap);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
void glAlphaFunc(GLenum func, GLclampf ref) {
|
|
if (func != GL_GREATER && ref != 0.1f) {
|
|
ERR("Unsupported Alpha Function");
|
|
}
|
|
}
|
|
|
|
// Fog
|
|
#define UNSUPPORTED_FOG() ERR("Unsupported Fog Configuration")
|
|
void glFogfv(GLenum pname, const GLfloat *params) {
|
|
if (pname == GL_FOG_COLOR) {
|
|
gl_state.fog.color.red = params[0];
|
|
gl_state.fog.color.green = params[1];
|
|
gl_state.fog.color.blue = params[2];
|
|
gl_state.fog.color.alpha = params[3];
|
|
} else {
|
|
UNSUPPORTED_FOG();
|
|
}
|
|
}
|
|
void glFogx(GLenum pname, GLfixed param) {
|
|
if (pname == GL_FOG_MODE && (param == GL_LINEAR || param == GL_EXP)) {
|
|
gl_state.fog.mode = param;
|
|
} else {
|
|
UNSUPPORTED_FOG();
|
|
}
|
|
}
|
|
void glFogf(GLenum pname, GLfloat param) {
|
|
switch (pname) {
|
|
case GL_FOG_DENSITY:
|
|
case GL_FOG_START: {
|
|
gl_state.fog.start = param;
|
|
break;
|
|
}
|
|
case GL_FOG_END: {
|
|
gl_state.fog.end = param;
|
|
break;
|
|
}
|
|
default: {
|
|
UNSUPPORTED_FOG();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Get Matrix Data
|
|
GL_FUNC(glGetFloatv, void, (GLenum pname, GLfloat *params));
|
|
void glGetFloatv(GLenum pname, GLfloat *params) {
|
|
switch (pname) {
|
|
case GL_MODELVIEW_MATRIX: {
|
|
memcpy((void *) params, gl_state.matrix_stacks.model_view.stack[gl_state.matrix_stacks.model_view.i].data, MATRIX_DATA_SIZE);
|
|
break;
|
|
}
|
|
case GL_PROJECTION_MATRIX: {
|
|
memcpy((void *) params, gl_state.matrix_stacks.projection.stack[gl_state.matrix_stacks.projection.i].data, MATRIX_DATA_SIZE);
|
|
break;
|
|
}
|
|
default: {
|
|
real_glGetFloatv()(pname, params);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Configure Light Sources
|
|
void glLightfv(GLenum light, GLenum pname, const GLfloat *params) {
|
|
light_source_t *light_source = &gl_state.lighting.light_sources[light - GL_LIGHT0];
|
|
if (pname == GL_DIFFUSE) {
|
|
light_source->diffuse.red = params[0];
|
|
light_source->diffuse.green = params[1];
|
|
light_source->diffuse.blue = params[2];
|
|
light_source->diffuse.alpha = params[3];
|
|
} else if (pname == GL_POSITION) {
|
|
// Transform Position By Modelview Matrix
|
|
matrix_t model_view = gl_state.matrix_stacks.model_view.stack[gl_state.matrix_stacks.model_view.i];
|
|
GLfloat out[4];
|
|
for (int i = 0; i < 4; i++) {
|
|
GLfloat result = 0;
|
|
for (int j = 0; j < 4; j++) {
|
|
result += model_view.data[j][i] * params[j];
|
|
}
|
|
out[i] = result;
|
|
}
|
|
// Store
|
|
light_source->position.x = out[0];
|
|
light_source->position.y = out[1];
|
|
light_source->position.z = out[2];
|
|
}
|
|
}
|
|
|
|
// Global Ambient Lighting
|
|
void glLightModelfv(GLenum pname, const GLfloat *params) {
|
|
if (pname == GL_LIGHT_MODEL_AMBIENT) {
|
|
gl_state.lighting.ambient.red = params[0];
|
|
gl_state.lighting.ambient.green = params[1];
|
|
gl_state.lighting.ambient.blue = params[2];
|
|
gl_state.lighting.ambient.alpha = params[3];
|
|
}
|
|
}
|
|
|
|
// Highlight Mode
|
|
void extra_enable_highlight_mode(float red, float green, float blue, float alpha) {
|
|
gl_state.highlight_mode.enabled = 1;
|
|
gl_state.highlight_mode.color.red = red;
|
|
gl_state.highlight_mode.color.green = green;
|
|
gl_state.highlight_mode.color.blue = blue;
|
|
gl_state.highlight_mode.color.alpha = alpha;
|
|
}
|
|
void extra_disable_highlight_mode() {
|
|
gl_state.highlight_mode.enabled = 0;
|
|
}
|