Initial Commit

This commit is contained in:
TheBrokenRail 2023-08-04 21:58:43 -04:00
commit 3dcbd2e903
15 changed files with 1379 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

13
CMakeLists.txt Normal file
View File

@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 3.16.0)
project(gles-compatibility-layer)
# Build
add_library(gles-compatibility-layer STATIC src/state.c src/passthrough.c src/matrix.c src/draw.c)
target_link_libraries(gles-compatibility-layer m SDL)
target_include_directories(gles-compatibility-layer PUBLIC include)
# Shaders
include(cmake/util.cmake)
embed_resource(gles-compatibility-layer src/shaders/main.vsh)
embed_resource(gles-compatibility-layer src/shaders/main.fsh)
# Warnings
target_compile_options(gles-compatibility-layer PRIVATE -Wall -Wextra -Werror -Wpointer-arith -Wshadow -Wnull-dereference)

View File

@ -0,0 +1,12 @@
# Read Hex Data
file(READ "${EMBED_IN}" data HEX)
# Convert Hex Data For C Compatibility
string(REGEX REPLACE "([0-9a-f][0-9a-f])" "0x\\1," data "${data}")
# Get C Name
get_filename_component(name "${EMBED_IN}" NAME)
string(MAKE_C_IDENTIFIER "${name}" name)
# Write Data
file(WRITE "${EMBED_OUT}" "#include <stddef.h>\nconst unsigned char ${name}[] = {${data}};\nconst size_t ${name}_len = sizeof (${name});\n")

15
cmake/util.cmake Normal file
View File

@ -0,0 +1,15 @@
# Embed Resources
set(util_list_dir "${CMAKE_CURRENT_LIST_DIR}")
function(embed_resource target file)
# Get C Name
get_filename_component(name "${file}" NAME)
string(MAKE_C_IDENTIFIER "${name}" name)
# Add Command
add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${name}.c"
COMMAND "${CMAKE_COMMAND}"
ARGS "-DEMBED_IN=${CMAKE_CURRENT_SOURCE_DIR}/${file}" "-DEMBED_OUT=${CMAKE_CURRENT_BINARY_DIR}/${name}.c" "-P" "${util_list_dir}/embed-resource.cmake"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/${file}" "${util_list_dir}/embed-resource.cmake"
)
# Add To Target
target_sources("${target}" PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/${name}.c")
endfunction()

188
include/GLES/gl.h Normal file
View File

@ -0,0 +1,188 @@
#pragma once
#include <stdio.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define GL_FALSE 0
#define GL_ARRAY_BUFFER_BINDING 0x8894
#define GL_ARRAY_BUFFER 0x8892
#define GL_TEXTURE_BINDING_2D 0x8069
#define GL_UNSIGNED_BYTE 0x1401
#define GL_FLOAT 0x1406
#define GL_RGB 0x1907
#define GL_RGBA 0x1908
#define GL_MODELVIEW_MATRIX 0xba6
#define GL_PROJECTION_MATRIX 0xba7
#define GL_VIEWPORT 0xba2
#define GL_DEPTH_TEST 0xb71
#define GL_PACK_ALIGNMENT 0xd05
#define GL_UNPACK_ALIGNMENT 0xcf5
#define GL_SRC_ALPHA 0x302
#define GL_DST_ALPHA 0x304
#define GL_ONE_MINUS_SRC_ALPHA 0x303
#define GL_MODELVIEW 0x1700
#define GL_PROJECTION 0x1701
#define GL_TEXTURE 0x1702
#define GL_VERTEX_ARRAY 0x8074
#define GL_COLOR_ARRAY 0x8076
#define GL_TEXTURE_COORD_ARRAY 0x8078
#define GL_GREATER 0x204
#define GL_ALPHA_TEST 0xbc0
#define GL_TEXTURE_2D 0xde1
#define GL_COLOR_MATERIAL 0xb57
#define GL_PERSPECTIVE_CORRECTION_HINT 0xc50
#define GL_FOG 0xb60
#define GL_LINEAR 0x2601
#define GL_EXP 0x800
#define GL_FOG_DENSITY 0xb62
#define GL_FOG_START 0xb63
#define GL_FOG_END 0xb64
#define GL_FOG_MODE 0xb65
#define GL_FOG_COLOR 0xb66
#define GL_BLEND 0xbe2
#define GL_TRIANGLES 0x4
#define GL_TRIANGLE_STRIP 0x5
#define GL_TRIANGLE_FAN 0x6
#define GL_FASTEST 0x1101
#define GL_BACK 0x405
#define GL_CULL_FACE 0xb44
#define GL_LEQUAL 0x203
#define GL_EQUAL 0x202
#define GL_ONE_MINUS_DST_COLOR 0x307
#define GL_ONE_MINUS_SRC_COLOR 0x301
#define GL_ZERO 0
#define GL_FLAT 0x1d00
#define GL_SMOOTH 0x1d01
#define GL_SCISSOR_TEST 0xc11
#define GL_TRUE 1
#define GL_POLYGON_OFFSET_FILL 0x8037
#define GL_SRC_COLOR 0x300
#define GL_DST_COLOR 0x306
#define GL_ONE 1
#define GL_LINES 0x1
#define GL_LINE_STRIP 0x3
#define GL_STATIC_DRAW 0x88e4
#define GL_DYNAMIC_DRAW 0x88e8
#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
#define GL_UNSIGNED_SHORT_5_6_5 0x8363
#define GL_TEXTURE_WRAP_T 0x2803
#define GL_TEXTURE_WRAP_S 0x2802
#define GL_REPEAT 0x2901
#define GL_CLAMP_TO_EDGE 0x812f
#define GL_TEXTURE_MAG_FILTER 0x2800
#define GL_TEXTURE_MIN_FILTER 0x2801
#define GL_NEAREST 0x2600
#define GL_LINEAR_MIPMAP_LINEAR 0x2703
#define GL_DEPTH_BUFFER_BIT 0x100
#define GL_COLOR_BUFFER_BIT 0x4000
#define GL_NO_ERROR 0
#define GL_NORMAL_ARRAY 0x8075
#define GL_LIGHTING 0xb50
#define GL_LIGHT0 0x4000
#define GL_LIGHT1 0x4001
#define GL_RESCALE_NORMAL 0x803a
#define GL_AMBIENT 0x1200
#define GL_DIFFUSE 0x1201
#define GL_SPECULAR 0x1202
#define GL_POSITION 0x1203
#define GL_LIGHT_MODEL_AMBIENT 0xb53
#define GL_BYTE 0x1400
#define GL_ACCUM 0x100
#define GL_ALPHA 0x1906
#define GL_NONE 0
typedef float GLfloat;
typedef float GLclampf;
typedef int GLint;
typedef unsigned char GLboolean;
typedef int GLsizei;
typedef unsigned int GLuint;
typedef ssize_t GLsizeiptr;
typedef intptr_t GLintptr;
typedef int32_t GLfixed;
typedef unsigned int GLbitfield;
typedef unsigned int GLenum;
typedef char GLchar;
typedef void GLvoid;
void glFogfv(GLenum pname, const GLfloat *params);
void glVertexPointer(GLint size, GLenum type, GLsizei stride, const void *pointer);
void glLineWidth(GLfloat width);
void glBlendFunc(GLenum sfactor, GLenum dfactor);
void glDrawArrays(GLenum mode, GLint first, GLsizei count);
void glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
void glClear(GLbitfield mask);
void glBufferData(GLenum target, GLsizeiptr size, const void *data, GLenum usage);
void glFogx(GLenum pname, GLfixed param);
#define glFogi glFogx
void glFogf(GLenum pname, GLfloat param);
void glMatrixMode(GLenum mode);
void glColorPointer(GLint size, GLenum type, GLsizei stride, const void *pointer);
void glScissor(GLint x, GLint y, GLsizei width, GLsizei height);
void glTexParameteri(GLenum target, GLenum pname, GLint param);
void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
void glEnable(GLenum cap);
void glEnableClientState(GLenum array);
void glPolygonOffset(GLfloat factor, GLfloat units);
void glDisableClientState(GLenum array);
void glDepthRangef(GLclampf near, GLclampf far);
void glDepthFunc(GLenum func);
void glBindBuffer(GLenum target, GLuint buffer);
void glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
void glPopMatrix();
void glLoadIdentity();
void glScalef(GLfloat x, GLfloat y, GLfloat z);
void glPushMatrix();
void glDepthMask(GLboolean flag);
void glHint(GLenum target, GLenum mode);
void glMultMatrixf(const GLfloat *m);
void glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const void *pointer);
void glDeleteBuffers(GLsizei n, const GLuint *buffers);
void glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
void glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
void glGenTextures(GLsizei n, GLuint *textures);
void glDeleteTextures(GLsizei n, const GLuint *textures);
void glAlphaFunc(GLenum func, GLclampf ref);
void glGetFloatv(GLenum pname, GLfloat *params);
void glBindTexture(GLenum target, GLuint texture);
void glTranslatef(GLfloat x, GLfloat y, GLfloat z);
void glShadeModel(GLenum mode);
void glOrthof(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat near, GLfloat far);
void glDisable(GLenum cap);
void glCullFace(GLenum mode);
void glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
void glViewport(GLint x, GLint y, GLsizei width, GLsizei height);
void glNormal3f(GLfloat nx, GLfloat ny, GLfloat nz);
GLboolean glIsEnabled(GLenum cap);
void glGetIntegerv(GLenum pname, GLint *data);
void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *data);
void glGenBuffers(GLsizei n, GLuint *buffers);
GLenum glGetError();
void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
void glNormalPointer(GLenum type, GLsizei stride, const void *pointer);
void glLightfv(GLenum light, GLenum pname, const GLfloat *params);
void glLightModelfv(GLenum pname, const GLfloat *params);
void glPixelStorei(GLenum pname, GLint param);
// Not Part Of OpenGL ES 1.1
#define GL_SAMPLES_PASSED_ARB 0x8c2f // GL_ANY_SAMPLES_PASSED
#define GL_QUERY_RESULT_AVAILABLE_ARB 0x8867 // GL_QUERY_RESULT_AVAILABLE
#define GL_QUERY_RESULT_ARB 0x8866 // GL_QUERY_RESULT
void glGenQueriesARB(GLsizei n, GLuint *ids);
void glDeleteQueriesARB(GLsizei n, const GLuint *ids);
void glBeginQueryARB(GLenum target, GLuint id);
void glEndQueryARB(GLenum target);
void glGetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params);
void extra_enable_highlight_mode(float red, float green, float blue, float alpha);
void extra_disable_highlight_mode();
void init_gles_compatibility_layer();
#ifdef __cplusplus
}
#endif

302
src/draw.c Normal file
View File

@ -0,0 +1,302 @@
#include <math.h>
#include "state.h"
#include "passthrough.h"
#include "log.h"
#include <GLES/gl.h>
// Shaders
#define REAL_GL_FRAGMENT_SHADER 0x8b30
#define REAL_GL_VERTEX_SHADER 0x8b31
#define REAL_GL_INFO_LOG_LENGTH 0x8b84
#define REAL_GL_COMPILE_STATUS 0x8b81
GL_FUNC(glUseProgram, void, (GLuint program));
GL_FUNC(glGetUniformLocation, GLint, (GLuint program, const GLchar *name));
GL_FUNC(glUniformMatrix4fv, void, (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value));
GL_FUNC(glUniform1i, void, (GLint location, GLint v0));
GL_FUNC(glUniform1f, void, (GLint location, GLfloat v0));
GL_FUNC(glUniform3f, void, (GLint location, GLfloat v0, GLfloat v1, GLfloat v2));
GL_FUNC(glUniform4f, void, (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3));
GL_FUNC(glGetAttribLocation, GLint, (GLuint program, const GLchar *name));
GL_FUNC(glEnableVertexAttribArray, void, (GLuint index));
GL_FUNC(glDisableVertexAttribArray, void, (GLuint index));
GL_FUNC(glVertexAttribPointer, void, (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer));
GL_FUNC(glVertexAttrib3f, void, (GLuint index, GLfloat v0, GLfloat v1, GLfloat v2));
GL_FUNC(glVertexAttrib4f, void, (GLuint index, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3));
GL_FUNC(glCreateShader, GLuint, (GLenum type));
GL_FUNC(glShaderSource, void, (GLuint shader, GLsizei count, const GLchar *const *string, const GLint *length));
GL_FUNC(glCompileShader, void, (GLuint shader));
GL_FUNC(glCreateProgram, GLuint, ());
GL_FUNC(glAttachShader, void, (GLuint program, GLuint shader));
GL_FUNC(glLinkProgram, void, (GLuint program));
GL_FUNC(glGetShaderiv, void, (GLuint shader, GLenum pname, GLint *params));
GL_FUNC(glGetShaderInfoLog, void, (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog));
// Compile Shader
static void log_shader(GLuint shader, const char *name) {
// Log
GLint log_length = 0;
real_glGetShaderiv()(shader, REAL_GL_INFO_LOG_LENGTH, &log_length);
GLchar *log = malloc(log_length * sizeof (GLchar));
ALLOC_CHECK(log);
real_glGetShaderInfoLog()(shader, log_length, &log_length, log);
if (log_length > 0) {
if (log_length > 1 && log[log_length - 1] == '\n') {
log[log_length - 1] = '\0';
}
DEBUG("%s Shader Compile Log: %s", name, log);
}
free(log);
// Check Status
GLint is_compiled = 0;
real_glGetShaderiv()(shader, REAL_GL_COMPILE_STATUS, &is_compiled);
if (!is_compiled) {
ERR("Failed To Compile %s Shader", name);
}
}
static GLuint compile_shader(const char *vertex_shader_text, const int vertex_shader_length, const char *fragment_shader_text, const int fragment_shader_length) {
// Vertex Shader
const GLuint vertex_shader = real_glCreateShader()(REAL_GL_VERTEX_SHADER);
real_glShaderSource()(vertex_shader, 1, &vertex_shader_text, &vertex_shader_length);
real_glCompileShader()(vertex_shader);
log_shader(vertex_shader, "Vertex");
// Fragment Shader
const GLuint fragment_shader = real_glCreateShader()(REAL_GL_FRAGMENT_SHADER);
real_glShaderSource()(fragment_shader, 1, &fragment_shader_text, &fragment_shader_length);
real_glCompileShader()(fragment_shader);
log_shader(fragment_shader, "Fragment");
// Link
GLuint program = real_glCreateProgram()();
real_glAttachShader()(program, vertex_shader);
real_glAttachShader()(program, fragment_shader);
real_glLinkProgram()(program);
// Return
return program;
}
// Reset Static Variables
typedef struct {
GLint *variable;
GLint default_value;
} static_variable_t;
static static_variable_t variables_to_reset[64];
static int variables_to_reset_size = 0;
static void mark_for_reset(GLint *variable) {
static_variable_t variable_obj;
variable_obj.variable = variable;
variable_obj.default_value = *variable;
variables_to_reset[variables_to_reset_size++] = variable_obj;
}
static void reset_variables() {
for (int i = 0; i < variables_to_reset_size; i++) {
static_variable_t variable_obj = variables_to_reset[i];
*variable_obj.variable = variable_obj.default_value;
}
variables_to_reset_size = 0;
}
// Shader
extern unsigned char main_vsh[];
extern size_t main_vsh_len;
extern unsigned char main_fsh[];
extern size_t main_fsh_len;
static GLuint get_shader() {
static GLuint program = 0;
if (program == 0) {
mark_for_reset((GLint *) &program);
program = compile_shader((const char *) main_vsh, main_vsh_len, (const char *) main_fsh, main_fsh_len);
}
return program;
}
// Init
GL_FUNC(glGenVertexArrays, void, (GLsizei n, GLuint *arrays));
GL_FUNC(glBindVertexArray, void, (GLuint array));
GL_FUNC(glActiveTexture, void, (GLenum texture));
void init_gles_compatibility_layer() {
// State
_init_gles_compatibility_layer_state();
// Reset Static Variables
reset_variables();
// Setup VAO
GLuint vao;
real_glGenVertexArrays()(1, &vao);
real_glBindVertexArray()(vao);
// Load Shader
GLuint program = get_shader();
real_glUseProgram()(program);
}
// Array Pointer Drawing
GL_FUNC(glDrawArrays, void, (GLenum mode, GLint first, GLsizei count));
#define lazy_handle(function, name) \
static GLint name##_handle = -1; \
if (name##_handle == -1) { \
mark_for_reset(&name##_handle); \
name##_handle = real_##function()(program, #name); \
if (name##_handle == -1) { \
ERR("Unable To Find: %s", #name); \
} \
}
#define lazy_uniform(name) lazy_handle(glGetUniformLocation, name)
#define lazy_attrib(name) lazy_handle(glGetAttribLocation, name)
void glDrawArrays(GLenum mode, GLint first, GLsizei count) {
// Verify
if (gl_state.array_pointers.vertex.size != 3 || !gl_state.array_pointers.vertex.enabled || gl_state.array_pointers.vertex.type != GL_FLOAT) {
ERR("Unsupported Vertex Conifguration");
}
// Check
GLint current_buffer;
glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &current_buffer);
if (current_buffer == 0) {
return;
}
// Check Mode
int use_color_pointer = gl_state.array_pointers.color.enabled;
if (use_color_pointer && (gl_state.array_pointers.color.size != 4 || gl_state.array_pointers.color.type != GL_UNSIGNED_BYTE)) {
ERR("Unsupported Color Conifguration");
}
int use_normal_pointer = gl_state.lighting.enabled && gl_state.array_pointers.normal.enabled;
if (use_normal_pointer && gl_state.array_pointers.normal.type != GL_BYTE) {
ERR("Unsupported Normal Conifguration");
}
int use_texture = gl_state.texture_2d && gl_state.array_pointers.tex_coord.enabled;
if (use_texture && (gl_state.array_pointers.tex_coord.size != 2 || gl_state.array_pointers.tex_coord.type != GL_FLOAT)) {
ERR("Unsupported Texture Conifguration");
}
// Get Shader
GLuint program = get_shader();
// Projection Matrix
lazy_uniform(u_projection);
matrix_t *projection = &gl_state.matrix_stacks.projection.stack[gl_state.matrix_stacks.projection.i];
real_glUniformMatrix4fv()(u_projection_handle, 1, 0, (GLfloat *) &projection->data[0][0]);
// Model View Matrix
lazy_uniform(u_model_view);
matrix_t *model_view = &gl_state.matrix_stacks.model_view.stack[gl_state.matrix_stacks.model_view.i];
real_glUniformMatrix4fv()(u_model_view_handle, 1, 0, (GLfloat *) &model_view->data[0][0]);
// Has Texture
lazy_uniform(u_has_texture); \
real_glUniform1i()(u_has_texture_handle, use_texture); \
// Texture Matrix
lazy_uniform(u_texture);
matrix_t *texture = &gl_state.matrix_stacks.texture.stack[gl_state.matrix_stacks.texture.i];
real_glUniformMatrix4fv()(u_texture_handle, 1, 0, (GLfloat *) &texture->data[0][0]);
// Texture Unit
lazy_uniform(u_texture_unit);
real_glUniform1i()(u_texture_unit_handle, 0);
// Alpha Test
lazy_uniform(u_alpha_test);
real_glUniform1i()(u_alpha_test_handle, gl_state.alpha_test);
// Color
lazy_attrib(a_color);
if (use_color_pointer) {
real_glVertexAttribPointer()(a_color_handle, gl_state.array_pointers.color.size, gl_state.array_pointers.color.type, 1, gl_state.array_pointers.color.stride, gl_state.array_pointers.color.pointer);
real_glEnableVertexAttribArray()(a_color_handle);
} else {
real_glVertexAttrib4f()(a_color_handle, gl_state.color.red, gl_state.color.green, gl_state.color.blue, gl_state.color.alpha);
}
// Highlight Mode
lazy_uniform(u_highlight_mode);
real_glUniform1i()(u_highlight_mode_handle, gl_state.highlight_mode.enabled);
if (gl_state.highlight_mode.enabled) {
lazy_uniform(u_highlight_mode_color);
real_glUniform4f()(u_highlight_mode_color_handle, gl_state.highlight_mode.color.red, gl_state.highlight_mode.color.green, gl_state.highlight_mode.color.blue, gl_state.highlight_mode.color.alpha);
}
// Lighting
lazy_uniform(u_lighting);
real_glUniform1i()(u_lighting_handle, gl_state.lighting.enabled);
lazy_attrib(a_normal);
if (gl_state.lighting.enabled) {
lazy_uniform(u_lighting_ambient);
real_glUniform4f()(u_lighting_ambient_handle, gl_state.lighting.ambient.red, gl_state.lighting.ambient.green, gl_state.lighting.ambient.blue, gl_state.lighting.ambient.alpha);
light_source_t *light_source;
#define light_source_uniforms(number) \
light_source = &gl_state.lighting.light_sources[number]; \
lazy_uniform(u_lighting_light_source_##number); \
real_glUniform1i()(u_lighting_light_source_##number##_handle, light_source->enabled); \
lazy_uniform(u_lighting_light_source_##number##_position); \
real_glUniform3f()(u_lighting_light_source_##number##_position_handle, light_source->position.x, light_source->position.y, light_source->position.z); \
lazy_uniform(u_lighting_light_source_##number##_diffuse); \
real_glUniform4f()(u_lighting_light_source_##number##_diffuse_handle, light_source->diffuse.red, light_source->diffuse.green, light_source->diffuse.blue, light_source->diffuse.alpha);
light_source_uniforms(0);
light_source_uniforms(1);
// Normal
if (use_normal_pointer) {
real_glVertexAttribPointer()(a_normal_handle, 3, gl_state.array_pointers.normal.type, 1, gl_state.array_pointers.normal.stride, gl_state.array_pointers.normal.pointer);
real_glEnableVertexAttribArray()(a_normal_handle);
} else {
real_glVertexAttrib3f()(a_normal_handle, gl_state.normal.x, gl_state.normal.y, gl_state.normal.z);
}
// Normal Rescale Factor (See Pages 46-47 Of https://registry.khronos.org/OpenGL/specs/gl/glspec15.pdf)
float normal_rescale_factor = 1;
if (gl_state.rescale_normal) {
normal_rescale_factor = 1.0f / sqrtf(powf(model_view->data[0][2], 2) + powf(model_view->data[1][2], 2) + powf(model_view->data[2][2], 2));
}
lazy_uniform(u_normal_rescale_factor);
real_glUniform1f()(u_normal_rescale_factor_handle, normal_rescale_factor);
}
// Fog
lazy_uniform(u_fog);
real_glUniform1i()(u_fog_handle, gl_state.fog.enabled);
if (gl_state.fog.enabled) {
lazy_uniform(u_fog_color);
real_glUniform4f()(u_fog_color_handle, gl_state.fog.color.red, gl_state.fog.color.green, gl_state.fog.color.blue, gl_state.fog.color.alpha);
lazy_uniform(u_fog_is_linear);
real_glUniform1i()(u_fog_is_linear_handle, gl_state.fog.mode == GL_LINEAR);
lazy_uniform(u_fog_start);
real_glUniform1f()(u_fog_start_handle, gl_state.fog.start);
lazy_uniform(u_fog_end);
real_glUniform1f()(u_fog_end_handle, gl_state.fog.end);
}
// Vertices
lazy_attrib(a_vertex_coords);
real_glVertexAttribPointer()(a_vertex_coords_handle, gl_state.array_pointers.vertex.size, gl_state.array_pointers.vertex.type, 0, gl_state.array_pointers.vertex.stride, gl_state.array_pointers.vertex.pointer);
real_glEnableVertexAttribArray()(a_vertex_coords_handle);
// Texture Coordinates
lazy_attrib(a_texture_coords);
if (use_texture) {
real_glVertexAttribPointer()(a_texture_coords_handle, gl_state.array_pointers.tex_coord.size, gl_state.array_pointers.tex_coord.type, 0, gl_state.array_pointers.tex_coord.stride, gl_state.array_pointers.tex_coord.pointer);
real_glEnableVertexAttribArray()(a_texture_coords_handle);
} else {
real_glVertexAttrib3f()(a_texture_coords_handle, 0, 0, 0);
}
// Draw
real_glDrawArrays()(mode, first, count);
// Cleanup
if (use_color_pointer) {
real_glDisableVertexAttribArray()(a_color_handle);
}
if (use_normal_pointer) {
real_glDisableVertexAttribArray()(a_normal_handle);
}
real_glDisableVertexAttribArray()(a_vertex_coords_handle);
if (use_texture) {
real_glDisableVertexAttribArray()(a_texture_coords_handle);
}
}

22
src/log.h Normal file
View File

@ -0,0 +1,22 @@
#pragma once
#include <stdlib.h>
#ifdef ANDROID
#include <android/log.h>
#define DEBUG(...) { ((void) __android_log_print(ANDROID_LOG_VERBOSE, "GL DEBUG", __VA_ARGS__)); }
#define ERR(...) { ((void) __android_log_print(ANDROID_LOG_ERROR, "GL ERROR", __VA_ARGS__)); exit(EXIT_FAILURE); }
#else
#include <stdio.h>
#define DEBUG(format, ...) { printf("GL DEBUG: " format "\n", ##__VA_ARGS__); }
#define ERR(format, ...) { printf("GL ERROR: (%s:%i): " format "\n", __FILE__, __LINE__, ##__VA_ARGS__); exit(EXIT_FAILURE); }
#endif
#define ALLOC_CHECK(obj) \
{ \
if (obj == NULL) { \
ERR("Memory Allocation Failed"); \
} \
}

131
src/matrix.c Normal file
View File

@ -0,0 +1,131 @@
#include <math.h>
#include <string.h>
#include "log.h"
#include "state.h"
// Matrix Common
static void matrix_copy(matrix_t *src, matrix_t *dst) {
memcpy((void *) dst->data, (void *) src->data, MATRIX_DATA_SIZE);
}
// Identity Matrix
static matrix_t identity_matrix = {
.data = {
{1, 0, 0, 0},
{0, 1, 0, 0},
{0, 0, 1, 0},
{0, 0, 0, 1}
}
};
static void init_matrix_stack(matrix_stack_t *stack) {
matrix_copy(&identity_matrix, &stack->stack[0]);
}
void _init_gles_compatibility_matrix_stacks() {
init_matrix_stack(&gl_state.matrix_stacks.model_view);
init_matrix_stack(&gl_state.matrix_stacks.projection);
init_matrix_stack(&gl_state.matrix_stacks.texture);
}
// Matrix Mode
static matrix_stack_t *get_matrix_stack() {
switch (gl_state.matrix_stacks.mode) {
case GL_MODELVIEW: {
return &gl_state.matrix_stacks.model_view;
}
case GL_PROJECTION: {
return &gl_state.matrix_stacks.projection;
}
case GL_TEXTURE: {
return &gl_state.matrix_stacks.texture;
}
default: {
ERR("Unsupported Matrix Mode: %i", gl_state.matrix_stacks.mode);
}
}
}
// Matrix Functions
void glMatrixMode(GLenum mode) {
gl_state.matrix_stacks.mode = mode;
}
void glPopMatrix() {
get_matrix_stack()->i--;
}
void glLoadIdentity() {
matrix_stack_t *stack = get_matrix_stack();
matrix_copy(&identity_matrix, &stack->stack[stack->i]);
}
void glPushMatrix() {
matrix_stack_t *stack = get_matrix_stack();
matrix_copy(&stack->stack[stack->i], &stack->stack[stack->i + 1]);
stack->i++;
}
void glMultMatrixf(const GLfloat *m) {
matrix_t new_matrix;
matrix_stack_t *stack = get_matrix_stack();
matrix_t *current_matrix = &stack->stack[stack->i];
for (int x = 0; x < MATRIX_SIZE; x++) {
for (int y = 0; y < MATRIX_SIZE; y++) {
GLfloat result = 0;
for (int i = 0; i < MATRIX_SIZE; i++) {
result += (current_matrix->data[i][y] * m[(x * MATRIX_SIZE) + i]);
}
new_matrix.data[x][y] = result;
}
}
matrix_copy(&new_matrix, current_matrix);
}
void glScalef(GLfloat x, GLfloat y, GLfloat z) {
GLfloat m[] = {
x, 0, 0, 0,
0, y, 0, 0,
0, 0, z, 0,
0, 0, 0, 1
};
glMultMatrixf(m);
}
void glTranslatef(GLfloat x, GLfloat y, GLfloat z) {
GLfloat m[] = {
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
x, y, z, 1
};
glMultMatrixf(m);
}
void glOrthof(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat near, GLfloat far) {
GLfloat m[] = {
(2.f / (right - left)), 0, 0, 0,
0, (2.f / (top - bottom)), 0, 0,
0, 0, (-2.f / (far - near)), 0,
-((right + left) / (right - left)), -((top + bottom) / (top - bottom)), -((far + near) / (far - near)), 1
};
glMultMatrixf(m);
}
#define DEG2RAD (M_PI / 180.f)
void glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) {
// Normalize
GLfloat length = sqrtf((x * x) + (y * y) + (z * z));
x /= length;
y /= length;
z /= length;
// Values
GLfloat angle_radians = angle * DEG2RAD;
GLfloat c = cosf(angle_radians);
GLfloat s = sinf(angle_radians);
GLfloat x2 = x * x;
GLfloat y2 = y * y;
GLfloat z2 = z * z;
// Multiply
GLfloat m[] = {
x2 * (1.f - c) + c, (x * y) * (1.f - c) + (z * s), (x * z) * (1.f - c) - (y * s), 0,
(x * y) * (1.f - c) - (z * s), y2 * (1.f - c) + c, (y * z) * (1.f - c) + (x * s), 0,
(x * z) * (1.f - c) + (y * s), (y * z) * (1.f - c) - (x * s), z2 * (1.f - c) + c, 0,
0, 0, 0, 1.f
};
glMultMatrixf(m);
}

9
src/matrix.h Normal file
View File

@ -0,0 +1,9 @@
#include <GLES/gl.h>
// Matrix Common
#define MATRIX_SIZE 4
#define MATRIX_DATA_SIZE (sizeof (GLfloat) * MATRIX_SIZE * MATRIX_SIZE)
// OpenGL Matrices Are Column-Major
typedef struct {
GLfloat data[MATRIX_SIZE][MATRIX_SIZE];
} matrix_t;

146
src/passthrough.c Normal file
View File

@ -0,0 +1,146 @@
#include <GLES/gl.h>
#include "passthrough.h"
// Simple v1.1 -> v2.0 Passthrough Functions
GL_FUNC(glLineWidth, void, (GLfloat width));
void glLineWidth(GLfloat width) {
real_glLineWidth()(width);
}
GL_FUNC(glBlendFunc, void, (GLenum sfactor, GLenum dfactor));
void glBlendFunc(GLenum sfactor, GLenum dfactor) {
real_glBlendFunc()(sfactor, dfactor);
}
GL_FUNC(glClear, void, (GLbitfield mask));
void glClear(GLbitfield mask) {
real_glClear()(mask);
}
GL_FUNC(glBufferData, void, (GLenum target, GLsizeiptr size, const void *data, GLenum usage));
void glBufferData(GLenum target, GLsizeiptr size, const void *data, GLenum usage) {
real_glBufferData()(target, size, data, usage);
}
GL_FUNC(glScissor, void, (GLint x, GLint y, GLsizei width, GLsizei height));
void glScissor(GLint x, GLint y, GLsizei width, GLsizei height) {
real_glScissor()(x, y, width, height);
}
GL_FUNC(glTexParameteri, void, (GLenum target, GLenum pname, GLint param));
void glTexParameteri(GLenum target, GLenum pname, GLint param) {
real_glTexParameteri()(target, pname, param);
}
GL_FUNC(glTexImage2D, void, (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels));
void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels) {
real_glTexImage2D()(target, level, internalformat, width, height, border, format, type, pixels);
}
GL_FUNC(glPolygonOffset, void, (GLfloat factor, GLfloat units));
void glPolygonOffset(GLfloat factor, GLfloat units) {
real_glPolygonOffset()(factor, units);
}
GL_FUNC(glDepthRangef, void, (GLclampf near, GLclampf far));
void glDepthRangef(GLclampf near, GLclampf far) {
real_glDepthRangef()(near, far);
}
GL_FUNC(glBindBuffer, void, (GLenum target, GLuint buffer));
void glBindBuffer(GLenum target, GLuint buffer) {
real_glBindBuffer()(target, buffer);
}
GL_FUNC(glDepthFunc, void, (GLenum func));
void glDepthFunc(GLenum func) {
real_glDepthFunc()(func);
}
GL_FUNC(glClearColor, void, (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha));
void glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
real_glClearColor()(red, green, blue, alpha);
}
GL_FUNC(glDepthMask, void, (GLboolean flag));
void glDepthMask(GLboolean flag) {
real_glDepthMask()(flag);
}
GL_FUNC(glHint, void, (GLenum target, GLenum mode));
void glHint(GLenum target, GLenum mode) {
if (target != GL_PERSPECTIVE_CORRECTION_HINT) {
real_glHint()(target, mode);
}
}
GL_FUNC(glDeleteBuffers, void, (GLsizei n, const GLuint *buffers));
void glDeleteBuffers(GLsizei n, const GLuint *buffers) {
real_glDeleteBuffers()(n, buffers);
}
GL_FUNC(glColorMask, void, (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha));
void glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
real_glColorMask()(red, green, blue, alpha);
}
GL_FUNC(glTexSubImage2D, void, (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels));
void glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels) {
real_glTexSubImage2D()(target, level, xoffset, yoffset, width, height, format, type, pixels);
}
GL_FUNC(glGenTextures, void, (GLsizei n, GLuint *textures));
void glGenTextures(GLsizei n, GLuint *textures) {
real_glGenTextures()(n, textures);
}
GL_FUNC(glDeleteTextures, void, (GLsizei n, const GLuint *textures));
void glDeleteTextures(GLsizei n, const GLuint *textures) {
real_glDeleteTextures()(n, textures);
}
GL_FUNC(glBindTexture, void, (GLenum target, GLuint texture));
void glBindTexture(GLenum target, GLuint texture) {
real_glBindTexture()(target, texture);
}
GL_FUNC(glCullFace, void, (GLenum mode));
void glCullFace(GLenum mode) {
real_glCullFace()(mode);
}
GL_FUNC(glViewport, void, (GLint x, GLint y, GLsizei width, GLsizei height));
void glViewport(GLint x, GLint y, GLsizei width, GLsizei height) {
real_glViewport()(x, y, width, height);
}
GL_FUNC(glIsEnabled, GLboolean, (GLenum cap));
GLboolean glIsEnabled(GLenum cap) {
return real_glIsEnabled()(cap);
}
GL_FUNC(glGetIntegerv, void, (GLenum pname, GLint *data));
void glGetIntegerv(GLenum pname, GLint *data) {
real_glGetIntegerv()(pname, data);
}
GL_FUNC(glReadPixels, void, (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *data));
void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *data) {
real_glReadPixels()(x, y, width, height, format, type, data);
}
void glShadeModel(__attribute__((unused)) GLenum mode) {
// Do Nothing
}
GL_FUNC(glGenBuffers, void, (GLsizei n, GLuint *buffers));
void glGenBuffers(GLsizei n, GLuint *buffers) {
real_glGenBuffers()(n, buffers);
}
GL_FUNC(glGetError, GLenum, ());
GLenum glGetError() {
return real_glGetError()();
}
GL_FUNC(glBufferSubData, void, (GLenum target, GLintptr offset, GLsizeiptr size, const void *data));
void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void *data) {
real_glBufferSubData()(target, offset, size, data);
}
GL_FUNC(glGenQueries, void, (GLsizei n, GLuint *ids));
void glGenQueriesARB(GLsizei n, GLuint *ids) {
real_glGenQueries()(n, ids);
}
GL_FUNC(glDeleteQueries, void, (GLsizei n, const GLuint *ids));
void glDeleteQueriesARB(GLsizei n, const GLuint *ids) {
real_glDeleteQueries()(n, ids);
}
GL_FUNC(glBeginQuery, void, (GLenum target, GLuint id));
void glBeginQueryARB(GLenum target, GLuint id) {
real_glBeginQuery()(target, id);
}
GL_FUNC(glEndQuery, void, (GLenum target));
void glEndQueryARB(GLenum target) {
real_glEndQuery()(target);
}
GL_FUNC(glGetQueryObjectuiv, void, (GLuint id, GLenum pname, GLuint *params));
void glGetQueryObjectuivARB(GLuint id, GLenum pname, GLuint *params) {
real_glGetQueryObjectuiv()(id, pname, params);
}
GL_FUNC(glPixelStorei, void, (GLenum pname, GLint param));
void glPixelStorei(GLenum pname, GLint param) {
real_glPixelStorei()(pname, param);
}

23
src/passthrough.h Normal file
View File

@ -0,0 +1,23 @@
#include <SDL.h>
#include "log.h"
// Load GL Function
#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
#define GL_APIENTRY __stdcall
#else
#define GL_APIENTRY
#endif
#define GL_FUNC(name, return_type, args) \
typedef return_type (GL_APIENTRY *real_##name##_t)args; \
\
real_##name##_t real_##name() { \
static real_##name##_t func = NULL; \
if (!func) { \
func = (real_##name##_t) SDL_GL_GetProcAddress(#name); \
if (!func) { \
ERR("Error Resolving GL Symbol: " #name); \
} \
} \
return func; \
}

52
src/shaders/main.fsh Normal file
View File

@ -0,0 +1,52 @@
#version 300 es
precision highp float;
// Result
out vec4 frag_color;
// Texture
uniform bool u_has_texture;
uniform sampler2D u_texture_unit;
// Color
in vec4 v_color;
in vec4 v_texture_pos;
// Highlight Mode
uniform bool u_highlight_mode;
uniform vec4 u_highlight_mode_color;
// Alpha Test
uniform bool u_alpha_test;
// Fog
uniform bool u_fog;
uniform vec4 u_fog_color;
uniform bool u_fog_is_linear;
uniform float u_fog_start;
uniform float u_fog_end;
in vec4 v_fog_eye_position;
// Main
void main(void) {
frag_color = v_color;
// Texture
if (u_has_texture) {
vec4 texture_color = texture(u_texture_unit, v_texture_pos.xy);
if (u_highlight_mode) {
texture_color.rgb = u_highlight_mode_color.rgb;
texture_color.a *= u_highlight_mode_color.a;
frag_color = texture_color;
} else {
frag_color *= texture_color;
}
}
// Fog
if (u_fog) {
float fog_factor;
if (u_fog_is_linear) {
fog_factor = (u_fog_end - length(v_fog_eye_position)) / (u_fog_end - u_fog_start);
} else {
fog_factor = exp(-u_fog_start * length(v_fog_eye_position));
}
fog_factor = clamp(fog_factor, 0.0, 1.0);
frag_color.rgb = mix(frag_color, u_fog_color, 1.0 - fog_factor).rgb;
}
// Alpha Test
if (u_alpha_test && frag_color.a <= 0.1) {
discard;
}
}

48
src/shaders/main.vsh Normal file
View File

@ -0,0 +1,48 @@
#version 300 es
precision highp float;
// Matrices
uniform mat4 u_projection;
uniform mat4 u_model_view;
uniform mat4 u_texture;
// Texture
in vec3 a_vertex_coords;
in vec2 a_texture_coords;
out vec4 v_texture_pos;
// Color
in vec4 a_color;
out vec4 v_color;
// Normal
in vec3 a_normal;
uniform float u_normal_rescale_factor;
// Lighting
uniform bool u_lighting;
uniform vec4 u_lighting_ambient;
uniform bool u_lighting_light_source_0;
uniform vec3 u_lighting_light_source_0_position;
uniform vec4 u_lighting_light_source_0_diffuse;
uniform bool u_lighting_light_source_1;
uniform vec3 u_lighting_light_source_1_position;
uniform vec4 u_lighting_light_source_1_diffuse;
// Fog
out vec4 v_fog_eye_position;
// Main
void main(void) {
v_texture_pos = u_texture * vec4(a_texture_coords.xy, 0.0, 1.0);
gl_Position = u_projection * u_model_view * vec4(a_vertex_coords.xyz, 1.0);
v_color = a_color;
v_fog_eye_position = u_model_view * vec4(a_vertex_coords.xyz, 1.0);
// Lighting
if (u_lighting) {
vec4 transformed_normal = u_model_view * vec4(a_normal, 0.0) * u_normal_rescale_factor;
vec4 total_light = u_lighting_ambient;
if (u_lighting_light_source_0) {
total_light += max(0.0, dot(transformed_normal.xyz, u_lighting_light_source_0_position)) * u_lighting_light_source_0_diffuse;
}
if (u_lighting_light_source_1) {
total_light += max(0.0, dot(transformed_normal.xyz, u_lighting_light_source_1_position)) * u_lighting_light_source_1_diffuse;
}
total_light = clamp(total_light, 0.0, 1.0);
v_color *= total_light;
}
}

336
src/state.c Normal file
View File

@ -0,0 +1,336 @@
#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;
}

81
src/state.h Normal file
View File

@ -0,0 +1,81 @@
#include <GLES/gl.h>
#include "matrix.h"
// Matrix Data
#define MATRIX_STACK_DEPTH 256
typedef struct {
matrix_t stack[MATRIX_STACK_DEPTH];
unsigned int i;
} matrix_stack_t;
// Position
typedef struct {
GLfloat x;
GLfloat y;
GLfloat z;
} position_t;
// Color
typedef struct {
GLfloat red;
GLfloat green;
GLfloat blue;
GLfloat alpha;
} color_t;
// Array Pointer Storage
typedef struct {
GLboolean enabled;
GLint size;
GLenum type;
GLsizei stride;
const void *pointer;
} array_pointer_t;
// Light
typedef struct {
GLboolean enabled;
position_t position;
color_t diffuse;
} light_source_t;
// GL State
typedef struct {
color_t color;
position_t normal;
GLboolean rescale_normal;
struct {
GLenum mode;
matrix_stack_t model_view;
matrix_stack_t projection;
matrix_stack_t texture;
} matrix_stacks;
struct {
array_pointer_t vertex;
array_pointer_t color;
array_pointer_t tex_coord;
array_pointer_t normal;
} array_pointers;
GLboolean alpha_test;
GLboolean texture_2d;
struct {
GLboolean enabled;
GLfixed mode;
color_t color;
GLfloat start;
GLfloat end;
} fog;
struct {
GLboolean enabled;
light_source_t light_sources[2];
color_t ambient;
} lighting;
struct {
GLboolean enabled;
color_t color;
} highlight_mode;
} gl_state_t;
extern gl_state_t gl_state;
void _init_gles_compatibility_layer_state();
void _init_gles_compatibility_matrix_stacks();