Add controller input and a laser-pointer-driven menu quad
build / build (push) Successful in 2m26s

- xr_input.c/h: an OpenXR action set (aim pose, trigger/select click, a
  menu-toggle button) plus ray/quad hit-testing, and a visible
  laser-pointer line drawn from the controller toward the hit point.
- xr_menu.c/h + MenuOverlay.java: a second composition-layer quad,
  toggled by a controller button, showing an off-screen, never-attached
  Android View tree (one "Keyboard" button so far) driven by synthetic
  touch events computed from the laser ray's hit UV.
- Migrate gl4es from a prebuilt binary baked into the Docker build-image
  to a vendored source snapshot (android/gl4es-src/) compiled from
  source at APK build time via CMake add_subdirectory(), patched through
  a new android/gl4es-patches/ (mirrors the existing engine-patches/
  pattern). This was needed to track down and fix a bug hit while
  building the menu: gl4es's fixed-pipeline emulation (fpe.c) was
  unconditionally substituting its own shader onto the menu's draw call
  (fpe_ReleventState() always sets alphafunc to a nonzero sentinel, so
  its fpe_IsEmpty() check could never see the state as empty), making
  the menu quad show the game's own rendering instead of its own
  content. Fixed by routing the menu's blit through a real
  glBlitFramebuffer() call instead of a shader-based draw, which gl4es's
  fpe.c has nothing to intercept - documented in README.md's new
  "Debugging notes" section.
- Renumber android/engine-patches/ to close the gap left by removing an
  unrelated diagnostic-only patch, and strip investigation-journal
  comments and dead diagnostic code (temporary tracing, env-var probes)
  left over from finding the bug above.
- Restructure README.md into numbered sections, document every
  engine/gl4es patch, add Android Studio dev/testing-cycle instructions,
  and generalize Quest-specific wording to any OpenXR headset. Update
  NOTICE.txt to match (gl4es is now vendored/patched source, not a
  prebuilt binary; add the OpenXR-SDK loader).
This commit is contained in:
ml
2026-08-02 06:27:49 +02:00
parent 2300d081c3
commit d2dc58391b
310 changed files with 141458 additions and 226 deletions
+255
View File
@@ -0,0 +1,255 @@
include_directories(util)
#file(GLOB_RECURSE GL_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/gl/*.c)
SET(GL_SRC
${CMAKE_CURRENT_SOURCE_DIR}/gl/arbconverter.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/arbgenerator.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/arbhelper.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/arbparser.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/array.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/blit.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/blend.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/buffers.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/build_info.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/debug.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/decompress.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/depth.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/directstate.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/drawing.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/enable.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/envvars.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/eval.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/face.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/fog.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/fpe.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/fpe_cache.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/fpe_shader.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/framebuffers.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/gl_lookup.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/getter.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/gl4es.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/glstate.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/hint.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/init.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/light.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/line.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/list.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/listdraw.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/listrl.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/loader.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/logs.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/matrix.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/matvec.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/oldprogram.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/pixel.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/planes.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/pointsprite.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/preproc.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/program.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/queries.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/raster.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/render.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/samplers.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/shader.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/shaderconv.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/shader_hacks.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/stack.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/stencil.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/string_utils.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/stubs.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/texenv.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/texgen.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/texture.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/texture_compressed.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/texture_params.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/texture_read.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/texture_3d.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/uniform.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/vertexattrib.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/wrap/gl4eswraps.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/wrap/gles.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/wrap/glstub.c
${CMAKE_CURRENT_SOURCE_DIR}/gl/math/matheval.c
)
SET(GL_H
${CMAKE_CURRENT_SOURCE_DIR}/../version.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/arbconverter.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/arbgenerator.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/arbhelper.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/arbparser.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/array.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/blend.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/blit.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/buffers.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/build_info.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/const.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/debug.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/decompress.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/depth.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/directstate.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/envvars.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/eval.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/face.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/fog.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/fpe.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/fpe_shader.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/framebuffers.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/gl_lookup.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/gles.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/gl4es.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/glstate.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/hint.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/init.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/light.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/line.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/list.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/loader.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/logs.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/matrix.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/matvec.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/oldprogram.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/pixel.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/planes.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/pointsprite.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/preproc.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/program.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/queries.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/raster.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/render.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/samplers.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/shader.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/shaderconv.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/shader_hacks.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/stack.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/state.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/stencil.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/stb_dxt_104.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/string_utils.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/texenv.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/texgen.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/uniform.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/texture.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/vertexattrib.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/math/eval.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/wrap/gl4es.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/wrap/gles.h
${CMAKE_CURRENT_SOURCE_DIR}/gl/wrap/stub.h
)
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux" AND NOT NO_LOADER)
include_directories(glx)
# aux_source_directory(glx GLX_SOURCES)
# list(APPEND GL_SOURCES ${GLX_SOURCES})
list(APPEND GL_SRC
${CMAKE_CURRENT_SOURCE_DIR}/glx/hardext.c
${CMAKE_CURRENT_SOURCE_DIR}/glx/gbm.c
${CMAKE_CURRENT_SOURCE_DIR}/glx/glx.c
${CMAKE_CURRENT_SOURCE_DIR}/glx/glx_stubs.c
${CMAKE_CURRENT_SOURCE_DIR}/glx/lookup.c
${CMAKE_CURRENT_SOURCE_DIR}/glx/rpi.c
${CMAKE_CURRENT_SOURCE_DIR}/glx/streaming.c
${CMAKE_CURRENT_SOURCE_DIR}/glx/utils.c
)
list(APPEND GL_H
${CMAKE_CURRENT_SOURCE_DIR}/glx/glx_gbm.h
${CMAKE_CURRENT_SOURCE_DIR}/glx/gbmfunc.h
${CMAKE_CURRENT_SOURCE_DIR}/glx/drmfunc.h
${CMAKE_CURRENT_SOURCE_DIR}/glx/glx.h
${CMAKE_CURRENT_SOURCE_DIR}/glx/hardext.h
${CMAKE_CURRENT_SOURCE_DIR}/glx/rpi.h
${CMAKE_CURRENT_SOURCE_DIR}/glx/streaming.h
${CMAKE_CURRENT_SOURCE_DIR}/glx/utils.h
)
else()
include_directories(glx)
list(APPEND GL_SRC
${CMAKE_CURRENT_SOURCE_DIR}/glx/hardext.c
)
message(STATUS "Not on Linux: building without GLX support.")
endif()
if(AMIGAOS4)
include_directories(agl)
list(APPEND GL_SRC
${CMAKE_CURRENT_SOURCE_DIR}/glx/gbm.c
${CMAKE_CURRENT_SOURCE_DIR}/glx/glx.c
${CMAKE_CURRENT_SOURCE_DIR}/agl/lookup.c
${CMAKE_CURRENT_SOURCE_DIR}/agl/amigaos.c
${CMAKE_CURRENT_SOURCE_DIR}/agl/agl.c
)
list(APPEND GL_H
${CMAKE_CURRENT_SOURCE_DIR}/glx/hardext.h
${CMAKE_CURRENT_SOURCE_DIR}/glx/glx.h
${CMAKE_CURRENT_SOURCE_DIR}/agl/amigaos.h
${CMAKE_CURRENT_SOURCE_DIR}/agl/agl.h
)
endif()
set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/gl/build_info.c PROPERTIES OBJECT_DEPENDS "${GL_SRC};${GL_H}")
if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
if(STATICLIB)
add_library(OPENGL32 STATIC ${GL_SRC})
else()
add_library(OPENGL32 SHARED ${GL_SRC})
# some ES simulators used opengl32.dll :(
set_target_properties(OPENGL32 PROPERTIES OUTPUT_NAME "GL32")
set_target_properties(OPENGL32 PROPERTIES IMPORT_PREFIX "OPEN")
endif()
elseif(STATICLIB)
add_library(GL STATIC ${GL_SRC})
else()
add_library(GL SHARED ${GL_SRC})
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
if(NOX11)
if(AMIGAOS4)
target_link_libraries(GL m)
else()
target_link_libraries(GL m dl)
endif()
else()
target_link_libraries(GL X11 m dl)
endif()
endif()
if(USE_CLOCK)
target_link_libraries(GL rt)
endif()
if(USE_ANDROID_LOG)
target_link_libraries(GL ${log-lib})
endif()
if(CMAKE_SHARED_LIBRARY_SUFFIX MATCHES ".so")
set_target_properties(GL PROPERTIES SUFFIX ".so.1")
endif()
install(TARGETS GL
LIBRARY
DESTINATION "/usr/lib/gl4es/"
)
install(FILES "../include/gl4esinit.h" "../include/gl4eshint.h"
DESTINATION "/usr/include/gl4es/"
)
endif()
SET(EGL_SRC
${CMAKE_CURRENT_SOURCE_DIR}/egl/egl.c
${CMAKE_CURRENT_SOURCE_DIR}/egl/lookup.c
)
SET(EGL_H
${CMAKE_CURRENT_SOURCE_DIR}/egl/egl.h
)
if(EGL_WRAPPER)
add_library(EGL SHARED ${EGL_SRC})
target_link_libraries(EGL GL dl)
if(USE_ANDROID_LOG)
target_link_libraries(EGL ${log-lib})
endif()
if(CMAKE_SHARED_LIBRARY_SUFFIX MATCHES ".so")
set_target_properties(EGL PROPERTIES SUFFIX ".so.1")
endif()
endif()
+169
View File
@@ -0,0 +1,169 @@
#include "agl.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
//#include <stdarg.h>
#undef __USE_INLINE__
#include <proto/exec.h>
#include <interfaces/ogles2.h>
extern struct OGLES2IFace *IOGLES2;
void* NewGLState(void* shared_glstate, int es2only);
void DeleteGLState(void* oldstate);
void ActivateGLState(void* new_glstate);
void GetHardwareExtensions(int notest);
typedef struct _agl_ctx_glstate {
void* context;
void* glstate;
} agl_ctx_glstate;
static agl_ctx_glstate *agl_context = NULL;
static int agl_context_len = 0;
static int agl_context_cap = 0;
static void* agl_current_ctx = NULL;
// find (or add if not found) a context in the list, and activate glstate...
void agl_context_find(void* ctx) {
if(!ctx)
return;
if(!agl_context) {
agl_context_cap = 10;
agl_context = (agl_ctx_glstate*)malloc(sizeof(agl_ctx_glstate)*agl_context_cap);
memset(agl_context, 0, sizeof(agl_ctx_glstate)*agl_context_cap);
}
int idx = 0;
while (idx<agl_context_len && agl_context[idx].context!=ctx) idx++;
if(idx==agl_context_len) {
agl_context = (agl_ctx_glstate*)realloc(agl_context, sizeof(agl_ctx_glstate)*(agl_context_cap+10));
memset(agl_context+agl_context_cap, 0, sizeof(agl_ctx_glstate)*10);
agl_context_cap+=10;
}
agl_context[idx].context = ctx;
if(idx==agl_context_len) ++agl_context_len;
// create glstate if needed
if(!agl_context[idx].glstate) {
agl_context[idx].glstate = NewGLState(NULL, 0);
// Hardware testing
GetHardwareExtensions(0);
}
ActivateGLState(agl_context[idx].glstate);
}
// remove a context (delete array if size is null)
void agl_context_remove(void* ctx) {
if (!ctx)
return;
if(!agl_context)
return; // empty list?
int idx = 0;
while (idx<agl_context_len && agl_context[idx].context!=ctx) idx++;
if(idx==agl_context_len)
return; // not found...
if(agl_context[idx].glstate) {
DeleteGLState(agl_context[idx].glstate);
agl_context[idx].glstate = NULL;
}
agl_context[idx].context = 0;
// shrink if possible
while(agl_context_len && !agl_context[agl_context_len-1].context) --agl_context_len;
if(!agl_context_len) {
agl_context_cap = 0;
free(agl_context);
agl_context = NULL;
}
}
// AGL functions
void* aglCreateContext(ULONG * errcode, struct TagItem * tags) {
if(IOGLES2)
return IOGLES2->aglCreateContext2(errcode, tags);
return NULL;
}
void* aglCreateContext2(ULONG * errcode, struct TagItem * tags) {
return aglCreateContext(errcode, tags);
}
/*
void* VARARGS68K aglCreateContextTags(ULONG * errcode, ...) {
void* ret = NULL;
if(IOGLES2) {
struct TagItem tags[100];
VA_LIST args;
VA_START(args, errcode);
int i = 0;
do {
struct Tagitem tag = VA_ARG(args, struct TagItem);
tags[i++] = tag;
} while (tag!=TAG_DONE);
VA_END(args);
ret = IOGLES2->aglCreateContext2(errcode, tags);
}
return ret;
}
*/
void aglDestroyContext(void* context) {
if(IOGLES2) {
//bind the context before deleting stuffs.
if(context!=agl_current_ctx)
IOGLES2->aglMakeCurrent(context);
agl_context_remove(context); // remove the associated glstate
if(context!=agl_current_ctx) // rebind old context if needed
IOGLES2->aglMakeCurrent(agl_current_ctx);
IOGLES2->aglDestroyContext(context);
}
}
void aglMakeCurrent(void* context) {
agl_current_ctx = context;
if(IOGLES2) {
IOGLES2->aglMakeCurrent(context);
if (context)
agl_context_find(context); // activate (and create if needed) the correct glstate
}
}
void aglSetParams2(struct TagItem * tags) {
if(IOGLES2) {
return IOGLES2->aglSetParams2(tags);
}
}
void amiga_pre_swap();
void amiga_post_swap();
void aglSwapBuffers() {
amiga_pre_swap();
// Swap the Buffers!
if(IOGLES2) {
IOGLES2->aglSwapBuffers();
}
amiga_post_swap();
}
// what is the use of this function?
void aglSetBitmap(struct BitMap *bitmap) {
if(IOGLES2) {
IOGLES2->aglSetBitmap(bitmap);
}
}
//void* aglGetProcAddress(const char* name); //-> declared in agl/lookup.c
#ifdef GL4ES_COMPILE_FOR_USE_IN_SHARED_LIB
void agl_reset_internals() {
if(agl_context) {
free(agl_context);
agl_context=NULL;
}
agl_context_len=0;
agl_context_cap=0;
agl_current_ctx=NULL;
}
#endif
+34
View File
@@ -0,0 +1,34 @@
#ifndef _AGL_H_
#define _AGL_H_
#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif
#ifndef EXEC_EXEC_H
#include <exec/exec.h>
#endif
#ifndef EXEC_INTERFACES_H
#include <exec/interfaces.h>
#endif
#ifndef GRAPHICS_GFX_H
#include <graphics/gfx.h>
#endif
#ifndef OGLES2_OGLES2_DEFS_H
// it would be better to have an include with only the CreateContextTags enum difed, to avoid conflict
// of other typedef with full OpenGL header file...
//#include <ogles2/ogles2_defs.h>
#endif
void* aglCreateContext(ULONG * errcode, struct TagItem * tags);
void* aglCreateContext2(ULONG * errcode, struct TagItem * tags);
//void* aglCreateContextTags(ULONG * errcode, ...);
void aglDestroyContext(void* context);
void aglMakeCurrent(void* context);
void aglSwapBuffers();
void aglSetParams2(struct TagItem * tags);
void aglSetBitmap(struct BitMap *bitmap);
void* aglGetProcAddress(const char* name);
#endif //_AGL_H_
+814
View File
@@ -0,0 +1,814 @@
#include "amigaos.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <proto/exec.h>
// make sure we don't use inline version here
#undef __USE_INLINE__
#include <proto/ogles2.h>
#include <proto/Warp3DNova.h>
#include "../glx/hardext.h"
#include "../gl/logs.h"
#define MIN_W3DNOVA_LIB_VERSION 1
#define MIN_W3DNOVA_LIB_REVISION 62
#define MIN_OGLES2_LIB_VERSION 1
#define MIN_OGLES2_LIB_REVISION 22
struct Library *LOGLES2 = NULL;
struct OGLES2IFace *IOGLES2 = NULL;
struct so_bases
{
struct ExecIFace *IExec;
};
struct so_bases so_exec;
// Open OGLES2 library and interface
void os4OpenLib(void** lib)
{
so_exec.IExec = (struct ExecIFace *)(*(struct ExecBase **)4)->MainInterface;
if(!IOGLES2) {
// first check version for Warp3DNova lib
struct Library *Warp3DNovaBase = NULL;
Warp3DNovaBase = so_exec.IExec->OpenLibrary("Warp3DNova.library", MIN_W3DNOVA_LIB_VERSION);
if(!Warp3DNovaBase) {
SHUT_LOGE("Error, cannot open Warp3DNova.library!\n");
return;
}
SHUT_LOGD("Using Warp3DNova.library v%d revision %d\n", Warp3DNovaBase->lib_Version, Warp3DNovaBase->lib_Revision);
if (!(Warp3DNovaBase->lib_Version > MIN_W3DNOVA_LIB_VERSION || (Warp3DNovaBase->lib_Version == MIN_W3DNOVA_LIB_VERSION && Warp3DNovaBase->lib_Revision >= MIN_W3DNOVA_LIB_REVISION))) {
SHUT_LOGE("Warning, your Warp3DNovaBase.library is too old, minimum is v%d.%d, please update!\n", MIN_W3DNOVA_LIB_VERSION,MIN_W3DNOVA_LIB_REVISION);
}
//close warp3dnova.library, we open it just for version check
so_exec.IExec->CloseLibrary(Warp3DNovaBase);
Warp3DNovaBase = NULL;
LOGLES2 = so_exec.IExec->OpenLibrary("ogles2.library", MIN_OGLES2_LIB_VERSION);
if(!LOGLES2) {
SHUT_LOGE("Error, cannot open ogles2 Library!\n");
return;
}
SHUT_LOGD("Using OGLES2.library v%d revision %d\n", LOGLES2->lib_Version, LOGLES2->lib_Revision);
if (!(LOGLES2->lib_Version > MIN_OGLES2_LIB_VERSION || (LOGLES2->lib_Version == MIN_OGLES2_LIB_VERSION && LOGLES2->lib_Revision >= MIN_OGLES2_LIB_REVISION))) {
SHUT_LOGE("Warning, your OGLES2.library is too old, minimum is v%d.%d, please update!\n", MIN_OGLES2_LIB_VERSION,MIN_OGLES2_LIB_REVISION);
}
IOGLES2 = (struct OGLES2IFace *)so_exec.IExec->GetInterface(LOGLES2, "main", 1, NULL);
if(!IOGLES2) {
SHUT_LOGE("Error, cannot open ogles2 Interface!\n");
so_exec.IExec->CloseLibrary(LOGLES2);
LOGLES2 = NULL;
return;
}
if (LOGLES2->lib_Version > 2 || (LOGLES2->lib_Version == 2 && LOGLES2->lib_Revision >= 9)) {
hardext.prgbin_n = 1;
}
}
*lib = LOGLES2;
// small debug message, always helpfull at beggining
SHUT_LOGD("OGLES2 Library and Interface open successfuly\n");
}
// Close OGLES2 lib and interface
void os4CloseLib()
{
if(IOGLES2) {
so_exec.IExec->DropInterface((struct Interface*)IOGLES2);
IOGLES2 = NULL;
}
if(LOGLES2) {
so_exec.IExec->CloseLibrary(LOGLES2);
LOGLES2 = NULL;
}
SHUT_LOGD("OGLES2 Library and Interface closed\n");
}
static void AmiglActiveTexture (GLenum texture) {
return IOGLES2->glActiveTexture(texture);
}
static void AmiglAttachShader (GLuint program, GLuint shader) {
return IOGLES2->glAttachShader(program, shader);
}
static void AmiglBindAttribLocation (GLuint program, GLuint index, const GLchar *name) {
return IOGLES2->glBindAttribLocation(program, index, name);
}
static void AmiglBindBuffer (GLenum target, GLuint buffer) {
return IOGLES2->glBindBuffer(target, buffer);
}
static void AmiglBindFramebuffer (GLenum target, GLuint framebuffer) {
return IOGLES2->glBindFramebuffer(target, framebuffer);
}
static void AmiglBindRenderbuffer (GLenum target, GLuint renderbuffer) {
return IOGLES2->glBindRenderbuffer(target, renderbuffer);
}
static void AmiglBindTexture (GLenum target, GLuint texture) {
return IOGLES2->glBindTexture(target, texture);
}
static void AmiglBlendColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
return IOGLES2->glBlendColor(red, green, blue, alpha);
}
static void AmiglBlendEquation (GLenum mode) {
return IOGLES2->glBlendEquation(mode);
}
static void AmiglBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha) {
return IOGLES2->glBlendEquationSeparate(modeRGB, modeAlpha);
}
static void AmiglBlendFunc (GLenum sfactor, GLenum dfactor) {
return IOGLES2->glBlendFunc(sfactor, dfactor);
}
static void AmiglBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha) {
return IOGLES2->glBlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha);
}
static void AmiglBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage) {
return IOGLES2->glBufferData(target, size, data, usage);
}
static void AmiglBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data) {
return IOGLES2->glBufferSubData(target, offset, size, data);
}
static GLenum AmiglCheckFramebufferStatus (GLenum target) {
return IOGLES2->glCheckFramebufferStatus(target);
}
static void AmiglClear (GLbitfield mask) {
return IOGLES2->glClear(mask);
}
static void AmiglClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
return IOGLES2->glClearColor(red, green, blue, alpha);
}
static void AmiglClearDepthf (GLfloat d) {
return IOGLES2->glClearDepthf(d);
}
static void AmiglClearStencil (GLint s) {
return IOGLES2->glClearStencil(s);
}
static void AmiglColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) {
return IOGLES2->glColorMask(red, green, blue, alpha);
}
static void AmiglCompileShader (GLuint shader) {
return IOGLES2->glCompileShader(shader);
}
static void AmiglCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data) {
return IOGLES2->glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data);
}
static void AmiglCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data) {
return IOGLES2->glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data);
}
static void AmiglCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) {
return IOGLES2->glCopyTexImage2D(target, level, internalformat, x, y, width, height, border);
}
static void AmiglCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) {
return IOGLES2->glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
}
static GLuint AmiglCreateProgram (void) {
return IOGLES2->glCreateProgram();
}
static GLuint AmiglCreateShader (GLenum type) {
return IOGLES2->glCreateShader(type);
}
static void AmiglCullFace (GLenum mode) {
return IOGLES2->glCullFace(mode);
}
static void AmiglDeleteBuffers (GLsizei n, const GLuint *buffers) {
return IOGLES2->glDeleteBuffers(n, buffers);
}
static void AmiglDeleteFramebuffers (GLsizei n, const GLuint *framebuffers) {
return IOGLES2->glDeleteFramebuffers(n, framebuffers);
}
static void AmiglDeleteProgram (GLuint program) {
return IOGLES2->glDeleteProgram(program);
}
static void AmiglDeleteRenderbuffers (GLsizei n, const GLuint *renderbuffers) {
return IOGLES2->glDeleteRenderbuffers(n, renderbuffers);
}
static void AmiglDeleteShader (GLuint shader) {
return IOGLES2->glDeleteShader(shader);
}
static void AmiglDeleteTextures (GLsizei n, const GLuint *textures) {
return IOGLES2->glDeleteTextures(n, textures);
}
static void AmiglDepthFunc (GLenum func) {
return IOGLES2->glDepthFunc(func);
}
static void AmiglDepthMask (GLboolean flag) {
return IOGLES2->glDepthMask(flag);
}
static void AmiglDepthRangef (GLfloat n, GLfloat f) {
return IOGLES2->glDepthRangef(n, f);
}
static void AmiglDetachShader (GLuint program, GLuint shader) {
return IOGLES2->glDetachShader(program, shader);
}
static void AmiglDisable (GLenum cap) {
return IOGLES2->glDisable(cap);
}
static void AmiglDisableVertexAttribArray (GLuint index) {
return IOGLES2->glDisableVertexAttribArray(index);
}
static void AmiglDrawArrays (GLenum mode, GLint first, GLsizei count) {
return IOGLES2->glDrawArrays(mode, first, count);
}
static void AmiglDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices) {
return IOGLES2->glDrawElements(mode, count, type, indices);
}
static void AmiglEnable (GLenum cap) {
return IOGLES2->glEnable(cap);
}
static void AmiglEnableVertexAttribArray (GLuint index) {
return IOGLES2->glEnableVertexAttribArray(index);
}
static void AmiglFinish (void) {
return IOGLES2->glFinish();
}
static void AmiglFlush (void) {
return IOGLES2->glFlush();
}
static void AmiglFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) {
return IOGLES2->glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
}
static void AmiglFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) {
return IOGLES2->glFramebufferTexture2D(target, attachment, textarget, texture, level);
}
static void AmiglFrontFace (GLenum mode) {
return IOGLES2->glFrontFace(mode);
}
static void AmiglGenBuffers (GLsizei n, GLuint *buffers) {
return IOGLES2->glGenBuffers(n, buffers);
}
static void AmiglGenerateMipmap (GLenum target) {
return IOGLES2->glGenerateMipmap(target);
}
static void AmiglGenFramebuffers (GLsizei n, GLuint *framebuffers) {
return IOGLES2->glGenFramebuffers(n, framebuffers);
}
static void AmiglGenRenderbuffers (GLsizei n, GLuint *renderbuffers) {
return IOGLES2->glGenRenderbuffers(n, renderbuffers);
}
static void AmiglGenTextures (GLsizei n, GLuint *textures) {
return IOGLES2->glGenTextures(n, textures);
}
static void AmiglGetActiveAttrib (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) {
return IOGLES2->glGetActiveAttrib(program, index, bufSize, length, size, type, name);
}
static void AmiglGetActiveUniform (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) {
return IOGLES2->glGetActiveUniform(program, index, bufSize, length, size, type, name);
}
static void AmiglGetAttachedShaders (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders) {
return IOGLES2->glGetAttachedShaders(program, maxCount, count, shaders);
}
static GLint AmiglGetAttribLocation (GLuint program, const GLchar *name) {
return IOGLES2->glGetAttribLocation(program, name);
}
static void AmiglGetBooleanv (GLenum pname, GLboolean *data) {
return IOGLES2->glGetBooleanv(pname, data);
}
static void AmiglGetBufferParameteriv (GLenum target, GLenum pname, GLint *params) {
return IOGLES2->glGetBufferParameteriv(target, pname, params);
}
static GLenum AmiglGetError (void) {
return IOGLES2->glGetError();
}
static void AmiglGetFloatv (GLenum pname, GLfloat *data) {
return IOGLES2->glGetFloatv(pname, data);
}
static void AmiglGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint *params) {
return IOGLES2->glGetFramebufferAttachmentParameteriv(target, attachment, pname, params);
}
static void AmiglGetIntegerv (GLenum pname, GLint *data) {
return IOGLES2->glGetIntegerv(pname, data);
}
static void AmiglGetProgramiv (GLuint program, GLenum pname, GLint *params) {
return IOGLES2->glGetProgramiv(program, pname, params);
}
static void AmiglGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog) {
return IOGLES2->glGetProgramInfoLog(program, bufSize, length, infoLog);
}
static void AmiglGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint *params) {
return IOGLES2->glGetRenderbufferParameteriv(target, pname, params);
}
static void AmiglGetShaderiv (GLuint shader, GLenum pname, GLint *params) {
return IOGLES2->glGetShaderiv(shader, pname, params);
}
static void AmiglGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog) {
return IOGLES2->glGetShaderInfoLog(shader, bufSize, length, infoLog);
}
static void AmiglGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision) {
return IOGLES2->glGetShaderPrecisionFormat(shadertype, precisiontype, range, precision);
}
static void AmiglGetShaderSource (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source) {
return IOGLES2->glGetShaderSource(shader, bufSize, length, source);
}
static const GLubyte *AmiglGetString (GLenum name) {
return IOGLES2->glGetString(name);
}
static void AmiglGetTexParameterfv (GLenum target, GLenum pname, GLfloat *params) {
return IOGLES2->glGetTexParameterfv(target, pname, params);
}
static void AmiglGetTexParameteriv (GLenum target, GLenum pname, GLint *params) {
return IOGLES2->glGetTexParameteriv(target, pname, params);
}
static void AmiglGetUniformfv (GLuint program, GLint location, GLfloat *params) {
return IOGLES2->glGetUniformfv(program, location, params);
}
static void AmiglGetUniformiv (GLuint program, GLint location, GLint *params) {
return IOGLES2->glGetUniformiv(program, location, params);
}
static GLint AmiglGetUniformLocation (GLuint program, const GLchar *name) {
return IOGLES2->glGetUniformLocation(program, name);
}
static void AmiglGetVertexAttribfv (GLuint index, GLenum pname, GLfloat *params) {
return IOGLES2->glGetVertexAttribfv(index, pname, params);
}
static void AmiglGetVertexAttribiv (GLuint index, GLenum pname, GLint *params) {
return IOGLES2->glGetVertexAttribiv(index, pname, params);
}
static void AmiglGetVertexAttribPointerv (GLuint index, GLenum pname, void **pointer) {
return IOGLES2->glGetVertexAttribPointerv(index, pname, pointer);
}
static void AmiglHint (GLenum target, GLenum mode) {
return IOGLES2->glHint(target, mode);
}
static GLboolean AmiglIsBuffer (GLuint buffer) {
return IOGLES2->glIsBuffer(buffer);
}
static GLboolean AmiglIsEnabled (GLenum cap) {
return IOGLES2->glIsEnabled(cap);
}
static GLboolean AmiglIsFramebuffer (GLuint framebuffer) {
return IOGLES2->glIsFramebuffer(framebuffer);
}
static GLboolean AmiglIsProgram (GLuint program) {
return IOGLES2->glIsProgram(program);
}
static GLboolean AmiglIsRenderbuffer (GLuint renderbuffer) {
return IOGLES2->glIsRenderbuffer(renderbuffer);
}
static GLboolean AmiglIsShader (GLuint shader) {
return IOGLES2->glIsShader(shader);
}
static GLboolean AmiglIsTexture (GLuint texture) {
return IOGLES2->glIsTexture(texture);
}
static void AmiglLineWidth (GLfloat width) {
return IOGLES2->glLineWidth(width);
}
static void AmiglLinkProgram (GLuint program) {
return IOGLES2->glLinkProgram(program);
}
static void AmiglPixelStorei (GLenum pname, GLint param) {
return IOGLES2->glPixelStorei(pname, param);
}
static void AmiglPolygonOffset (GLfloat factor, GLfloat units) {
return IOGLES2->glPolygonOffset(factor, units);
}
static void AmiglReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels) {
return IOGLES2->glReadPixels(x, y, width, height, format, type, pixels);
}
static void AmiglReleaseShaderCompiler (void) {
return IOGLES2->glReleaseShaderCompiler();
}
static void AmiglRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
return IOGLES2->glRenderbufferStorage(target, internalformat, width, height);
}
static void AmiglSampleCoverage (GLfloat value, GLboolean invert) {
return IOGLES2->glSampleCoverage(value, invert);
}
static void AmiglScissor (GLint x, GLint y, GLsizei width, GLsizei height) {
return IOGLES2->glScissor(x, y, width, height);
}
static void AmiglShaderBinary (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length) {
return IOGLES2->glShaderBinary(count, shaders, binaryformat, binary, length);
}
static void AmiglShaderSource (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length) {
return IOGLES2->glShaderSource(shader, count, string, length);
}
static void AmiglStencilFunc (GLenum func, GLint ref, GLuint mask) {
return IOGLES2->glStencilFunc(func, ref, mask);
}
static void AmiglStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask) {
return IOGLES2->glStencilFuncSeparate(face, func, ref, mask);
}
static void AmiglStencilMask (GLuint mask) {
return IOGLES2->glStencilMask(mask);
}
static void AmiglStencilMaskSeparate (GLenum face, GLuint mask) {
return IOGLES2->glStencilMaskSeparate(face, mask);
}
static void AmiglStencilOp (GLenum fail, GLenum zfail, GLenum zpass) {
return IOGLES2->glStencilOp(fail, zfail, zpass);
}
static void AmiglStencilOpSeparate (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass) {
return IOGLES2->glStencilOpSeparate(face, sfail, dpfail, dppass);
}
static void AmiglTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels) {
return IOGLES2->glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels);
}
static void AmiglTexParameterf (GLenum target, GLenum pname, GLfloat param) {
return IOGLES2->glTexParameterf(target, pname, param);
}
static void AmiglTexParameterfv (GLenum target, GLenum pname, const GLfloat *params) {
return IOGLES2->glTexParameterfv(target, pname, params);
}
static void AmiglTexParameteri (GLenum target, GLenum pname, GLint param) {
return IOGLES2->glTexParameteri(target, pname, param);
}
static void AmiglTexParameteriv (GLenum target, GLenum pname, const GLint *params) {
return IOGLES2->glTexParameteriv(target, pname, params);
}
static void AmiglTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels) {
return IOGLES2->glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
}
static void AmiglUniform1f (GLint location, GLfloat v0) {
return IOGLES2->glUniform1f(location, v0);
}
static void AmiglUniform1fv (GLint location, GLsizei count, const GLfloat *value) {
return IOGLES2->glUniform1fv(location, count, value);
}
static void AmiglUniform1i (GLint location, GLint v0) {
return IOGLES2->glUniform1i(location, v0);
}
static void AmiglUniform1iv (GLint location, GLsizei count, const GLint *value) {
return IOGLES2->glUniform1iv(location, count, value);
}
static void AmiglUniform2f (GLint location, GLfloat v0, GLfloat v1) {
return IOGLES2->glUniform2f(location, v0, v1);
}
static void AmiglUniform2fv (GLint location, GLsizei count, const GLfloat *value) {
return IOGLES2->glUniform2fv(location, count, value);
}
static void AmiglUniform2i (GLint location, GLint v0, GLint v1) {
return IOGLES2->glUniform2i(location, v0, v1);
}
static void AmiglUniform2iv (GLint location, GLsizei count, const GLint *value) {
return IOGLES2->glUniform2iv(location, count, value);
}
static void AmiglUniform3f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2) {
return IOGLES2->glUniform3f(location, v0, v1, v2);
}
static void AmiglUniform3fv (GLint location, GLsizei count, const GLfloat *value) {
return IOGLES2->glUniform3fv(location, count, value);
}
static void AmiglUniform3i (GLint location, GLint v0, GLint v1, GLint v2) {
return IOGLES2->glUniform3i(location, v0, v1, v2);
}
static void AmiglUniform3iv (GLint location, GLsizei count, const GLint *value) {
return IOGLES2->glUniform3iv(location, count, value);
}
static void AmiglUniform4f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
return IOGLES2->glUniform4f(location, v0, v1, v2, v3);
}
static void AmiglUniform4fv (GLint location, GLsizei count, const GLfloat *value) {
return IOGLES2->glUniform4fv(location, count, value);
}
static void AmiglUniform4i (GLint location, GLint v0, GLint v1, GLint v2, GLint v3) {
return IOGLES2->glUniform4i(location, v0, v1, v2, v3);
}
static void AmiglUniform4iv (GLint location, GLsizei count, const GLint *value) {
return IOGLES2->glUniform4iv(location, count, value);
}
static void AmiglUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
return IOGLES2->glUniformMatrix2fv(location, count, transpose, value);
}
static void AmiglUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
return IOGLES2->glUniformMatrix3fv(location, count, transpose, value);
}
static void AmiglUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) {
return IOGLES2->glUniformMatrix4fv(location, count, transpose, value);
}
static void AmiglUseProgram (GLuint program) {
return IOGLES2->glUseProgram(program);
}
static void AmiglValidateProgram (GLuint program) {
return IOGLES2->glValidateProgram(program);
}
static void AmiglVertexAttrib1f (GLuint index, GLfloat x) {
return IOGLES2->glVertexAttrib1f(index, x);
}
static void AmiglVertexAttrib1fv (GLuint index, const GLfloat *v) {
return IOGLES2->glVertexAttrib1fv(index, v);
}
static void AmiglVertexAttrib2f (GLuint index, GLfloat x, GLfloat y) {
return IOGLES2->glVertexAttrib2f(index, x, y);
}
static void AmiglVertexAttrib2fv (GLuint index, const GLfloat *v) {
return IOGLES2->glVertexAttrib2fv(index, v);
}
static void AmiglVertexAttrib3f (GLuint index, GLfloat x, GLfloat y, GLfloat z) {
return IOGLES2->glVertexAttrib3f(index, x, y, z);
}
static void AmiglVertexAttrib3fv (GLuint index, const GLfloat *v) {
return IOGLES2->glVertexAttrib3fv(index, v);
}
static void AmiglVertexAttrib4f (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
return IOGLES2->glVertexAttrib4f(index, x, y, z, w);
}
static void AmiglVertexAttrib4fv (GLuint index, const GLfloat *v) {
return IOGLES2->glVertexAttrib4fv(index, v);
}
static void AmiglVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer) {
return IOGLES2->glVertexAttribPointer(index, size, type, normalized, stride, pointer);
}
static void AmiglViewport (GLint x, GLint y, GLsizei width, GLsizei height) {
return IOGLES2->glViewport(x, y, width, height);
}
// Using glXXX name, return the function pointer of that function in ogles2 library
#define MAP(func_name, func) \
if (strcmp(name, func_name) == 0) return (void *)Ami##func;
#define EX(func_name) MAP(#func_name, func_name)
void* os4GetProcAddress(const char* name)
{
if(!IOGLES2)
return NULL;
// All GL functions from OGLES2 drivers
EX(glActiveTexture)
EX(glAttachShader)
EX(glBindAttribLocation)
EX(glBindBuffer)
EX(glBindFramebuffer)
EX(glBindRenderbuffer)
EX(glBindTexture)
EX(glBlendColor)
EX(glBlendEquation)
EX(glBlendEquationSeparate)
EX(glBlendFunc)
EX(glBlendFuncSeparate)
EX(glBufferData)
EX(glBufferSubData)
EX(glCheckFramebufferStatus)
EX(glClear)
EX(glClearColor)
EX(glClearDepthf)
EX(glClearStencil)
EX(glColorMask)
EX(glCompileShader)
EX(glCompressedTexImage2D)
EX(glCompressedTexSubImage2D)
EX(glCopyTexImage2D)
EX(glCopyTexSubImage2D)
EX(glCreateProgram)
EX(glCreateShader)
EX(glCullFace)
EX(glDeleteBuffers)
EX(glDeleteFramebuffers)
EX(glDeleteProgram)
EX(glDeleteRenderbuffers)
EX(glDeleteShader)
EX(glDeleteTextures)
EX(glDepthFunc)
EX(glDepthMask)
EX(glDepthRangef)
EX(glDetachShader)
EX(glDisable)
EX(glDisableVertexAttribArray)
EX(glDrawArrays)
EX(glDrawElements)
EX(glEnable)
EX(glEnableVertexAttribArray)
EX(glFinish)
EX(glFlush)
EX(glFramebufferRenderbuffer)
EX(glFramebufferTexture2D)
EX(glFrontFace)
EX(glGenBuffers)
EX(glGenerateMipmap)
EX(glGenFramebuffers)
EX(glGenRenderbuffers)
EX(glGenTextures)
EX(glGetActiveAttrib)
EX(glGetActiveUniform)
EX(glGetAttachedShaders)
EX(glGetAttribLocation)
EX(glGetBooleanv)
EX(glGetBufferParameteriv)
EX(glGetError)
EX(glGetFloatv)
EX(glGetFramebufferAttachmentParameteriv)
EX(glGetIntegerv)
EX(glGetProgramiv)
EX(glGetProgramInfoLog)
EX(glGetRenderbufferParameteriv)
EX(glGetShaderiv)
EX(glGetShaderInfoLog)
EX(glGetShaderPrecisionFormat)
EX(glGetShaderSource)
EX(glGetString)
EX(glGetTexParameterfv)
EX(glGetTexParameteriv)
EX(glGetUniformfv)
EX(glGetUniformiv)
EX(glGetUniformLocation)
EX(glGetVertexAttribfv)
EX(glGetVertexAttribiv)
EX(glGetVertexAttribPointerv)
EX(glHint)
EX(glIsBuffer)
EX(glIsEnabled)
EX(glIsFramebuffer)
EX(glIsProgram)
EX(glIsRenderbuffer)
EX(glIsShader)
EX(glIsTexture)
EX(glLineWidth)
EX(glLinkProgram)
EX(glPixelStorei)
EX(glPolygonOffset)
EX(glReadPixels)
EX(glReleaseShaderCompiler)
EX(glRenderbufferStorage)
EX(glSampleCoverage)
EX(glScissor)
EX(glShaderBinary)
EX(glShaderSource)
EX(glStencilFunc)
EX(glStencilFuncSeparate)
EX(glStencilMask)
EX(glStencilMaskSeparate)
EX(glStencilOp)
EX(glStencilOpSeparate)
EX(glTexImage2D)
EX(glTexParameterf)
EX(glTexParameterfv)
EX(glTexParameteri)
EX(glTexParameteriv)
EX(glTexSubImage2D)
EX(glUniform1f)
EX(glUniform1fv)
EX(glUniform1i)
EX(glUniform1iv)
EX(glUniform2f)
EX(glUniform2fv)
EX(glUniform2i)
EX(glUniform2iv)
EX(glUniform3f)
EX(glUniform3fv)
EX(glUniform3i)
EX(glUniform3iv)
EX(glUniform4f)
EX(glUniform4fv)
EX(glUniform4i)
EX(glUniform4iv)
EX(glUniformMatrix2fv)
EX(glUniformMatrix3fv)
EX(glUniformMatrix4fv)
EX(glUseProgram)
EX(glValidateProgram)
EX(glVertexAttrib1f)
EX(glVertexAttrib1fv)
EX(glVertexAttrib2f)
EX(glVertexAttrib2fv)
EX(glVertexAttrib3f)
EX(glVertexAttrib3fv)
EX(glVertexAttrib4f)
EX(glVertexAttrib4fv)
EX(glVertexAttribPointer)
EX(glViewport)
//EX(glPolygonMode) //This is a non-standard function, and gl4es will ignore it (and emulate it), even if Amiga OGLES2 driver implement it
return IOGLES2->aglGetProcAddress(name);
}
+9
View File
@@ -0,0 +1,9 @@
#ifndef _AMIGAOS_H_
#define _AMIGAOS_H_
void* os4GetProcAddress(const char* name);
void os4OpenLib(void** lib);
void os4CloseLib();
#endif //_AMIGAOS_H_
+43
View File
@@ -0,0 +1,43 @@
#include "../gl/attributes.h"
#include "../gl/init.h"
#include "../gl/logs.h"
#define STUB_FCT aglStub
#include "../gl/gl_lookup.h"
#include "../glx/glx.h"
#include "../glx/hardext.h"
void aglStub(void *x, ...) {
return;
}
// Copy/ Paste of agl specifics function, but simplified whithout the Amiga speicifc types
void* aglCreateContext(void * errcode, void * tags);
void* aglCreateContext2(void * errcode, void * tags);
void aglDestroyContext(void* context);
void aglMakeCurrent(void* context);
void aglSwapBuffers();
void aglSetParams2(void * tags);
void aglSetBitmap(void * bitmap);
void* aglGetProcAddress(const char* name);
// TODO: something less error prone, but agl.h cannot be included here, as some Amiga header conflict with some GLES ones
void *gl4es_aglGetProcAddress(const char *name) {
MAP("glXSwapIntervalMESA", gl4es_glXSwapInterval);
MAP("glXSwapIntervalSGI", gl4es_glXSwapInterval);
_EX(aglGetProcAddress);
MAP("glXGetProcAddress", gl4es_aglGetProcAddress);
MAP("glXGetProcAddressARB", gl4es_aglGetProcAddress);
// direct mapping
MAP("aglCreateContext", aglCreateContext);
MAP("aglCreateContext2", aglCreateContext2);
MAP("aglDestroyContext", aglDestroyContext);
MAP("aglMakeCurrent", aglMakeCurrent);
MAP("aglSwapBuffers", aglSwapBuffers);
MAP("aglSetParams2", aglSetParams2);
MAP("aglSetBitmap", aglSetBitmap);
return gl4es_GetProcAddress(name);
}
AliasExport(void*,aglGetProcAddress,,(const char* name));
+23
View File
@@ -0,0 +1,23 @@
#ifndef _GL4ES_MAIN_CONFIG_H
#define _GL4ES_MAIN_CONFIG_H
#define SYS_proxy 9999
#define MAX_EVAL_ORDER 30
#define MAX_TEX 16
#define MAX_LIGHT 8
#define MAX_STACK_PROJECTION 16
#define MAX_STACK_TEXTURE 16
#define MAX_STACK_MODELVIEW 64
#define MAX_STACK_COLOR 16
#define MAX_STACK_ARB_MATRIX 8
#define MAX_CLIP_PLANES 6
#define MAX_VATTRIB 32
#define MAX_MAP_SIZE 256
#define MAX_ARB_MATRIX 8
#define MAX_VTX_PROG_ENV_PARAMS 96
#define MAX_VTX_PROG_LOC_PARAMS 96
#define MAX_FRG_PROG_ENV_PARAMS 24
#define MAX_FRG_PROG_LOC_PARAMS 24
#define MAX_DRAW_BUFFERS 16
#endif // _GL4ES_MAIN_CONFIG_H
+263
View File
@@ -0,0 +1,263 @@
#include "egl.h"
#include "../gl/loader.h"
#include "../glx/hardext.h"
#ifndef AliasExport
#define AliasExport(name) __attribute__((alias(name))) __attribute__((visibility("default")))
#endif
static EGLint egl_context_attrib_es2[] = {
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE
};
static EGLint egl_context_attrib[] = {
EGL_NONE
};
EGLint gl4es_eglGetError(void) {
LOAD_EGL(eglGetError);
return egl_eglGetError();
}
EGLDisplay gl4es_eglGetDisplay(EGLNativeDisplayType display_id) {
LOAD_EGL(eglGetDisplay);
return egl_eglGetDisplay(display_id);
}
EGLBoolean gl4es_eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) {
LOAD_EGL(eglInitialize);
return egl_eglInitialize(dpy, major, minor);
}
EGLBoolean gl4es_eglTerminate(EGLDisplay dpy) {
LOAD_EGL(eglTerminate);
return egl_eglTerminate(dpy);
}
const char * gl4es_eglQueryString(EGLDisplay dpy, EGLint name) {
LOAD_EGL(eglQueryString);
return egl_eglQueryString(dpy, name);
}
EGLBoolean gl4es_eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config) {
LOAD_EGL(eglGetConfigs);
return egl_eglGetConfigs(dpy, configs, config_size, num_config);
}
EGLBoolean gl4es_eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config) {
LOAD_EGL(eglChooseConfig);
return egl_eglChooseConfig(dpy, attrib_list, configs, config_size, num_config);
}
EGLBoolean gl4es_eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value) {
EGLint old_value = 0;
LOAD_EGL(eglGetConfigAttrib);
EGLBoolean ret = egl_eglGetConfigAttrib(dpy, config, attribute, &old_value);
switch (attribute) {
case EGL_RENDERABLE_TYPE:
*value = old_value | EGL_OPENGL_BIT;
break;
default:
*value = old_value;
}
return ret;
}
EGLSurface gl4es_eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list) {
LOAD_EGL(eglCreateWindowSurface);
return egl_eglCreateWindowSurface(dpy, config, win, attrib_list);
}
EGLSurface gl4es_eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) {
LOAD_EGL(eglCreatePbufferSurface);
return egl_eglCreatePbufferSurface(dpy, config, attrib_list);
}
EGLSurface gl4es_eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list) {
LOAD_EGL(eglCreatePixmapSurface);
return egl_eglCreatePixmapSurface(dpy, config, pixmap, attrib_list);
}
EGLBoolean gl4es_eglDestroySurface(EGLDisplay dpy, EGLSurface surface) {
LOAD_EGL(eglDestroySurface);
return egl_eglDestroySurface(dpy, surface);
}
EGLBoolean gl4es_eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value) {
LOAD_EGL(eglQuerySurface);
return egl_eglQuerySurface(dpy, surface, attribute, value);
}
EGLBoolean gl4es_eglBindAPI(EGLenum api) {
LOAD_EGL(eglBindAPI);
return egl_eglBindAPI(EGL_OPENGL_ES_API);
}
EGLenum gl4es_eglQueryAPI(void) {
return EGL_OPENGL_API;
}
EGLBoolean gl4es_eglWaitClient(void) {
LOAD_EGL(eglWaitClient);
return egl_eglWaitClient();
}
EGLBoolean gl4es_eglReleaseThread(void) {
LOAD_EGL(eglReleaseThread);
return egl_eglReleaseThread();
}
EGLSurface gl4es_eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list) {
LOAD_EGL(eglCreatePbufferFromClientBuffer);
return egl_eglCreatePbufferFromClientBuffer(dpy, buftype, buffer, config, attrib_list);
}
EGLBoolean gl4es_eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) {
LOAD_EGL(eglSurfaceAttrib);
return egl_eglSurfaceAttrib(dpy, surface, attribute, value);
}
EGLBoolean gl4es_eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) {
LOAD_EGL(eglBindTexImage);
return egl_eglBindTexImage(dpy, surface, buffer);
}
EGLBoolean gl4es_eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) {
LOAD_EGL(eglReleaseTexImage);
return egl_eglReleaseTexImage(dpy, surface, buffer);
}
EGLBoolean gl4es_eglSwapInterval(EGLDisplay dpy, EGLint interval) {
LOAD_EGL(eglSwapInterval);
return egl_eglSwapInterval(dpy, interval);
}
EGLContext gl4es_eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list) {
LOAD_EGL(eglCreateContext);
return egl_eglCreateContext(dpy, config, share_context, (hardext.esversion == 1) ? egl_context_attrib : egl_context_attrib_es2);
}
EGLBoolean gl4es_eglDestroyContext(EGLDisplay dpy, EGLContext ctx) {
LOAD_EGL(eglDestroyContext);
return egl_eglDestroyContext(dpy, ctx);
}
EGLBoolean gl4es_eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) {
LOAD_EGL(eglMakeCurrent);
return egl_eglMakeCurrent(dpy, draw, read, ctx);
}
EGLContext gl4es_eglGetCurrentContext(void) {
LOAD_EGL(eglGetCurrentContext);
return egl_eglGetCurrentContext();
}
EGLSurface gl4es_eglGetCurrentSurface(EGLint readdraw) {
LOAD_EGL(eglGetCurrentSurface);
return egl_eglGetCurrentSurface(readdraw);
}
EGLDisplay gl4es_eglGetCurrentDisplay(void) {
LOAD_EGL(eglGetCurrentDisplay);
return egl_eglGetCurrentDisplay();
}
EGLDisplay gl4es_eglGetPlatformDisplay(EGLenum platform, void *native_display, const EGLAttrib *attrib_list) {
LOAD_EGL_EXT(eglGetPlatformDisplay);
if (egl_eglGetPlatformDisplay)
return egl_eglGetPlatformDisplay(platform, native_display, attrib_list);
else {
LOAD_EGL(eglGetDisplay);
return egl_eglGetDisplay((EGLNativeDisplayType)native_display);
}
}
EGLBoolean gl4es_eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value) {
LOAD_EGL(eglQueryContext);
return egl_eglQueryContext(dpy, ctx, attribute, value);
}
EGLBoolean gl4es_eglWaitGL(void) {
LOAD_EGL(eglWaitGL);
return egl_eglWaitGL();
}
EGLBoolean gl4es_eglWaitNative(EGLint engine) {
LOAD_EGL(eglWaitNative);
return egl_eglWaitNative(engine);
}
EGLBoolean gl4es_eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) {
LOAD_EGL(eglSwapBuffers);
return egl_eglSwapBuffers(dpy, surface);
}
EGLBoolean gl4es_eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target) {
LOAD_EGL(eglCopyBuffers);
return egl_eglCopyBuffers(dpy, surface, target);
}
EGLSyncKHR gl4es_eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list) {
LOAD_EGL(eglCreateSyncKHR);
return egl_eglCreateSyncKHR(dpy, type, attrib_list);
}
EGLint gl4es_eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout) {
LOAD_EGL(eglClientWaitSyncKHR);
return egl_eglClientWaitSyncKHR(dpy, sync, flags, timeout);
}
NativePixmapType gl4es_egl_create_pixmap_ID_mapping(void *pixmap)
{
LOAD_EGL(egl_create_pixmap_ID_mapping);
return egl_egl_create_pixmap_ID_mapping(pixmap);
}
NativePixmapType gl4es_egl_destroy_pixmap_ID_mapping(int id)
{
LOAD_EGL(egl_destroy_pixmap_ID_mapping);
return egl_egl_destroy_pixmap_ID_mapping(id);
}
AliasExport(EGLint, eglGetError,,(void));
AliasExport(EGLDisplay, eglGetDisplay,,(EGLNativeDisplayType display_id));
AliasExport(EGLBoolean, eglInitialize,,(EGLDisplay dpy, EGLint *major, EGLint *minor));
AliasExport(EGLBoolean, eglTerminate,,(EGLDisplay dpy));
AliasExport(const char *, eglQueryString,,(EGLDisplay dpy, EGLint name));
AliasExport(EGLBoolean, eglGetConfigs,,(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config));
AliasExport(EGLBoolean, eglChooseConfig,,(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config));
AliasExport(EGLBoolean, eglGetConfigAttrib,,(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value));
AliasExport(EGLSurface, eglCreateWindowSurface,,(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list));
AliasExport(EGLSurface, eglCreatePbufferSurface,,(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list));
AliasExport(EGLSurface, eglCreatePixmapSurface,,(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list));
AliasExport(EGLBoolean, eglDestroySurface,,(EGLDisplay dpy, EGLSurface surface));
AliasExport(EGLBoolean, eglQuerySurface,,(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value));
AliasExport(EGLBoolean, eglBindAPI,,(EGLenum api));
AliasExport(EGLenum, eglQueryAPI,,(void));
AliasExport(EGLBoolean, eglWaitClient,,(void));
AliasExport(EGLBoolean, eglReleaseThread,,(void));
AliasExport(EGLSurface, eglCreatePbufferFromClientBuffer,,(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list));
AliasExport(EGLBoolean, eglSurfaceAttrib,,(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value));
AliasExport(EGLBoolean, eglBindTexImage,,(EGLDisplay dpy, EGLSurface surface, EGLint buffer));
AliasExport(EGLBoolean, eglReleaseTexImage,,(EGLDisplay dpy, EGLSurface surface, EGLint buffer));
AliasExport(EGLBoolean, eglSwapInterval,,(EGLDisplay dpy, EGLint interval));
AliasExport(EGLContext, eglCreateContext,,(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list));
AliasExport(EGLBoolean, eglDestroyContext,,(EGLDisplay dpy, EGLContext ctx));
AliasExport(EGLBoolean, eglMakeCurrent,,(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx));
AliasExport(EGLContext, eglGetCurrentContext,,(void));
AliasExport(EGLSurface, eglGetCurrentSurface,,(EGLint readdraw));
AliasExport(EGLDisplay, eglGetCurrentDisplay,,(void));
AliasExport(EGLDisplay, eglGetPlatformDisplay,, (EGLenum platform, void *native_display, const EGLAttrib *attrib_list));
AliasExport(EGLDisplay, eglGetPlatformDisplay, EXT, (EGLenum platform, void *native_display, const EGLAttrib *attrib_list));
AliasExport(EGLBoolean, eglQueryContext,,(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value));
AliasExport(EGLBoolean, eglWaitGL,,(void));
AliasExport(EGLBoolean, eglWaitNative,,(EGLint engine));
AliasExport(EGLBoolean, eglSwapBuffers,,(EGLDisplay dpy, EGLSurface surface));
AliasExport(EGLBoolean, eglCopyBuffers,,(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target));
AliasExport(EGLSyncKHR, eglCreateSyncKHR,,(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list));
AliasExport(EGLint, eglClientWaitSyncKHR,,(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout));
AliasExport(NativePixmapType, egl_create_pixmap_ID_mapping,,(void *pixmap));
AliasExport(NativePixmapType, egl_destroy_pixmap_ID_mapping,,(int id));
+59
View File
@@ -0,0 +1,59 @@
#ifndef _EGL_EGL_H_
#define _EGL_EGL_H_
#ifdef NOEGL
# error Building EGL wrapper without EGL
#endif
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <stdbool.h>
#include <stdlib.h>
EGLint gl4es_eglGetError(void);
EGLDisplay gl4es_eglGetDisplay(EGLNativeDisplayType display_id);
EGLBoolean gl4es_eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor);
EGLBoolean gl4es_eglTerminate(EGLDisplay dpy);
const char * gl4es_eglQueryString(EGLDisplay dpy, EGLint name);
EGLBoolean gl4es_eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config);
EGLBoolean gl4es_eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
EGLBoolean gl4es_eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value);
EGLSurface gl4es_eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list);
EGLSurface gl4es_eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
EGLSurface gl4es_eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list);
EGLBoolean gl4es_eglDestroySurface(EGLDisplay dpy, EGLSurface surface);
EGLBoolean gl4es_eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value);
EGLBoolean gl4es_eglBindAPI(EGLenum api);
EGLenum gl4es_eglQueryAPI(void);
EGLBoolean gl4es_eglWaitClient(void);
EGLBoolean gl4es_eglReleaseThread(void);
EGLSurface gl4es_eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list);
EGLBoolean gl4es_eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value);
EGLBoolean gl4es_eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
EGLBoolean gl4es_eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
EGLBoolean gl4es_eglSwapInterval(EGLDisplay dpy, EGLint interval);
EGLContext gl4es_eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list);
EGLBoolean gl4es_eglDestroyContext(EGLDisplay dpy, EGLContext ctx);
EGLBoolean gl4es_eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
EGLContext gl4es_eglGetCurrentContext(void);
EGLSurface gl4es_eglGetCurrentSurface(EGLint readdraw);
EGLDisplay gl4es_eglGetCurrentDisplay(void);
EGLDisplay gl4es_eglGetPlatformDisplay(EGLenum platform, void *native_display, const EGLAttrib *attrib_list);
EGLBoolean gl4es_eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value);
EGLBoolean gl4es_eglWaitGL(void);
EGLBoolean gl4es_eglWaitNative(EGLint engine);
EGLBoolean gl4es_eglSwapBuffers(EGLDisplay dpy, EGLSurface surface);
EGLBoolean gl4es_eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target);
void* gl4es_eglGetProcAddress(const char *name);
EGLSyncKHR gl4es_eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list);
EGLint gl4es_eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
// Undocumented libmali internals, needed for ODROID Go Ultra
NativePixmapType gl4es_egl_create_pixmap_ID_mapping(void *pixmap);
NativePixmapType gl4es_egl_destroy_pixmap_ID_mapping(int id);
#endif // _EGL_EGL_H
+71
View File
@@ -0,0 +1,71 @@
#include <string.h>
#include "../gl/attributes.h"
#include "../gl/init.h"
#include "../gl/logs.h"
#define STUB_FCT eglStub
#include "../gl/gl_lookup.h"
#include "egl.h"
#include "../glx/hardext.h"
extern void *gl4es_glXGetProcAddress(const char *name);
void eglStub(void *x, ...) {
return;
}
void* gl4es_eglGetProcAddress(const char *name) {
_EX(eglGetError);
_EX(eglGetDisplay);
_EX(eglInitialize);
_EX(eglTerminate);
_EX(eglQueryString);
_EX(eglGetConfigs);
_EX(eglChooseConfig);
_EX(eglGetConfigAttrib);
_EX(eglCreateWindowSurface);
_EX(eglCreatePbufferSurface);
_EX(eglCreatePixmapSurface);
_EX(eglDestroySurface);
_EX(eglQuerySurface);
_EX(eglBindAPI);
_EX(eglQueryAPI);
_EX(eglWaitClient);
_EX(eglReleaseThread);
_EX(eglCreatePbufferFromClientBuffer);
_EX(eglSurfaceAttrib);
_EX(eglBindTexImage);
_EX(eglReleaseTexImage);
_EX(eglSwapInterval);
_EX(eglCreateContext);
_EX(eglDestroyContext);
_EX(eglMakeCurrent);
_EX(eglGetCurrentContext);
_EX(eglGetCurrentSurface);
_EX(eglGetCurrentDisplay);
_EX(eglGetPlatformDisplay);
_EXT(eglGetPlatformDisplay);
_EX(eglQueryContext);
_EX(eglWaitGL);
_EX(eglWaitNative);
_EX(eglSwapBuffers);
_EX(eglCopyBuffers);
_EX(eglCreateSyncKHR);
_EX(eglClientWaitSyncKHR);
_EX(egl_create_pixmap_ID_mapping);
_EX(egl_destroy_pixmap_ID_mapping);
_EX(glXGetProcAddress);
_ARB(glXGetProcAddress);
_EX(eglGetProcAddress);
return gl4es_GetProcAddress(name);
}
AliasExport(__eglMustCastToProperFunctionPointerType, eglGetProcAddress,, (const char *name));
+352
View File
@@ -0,0 +1,352 @@
#include "arbconverter.h"
#include <stddef.h>
#include "arbgenerator.h"
#include "arbhelper.h"
#include "arbparser.h"
#include "khash.h"
#define FAIL(str) curStatus.status = ST_ERROR; if (*error_msg) free(*error_msg); \
*error_msg = strdup(str); continue
#define curStatusPtr &curStatus
char* gl4es_convertARB(const char* const code, int vertex, char **error_msg, int *error_ptr) {
*error_ptr = -1; // Reinit error pointer
struct sSpecialCases specialCases = {0, 0};
const char *codeStart = code;
// Not sure this is really OK...
if ((codeStart[0] != '!') || (codeStart[1] != '!')) {
while (1) {
while ((*codeStart != '!') && (*codeStart != '\0')) {
++codeStart;
}
if (*codeStart == '\0') {
// Invalid start
if (*error_msg)
free(*error_msg);
*error_msg = strdup("Invalid program start");
*error_ptr = 0;
return NULL;
}
if ((codeStart[0] == '!') && (codeStart[1] == '!')) {
break;
}
++codeStart;
}
}
if (vertex) {
if (strncmp(codeStart, "!!ARBvp1.0", 10)) {
if (*error_msg)
free(*error_msg);
*error_msg = strdup("Invalid program start");
*error_ptr = codeStart - code;
return NULL;
}
} else {
if (strncmp(codeStart, "!!ARBfp1.0", 10)) {
if (*error_msg)
free(*error_msg);
*error_msg = strdup("Invalid program start");
*error_ptr = codeStart - code;
return NULL;
}
}
codeStart += 10;
ARBCONV_DBG_HEAVY(printf("Generating code for:\n%s\n", codeStart);)
sCurStatus curStatus = {0};
initStatus(&curStatus, codeStart);
readNextToken(&curStatus);
if ((curStatus.curToken != TOK_NEWLINE) && (curStatus.curToken != TOK_WHITESPACE)) {
curStatus.status = ST_ERROR;
} else {
readNextToken(&curStatus);
}
while ((curStatus.status != ST_ERROR) && (curStatus.status != ST_DONE)) {
ARBCONV_DBG_LP(
printf(
"%-13s",
STATUS2STR(curStatus.status)
);
if (curStatus.valueType == TYPE_INST_DECL) {
printf(
"-%3s%4s (%2d)",
INST2STR(curStatus.curValue.newInst.inst.type),
curStatus.curValue.newInst.inst.saturated ? "_SAT" : " ",
curStatus.curValue.newInst.state
);
} else if (curStatus.valueType == TYPE_VARIABLE_DECL) {
printf(
"-%-10s (%2d)",
VARTYPE2STR(curStatus.curValue.newVar.var->type),
curStatus.curValue.newVar.state
);
} else if (curStatus.valueType == TYPE_ALIAS_DECL) {
printf("-(string) ");
} else if (curStatus.valueType == TYPE_OPTION_DECL) {
printf("-%15s", curStatus.curValue.newOpt.optName ? curStatus.curValue.newOpt.optName : "");
} else {
printf(" ");
}
printf(" / %-11s: %p - %p (%ld)\n",
TOKEN2STR(curStatus.curToken),
curStatus.codePtr,
curStatus.endOfToken,
curStatus.endOfToken - curStatus.codePtr
);
fflush(stdout);
)
parseToken(&curStatus, vertex, error_msg, &specialCases);
readNextToken(&curStatus);
}
if (curStatus.status == ST_ERROR) {
ARBCONV_DBG(
char *codeDup = strdup(code);
codeDup[curStatus.codePtr - code] = '\0';
printf(
"Failure, copy until EOF\n\n%s\033[91m%s\033[m\n",
codeDup,
curStatus.codePtr
);
free(codeDup);
printf("\nVariables:\n==========\n");
{
const char *kvar;
sVariable *vvar;
kh_foreach(curStatus.varsMap, kvar, vvar,
if (vvar) {
printf("Variable %10s pointing to %p (%10s)\n", kvar, vvar, vvar->names[0]);
} else {
printf("\033[91mVariable %10s pointing to NULLptr!\033[m\n", kvar);
}
)
}
for (size_t i = 0; i < curStatus.variables.size; ++i) {
sVariable *varPtr = curStatus.variables.vars[i];
printf("Variable %p %10s (%lu): %-10s (init = %3lu %s)\n", varPtr, varPtr->names[0], varPtr->names_count, VARTYPE2STR(varPtr->type), varPtr->init.strings_total_len, varPtr->init.strings_count ? varPtr->init.strings[0] : "(none)");
}
printf("\nInstructions:\n=============\n");
for (size_t i = 0; i < curStatus.instructions.size; ++i) {
sInstruction *instPtr = curStatus.instructions.insts[i];
instPtr = curStatus.instructions.insts[i];
if (INSTTEX(instPtr->type)) {
printf("Instruction %3s%4s %c%10s[%2s].%c%c%c%c %c%10s[%2s].%c%c%c%c %ctexture[%2s] %c%19s\n", INST2STR(instPtr->type), instPtr->saturated ? "_SAT" : " ",
instPtr->vars[0].sign ? (instPtr->vars[0].sign == -1 ? '-' : '+') : ' ', instPtr->vars[0].var ? ((instPtr->vars[0].var->type == VARTYPE_CONST) ? instPtr->vars[0].var->init.strings[0] : instPtr->vars[0].var->names[0]) : "(none)", instPtr->vars[0].floatArrAddr ? instPtr->vars[0].floatArrAddr : "", (instPtr->vars[0].swizzle[0] == SWIZ_X) ? 'x' : (instPtr->vars[0].swizzle[0] == SWIZ_Y) ? 'y' : (instPtr->vars[0].swizzle[0] == SWIZ_Z) ? 'z' : (instPtr->vars[0].swizzle[0] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[0].swizzle[1] == SWIZ_X) ? 'x' : (instPtr->vars[0].swizzle[1] == SWIZ_Y) ? 'y' : (instPtr->vars[0].swizzle[1] == SWIZ_Z) ? 'z' : (instPtr->vars[0].swizzle[1] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[0].swizzle[2] == SWIZ_X) ? 'x' : (instPtr->vars[0].swizzle[2] == SWIZ_Y) ? 'y' : (instPtr->vars[0].swizzle[2] == SWIZ_Z) ? 'z' : (instPtr->vars[0].swizzle[2] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[0].swizzle[3] == SWIZ_X) ? 'x' : (instPtr->vars[0].swizzle[3] == SWIZ_Y) ? 'y' : (instPtr->vars[0].swizzle[3] == SWIZ_Z) ? 'z' : (instPtr->vars[0].swizzle[3] == SWIZ_W) ? 'w' : ' ',
instPtr->vars[1].sign ? (instPtr->vars[1].sign == -1 ? '-' : '+') : ' ', instPtr->vars[1].var ? ((instPtr->vars[1].var->type == VARTYPE_CONST) ? instPtr->vars[1].var->init.strings[0] : instPtr->vars[1].var->names[0]) : "(none)", instPtr->vars[1].floatArrAddr ? instPtr->vars[1].floatArrAddr : "", (instPtr->vars[1].swizzle[0] == SWIZ_X) ? 'x' : (instPtr->vars[1].swizzle[0] == SWIZ_Y) ? 'y' : (instPtr->vars[1].swizzle[0] == SWIZ_Z) ? 'z' : (instPtr->vars[1].swizzle[0] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[1].swizzle[1] == SWIZ_X) ? 'x' : (instPtr->vars[1].swizzle[1] == SWIZ_Y) ? 'y' : (instPtr->vars[1].swizzle[1] == SWIZ_Z) ? 'z' : (instPtr->vars[1].swizzle[1] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[1].swizzle[2] == SWIZ_X) ? 'x' : (instPtr->vars[1].swizzle[2] == SWIZ_Y) ? 'y' : (instPtr->vars[1].swizzle[2] == SWIZ_Z) ? 'z' : (instPtr->vars[1].swizzle[2] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[1].swizzle[3] == SWIZ_X) ? 'x' : (instPtr->vars[1].swizzle[3] == SWIZ_Y) ? 'y' : (instPtr->vars[1].swizzle[3] == SWIZ_Z) ? 'z' : (instPtr->vars[1].swizzle[3] == SWIZ_W) ? 'w' : ' ',
instPtr->vars[2].sign ? (instPtr->vars[2].sign == -1 ? '-' : '+') : ' ', instPtr->vars[2].var->names[0],
instPtr->vars[3].sign ? (instPtr->vars[3].sign == -1 ? '-' : '+') : ' ', (instPtr->vars[3].var == curStatus.tex1D) ? "1D" : (instPtr->vars[3].var == curStatus.tex2D) ? "2D" : (instPtr->vars[3].var == curStatus.tex3D) ? "3D" : (instPtr->vars[3].var == curStatus.texCUBE) ? "CUBE" : (instPtr->vars[3].var == curStatus.texRECT) ? "RECT" : "!!!"
);
} else {
printf("Instruction %3s%4s %c%10s[%2s].%c%c%c%c %c%10s[%2s].%c%c%c%c %c%10s[%2s].%c%c%c%c %c%10s[%2s].%c%c%c%c\n", INST2STR(instPtr->type), instPtr->saturated ? "_SAT" : " ",
instPtr->vars[0].sign ? (instPtr->vars[0].sign == -1 ? '-' : '+') : ' ', instPtr->vars[0].var ? ((instPtr->vars[0].var->type == VARTYPE_CONST) ? instPtr->vars[0].var->init.strings[0] : instPtr->vars[0].var->names[0]) : "(none)", instPtr->vars[0].floatArrAddr ? instPtr->vars[0].floatArrAddr : "", (instPtr->vars[0].swizzle[0] == SWIZ_X) ? 'x' : (instPtr->vars[0].swizzle[0] == SWIZ_Y) ? 'y' : (instPtr->vars[0].swizzle[0] == SWIZ_Z) ? 'z' : (instPtr->vars[0].swizzle[0] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[0].swizzle[1] == SWIZ_X) ? 'x' : (instPtr->vars[0].swizzle[1] == SWIZ_Y) ? 'y' : (instPtr->vars[0].swizzle[1] == SWIZ_Z) ? 'z' : (instPtr->vars[0].swizzle[1] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[0].swizzle[2] == SWIZ_X) ? 'x' : (instPtr->vars[0].swizzle[2] == SWIZ_Y) ? 'y' : (instPtr->vars[0].swizzle[2] == SWIZ_Z) ? 'z' : (instPtr->vars[0].swizzle[2] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[0].swizzle[3] == SWIZ_X) ? 'x' : (instPtr->vars[0].swizzle[3] == SWIZ_Y) ? 'y' : (instPtr->vars[0].swizzle[3] == SWIZ_Z) ? 'z' : (instPtr->vars[0].swizzle[3] == SWIZ_W) ? 'w' : ' ',
instPtr->vars[1].sign ? (instPtr->vars[1].sign == -1 ? '-' : '+') : ' ', instPtr->vars[1].var ? ((instPtr->vars[1].var->type == VARTYPE_CONST) ? instPtr->vars[1].var->init.strings[0] : instPtr->vars[1].var->names[0]) : "(none)", instPtr->vars[1].floatArrAddr ? instPtr->vars[1].floatArrAddr : "", (instPtr->vars[1].swizzle[0] == SWIZ_X) ? 'x' : (instPtr->vars[1].swizzle[0] == SWIZ_Y) ? 'y' : (instPtr->vars[1].swizzle[0] == SWIZ_Z) ? 'z' : (instPtr->vars[1].swizzle[0] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[1].swizzle[1] == SWIZ_X) ? 'x' : (instPtr->vars[1].swizzle[1] == SWIZ_Y) ? 'y' : (instPtr->vars[1].swizzle[1] == SWIZ_Z) ? 'z' : (instPtr->vars[1].swizzle[1] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[1].swizzle[2] == SWIZ_X) ? 'x' : (instPtr->vars[1].swizzle[2] == SWIZ_Y) ? 'y' : (instPtr->vars[1].swizzle[2] == SWIZ_Z) ? 'z' : (instPtr->vars[1].swizzle[2] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[1].swizzle[3] == SWIZ_X) ? 'x' : (instPtr->vars[1].swizzle[3] == SWIZ_Y) ? 'y' : (instPtr->vars[1].swizzle[3] == SWIZ_Z) ? 'z' : (instPtr->vars[1].swizzle[3] == SWIZ_W) ? 'w' : ' ',
instPtr->vars[2].sign ? (instPtr->vars[2].sign == -1 ? '-' : '+') : ' ', instPtr->vars[2].var ? ((instPtr->vars[2].var->type == VARTYPE_CONST) ? instPtr->vars[2].var->init.strings[0] : instPtr->vars[2].var->names[0]) : "(none)", instPtr->vars[2].floatArrAddr ? instPtr->vars[2].floatArrAddr : "", (instPtr->vars[2].swizzle[0] == SWIZ_X) ? 'x' : (instPtr->vars[2].swizzle[0] == SWIZ_Y) ? 'y' : (instPtr->vars[2].swizzle[0] == SWIZ_Z) ? 'z' : (instPtr->vars[2].swizzle[0] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[2].swizzle[1] == SWIZ_X) ? 'x' : (instPtr->vars[2].swizzle[1] == SWIZ_Y) ? 'y' : (instPtr->vars[2].swizzle[1] == SWIZ_Z) ? 'z' : (instPtr->vars[2].swizzle[1] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[2].swizzle[2] == SWIZ_X) ? 'x' : (instPtr->vars[2].swizzle[2] == SWIZ_Y) ? 'y' : (instPtr->vars[2].swizzle[2] == SWIZ_Z) ? 'z' : (instPtr->vars[2].swizzle[2] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[2].swizzle[3] == SWIZ_X) ? 'x' : (instPtr->vars[2].swizzle[3] == SWIZ_Y) ? 'y' : (instPtr->vars[2].swizzle[3] == SWIZ_Z) ? 'z' : (instPtr->vars[2].swizzle[3] == SWIZ_W) ? 'w' : ' ',
instPtr->vars[3].sign ? (instPtr->vars[3].sign == -1 ? '-' : '+') : ' ', instPtr->vars[3].var ? ((instPtr->vars[3].var->type == VARTYPE_CONST) ? instPtr->vars[3].var->init.strings[0] : instPtr->vars[3].var->names[0]) : "(none)", instPtr->vars[3].floatArrAddr ? instPtr->vars[3].floatArrAddr : "", (instPtr->vars[3].swizzle[0] == SWIZ_X) ? 'x' : (instPtr->vars[3].swizzle[0] == SWIZ_Y) ? 'y' : (instPtr->vars[3].swizzle[0] == SWIZ_Z) ? 'z' : (instPtr->vars[3].swizzle[0] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[3].swizzle[1] == SWIZ_X) ? 'x' : (instPtr->vars[3].swizzle[1] == SWIZ_Y) ? 'y' : (instPtr->vars[3].swizzle[1] == SWIZ_Z) ? 'z' : (instPtr->vars[3].swizzle[1] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[3].swizzle[2] == SWIZ_X) ? 'x' : (instPtr->vars[3].swizzle[2] == SWIZ_Y) ? 'y' : (instPtr->vars[3].swizzle[2] == SWIZ_Z) ? 'z' : (instPtr->vars[3].swizzle[2] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[3].swizzle[3] == SWIZ_X) ? 'x' : (instPtr->vars[3].swizzle[3] == SWIZ_Y) ? 'y' : (instPtr->vars[3].swizzle[3] == SWIZ_Z) ? 'z' : (instPtr->vars[3].swizzle[3] == SWIZ_W) ? 'w' : ' '
);
}
}
printf("\n");)
*error_ptr = curStatus.codePtr - code;
// We have errored, output NULL
freeStatus(&curStatus);
free(curStatus.outputString);
return NULL;
}
ARBCONV_DBG(printf("Success!\n");)
// Variables are automatically created, only need to write main()
size_t varIdx = (size_t)0;
sVariable *varPtr;
size_t instIdx = (size_t)0;
sInstruction *instPtr;
do {
if (vertex) {
// Add a structure (for addresses) with only an 'x' component
APPEND_OUTPUT("#version 120\n\nstruct _structOnlyX { int x; };\n\nvoid main() {\n", 61)
if (specialCases.hasFogFragCoord) {
APPEND_OUTPUT("\tvec4 gl4es_FogFragCoordTemp = vec4(gl_FogFragCoord);\n", 54)
}
} else {
// No address
APPEND_OUTPUT("#version 120\n\nvoid main() {\n", 28)
if (specialCases.isDepthReplacing) {
APPEND_OUTPUT("\tvec4 gl4es_FragDepthTemp = vec4(gl_FragDepth);\n", 48)
}
}
for (; (varIdx < curStatus.variables.size) && (curStatus.status != ST_ERROR); ++varIdx) {
varPtr = curStatus.variables.vars[varIdx];
ARBCONV_DBG_AS(
printf("Variable #%2ld: %10s (%10s)\n", varIdx, varPtr->names[0], VARTYPE2STR(varPtr->type));
fflush(stdout);
)
generateVariablePre(&curStatus, vertex, error_msg, varPtr);
}
if (curStatus.status == ST_ERROR) {
--varIdx;
*error_ptr = 1;
break;
}
APPEND_OUTPUT("\t\n", 2)
for (; (instIdx < curStatus.instructions.size) && (curStatus.status != ST_ERROR); ++instIdx) {
instPtr = curStatus.instructions.insts[instIdx];
ARBCONV_DBG_AS(
if (INSTTEX(instPtr->type)) {
printf("Instruction #%3ld: %3s%4s %c%10s[%2s].%c%c%c%c %c%10s[%2s].%c%c%c%c %ctexture[%2s] %c%19s\n", instIdx, INST2STR(instPtr->type), instPtr->saturated ? "_SAT" : " ",
instPtr->vars[0].sign ? (instPtr->vars[0].sign == -1 ? '-' : '+') : ' ', instPtr->vars[0].var ? ((instPtr->vars[0].var->type == VARTYPE_CONST) ? instPtr->vars[0].var->init.strings[0] : instPtr->vars[0].var->names[0]) : "(none)", instPtr->vars[0].floatArrAddr ? instPtr->vars[0].floatArrAddr : "", (instPtr->vars[0].swizzle[0] == SWIZ_X) ? 'x' : (instPtr->vars[0].swizzle[0] == SWIZ_Y) ? 'y' : (instPtr->vars[0].swizzle[0] == SWIZ_Z) ? 'z' : (instPtr->vars[0].swizzle[0] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[0].swizzle[1] == SWIZ_X) ? 'x' : (instPtr->vars[0].swizzle[1] == SWIZ_Y) ? 'y' : (instPtr->vars[0].swizzle[1] == SWIZ_Z) ? 'z' : (instPtr->vars[0].swizzle[1] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[0].swizzle[2] == SWIZ_X) ? 'x' : (instPtr->vars[0].swizzle[2] == SWIZ_Y) ? 'y' : (instPtr->vars[0].swizzle[2] == SWIZ_Z) ? 'z' : (instPtr->vars[0].swizzle[2] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[0].swizzle[3] == SWIZ_X) ? 'x' : (instPtr->vars[0].swizzle[3] == SWIZ_Y) ? 'y' : (instPtr->vars[0].swizzle[3] == SWIZ_Z) ? 'z' : (instPtr->vars[0].swizzle[3] == SWIZ_W) ? 'w' : ' ',
instPtr->vars[1].sign ? (instPtr->vars[1].sign == -1 ? '-' : '+') : ' ', instPtr->vars[1].var ? ((instPtr->vars[1].var->type == VARTYPE_CONST) ? instPtr->vars[1].var->init.strings[0] : instPtr->vars[1].var->names[0]) : "(none)", instPtr->vars[1].floatArrAddr ? instPtr->vars[1].floatArrAddr : "", (instPtr->vars[1].swizzle[0] == SWIZ_X) ? 'x' : (instPtr->vars[1].swizzle[0] == SWIZ_Y) ? 'y' : (instPtr->vars[1].swizzle[0] == SWIZ_Z) ? 'z' : (instPtr->vars[1].swizzle[0] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[1].swizzle[1] == SWIZ_X) ? 'x' : (instPtr->vars[1].swizzle[1] == SWIZ_Y) ? 'y' : (instPtr->vars[1].swizzle[1] == SWIZ_Z) ? 'z' : (instPtr->vars[1].swizzle[1] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[1].swizzle[2] == SWIZ_X) ? 'x' : (instPtr->vars[1].swizzle[2] == SWIZ_Y) ? 'y' : (instPtr->vars[1].swizzle[2] == SWIZ_Z) ? 'z' : (instPtr->vars[1].swizzle[2] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[1].swizzle[3] == SWIZ_X) ? 'x' : (instPtr->vars[1].swizzle[3] == SWIZ_Y) ? 'y' : (instPtr->vars[1].swizzle[3] == SWIZ_Z) ? 'z' : (instPtr->vars[1].swizzle[3] == SWIZ_W) ? 'w' : ' ',
instPtr->vars[2].sign ? (instPtr->vars[2].sign == -1 ? '-' : '+') : ' ', instPtr->vars[2].var->names[0],
instPtr->vars[3].sign ? (instPtr->vars[3].sign == -1 ? '-' : '+') : ' ', (instPtr->vars[3].var == curStatus.tex1D) ? "1D" : (instPtr->vars[3].var == curStatus.tex2D) ? "2D" : (instPtr->vars[3].var == curStatus.tex3D) ? "3D" : (instPtr->vars[3].var == curStatus.texCUBE) ? "CUBE" : (instPtr->vars[3].var == curStatus.texRECT) ? "RECT" : "!!!"
);
} else {
printf("Instruction #%3ld: %3s%4s %c%10s[%2s].%c%c%c%c %c%10s[%2s].%c%c%c%c %c%10s[%2s].%c%c%c%c %c%10s[%2s].%c%c%c%c\n", instIdx, INST2STR(instPtr->type), instPtr->saturated ? "_SAT" : " ",
instPtr->vars[0].sign ? (instPtr->vars[0].sign == -1 ? '-' : '+') : ' ', instPtr->vars[0].var ? ((instPtr->vars[0].var->type == VARTYPE_CONST) ? instPtr->vars[0].var->init.strings[0] : instPtr->vars[0].var->names[0]) : "(none)", instPtr->vars[0].floatArrAddr ? instPtr->vars[0].floatArrAddr : "", (instPtr->vars[0].swizzle[0] == SWIZ_X) ? 'x' : (instPtr->vars[0].swizzle[0] == SWIZ_Y) ? 'y' : (instPtr->vars[0].swizzle[0] == SWIZ_Z) ? 'z' : (instPtr->vars[0].swizzle[0] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[0].swizzle[1] == SWIZ_X) ? 'x' : (instPtr->vars[0].swizzle[1] == SWIZ_Y) ? 'y' : (instPtr->vars[0].swizzle[1] == SWIZ_Z) ? 'z' : (instPtr->vars[0].swizzle[1] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[0].swizzle[2] == SWIZ_X) ? 'x' : (instPtr->vars[0].swizzle[2] == SWIZ_Y) ? 'y' : (instPtr->vars[0].swizzle[2] == SWIZ_Z) ? 'z' : (instPtr->vars[0].swizzle[2] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[0].swizzle[3] == SWIZ_X) ? 'x' : (instPtr->vars[0].swizzle[3] == SWIZ_Y) ? 'y' : (instPtr->vars[0].swizzle[3] == SWIZ_Z) ? 'z' : (instPtr->vars[0].swizzle[3] == SWIZ_W) ? 'w' : ' ',
instPtr->vars[1].sign ? (instPtr->vars[1].sign == -1 ? '-' : '+') : ' ', instPtr->vars[1].var ? ((instPtr->vars[1].var->type == VARTYPE_CONST) ? instPtr->vars[1].var->init.strings[0] : instPtr->vars[1].var->names[0]) : "(none)", instPtr->vars[1].floatArrAddr ? instPtr->vars[1].floatArrAddr : "", (instPtr->vars[1].swizzle[0] == SWIZ_X) ? 'x' : (instPtr->vars[1].swizzle[0] == SWIZ_Y) ? 'y' : (instPtr->vars[1].swizzle[0] == SWIZ_Z) ? 'z' : (instPtr->vars[1].swizzle[0] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[1].swizzle[1] == SWIZ_X) ? 'x' : (instPtr->vars[1].swizzle[1] == SWIZ_Y) ? 'y' : (instPtr->vars[1].swizzle[1] == SWIZ_Z) ? 'z' : (instPtr->vars[1].swizzle[1] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[1].swizzle[2] == SWIZ_X) ? 'x' : (instPtr->vars[1].swizzle[2] == SWIZ_Y) ? 'y' : (instPtr->vars[1].swizzle[2] == SWIZ_Z) ? 'z' : (instPtr->vars[1].swizzle[2] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[1].swizzle[3] == SWIZ_X) ? 'x' : (instPtr->vars[1].swizzle[3] == SWIZ_Y) ? 'y' : (instPtr->vars[1].swizzle[3] == SWIZ_Z) ? 'z' : (instPtr->vars[1].swizzle[3] == SWIZ_W) ? 'w' : ' ',
instPtr->vars[2].sign ? (instPtr->vars[2].sign == -1 ? '-' : '+') : ' ', instPtr->vars[2].var ? ((instPtr->vars[2].var->type == VARTYPE_CONST) ? instPtr->vars[2].var->init.strings[0] : instPtr->vars[2].var->names[0]) : "(none)", instPtr->vars[2].floatArrAddr ? instPtr->vars[2].floatArrAddr : "", (instPtr->vars[2].swizzle[0] == SWIZ_X) ? 'x' : (instPtr->vars[2].swizzle[0] == SWIZ_Y) ? 'y' : (instPtr->vars[2].swizzle[0] == SWIZ_Z) ? 'z' : (instPtr->vars[2].swizzle[0] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[2].swizzle[1] == SWIZ_X) ? 'x' : (instPtr->vars[2].swizzle[1] == SWIZ_Y) ? 'y' : (instPtr->vars[2].swizzle[1] == SWIZ_Z) ? 'z' : (instPtr->vars[2].swizzle[1] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[2].swizzle[2] == SWIZ_X) ? 'x' : (instPtr->vars[2].swizzle[2] == SWIZ_Y) ? 'y' : (instPtr->vars[2].swizzle[2] == SWIZ_Z) ? 'z' : (instPtr->vars[2].swizzle[2] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[2].swizzle[3] == SWIZ_X) ? 'x' : (instPtr->vars[2].swizzle[3] == SWIZ_Y) ? 'y' : (instPtr->vars[2].swizzle[3] == SWIZ_Z) ? 'z' : (instPtr->vars[2].swizzle[3] == SWIZ_W) ? 'w' : ' ',
instPtr->vars[3].sign ? (instPtr->vars[3].sign == -1 ? '-' : '+') : ' ', instPtr->vars[3].var ? ((instPtr->vars[3].var->type == VARTYPE_CONST) ? instPtr->vars[3].var->init.strings[0] : instPtr->vars[3].var->names[0]) : "(none)", instPtr->vars[3].floatArrAddr ? instPtr->vars[3].floatArrAddr : "", (instPtr->vars[3].swizzle[0] == SWIZ_X) ? 'x' : (instPtr->vars[3].swizzle[0] == SWIZ_Y) ? 'y' : (instPtr->vars[3].swizzle[0] == SWIZ_Z) ? 'z' : (instPtr->vars[3].swizzle[0] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[3].swizzle[1] == SWIZ_X) ? 'x' : (instPtr->vars[3].swizzle[1] == SWIZ_Y) ? 'y' : (instPtr->vars[3].swizzle[1] == SWIZ_Z) ? 'z' : (instPtr->vars[3].swizzle[1] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[3].swizzle[2] == SWIZ_X) ? 'x' : (instPtr->vars[3].swizzle[2] == SWIZ_Y) ? 'y' : (instPtr->vars[3].swizzle[2] == SWIZ_Z) ? 'z' : (instPtr->vars[3].swizzle[2] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[3].swizzle[3] == SWIZ_X) ? 'x' : (instPtr->vars[3].swizzle[3] == SWIZ_Y) ? 'y' : (instPtr->vars[3].swizzle[3] == SWIZ_Z) ? 'z' : (instPtr->vars[3].swizzle[3] == SWIZ_W) ? 'w' : ' '
);
}
fflush(stdout);
)
generateInstruction(&curStatus, vertex, error_msg, instPtr);
}
if (curStatus.status == ST_ERROR) {
--instIdx;
*error_ptr = curStatus.instructions.insts[instIdx]->codeLocation - code;
break;
}
APPEND_OUTPUT("\t\n", 2)
for (varIdx = 0; (varIdx < curStatus.variables.size) && (curStatus.status != ST_ERROR); ++varIdx) {
varPtr = curStatus.variables.vars[varIdx];
ARBCONV_DBG_AS(
printf("Variable #%2ld (output): %10s (%10s)\n", varIdx, varPtr->names[0], VARTYPE2STR(varPtr->type));
fflush(stdout);
)
generateVariablePst(&curStatus, vertex, error_msg, varPtr);
}
if (curStatus.status == ST_ERROR) {
--varIdx;
*error_ptr = 2;
break;
}
if (specialCases.hasFogFragCoord) {
APPEND_OUTPUT("\tgl_FogFragCoord = gl4es_FogFragCoordTemp.x;\n", 45)
}
if (specialCases.isDepthReplacing) {
APPEND_OUTPUT("\tgl_FragDepth = gl4es_FragDepthTemp.z;\n", 39)
}
switch (curStatus.fogType) {
case FOG_NONE:
break;
case FOG_EXP:
APPEND_OUTPUT(
"\tgl_FragColor.rgb = mix(gl_Fog.color.rgb, gl_FragColor.rgb, "
"clamp(exp(-gl_Fog.density * gl_FogFragCoord), 0., 1.));\n",
116
)
break;
case FOG_EXP2:
APPEND_OUTPUT(
"\tgl_FragColor.rgb = mix(gl_Fog.color.rgb, gl_FragColor.rgb, "
"clamp(exp(-(gl_Fog.density * gl_FogFragCoord)*(gl_Fog.density * gl_FogFragCoord)), 0., 1.));\n",
153
)
break;
case FOG_LINEAR:
APPEND_OUTPUT(
"\tgl_FragColor.rgb = mix(gl_Fog.color.rgb, gl_FragColor.rgb, "
"clamp((gl_Fog.end - gl_FogFragCoord) * gl_Fog.scale, 0., 1.));\n",
123
)
break;
}
if(curStatus.position_invariant) {
APPEND_OUTPUT("\tgl_Position = ftransform();\n", 29)
}
APPEND_OUTPUT("}\n", 2)
} while (0);
#undef FAIL
#undef APPEND_OUTPUT
#undef APPEND_OUTPUT2
if (curStatus.status == ST_ERROR) {
ARBCONV_DBG(printf("Failure!\n");
printf("\nVariables:\n==========\n");
{
const char *kvar;
sVariable *vvar;
kh_foreach(curStatus.varsMap, kvar, vvar,
if (vvar) {
printf("Variable %10s pointing to %p (%10s)\n", kvar, vvar, vvar->names[0]);
} else {
printf("\033[91mVariable %10s pointing to NULLptr!\033[m\n", kvar);
}
)
}
for (size_t i = 0; i < curStatus.variables.size; ++i) {
varPtr = curStatus.variables.vars[i];
printf("%sVariable %p %10s (%lu): %-10s (init = %3lu %s)\033[m\n", (i < varIdx) ? "" : "\033[91m", varPtr, varPtr->names[0], varPtr->names_count, VARTYPE2STR(varPtr->type), varPtr->init.strings_total_len, varPtr->init.strings_count ? varPtr->init.strings[0] : "(none)");
}
printf("\nInstructions:\n=============\n");
for (size_t i = 0; i < curStatus.instructions.size; ++i) {
instPtr = curStatus.instructions.insts[i];
if (INSTTEX(instPtr->type)) {
printf("%sInstruction %3s%4s %c%10s[%2s].%c%c%c%c %c%10s[%2s].%c%c%c%c %ctexture[%2s] %c%19s\033[m\n", (i < instIdx) ? "" : "\033[91m", INST2STR(instPtr->type), instPtr->saturated ? "_SAT" : " ",
instPtr->vars[0].sign ? (instPtr->vars[0].sign == -1 ? '-' : '+') : ' ', instPtr->vars[0].var ? ((instPtr->vars[0].var->type == VARTYPE_CONST) ? instPtr->vars[0].var->init.strings[0] : instPtr->vars[0].var->names[0]) : "(none)", instPtr->vars[0].floatArrAddr ? instPtr->vars[0].floatArrAddr : "", (instPtr->vars[0].swizzle[0] == SWIZ_X) ? 'x' : (instPtr->vars[0].swizzle[0] == SWIZ_Y) ? 'y' : (instPtr->vars[0].swizzle[0] == SWIZ_Z) ? 'z' : (instPtr->vars[0].swizzle[0] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[0].swizzle[1] == SWIZ_X) ? 'x' : (instPtr->vars[0].swizzle[1] == SWIZ_Y) ? 'y' : (instPtr->vars[0].swizzle[1] == SWIZ_Z) ? 'z' : (instPtr->vars[0].swizzle[1] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[0].swizzle[2] == SWIZ_X) ? 'x' : (instPtr->vars[0].swizzle[2] == SWIZ_Y) ? 'y' : (instPtr->vars[0].swizzle[2] == SWIZ_Z) ? 'z' : (instPtr->vars[0].swizzle[2] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[0].swizzle[3] == SWIZ_X) ? 'x' : (instPtr->vars[0].swizzle[3] == SWIZ_Y) ? 'y' : (instPtr->vars[0].swizzle[3] == SWIZ_Z) ? 'z' : (instPtr->vars[0].swizzle[3] == SWIZ_W) ? 'w' : ' ',
instPtr->vars[1].sign ? (instPtr->vars[1].sign == -1 ? '-' : '+') : ' ', instPtr->vars[1].var ? ((instPtr->vars[1].var->type == VARTYPE_CONST) ? instPtr->vars[1].var->init.strings[0] : instPtr->vars[1].var->names[0]) : "(none)", instPtr->vars[1].floatArrAddr ? instPtr->vars[1].floatArrAddr : "", (instPtr->vars[1].swizzle[0] == SWIZ_X) ? 'x' : (instPtr->vars[1].swizzle[0] == SWIZ_Y) ? 'y' : (instPtr->vars[1].swizzle[0] == SWIZ_Z) ? 'z' : (instPtr->vars[1].swizzle[0] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[1].swizzle[1] == SWIZ_X) ? 'x' : (instPtr->vars[1].swizzle[1] == SWIZ_Y) ? 'y' : (instPtr->vars[1].swizzle[1] == SWIZ_Z) ? 'z' : (instPtr->vars[1].swizzle[1] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[1].swizzle[2] == SWIZ_X) ? 'x' : (instPtr->vars[1].swizzle[2] == SWIZ_Y) ? 'y' : (instPtr->vars[1].swizzle[2] == SWIZ_Z) ? 'z' : (instPtr->vars[1].swizzle[2] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[1].swizzle[3] == SWIZ_X) ? 'x' : (instPtr->vars[1].swizzle[3] == SWIZ_Y) ? 'y' : (instPtr->vars[1].swizzle[3] == SWIZ_Z) ? 'z' : (instPtr->vars[1].swizzle[3] == SWIZ_W) ? 'w' : ' ',
instPtr->vars[2].sign ? (instPtr->vars[2].sign == -1 ? '-' : '+') : ' ', instPtr->vars[2].var->names[0],
instPtr->vars[3].sign ? (instPtr->vars[3].sign == -1 ? '-' : '+') : ' ', (instPtr->vars[3].var == curStatus.tex1D) ? "1D" : (instPtr->vars[3].var == curStatus.tex2D) ? "2D" : (instPtr->vars[3].var == curStatus.tex3D) ? "3D" : (instPtr->vars[3].var == curStatus.texCUBE) ? "CUBE" : (instPtr->vars[3].var == curStatus.texRECT) ? "RECT" : "!!!"
);
} else {
printf("%sInstruction %3s%4s %c%10s[%2s].%c%c%c%c %c%10s[%2s].%c%c%c%c %c%10s[%2s].%c%c%c%c %c%10s[%2s].%c%c%c%c\033[m\n", (i < instIdx) ? "" : "\033[91m", INST2STR(instPtr->type), instPtr->saturated ? "_SAT" : " ",
instPtr->vars[0].sign ? (instPtr->vars[0].sign == -1 ? '-' : '+') : ' ', instPtr->vars[0].var ? ((instPtr->vars[0].var->type == VARTYPE_CONST) ? instPtr->vars[0].var->init.strings[0] : instPtr->vars[0].var->names[0]) : "(none)", instPtr->vars[0].floatArrAddr ? instPtr->vars[0].floatArrAddr : "", (instPtr->vars[0].swizzle[0] == SWIZ_X) ? 'x' : (instPtr->vars[0].swizzle[0] == SWIZ_Y) ? 'y' : (instPtr->vars[0].swizzle[0] == SWIZ_Z) ? 'z' : (instPtr->vars[0].swizzle[0] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[0].swizzle[1] == SWIZ_X) ? 'x' : (instPtr->vars[0].swizzle[1] == SWIZ_Y) ? 'y' : (instPtr->vars[0].swizzle[1] == SWIZ_Z) ? 'z' : (instPtr->vars[0].swizzle[1] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[0].swizzle[2] == SWIZ_X) ? 'x' : (instPtr->vars[0].swizzle[2] == SWIZ_Y) ? 'y' : (instPtr->vars[0].swizzle[2] == SWIZ_Z) ? 'z' : (instPtr->vars[0].swizzle[2] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[0].swizzle[3] == SWIZ_X) ? 'x' : (instPtr->vars[0].swizzle[3] == SWIZ_Y) ? 'y' : (instPtr->vars[0].swizzle[3] == SWIZ_Z) ? 'z' : (instPtr->vars[0].swizzle[3] == SWIZ_W) ? 'w' : ' ',
instPtr->vars[1].sign ? (instPtr->vars[1].sign == -1 ? '-' : '+') : ' ', instPtr->vars[1].var ? ((instPtr->vars[1].var->type == VARTYPE_CONST) ? instPtr->vars[1].var->init.strings[0] : instPtr->vars[1].var->names[0]) : "(none)", instPtr->vars[1].floatArrAddr ? instPtr->vars[1].floatArrAddr : "", (instPtr->vars[1].swizzle[0] == SWIZ_X) ? 'x' : (instPtr->vars[1].swizzle[0] == SWIZ_Y) ? 'y' : (instPtr->vars[1].swizzle[0] == SWIZ_Z) ? 'z' : (instPtr->vars[1].swizzle[0] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[1].swizzle[1] == SWIZ_X) ? 'x' : (instPtr->vars[1].swizzle[1] == SWIZ_Y) ? 'y' : (instPtr->vars[1].swizzle[1] == SWIZ_Z) ? 'z' : (instPtr->vars[1].swizzle[1] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[1].swizzle[2] == SWIZ_X) ? 'x' : (instPtr->vars[1].swizzle[2] == SWIZ_Y) ? 'y' : (instPtr->vars[1].swizzle[2] == SWIZ_Z) ? 'z' : (instPtr->vars[1].swizzle[2] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[1].swizzle[3] == SWIZ_X) ? 'x' : (instPtr->vars[1].swizzle[3] == SWIZ_Y) ? 'y' : (instPtr->vars[1].swizzle[3] == SWIZ_Z) ? 'z' : (instPtr->vars[1].swizzle[3] == SWIZ_W) ? 'w' : ' ',
instPtr->vars[2].sign ? (instPtr->vars[2].sign == -1 ? '-' : '+') : ' ', instPtr->vars[2].var ? ((instPtr->vars[2].var->type == VARTYPE_CONST) ? instPtr->vars[2].var->init.strings[0] : instPtr->vars[2].var->names[0]) : "(none)", instPtr->vars[2].floatArrAddr ? instPtr->vars[2].floatArrAddr : "", (instPtr->vars[2].swizzle[0] == SWIZ_X) ? 'x' : (instPtr->vars[2].swizzle[0] == SWIZ_Y) ? 'y' : (instPtr->vars[2].swizzle[0] == SWIZ_Z) ? 'z' : (instPtr->vars[2].swizzle[0] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[2].swizzle[1] == SWIZ_X) ? 'x' : (instPtr->vars[2].swizzle[1] == SWIZ_Y) ? 'y' : (instPtr->vars[2].swizzle[1] == SWIZ_Z) ? 'z' : (instPtr->vars[2].swizzle[1] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[2].swizzle[2] == SWIZ_X) ? 'x' : (instPtr->vars[2].swizzle[2] == SWIZ_Y) ? 'y' : (instPtr->vars[2].swizzle[2] == SWIZ_Z) ? 'z' : (instPtr->vars[2].swizzle[2] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[2].swizzle[3] == SWIZ_X) ? 'x' : (instPtr->vars[2].swizzle[3] == SWIZ_Y) ? 'y' : (instPtr->vars[2].swizzle[3] == SWIZ_Z) ? 'z' : (instPtr->vars[2].swizzle[3] == SWIZ_W) ? 'w' : ' ',
instPtr->vars[3].sign ? (instPtr->vars[3].sign == -1 ? '-' : '+') : ' ', instPtr->vars[3].var ? ((instPtr->vars[3].var->type == VARTYPE_CONST) ? instPtr->vars[3].var->init.strings[0] : instPtr->vars[3].var->names[0]) : "(none)", instPtr->vars[3].floatArrAddr ? instPtr->vars[3].floatArrAddr : "", (instPtr->vars[3].swizzle[0] == SWIZ_X) ? 'x' : (instPtr->vars[3].swizzle[0] == SWIZ_Y) ? 'y' : (instPtr->vars[3].swizzle[0] == SWIZ_Z) ? 'z' : (instPtr->vars[3].swizzle[0] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[3].swizzle[1] == SWIZ_X) ? 'x' : (instPtr->vars[3].swizzle[1] == SWIZ_Y) ? 'y' : (instPtr->vars[3].swizzle[1] == SWIZ_Z) ? 'z' : (instPtr->vars[3].swizzle[1] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[3].swizzle[2] == SWIZ_X) ? 'x' : (instPtr->vars[3].swizzle[2] == SWIZ_Y) ? 'y' : (instPtr->vars[3].swizzle[2] == SWIZ_Z) ? 'z' : (instPtr->vars[3].swizzle[2] == SWIZ_W) ? 'w' : ' ', (instPtr->vars[3].swizzle[3] == SWIZ_X) ? 'x' : (instPtr->vars[3].swizzle[3] == SWIZ_Y) ? 'y' : (instPtr->vars[3].swizzle[3] == SWIZ_Z) ? 'z' : (instPtr->vars[3].swizzle[3] == SWIZ_W) ? 'w' : ' '
);
}
}
printf("\nBuffered output:\n%s\n", curStatus.outputString);)
if (*error_ptr == -1) {
if (*error_msg)
free(*error_msg);
*error_msg = strdup("Not enough memory(?)");
*error_ptr = 0;
}
// We have errored, output NULL
freeStatus(&curStatus);
free(curStatus.outputString);
return NULL;
}
ARBCONV_DBG(printf("Success!\n\nOutput:\n%s", curStatus.outputString);)
freeStatus(&curStatus);
return curStatus.outputString;
}
+8
View File
@@ -0,0 +1,8 @@
#ifndef _GL4ES_ARBCONVERTER_H_
#define _GL4ES_ARBCONVERTER_H_
#include <stdint.h>
char* gl4es_convertARB(const char* const code, int vertex, char **error_msg, int *error_ptr);
#endif // _GL4ES_ARBCONVERTER_H_
File diff suppressed because it is too large Load Diff
+18
View File
@@ -0,0 +1,18 @@
#ifndef _GL4ES_ARBGENERATOR_H_
#define _GL4ES_ARBGENERATOR_H_
#include <stddef.h>
#include "arbhelper.h"
#define APPEND_OUTPUT(str, len) \
if (appendString(curStatusPtr, str, len)) { \
FAIL("Unknown error (not enough memory?"); \
}
#define APPEND_OUTPUT2(str) APPEND_OUTPUT(str, (size_t)-1)
void generateVariablePre(sCurStatus *curStatusPtr, int vertex, char **error_msg, sVariable *varPtr);
void generateInstruction(sCurStatus *curStatusPtr, int vertex, char **error_msg, sInstruction *instPtr);
void generateVariablePst(sCurStatus *curStatusPtr, int vertex, char **error_msg, sVariable *varPtr);
#endif // _GL4ES_ARBGENERATOR_H_
+383
View File
@@ -0,0 +1,383 @@
#include "arbhelper.h"
#include "../config.h"
#define SIZE_THRESHOLD 0x40
void *resize(void** obj, size_t* cap, size_t esize) {
size_t oldSize = *cap * esize;
size_t newSize;
if (oldSize >= SIZE_THRESHOLD) {
newSize = oldSize + SIZE_THRESHOLD * esize;
} else {
newSize = oldSize * 2;
}
void *reloc = realloc(*obj, newSize);
if (reloc) {
*obj = reloc;
*cap = newSize;
}
return reloc;
}
void initArray(sArray* arr) {
arr->objs = calloc(DEFAULT_MALLOC_COUNT, sizeof(void*));
arr->size = 0;
arr->cap = DEFAULT_MALLOC_COUNT;
}
int pushArray(sArray* arr, void* obj) {
if (arr->size >= arr->cap) {
if (!resize((void**)&arr->objs, &arr->cap, sizeof(void*))) {
return 0;
}
}
arr->objs[arr->size] = obj;
++arr->size;
return 1;
}
void* popArray(sArray* arr) {
if (!arr->size) {
return NULL;
}
--arr->size;
void *ret = arr->objs[arr->size];
arr->objs[arr->size] = NULL;
return ret;
}
void* popFIFO(sArray* arr) {
if (!arr->size) {
return NULL;
}
--arr->size;
void *ret = arr->objs[0];
memmove(arr->objs, arr->objs + 1, arr->size * sizeof(void*));
arr->objs[arr->size] = NULL;
return ret;
}
void freeArray(sArray* arr) {
while (arr->size) {
--arr->size;
free(arr->objs[arr->size]);
}
free(arr->objs);
arr->objs = NULL;
}
#define TST_STR_VAL_PREF(str, pref, inst) (!strncmp(str, #inst, strlen(#inst))) ? pref##inst :
eVariableType STR2VARTYPE(char *str) {
return
TST_STR_VAL_PREF(str, VARTYPE_, ADDRESS) TST_STR_VAL_PREF(str, VARTYPE_, ATTRIB)
TST_STR_VAL_PREF(str, VARTYPE_, PARAM) TST_STR_VAL_PREF(str, VARTYPE_, TEMP)
TST_STR_VAL_PREF(str, VARTYPE_, ALIAS) TST_STR_VAL_PREF(str, VARTYPE_, OUTPUT)
VARTYPE_UNK;
}
eInstruction STR2INST(char *str, int *sat) {
if ((str[0] == '\0') || (str[1] == '\0') || (str[2] == '\0')) return INST_UNK;
*sat = !strcmp(str + 3, "_SAT");
if ((((str[0] < 'A') || (str[0] > 'Z')) && ((str[0] < '0') || (str[0] > '9')))
|| (((str[1] < 'A') || (str[1] > 'Z')) && ((str[1] < '0') || (str[1] > '9')))
|| (((str[2] < 'A') || (str[2] > 'Z')) && ((str[2] < '0') || (str[2] > '9')))
|| ((str[3] != '\0') && !*sat)) {
return INST_UNK;
}
switch (str[0]) {
case 'A':
switch (str[1]) {
case 'B':
return (str[2] == 'S') ? INST_ABS : INST_UNK;
case 'D':
return (str[2] == 'D') ? INST_ADD : INST_UNK;
case 'R':
return (str[2] == 'L') ? INST_ARL : INST_UNK;
default:
return INST_UNK;
}
case 'C':
switch (str[1]) {
case 'M':
return (str[2] == 'P') ? INST_CMP : INST_UNK;
case 'O':
return (str[2] == 'S') ? INST_COS : INST_UNK;
default:
return INST_UNK;
}
case 'D':
switch (str[2]) {
case '3':
return (str[1] == 'P') ? INST_DP3 : INST_UNK;
case '4':
return (str[1] == 'P') ? INST_DP4 : INST_UNK;
case 'H':
return (str[1] == 'P') ? INST_DPH : INST_UNK;
case 'T':
return (str[1] == 'S') ? INST_DST : INST_UNK;
default:
return INST_UNK;
}
case 'E':
if (str[1] != 'X') return INST_UNK;
switch (str[2]) {
case '2':
return INST_EX2;
case 'P':
return INST_EXP;
default:
return INST_UNK;
}
case 'F':
switch (str[1]) {
case 'L':
return (str[2] == 'R') ? INST_FLR : INST_UNK;
case 'R':
return (str[2] == 'C') ? INST_FRC : INST_UNK;
default:
return INST_UNK;
}
case 'K':
return ((str[1] == 'I') && (str[2] == 'L')) ? INST_KIL : INST_UNK;
case 'L':
switch (str[1]) {
case 'G':
return (str[2] == '2') ? INST_LG2 : INST_UNK;
case 'I':
return (str[2] == 'T') ? INST_LIT : INST_UNK;
case 'O':
return (str[2] == 'G') ? INST_LOG : INST_UNK;
case 'R':
return (str[2] == 'P') ? INST_LRP : INST_UNK;
default:
return INST_UNK;
}
case 'M':
switch (str[2]) {
case 'D':
return (str[1] == 'A') ? INST_MAD : INST_UNK;
case 'X':
return (str[1] == 'A') ? INST_MAX : INST_UNK;
case 'N':
return (str[1] == 'I') ? INST_MIN : INST_UNK;
case 'V':
return (str[1] == 'O') ? INST_MOV : INST_UNK;
case 'L':
return (str[1] == 'U') ? INST_MUL : INST_UNK;
default:
return INST_UNK;
}
case 'P':
return ((str[1] == 'O') && (str[2] == 'W')) ? INST_POW : INST_UNK;
case 'R':
switch (str[1]) {
case 'C':
return (str[2] == 'P') ? INST_RCP : INST_UNK;
case 'S':
return (str[2] == 'Q') ? INST_RSQ : INST_UNK;
default:
return INST_UNK;
}
case 'S':
switch (str[1]) {
case 'C':
return (str[2] == 'S') ? INST_SCS : INST_UNK;
case 'G':
return (str[2] == 'E') ? INST_SGE : INST_UNK;
case 'I':
return (str[2] == 'N') ? INST_SIN : INST_UNK;
case 'L':
return (str[2] == 'T') ? INST_SLT : INST_UNK;
case 'U':
return (str[2] == 'B') ? INST_SUB : INST_UNK;
case 'W':
return (str[2] == 'Z') ? INST_SWZ : INST_UNK;
default:
return INST_UNK;
}
case 'T':
switch (str[2]) {
case 'X':
return (str[1] == 'E') ? INST_TEX : INST_UNK;
case 'B':
return (str[1] == 'X') ? INST_TXB : INST_UNK;
case 'P':
return (str[1] == 'X') ? INST_TXP : INST_UNK;
default:
return INST_UNK;
}
case 'X':
return ((str[1] == 'P') && (str[2] == 'D')) ? INST_XPD : INST_UNK;
default:
return INST_UNK;
}
}
#define INSTTEX(i) (((i) == INST_TEX) || ((i) == INST_TXB) || ((i) == INST_TXP))
KHASH_MAP_IMPL_STR(variables, sVariable*)
sVariable *createVariable(eVariableType type) {
sVariable *var = (sVariable*)calloc(1, sizeof(sVariable)); // malloc *should* be fine here
initArray((sArray*)var);
initArray((sArray*)&var->init);
var->type = type;
var->init.strings_total_len = 0;
var->size = 0;
return var;
}
void deleteVariable(sVariable **var) {
freeArray((sArray*)*var);
char *stringPtr;
while ((stringPtr = popArray((sArray*)&(*var)->init))) {
free(stringPtr);
}
freeArray((sArray*)&(*var)->init);
free(*var);
*var = NULL;
}
sInstruction *copyInstruction(const sInstruction *orig) {
sInstruction *dup = (sInstruction*)malloc(sizeof(sInstruction));
memcpy(dup, orig, sizeof(sInstruction));
return dup;
}
void initStatus(sCurStatus* curStatus, const char* code) {
curStatus->status = ST_LINE_START;
curStatus->arbVersion = 10; // Todo?
curStatus->codePtr = code;
curStatus->endOfToken = code;
curStatus->outputString = malloc(DEFAULT_STRING_MALLOC_SIZE);
curStatus->outputString[0] = '\0';
curStatus->outputEnd = curStatus->outputString;
curStatus->outLen = 0;
curStatus->outCap = DEFAULT_STRING_CAP;
curStatus->outLeft = DEFAULT_STRING_CAP - 1;
curStatus->valueType = TYPE_NONE;
curStatus->texVars = (sVariable**)malloc(MAX_TEX * sizeof(sVariable*));
for (size_t i = 0; i < MAX_TEX; ++i) {
curStatus->texVars[i] = createVariable(VARTYPE_TEXTURE);
}
curStatus->tex1D = (sVariable*)malloc(sizeof(sVariable));
curStatus->tex1D->type = VARTYPE_TEXTARGET;
curStatus->tex2D = (sVariable*)malloc(sizeof(sVariable));
curStatus->tex2D->type = VARTYPE_TEXTARGET;
curStatus->tex3D = (sVariable*)malloc(sizeof(sVariable));
curStatus->tex3D->type = VARTYPE_TEXTARGET;
curStatus->texCUBE = (sVariable*)malloc(sizeof(sVariable));
curStatus->texCUBE->type = VARTYPE_TEXTARGET;
curStatus->texRECT = (sVariable*)malloc(sizeof(sVariable));
curStatus->texRECT->type = VARTYPE_TEXTARGET;
curStatus->varsMap = kh_init(variables);
initArray((sArray*)&curStatus->variables);
initArray((sArray*)&curStatus->instructions);
curStatus->fogType = FOG_NONE;
initArray((sArray*)&curStatus->_fixedNewVar);
curStatus->_fixedNewVar.var = NULL;
}
void freeStatus(sCurStatus* curStatus) {
if (curStatus->valueType == TYPE_INST_DECL) {
for (int i = 0; i < MAX_OPERANDS; ++i) {
if (curStatus->curValue.newInst.inst.vars[i].floatArrAddr) {
free(curStatus->curValue.newInst.inst.vars[i].floatArrAddr);
}
}
} else if (curStatus->valueType == TYPE_VARIABLE_DECL) {
char *strPtr;
while ((strPtr = (char*)popArray((sArray*)&curStatus->curValue.newVar))) {
free(strPtr);
}
freeArray((sArray*)&curStatus->curValue.newVar);
deleteVariable(&curStatus->curValue.newVar.var);
} else if (curStatus->valueType == TYPE_ALIAS_DECL) {
if (curStatus->curValue.string) {
free(curStatus->curValue.string);
}
} else if (curStatus->valueType == TYPE_OPTION_DECL) {
if (curStatus->curValue.newOpt.optName) {
free(curStatus->curValue.newOpt.optName);
}
}
curStatus->valueType = TYPE_NONE;
for (size_t i = 0; i < MAX_TEX; ++i) {
deleteVariable(&curStatus->texVars[i]);
}
free(curStatus->texVars);
free(curStatus->tex1D);
free(curStatus->tex2D);
free(curStatus->tex3D);
free(curStatus->texCUBE);
free(curStatus->texRECT);
kh_destroy(variables, curStatus->varsMap);
sVariable *varPtr;
while ((varPtr = (sVariable*)popArray((sArray*)&curStatus->variables))) {
deleteVariable(&varPtr);
}
sInstruction *instPtr;
while ((instPtr = (sInstruction*)popArray((sArray*)&curStatus->instructions))) {
for (int i = 0; i < MAX_OPERANDS; ++i) {
if (instPtr->vars[i].floatArrAddr) {
free(instPtr->vars[i].floatArrAddr);
}
}
free(instPtr);
}
freeArray((sArray*)&curStatus->variables);
freeArray((sArray*)&curStatus->instructions);
freeArray((sArray*)&curStatus->_fixedNewVar);
}
int appendString(sCurStatus *curStatusPtr, const char *str, size_t strLen) {
if (strLen == (size_t)-1) {
strLen = strlen(str);
}
if (curStatusPtr->outLeft < strLen) {
char *oldOut = curStatusPtr->outputString;
while (curStatusPtr->outLeft < strLen) {
if (curStatusPtr->outCap >= SIZE_THRESHOLD) {
curStatusPtr->outLeft += SIZE_THRESHOLD * sizeof(char);
} else {
curStatusPtr->outLeft *= 2;
}
if (!resize((void**)&curStatusPtr->outputString, &curStatusPtr->outCap, sizeof(char))) {
return 1;
}
}
curStatusPtr->outputEnd += curStatusPtr->outputString - oldOut;
}
ARBCONV_DBG_HEAVY(ARBCONV_DBG(
char *dup = malloc((strLen + 1) * sizeof(char)); memcpy(dup, str, strLen); dup[strLen] = '\0'; printf(
"Appending '%s' to %p (%p + %ld = %p)\n",
dup,
curStatusPtr->outputEnd,
curStatusPtr->outputString,
curStatusPtr->outLen,
curStatusPtr->outputString + curStatusPtr->outLen
); free(dup); fflush(stdout);)
if (curStatusPtr->outputEnd != curStatusPtr->outputString + curStatusPtr->outLen) {
printf("\033[01;31mERROR!!!\033[m\n%s\n", str);
curStatusPtr->status = ST_ERROR;
return 1;
})
strcpy(curStatusPtr->outputEnd, str);
curStatusPtr->outLen += strLen;
curStatusPtr->outLeft -= strLen;
curStatusPtr->outputEnd += strLen;
return 0;
}
+317
View File
@@ -0,0 +1,317 @@
#ifndef _GL4ES_ARBHELPER_H_
#define _GL4ES_ARBHELPER_H_
#include <stddef.h>
#include "khash.h"
//#define DEBUG
#ifdef DEBUG
#include <stdio.h>
// ARBCONV_DBG - general ArbConverter debug logs
#define ARBCONV_DBG(a) a
// ARBCONV_DBG_LP - code loop ArbConverter debug logs
#define ARBCONV_DBG_LP(a) a
// ARBCONV_DBG_AS - reassembly loop (2nd loop) ArbConverter debug logs
#define ARBCONV_DBG_AS(a) a
// ARBCONV_DBG_HEAVY - heavy ArbConverter debug logs and operations (e.g. check for pointer correctness...)
#define ARBCONV_DBG_HEAVY(a) a
#else
// ARBCONV_DBG - general ArbConverter debug logs
#define ARBCONV_DBG(a)
// ARBCONV_DBG_LP - code loop ArbConverter debug logs
#define ARBCONV_DBG_LP(a)
// ARBCONV_DBG_AS - reassembly loop (2nd loop) ArbConverter debug logs
#define ARBCONV_DBG_AS(a)
// ARBCONV_DBG_HEAVY - heavy ArbConverter debug logs and operations (e.g. check for pointer correctness...)
#define ARBCONV_DBG_HEAVY(a)
#endif
#ifdef MAX_TEX
#if MAX_TEX != 16
#error Please update the string
#endif
#define MAX_TEX_STR "16"
#define MAX_TEX_STRLEN 2
#endif
#define DEFAULT_MALLOC_COUNT 32
#define DEFAULT_STRING_CAP 1024
#define DEFAULT_STRING_MALLOC_SIZE (DEFAULT_STRING_CAP * sizeof(char))
void *resize(void** obj, size_t* cap, size_t esize);
typedef struct _sArray {
void **objs; // Array of pointers
size_t size;
size_t cap;
} sArray;
void initArray(sArray* arr);
int pushArray(sArray* arr, void* obj);
void* popArray(sArray* arr);
void* popFIFO(sArray* arr);
void freeArray(sArray* arr);
typedef enum _eVariableType {
VARTYPE_ADDRESS = 0,
VARTYPE_ATTRIB,
VARTYPE_PARAM,
VARTYPE_PARAM_MULT,
VARTYPE_TEMP,
VARTYPE_ALIAS,
VARTYPE_OUTPUT,
VARTYPE_CONST, // Used when having an anonymous variable
VARTYPE_TEXTURE, // Not available in vertex programs, fixed name in fragment programs
VARTYPE_TEXTARGET, // Not available in vertex programs, fixed name in fragment programs
VARTYPE_UNK
} eVariableType;
typedef enum _eInstruction {
INST_ABS = 0, INST_ADD, INST_ARL, INST_CMP, INST_COS, INST_DP3, INST_DP4, INST_DPH,
INST_DST, INST_EX2, INST_EXP, INST_FLR, INST_FRC, INST_KIL, INST_LG2, INST_LIT,
INST_LOG, INST_LRP, INST_MAD, INST_MAX, INST_MIN, INST_MOV, INST_MUL, INST_POW,
INST_RCP, INST_RSQ, INST_SCS, INST_SGE, INST_SIN, INST_SLT, INST_SUB, INST_SWZ,
INST_TEX, INST_TXB, INST_TXP, INST_XPD,
INST_UNK
} eInstruction;
typedef enum _eStatus {
ST_LINE_START = 0,
ST_LINE_COMMENT,
ST_VARIABLE,
ST_VARIABLE_INIT,
ST_ALIAS,
ST_ALIASING,
ST_INSTRUCTION,
ST_OPTION,
ST_DONE,
ST_ERROR
} eStatus;
typedef enum _eToken {
TOK_NULL = 0,
TOK_WHITESPACE,
TOK_SIGN,
TOK_INTEGER,
TOK_FLOATCONST,
TOK_IDENTIFIER,
TOK_POINT,
TOK_UPTO,
TOK_COMMA,
TOK_EQUALS,
TOK_LSQBRACKET,
TOK_RSQBRACKET,
TOK_LBRACE,
TOK_RBRACE,
TOK_END_OF_INST,
TOK_LINE_COMMENT,
TOK_NEWLINE,
TOK_END,
TOK_UNKNOWN
} eToken;
eVariableType STR2VARTYPE(char *str);
eInstruction STR2INST(char *str, int *sat);
#define INSTTEX(i) (((i) == INST_TEX) || ((i) == INST_TXB) || ((i) == INST_TXP))
#define ENUMVALUE2STR(v, e, v2) (v == e##v2) ? #v2 :
#ifdef DEBUG
#define VARTYPE2STR(vartype) ( \
ENUMVALUE2STR(vartype, VARTYPE_,ADDRESS) \
ENUMVALUE2STR(vartype, VARTYPE_,ATTRIB) \
ENUMVALUE2STR(vartype, VARTYPE_,PARAM) \
ENUMVALUE2STR(vartype, VARTYPE_,PARAM_MULT) \
ENUMVALUE2STR(vartype, VARTYPE_,TEMP) \
ENUMVALUE2STR(vartype, VARTYPE_,OUTPUT) \
ENUMVALUE2STR(vartype, VARTYPE_,CONST) \
"???")
#define INST2STR(inst) ( \
ENUMVALUE2STR(inst, INST_,ABS) ENUMVALUE2STR(inst, INST_,ADD) \
ENUMVALUE2STR(inst, INST_,ARL) ENUMVALUE2STR(inst, INST_,CMP) \
ENUMVALUE2STR(inst, INST_,COS) ENUMVALUE2STR(inst, INST_,DP3) \
ENUMVALUE2STR(inst, INST_,DP4) ENUMVALUE2STR(inst, INST_,DPH) \
ENUMVALUE2STR(inst, INST_,DST) ENUMVALUE2STR(inst, INST_,EX2) \
ENUMVALUE2STR(inst, INST_,EXP) ENUMVALUE2STR(inst, INST_,FLR) \
ENUMVALUE2STR(inst, INST_,FRC) ENUMVALUE2STR(inst, INST_,KIL) \
ENUMVALUE2STR(inst, INST_,LG2) ENUMVALUE2STR(inst, INST_,LIT) \
ENUMVALUE2STR(inst, INST_,LOG) ENUMVALUE2STR(inst, INST_,LRP) \
ENUMVALUE2STR(inst, INST_,MAD) ENUMVALUE2STR(inst, INST_,MAX) \
ENUMVALUE2STR(inst, INST_,MIN) ENUMVALUE2STR(inst, INST_,MOV) \
ENUMVALUE2STR(inst, INST_,MUL) ENUMVALUE2STR(inst, INST_,POW) \
ENUMVALUE2STR(inst, INST_,RCP) ENUMVALUE2STR(inst, INST_,RSQ) \
ENUMVALUE2STR(inst, INST_,SCS) ENUMVALUE2STR(inst, INST_,SGE) \
ENUMVALUE2STR(inst, INST_,SIN) ENUMVALUE2STR(inst, INST_,SLT) \
ENUMVALUE2STR(inst, INST_,SUB) ENUMVALUE2STR(inst, INST_,SWZ) \
ENUMVALUE2STR(inst, INST_,TEX) ENUMVALUE2STR(inst, INST_,TXB) \
ENUMVALUE2STR(inst, INST_,TXP) ENUMVALUE2STR(inst, INST_,XPD) \
"???")
#define STATUS2STR(s) (\
ENUMVALUE2STR(s, ST_,LINE_START) \
ENUMVALUE2STR(s, ST_,LINE_COMMENT) \
ENUMVALUE2STR(s, ST_,VARIABLE) \
ENUMVALUE2STR(s, ST_,VARIABLE_INIT) \
ENUMVALUE2STR(s, ST_,ALIAS) \
ENUMVALUE2STR(s, ST_,ALIASING) \
ENUMVALUE2STR(s, ST_,INSTRUCTION) \
ENUMVALUE2STR(s, ST_,OPTION) \
ENUMVALUE2STR(s, ST_,DONE) \
ENUMVALUE2STR(s, ST_,ERROR) \
"???")
#endif
#define TOKEN2STR(t) (\
ENUMVALUE2STR(t, TOK_,NULL) \
ENUMVALUE2STR(t, TOK_,WHITESPACE) \
ENUMVALUE2STR(t, TOK_,SIGN) \
ENUMVALUE2STR(t, TOK_,INTEGER) \
ENUMVALUE2STR(t, TOK_,FLOATCONST) \
ENUMVALUE2STR(t, TOK_,IDENTIFIER) \
ENUMVALUE2STR(t, TOK_,POINT) \
ENUMVALUE2STR(t, TOK_,UPTO) \
ENUMVALUE2STR(t, TOK_,COMMA) \
ENUMVALUE2STR(t, TOK_,EQUALS) \
ENUMVALUE2STR(t, TOK_,LSQBRACKET) \
ENUMVALUE2STR(t, TOK_,RSQBRACKET) \
ENUMVALUE2STR(t, TOK_,LBRACE) \
ENUMVALUE2STR(t, TOK_,RBRACE) \
ENUMVALUE2STR(t, TOK_,END_OF_INST) \
ENUMVALUE2STR(t, TOK_,LINE_COMMENT) \
ENUMVALUE2STR(t, TOK_,NEWLINE) \
ENUMVALUE2STR(t, TOK_,END) \
ENUMVALUE2STR(t, TOK_,UNKNOWN) \
"???")
typedef struct _sVariableInit { // sArray manipulable
char **strings;
size_t strings_count;
size_t strings_cap;
size_t strings_total_len;
} sVariableInit;
typedef struct _sVariable { // sArray manipulable
char **names;
size_t names_count;
size_t names_cap;
eVariableType type;
sVariableInit init;
int size; // Optional (VARTYPE_PARAM_MULT)
} sVariable;
typedef struct _sVariables {
sVariable **vars;
size_t size;
size_t cap;
} sVariables;
sVariable *createVariable(eVariableType type);
void deleteVariable(sVariable **var);
KHASH_MAP_DECLARE_STR(variables, sVariable*)
#define kh_truly_exist(h, i) ((i < kh_end(h)) && kh_exist(h, i))
#define kh_str_exist(h, s) kh_truly_exist(h, kh_get(variables, h, s))
#define MAX_OPERANDS 4
typedef struct _sInstruction {
eInstruction type;
int saturated;
struct _sInstruction_Vars {
sVariable *var;
char *floatArrAddr;
int sign;
enum {
SWIZ_NONE = 0, SWIZ_X, SWIZ_Y, SWIZ_Z, SWIZ_W
} swizzle[4];
} vars[MAX_OPERANDS];
const char *codeLocation;
} sInstruction;
typedef struct _sInstruction_Vars sInstruction_Vars;
typedef struct _sInstructions {
sInstruction **insts;
size_t size;
size_t cap;
} sInstructions;
sInstruction *copyInstruction(const sInstruction *orig);
typedef struct _sCurStatus_NewInst {
sInstruction inst; // duplicateInstruction(&newInst);
unsigned int curArg;
int state; // Dependant on variable type and current status
} sCurStatus_NewInst;
typedef struct _sCurStatus_NewVar { // sArray manipulable
char **strParts; // copyToken();
size_t strLen;
size_t strCap;
sVariable *var; // createVariable();
int state; // Dependant on variable type and current status
} sCurStatus_NewVar;
typedef struct _sCurStatus_NewOpt {
char *optName;
} sCurStatus_NewOpt;
typedef struct _sCurStatus {
eStatus status;
int arbVersion;
const char *codePtr;
const char *endOfToken;
eToken curToken;
unsigned int tokInt;
float tokFloat;
char *outputString;
char *outputEnd;
size_t outLen;
size_t outCap;
size_t outLeft;
enum {
TYPE_NONE, TYPE_INST_DECL, TYPE_VARIABLE_DECL, TYPE_ALIAS_DECL, TYPE_OPTION_DECL
} valueType;
union {
sCurStatus_NewInst newInst;
sCurStatus_NewVar newVar;
char *string; // getToken();
sCurStatus_NewOpt newOpt;
} curValue;
sCurStatus_NewVar _fixedNewVar;
sVariable **texVars;
sVariable *tex1D;
sVariable *tex2D;
sVariable *tex3D;
sVariable *texCUBE;
sVariable *texRECT;
khash_t(variables) *varsMap;
sVariables variables;
sInstructions instructions;
enum { FOG_NONE, FOG_EXP, FOG_EXP2, FOG_LINEAR } fogType;
int position_invariant;
} sCurStatus;
void initStatus(sCurStatus* curStatus, const char* code);
void freeStatus(sCurStatus* curStatus);
int appendString(sCurStatus *curStatusPtr, const char *str, size_t strLen);
#endif // _GL4ES_ARBHELPER_H_
File diff suppressed because it is too large Load Diff
+16
View File
@@ -0,0 +1,16 @@
#ifndef _GL4ES_ARBPARSER_H_
#define _GL4ES_ARBPARSER_H_
#include <stddef.h>
#include "arbhelper.h"
struct sSpecialCases {
int hasFogFragCoord;
int isDepthReplacing;
};
eToken readNextToken(sCurStatus* curStatus);
void parseToken(sCurStatus *curStatus, int vertex, char **error_msg, struct sSpecialCases *hasFogFragCoord);
#endif // _GL4ES_ARBPARSER_H_
+508
View File
@@ -0,0 +1,508 @@
#include "array.h"
#include "debug.h"
#include "enum_info.h"
#include "glcase.h"
#include "light.h"
#include "state.h"
GLvoid *copy_gl_array(const GLvoid *src,
GLenum from, GLsizei width, GLsizei stride,
GLenum to, GLsizei to_width, GLsizei skip, GLsizei count, void* dst) {
if (! src || !count)
return NULL;
if (! stride)
stride = width * gl_sizeof(from);
const char *unknown_str = "LIBGL: copy_gl_array -> unknown type: %x\n";
if(!dst) {
dst = malloc((count-skip) * to_width * gl_sizeof(to));
}
GLsizei from_size = gl_sizeof(from) * width;
if (to_width < width) {
/* printf("Warning: copy_gl_array: %i < %i\n", to_width, width);
return NULL;*/
width = to_width;
}
// quick path if just copying same to same and no specific stride involved
if(stride == (to_width*gl_sizeof(to)) && width==to_width && from==to) {
memcpy(dst, (char*)src + stride*skip, (count-skip) * to_width * gl_sizeof(to));
return dst;
}
// if stride is weird, we need to be able to arbitrarily shift src
// so we leave it in a uintptr_t and cast after incrementing
uintptr_t in = (uintptr_t)src;
in += stride*skip;
if (from == to && to_width >= width) {
GL_TYPE_SWITCH(out, dst, to,
for (int i = skip; i < count; i++) {
memcpy(out, (GLvoid *)in, from_size);
for (int j = width; j < to_width; j++) {
out[j] = 0;
}
out += to_width;
in += stride;
},
default:
printf(unknown_str, from);
return NULL;
)
} else {
GL_TYPE_SWITCH(out, dst, to,
for (int i = skip; i < count; i++) {
GL_TYPE_SWITCH(input, in, from,
for (int j = 0; j < width; j++) {
out[j] = input[j];
}
for (int j = width; j < to_width; j++) {
out[j] = 0;
}
out += to_width;
in += stride;
,
default:
printf(unknown_str, from);
return NULL;
)
},
default:
printf(unknown_str, to);
return NULL;
)
}
return dst;
}
GLvoid *copy_gl_array_texcoord(const GLvoid *src,
GLenum from, GLsizei width, GLsizei stride,
GLsizei to_width, GLsizei skip, GLsizei count, void* dst) {
if (! src || !count)
return NULL;
if (! stride)
stride = width * gl_sizeof(from);
static const char *unknown_str = "LIBGL: copy_gl_array -> unknown type: %x\n";
if(!dst)
dst = malloc((count-skip) * to_width * gl_sizeof(GL_FLOAT));
GLsizei from_size = gl_sizeof(from) * width;
GLsizei to_elem = gl_sizeof(GL_FLOAT);
uintptr_t in = (uintptr_t)src;
in += stride*skip;
GLfloat* out = (GLfloat*)dst;
if (from == GL_FLOAT && to_width >= width) {
for (int i = skip; i < count; i++) {
GLfloat* input = (GLfloat*)in;
//memcpy(out, (GLvoid *)in, from_size); // which one is faster ?
for (int j = 0; j < width; j++) {
out[j] = input[j];
}
for (int j = width; j < to_width; j++) {
if(j==3)
out[j] = 1.0f;
else
out[j] = 0.0f;
}
out += to_width;
in += stride;
}
} else {
for (int i = skip; i < count; i++) {
GL_TYPE_SWITCH(input, in, from,
for (int j = 0; j < width; j++) {
out[j] = input[j];
}
for (int j = width; j < to_width; j++) {
if(j==3)
out[j] = 1.0f;
else
out[j] = 0.0f;
}
out += to_width;
in += stride;
,
default:
printf(unknown_str, from);
return NULL;
)
}
}
return dst;
}
GLvoid *copy_gl_array_quickconvert(const GLvoid *src,
GLenum from, GLsizei stride,
GLsizei skip, GLsizei count, void* dest) {
if (! stride)
stride = 4 * gl_sizeof(from);
const char *unknown_str = "LIBGL: copy_gl_array_quickconvert -> unknown type: %x\n";
GLvoid *dst = (dest)?dest:malloc((count-skip) * 4 * gl_sizeof(GL_FLOAT));
uintptr_t in = (uintptr_t)src;
in += stride*skip;
int j;
GLfloat *out = (GLfloat*)dst;
GL_TYPE_SWITCH2(input, in, from,
const GLfloat maxf = 1.0f/gl_max_value(from);
for (int i = skip; i < count; i++)
,
for (j = 0; j < 4; j++) {
out[j] = ((GLfloat)input[j])*maxf;
}
out += 4;
in += stride;
,
default:
printf(unknown_str, from);
return NULL;
)
return dst;
}
GLvoid *copy_gl_array_convert(const GLvoid *src,
GLenum from, GLsizei width, GLsizei stride,
GLenum to, GLsizei to_width, GLsizei skip, GLsizei count, GLvoid* filler, void* dst) {
if (! src || !count)
return NULL;
if (! stride)
stride = width * gl_sizeof(from);
GLsizei from_size = gl_sizeof(from) * width;
if(to==from && width==to_width && stride==(to_width * gl_sizeof(to))) {
if(!dst) dst = malloc((count-skip) * stride);
memcpy(dst, (char*)src+stride*skip, (count-skip)*stride);
return dst;
}
if(to==GL_FLOAT && width==to_width && width==4)
return copy_gl_array_quickconvert(src, from, stride, skip, count, dst);
if(to==GL_FLOAT && from==GL_FLOAT)
if(width<4 || *(GLfloat*)filler==1.0f) // no need to convert
return copy_gl_array_texcoord(src, from, width, stride, to_width, skip, count, dst);
else
return copy_gl_array(src, from, width, stride, to, to_width, skip, count, dst);
const char *unknown_str = "LIBGL: copy_gl_array_convert -> unknown type: %x\n";
if(!dst) dst = malloc((count-skip) * to_width * gl_sizeof(to));
if (to_width < width) {
/*printf("Warning: copy_gl_array: %i < %i\n", to_width, width);
return NULL;*/
width = to_width;
}
// if stride is weird, we need to be able to arbitrarily shift src
// so we leave it in a uintptr_t and cast after incrementing
uintptr_t in = (uintptr_t)src;
in += stride*skip;
int j;
if (from == to && to_width >= width) {
GL_TYPE_SWITCH(out, dst, to,
for (int i = skip; i < count; i++) {
memcpy(out, (GLvoid *)in, from_size);
for (j = width; j < to_width-1; j++) {
out[j]=0;
}
for (; j < to_width; j++) {
memcpy(&out[j], filler, gl_sizeof(to));
}
out += to_width;
in += stride;
},
default:
printf(unknown_str, from);
return NULL;
)
} else {
GL_TYPE_SWITCH_MAX(out, dst, to,
GL_TYPE_SWITCH2(input, in, from,
const GLuint maxf = gl_max_value(from);
for (int i = skip; i < count; i++)
,
for (j = 0; j < width; j++) {
out[j] = input[j]*maxv/maxf;
}
for (; j < to_width-1; j++) {
out[j]=0;
}
for (; j < to_width; j++) {
memcpy(&out[j], filler, gl_sizeof(to));
}
out += to_width;
in += stride;
,
default:
printf(unknown_str, from);
return NULL;
),
default:
printf(unknown_str, to);
return NULL;
)
}
return dst;
}
GLvoid *copy_gl_pointer(vertexattrib_t *ptr, GLsizei width, GLsizei skip, GLsizei count) {
float filler = 0.0f;
return copy_gl_array_convert((const GLvoid*)((uintptr_t)ptr->pointer+(uintptr_t)ptr->real_pointer), ptr->type, ptr->size, ptr->stride,
GL_FLOAT, width, skip, count, &filler, NULL);
}
GLvoid *copy_gl_pointer_color(vertexattrib_t *ptr, GLsizei width, GLsizei skip, GLsizei count) {
float filler = 1.0f;
return copy_gl_array_convert((const GLvoid*)((uintptr_t)ptr->pointer+(uintptr_t)ptr->real_pointer), ptr->type, ptr->size, ptr->stride,
GL_FLOAT, width, skip, count, &filler, NULL);
}
GLvoid *copy_gl_pointer_bytecolor(vertexattrib_t *ptr, GLsizei width, GLsizei skip, GLsizei count) {
GLubyte filler = 255;
return copy_gl_array_convert((const GLvoid*)((uintptr_t)ptr->pointer+(uintptr_t)ptr->real_pointer), ptr->type, ptr->size, ptr->stride,
GL_UNSIGNED_BYTE, width, skip, count, &filler, NULL);
}
GLvoid *copy_gl_pointer_raw(vertexattrib_t *ptr, GLsizei width, GLsizei skip, GLsizei count) {
return copy_gl_array((const GLvoid*)((uintptr_t)ptr->pointer+(uintptr_t)ptr->real_pointer), ptr->type, ptr->size, ptr->stride,
GL_FLOAT, width, skip, count, NULL);
}
GLvoid *copy_gl_pointer_tex(vertexattrib_t *ptr, GLsizei width, GLsizei skip, GLsizei count) {
//float filler = 1.0f;
return copy_gl_array_texcoord((const GLvoid*)((uintptr_t)ptr->pointer+(uintptr_t)ptr->real_pointer), ptr->type, ptr->size, ptr->stride,
/*GL_FLOAT,*/ width, skip, count, /*&filler,*/ NULL);
}
void copy_gl_pointer_noalloc(void* dest, vertexattrib_t *ptr, GLsizei width, GLsizei skip, GLsizei count) {
float filler = 0.0f;
copy_gl_array_convert((const GLvoid*)((uintptr_t)ptr->pointer+(uintptr_t)ptr->real_pointer), ptr->type, ptr->size, ptr->stride,
GL_FLOAT, width, skip, count, &filler, dest);
}
void copy_gl_pointer_color_noalloc(void* dest, vertexattrib_t *ptr, GLsizei width, GLsizei skip, GLsizei count) {
float filler = 1.0f;
copy_gl_array_convert((const GLvoid*)((uintptr_t)ptr->pointer+(uintptr_t)ptr->real_pointer), ptr->type, ptr->size, ptr->stride,
GL_FLOAT, width, skip, count, &filler, dest);
}
void copy_gl_pointer_bytecolor_noalloc(void* dest, vertexattrib_t *ptr, GLsizei width, GLsizei skip, GLsizei count) {
GLubyte filler = 255;
copy_gl_array_convert((const GLvoid*)((uintptr_t)ptr->pointer+(uintptr_t)ptr->real_pointer), ptr->type, ptr->size, ptr->stride,
GL_UNSIGNED_BYTE, width, skip, count, &filler, dest);
}
void copy_gl_pointer_raw_noalloc(void* dest, vertexattrib_t *ptr, GLsizei width, GLsizei skip, GLsizei count) {
copy_gl_array((const GLvoid*)((uintptr_t)ptr->pointer+(uintptr_t)ptr->real_pointer), ptr->type, ptr->size, ptr->stride,
GL_FLOAT, width, skip, count, dest);
}
void copy_gl_pointer_tex_noalloc(void* dest, vertexattrib_t *ptr, GLsizei width, GLsizei skip, GLsizei count) {
//float filler = 1.0f;
copy_gl_array_texcoord((const GLvoid*)((uintptr_t)ptr->pointer+(uintptr_t)ptr->real_pointer), ptr->type, ptr->size, ptr->stride,
/*GL_FLOAT,*/ width, skip, count, /*&filler,*/ dest);
}
GLfloat *gl_pointer_index(vertexattrib_t *p, GLint index) {
static GLfloat buf[4];
GLsizei size = gl_sizeof(p->type);
GLsizei stride = p->stride ? p->stride : (size * p->size);
uintptr_t ptr = (uintptr_t)p->pointer+(uintptr_t)p->real_pointer + (stride * index);
GL_TYPE_SWITCH(src, ptr, p->type,
for (int i = 0; i < p->size; i++) {
buf[i] = src[i];
}
// zero anything not set by the pointer
for (int i = p->size; i < 4; i++) {
buf[i] = 0;
},
default:
printf("LIBGL: unknown pointer type: 0x%x\n", p->type);
)
return buf;
}
GLfloat *copy_eval_double1(GLenum target, GLint ustride, GLint uorder,
const GLdouble *src) {
GLsizei width = get_map_width(target);
GLfloat* out;
if(!src || !width)
return NULL;
out = malloc(uorder*width*sizeof(GLfloat));
GLfloat *p = out;
for (int i=0; i<uorder; i++, src+=ustride)
for (int k=0; k<width; k++)
*p++ = src[k];
return out;
}
GLfloat *copy_eval_float1(GLenum target, GLint ustride, GLint uorder,
const GLfloat *src) {
GLsizei width = get_map_width(target);
GLfloat* out;
if(!src || !width)
return NULL;
out = malloc(uorder*width*sizeof(GLfloat));
GLfloat *p = out;
for (int i=0; i<uorder; i++, src+=ustride)
for (int k=0; k<width; k++)
*p++ = src[k];
return out;
}
GLfloat *copy_eval_double2(GLenum target, GLint ustride, GLint uorder,
GLint vstride, GLint vorder,
const GLdouble *src) {
/* Additional memory is allocated to be used by the horner and
* de Casteljau evaluation schemes.*/
GLsizei width = get_map_width(target);
GLfloat* out;
if(!src || !width)
return NULL;
int dsize = (uorder == 2 && vorder == 2)? 0 : uorder*vorder;
int hsize = (uorder > vorder ? uorder : vorder)*width;
if(hsize>dsize)
out = malloc((uorder*vorder*width+hsize)*sizeof(GLfloat));
else
out = malloc((uorder*vorder*width+dsize)*sizeof(GLfloat));
int uinc = ustride - vorder*vstride;
GLfloat* p = out;
for (int i=0; i<uorder; i++, src += uinc)
for (int j=0; j<vorder; j++, src += vstride)
for (int k=0; k<width; k++)
*p++ = src[k];
return out;
}
GLfloat *copy_eval_float2(GLenum target, GLint ustride, GLint uorder,
GLint vstride, GLint vorder,
const GLfloat *src) {
/* Additional memory is allocated to be used by the horner and
* de Casteljau evaluation schemes.*/
GLsizei width = get_map_width(target);
GLfloat* out;
if(!src || !width)
return NULL;
int dsize = (uorder == 2 && vorder == 2)? 0 : uorder*vorder;
int hsize = (uorder > vorder ? uorder : vorder)*width;
if(hsize>dsize)
out = malloc((uorder*vorder*width+hsize)*sizeof(GLfloat));
else
out = malloc((uorder*vorder*width+dsize)*sizeof(GLfloat));
int uinc = ustride - vorder*vstride;
GLfloat* p = out;
for (int i=0; i<uorder; i++, src += uinc)
for (int j=0; j<vorder; j++, src += vstride)
for (int k=0; k<width; k++)
*p++ = src[k];
return out;
}
void getminmax_indices_us(const GLushort *indices, GLsizei *max, GLsizei *min, GLsizei count) {
if (!count) return;
*max = indices[0];
*min = indices[0];
for (int i = 1; i < count; i++) {
GLsizei n = indices[i];
if( n < *min) *min = n;
if (n > *max) *max = n;
}
}
void normalize_indices_us(GLushort *indices, GLsizei *max, GLsizei *min, GLsizei count) {
getminmax_indices_us(indices, max, min, count);
for (int i = 0; i < count; i++) {
indices[i] -= *min;
}
}
void getminmax_indices_ui(const GLuint *indices, GLsizei *max, GLsizei *min, GLsizei count) {
if (!count) return;
*max = indices[0];
*min = indices[0];
for (int i = 1; i < count; i++) {
GLsizei n = indices[i];
if( n < *min) *min = n;
if (n > *max) *max = n;
}
}
void normalize_indices_ui(GLuint *indices, GLsizei *max, GLsizei *min, GLsizei count) {
getminmax_indices_ui(indices, max, min, count);
for (int i = 0; i < count; i++) {
indices[i] -= *min;
}
}
void *copy_gl_array_bgra(void* dest, const void *ptr, GLint stride, GLsizei width, GLsizei skip, GLsizei count) {
// this one only convert from BGRA (unsigned byte) to RGBA FLOAT
GLubyte* src = (GLubyte*)ptr;
if (! src || !(count-skip))
return NULL;
if (! stride)
stride = 4;
if(!dest)
dest = malloc(4*sizeof(GLfloat)*(count-skip));
GLfloat* dst = dest;
src += skip*(stride);
static const float d = 1.0f/255.0f;
for (int i=skip; i<count; i++) {
#if defined(__ARM_NEON__) && !defined(__APPLE__)
int lsrc = *(int*)src;
lsrc = (lsrc&0xff00ff00) | ((lsrc&0x00ff0000)>>16) | ((lsrc&0x000000ff)<<16);
asm volatile (
"vmov s12, %1 \n\t" // because you cannot vmovl.u8 d6, s11
"vmovl.u8 q3, d6 \n\t" // Expand to 16-bit (so unsetuped s13 is expanded in d7)
"vmovl.u16 q3, d6 \n\t" // Expand to 32-bit, ignoring expanded d7
"vcvt.f32.u32 q3, q3 \n\t" // Convert to float
"vmul.f32 q3, q3, %y2 \n\t" // Normalize
"vst1.f32 {q3}, [%0]! \n\t" // Store, next
:"+r"(dst) :"r"(lsrc), "w"(d)
: "q3", "memory"
);
#else
const GLubyte b = src[0], g = src[1], r = src[2], a = src[3];
*dst++ = r*d;
*dst++ = g*d;
*dst++ = b*d;
*dst++ = a*d;
#endif
src+=stride;
}
return dest;
}
GLvoid *copy_gl_pointer_color_bgra(const void *ptr, GLint stride, GLsizei width, GLsizei skip, GLsizei count) {
return copy_gl_array_bgra(NULL, ptr, stride, width, skip, count);
}
void copy_gl_pointer_color_bgra_noalloc(void* dest, const void *ptr, GLint stride, GLsizei width, GLsizei skip, GLsizei count)
{
copy_gl_array_bgra(dest, ptr, stride, width, skip, count);
}
+38
View File
@@ -0,0 +1,38 @@
#ifndef _GL4ES_ARRAY_H_
#define _GL4ES_ARRAY_H_
#include "buffers.h"
#include "gles.h"
GLvoid *copy_gl_array(const GLvoid *src,
GLenum from, GLsizei width, GLsizei stride,
GLenum to, GLsizei to_width, GLsizei skip, GLsizei count, void* dst);
GLvoid *copy_gl_array_convert(const GLvoid *src,
GLenum from, GLsizei width, GLsizei stride,
GLenum to, GLsizei to_width, GLsizei skip, GLsizei count, GLvoid* filler, void* dst);
GLvoid *copy_gl_pointer(vertexattrib_t *ptr, GLsizei width, GLsizei skip, GLsizei count);
GLvoid *copy_gl_pointer_color(vertexattrib_t *ptr, GLsizei width, GLsizei skip, GLsizei count);
GLvoid *copy_gl_pointer_color_bgra(const void *ptr, GLint stride, GLsizei width, GLsizei skip, GLsizei count);
GLvoid *copy_gl_pointer_bytecolor(vertexattrib_t *ptr, GLsizei width, GLsizei skip, GLsizei count);
GLvoid *copy_gl_pointer_raw(vertexattrib_t *ptr, GLsizei width, GLsizei skip, GLsizei count);
GLvoid *copy_gl_pointer_tex(vertexattrib_t *ptr, GLsizei width, GLsizei skip, GLsizei count);
void copy_gl_pointer_noalloc(void* dest, vertexattrib_t *ptr, GLsizei width, GLsizei skip, GLsizei count);
void copy_gl_pointer_color_noalloc(void* dest, vertexattrib_t *ptr, GLsizei width, GLsizei skip, GLsizei count);
void copy_gl_pointer_color_bgra_noalloc(void* dest, const void *ptr, GLint stride, GLsizei width, GLsizei skip, GLsizei count);
void copy_gl_pointer_bytecolor_noalloc(void* dest, vertexattrib_t *ptr, GLsizei width, GLsizei skip, GLsizei count);
void copy_gl_pointer_raw_noalloc(void* dest, vertexattrib_t *ptr, GLsizei width, GLsizei skip, GLsizei count);
void copy_gl_pointer_tex_noalloc(void* dest, vertexattrib_t *ptr, GLsizei width, GLsizei skip, GLsizei count);
GLfloat *gl_pointer_index(vertexattrib_t *ptr, GLint index);
void normalize_indices_us(GLushort *indices, GLsizei *max, GLsizei *min, GLsizei count);
void getminmax_indices_us(const GLushort *indices, GLsizei *max, GLsizei *min, GLsizei count);
void normalize_indices_ui(GLuint *indices, GLsizei *max, GLsizei *min, GLsizei count);
void getminmax_indices_ui(const GLuint *indices, GLsizei *max, GLsizei *min, GLsizei count);
GLfloat *copy_eval_double1(GLenum target, GLint ustride, GLint uorder, const GLdouble *points);
GLfloat *copy_eval_float1(GLenum target, GLint ustride, GLint uorder, const GLfloat *points);
GLfloat *copy_eval_double2(GLenum target, GLint ustride, GLint uorder, GLint vstride, GLint vorder, const GLdouble *points);
GLfloat *copy_eval_float2(GLenum target, GLint ustride, GLint uorder, GLint vstride, GLint vorder, const GLfloat *points);
#endif // _GL4ES_ARRAY_H_
+189
View File
@@ -0,0 +1,189 @@
#ifndef _GL4ES_ATTRIBUTES_H_
#define _GL4ES_ATTRIBUTES_H_
#ifndef EXPORT
#if defined(__EMSCRIPTEN__) || defined(__APPLE__)
#define EXPORT
#elif defined(STATICLIB)
#define EXPORT
#elif defined(_WIN32) || defined(__CYGWIN__)
#define EXPORT __declspec(dllexport)
#elif defined(__GNUC__)
#define EXPORT __attribute__((visibility("default")))
#else
#define EXPORT
#endif
#endif // EXPORT
#ifndef _STR
#define _STR(n) #n
#endif
#ifndef _MNG
#if defined(_WIN32) && !defined(_WIN64)
#ifdef _MSC_VER
#define _MNG(NAME,SUF) "_" _STR(NAME) "@" SUF
#elif defined(__GNUC__)
#define _MNG(NAME,SUF) _STR(NAME) "@" SUF
#endif
#endif
#ifdef _MNG
#define _STM(NAME,DEF) _MNG(NAME,_VCR(_SUF1 DEF))
#define _SUFF(...) _VCR(_SUF1 __VA_ARGS__)
#define _SU2F(...) _VCR(_SUF2 __VA_ARGS__)
#define _S2F1(...) _VCR(_SU21 __VA_ARGS__)
#define _SUF1(...) \
_VCS(_SUFS,(0,##__VA_ARGS__,100,96,92,88,84,80,76,72,68,64,60,56,52,\
48,44,40,36,32,28,24,20,16,12,8,4,0))
#define _SUF2(...) \
_VCS(_SUFS,(0,##__VA_ARGS__,200,192,184,176,168,160,152,144,136,128,120,\
112,104,96,88,80,72,64,56,48,40,32,24,16,8,0))
#define _SU21(...) \
_VCS(_SUFS,(0,##__VA_ARGS__,196,188,180,172,164,156,148,140,132,124,116,\
108,100,92,84,76,68,60,52,44,36,28,20,12,4))
#define _SUFS(a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,\
a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,\
a20,a21,a22,a23,a24,a25,n,...) #n
#define _VCS(a,b) a b
#define _VCR(n) n
#endif
#endif
#ifndef _MNG
#define _MNG(NAME,SUF) _STR(NAME)
#define _STM(NAME,DEF) _STR(NAME)
#endif
#ifndef AliasDecl
#ifdef __GNUC__
#define AliasDecl(RET,NAME,DEF,OLD) \
RET APIENTRY_GL4ES NAME DEF __attribute__((alias(_STM(OLD,DEF))))
#elif defined(_MSC_VER)
#define AliasDecl(RET,NAME,DEF,OLD) \
__pragma(comment(linker, "/ALTERNATENAME:" _STM(NAME,DEF) "=" _STM(OLD,DEF))) \
RET APIENTRY_GL4ES NAME DEF
#else
#define AliasDecl(RET,NAME,DEF,OLD) \
RET APIENTRY_GL4ES NAME DEF
#endif
#endif // AliasDecl
#ifndef AliasExport
#if !defined(__EMSCRIPTEN__) && !defined(__APPLE__)
#ifdef __GNUC__
#define _AliasExport_(RET,ENM,DEF,INM,SUF) EXPORT \
RET APIENTRY_GL4ES ENM DEF __attribute__((alias(_MNG(gl4es_##INM,SUF))))
#define NonAliasExportDecl(RET,NAME,DEF) EXPORT \
RET APIENTRY_GL4ES NAME DEF
#elif defined(_MSC_VER)
#define _DIR(DIR,ENM,INM,OP) \
__pragma(comment(linker, "/" DIR ":" ENM OP INM))
#ifdef STATICLIB
#define _EXP(ENM,SUF)
#elif !defined(_WIN64) && (_MSC_VER >= 1911 || defined(LINK_ULINK))
#define _EXP(ENM,SUF) _DIR("EXPORT",_MNG(ENM,SUF),_STR(ENM),",exportas,")
#else
#ifndef _WIN64
/* Unfortunatelly, old MS-link can create undecorated dll-names
* with decorated library names only when use DEF-file.
* Create stdcall-alias.*/
#define _DOPEXP(ENM,SUF) _DIR("EXPORT",_MNG(ENM,SUF),,)
#else
#define _DOPEXP(ENM,SUF)
#endif
#define _EXP(ENM,SUF) _DIR("EXPORT",_STR(ENM),_MNG(ENM,SUF),"=") \
_DOPEXP(ENM,SUF)
#endif
#define _DECL(ENM,INM,SUF) \
_EXP(ENM,SUF) _DIR("ALTERNATENAME",_MNG(ENM,SUF),_MNG(INM,SUF), "=")
#define _AliasExport_(RET,ENM,DEF,INM,SUF) _DECL(ENM,gl4es_##INM,SUF) \
RET APIENTRY_GL4ES ENM DEF
#define NonAliasExportDecl(RET,NAME,DEF) _EXP(NAME,_SUFF(DEF)) \
RET APIENTRY_GL4ES NAME DEF
#endif
#define AliasExport(RET,NAME,X,DEF) \
_AliasExport_(RET,NAME##X,DEF,NAME,_SUFF(DEF))
#define AliasExport_A(RET,NAME,X,DEF,INM) \
_AliasExport_(RET,NAME##X,DEF,INM,_SUFF(DEF))
#define AliasExport_D(RET,NAME,X,DEF) \
_AliasExport_(RET,NAME##X,DEF,NAME,_SU2F(DEF))
#define AliasExport_D_1(RET,NAME,X,DEF) \
_AliasExport_(RET,NAME##X,DEF,NAME,_S2F1(DEF))
#define AliasExport_M(RET,NAME,X,DEF,SUF) \
_AliasExport_(RET,NAME##X,DEF,NAME,_STR(SUF))
#define AliasExport_V(RET,NAME) \
_AliasExport_(RET,NAME,(void),NAME,"0")
#endif
#ifndef _AliasExport_
#define AliasExport(RET,NAME,X,DEF) RET NAME##X DEF
#define AliasExport_A(RET,NAME,X,DEF,INM) AliasExport(RET,NAME,X,DEF)
#define AliasExport_D(RET,NAME,X,DEF) AliasExport(RET,NAME,X,DEF)
#define AliasExport_D_1(RET,NAME,X,DEF) AliasExport(RET,NAME,X,DEF)
#define AliasExport_M(RET,NAME,X,DEF,SUF) AliasExport(RET,NAME,X,DEF)
#define AliasExport_V(RET,NAME) AliasExport(RET,NAME,,(void))
#define NonAliasExportDecl(RET,NAME,DEF) RET NAME DEF
#endif
#define AliasExport_1(RET,NAME,X,DEF) AliasExport(RET,NAME,X,DEF)
#endif // AliasExport
// ensure APIENTRY used from platform if it defined, win32 should use STDCALL conversion
#include <GLES/glplatform.h>
#ifndef NOEGL
#include <EGL/eglplatform.h>
#endif
#ifndef APIENTRY
# if defined(_WIN32) || defined(__MINGW32__)
# define APIENTRY __stdcall
# else
# define APIENTRY
# endif
#endif
#ifndef SOFTFLOAT
#ifdef __arm__
#define SOFTFLOAT __attribute__((pcs("aapcs")))
#else
#define SOFTFLOAT
#endif
#endif // SOFTFLOAT
#ifndef APIENTRY_GLES
#ifdef GLES_SOFTFLOAT
#define APIENTRY_GLES APIENTRY SOFTFLOAT
#else
#define APIENTRY_GLES APIENTRY
#endif
#endif // APIENTRY_GLES
#ifndef APIENTRY_GL4ES
#ifdef GL_SOFTFLOAT
#define APIENTRY_GL4ES APIENTRY SOFTFLOAT
#else
#define APIENTRY_GL4ES APIENTRY
#endif
#endif //APIENTRY_GL4ES
#ifndef FASTMATH
#ifdef __GNUC__
#ifdef __arm__
#ifdef __ARM_PCS_VFP
//#warning Arm Hardfloat detected
#define FASTMATH
#else // __ARM_PCS_VFP
#if defined(__ARM_FP) && defined(PANDORA)
//#warning Arm SoftFP detected
#define FASTMATH __attribute__((pcs("aapcs-vfp")))
#else // defined(__ARM_FP) && defined(PANDORA)
//#warning Arm no FP detected
#define FASTMATH
#endif // defined(__ARM_FP) && defined(PANDORA)
#endif // __ARM_PCS_VFP
#else // __arm__
#define FASTMATH
#endif // __arm__
#else // __GNUC__
#define FASTMATH
#endif // __GNUC__
#endif // FASTMATH
#endif // _GL4ES_ATTRIBUTES_H_
+297
View File
@@ -0,0 +1,297 @@
#include "blend.h"
#include "../glx/hardext.h"
#include "debug.h"
#include "gl4es.h"
#include "glstate.h"
#include "init.h"
#include "loader.h"
#include "logs.h"
static int fpeBlendFunc(GLenum func)
{
int ret = -1;
#define GO(A) case GL_##A: ret = FPE_BLEND_##A; break
switch(func) {
GO(ZERO);
GO(ONE);
GO(SRC_COLOR);
GO(ONE_MINUS_SRC_COLOR);
GO(DST_COLOR);
GO(ONE_MINUS_DST_COLOR);
GO(SRC_ALPHA);
GO(ONE_MINUS_SRC_ALPHA);
GO(DST_ALPHA);
GO(ONE_MINUS_DST_ALPHA);
GO(CONSTANT_COLOR);
GO(ONE_MINUS_CONSTANT_COLOR);
GO(CONSTANT_ALPHA);
GO(ONE_MINUS_CONSTANT_ALPHA);
GO(SRC_ALPHA_SATURATE);
}
#undef GO
return ret;
}
static int fpeBlendEq(GLenum func)
{
int ret = -1;
#define GO(A) case GL_##A: ret = FPE_BLENDEQ_##A; break
switch(func) {
GO(FUNC_ADD);
GO(FUNC_SUBTRACT);
GO(FUNC_REVERSE_SUBTRACT);
GO(MIN);
GO(MAX);
}
#undef GO
return ret;
}
void APIENTRY_GL4ES gl4es_glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) {
if(!glstate->list.pending)
PUSH_IF_COMPILING(glBlendColor)
if(glstate->blend_color[0]==red
&& glstate->blend_color[1]==green
&& glstate->blend_color[2]==blue
&& glstate->blend_color[3]==alpha)
return;
FLUSH_BEGINEND;
glstate->blend_color[0] = red;
glstate->blend_color[1] = green;
glstate->blend_color[2] = blue;
glstate->blend_color[3] = alpha;
if(!globals4es.shaderblend) {
LOAD_GLES2_OR_OES(glBlendColor);
if (gles_glBlendColor)
gles_glBlendColor(red, green, blue, alpha);
else {
static int test = 1;
if (test) {
LOGD("stub glBlendColor(%f, %f, %f, %f)\n", red, green, blue, alpha);
test = 0;
}
}
}
}
AliasExport(void,glBlendColor,,(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha));
AliasExport(void,glBlendColor,EXT,(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha));
AliasExport(void,glBlendColor,ARB,(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha));
void APIENTRY_GL4ES gl4es_glBlendFuncSeparate(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha)
{
if(!glstate->list.pending)
PUSH_IF_COMPILING(glBlendFuncSeparate)
LOAD_GLES2_OR_OES(glBlendFuncSeparate);
if(sfactorRGB==glstate->blendsfactorrgb && dfactorRGB==glstate->blenddfactorrgb
&& sfactorAlpha==glstate->blendsfactoralpha && dfactorAlpha==glstate->blenddfactoralpha)
return; // no change...
FLUSH_BEGINEND;
if(globals4es.shaderblend) {
int srcrgb = fpeBlendFunc(sfactorRGB);
int dstrgb = fpeBlendFunc(dfactorRGB);
int srcalpha = fpeBlendFunc(sfactorAlpha);
int dstalpha = fpeBlendFunc(dfactorAlpha);
if(srcrgb<0 || dstrgb<0 || srcalpha<0 || dstalpha<0) {
errorShim(GL_INVALID_VALUE);
return;
}
glstate->fpe_state->blendsrcrgb = srcrgb;
glstate->fpe_state->blenddstrgb = dstrgb;
glstate->fpe_state->blendsrcalpha = srcalpha;
glstate->fpe_state->blenddstalpha = dstalpha;
} else {
#ifndef PANDORA
if(gles_glBlendFuncSeparate==NULL) {
// some fallback function to have better rendering with SDL2, better then nothing...
if(sfactorRGB==GL_SRC_ALPHA && dfactorRGB==GL_ONE_MINUS_SRC_ALPHA && sfactorAlpha==GL_ONE && dfactorAlpha==GL_ONE_MINUS_SRC_ALPHA)
gl4es_glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
else if (sfactorRGB==GL_SRC_ALPHA && dfactorRGB==GL_ONE && sfactorAlpha==GL_ZERO && dfactorAlpha==GL_ONE)
gl4es_glBlendFunc(GL_SRC_ALPHA, GL_ONE);
else if (sfactorRGB==GL_ZERO && dfactorRGB==GL_SRC_COLOR && sfactorAlpha==GL_ZERO && dfactorAlpha==GL_ONE)
gl4es_glBlendFunc(GL_ZERO, GL_SRC_COLOR);
else if (sfactorRGB==sfactorAlpha && dfactorRGB==dfactorAlpha)
gl4es_glBlendFunc(sfactorRGB, dfactorRGB);
} else
#endif
gles_glBlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha);
}
glstate->blendsfactorrgb = sfactorRGB;
glstate->blenddfactorrgb = dfactorRGB;
glstate->blendsfactoralpha = sfactorAlpha;
glstate->blenddfactoralpha = dfactorAlpha;
}
AliasExport(void,glBlendFuncSeparate,,(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha));
AliasExport(void,glBlendFuncSeparate,EXT,(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha));
void APIENTRY_GL4ES gl4es_glBlendEquationSeparate(GLenum modeRGB, GLenum modeA) {
if(!glstate->list.pending)
PUSH_IF_COMPILING(glBlendEquationSeparate);
if(glstate->blendeqrgb==modeRGB
&& glstate->blendeqalpha==modeA)
return;
if(globals4es.shaderblend) {
int rgb = fpeBlendEq(modeRGB);
int alpha = fpeBlendEq(modeA);
if(rgb<0 || alpha<0) {
errorShim(GL_INVALID_VALUE);
return;
}
glstate->fpe_state->blendeqrgb = rgb;
glstate->fpe_state->blendeqalpha = alpha;
} else {
LOAD_GLES2_OR_OES(glBlendEquationSeparate);
#ifndef PANDORA
if(gles_glBlendEquationSeparate)
#endif
gles_glBlendEquationSeparate(modeRGB, modeA);
}
glstate->blendeqrgb = modeRGB;
glstate->blendeqalpha = modeA;
}
AliasExport(void,glBlendEquationSeparate,,(GLenum modeRGB, GLenum modeA));
AliasExport(void,glBlendEquationSeparate,EXT,(GLenum modeRGB, GLenum modeA));
void APIENTRY_GL4ES gl4es_glBlendFunc(GLenum sfactor, GLenum dfactor) {
if(!glstate->list.pending)
PUSH_IF_COMPILING(glBlendFunc)
if(sfactor==glstate->blendsfactorrgb && dfactor==glstate->blenddfactorrgb
&& sfactor==glstate->blendsfactoralpha && dfactor==glstate->blenddfactoralpha)
return; // already set
FLUSH_BEGINEND;
glstate->blendsfactorrgb = sfactor;
glstate->blenddfactorrgb = dfactor;
glstate->blendsfactoralpha = sfactor;
glstate->blenddfactoralpha = dfactor;
if(globals4es.shaderblend) {
int srcrgb = fpeBlendFunc(sfactor);
int dstrgb = fpeBlendFunc(dfactor);
int srcalpha = fpeBlendFunc(sfactor);
int dstalpha = fpeBlendFunc(dfactor);
if(srcrgb<0 || dstrgb<0 || srcalpha<0 || dstalpha<0) {
errorShim(GL_INVALID_VALUE);
return;
}
glstate->fpe_state->blendsrcrgb = srcrgb;
glstate->fpe_state->blenddstrgb = dstrgb;
glstate->fpe_state->blendsrcalpha = srcalpha;
glstate->fpe_state->blenddstalpha = dstalpha;
} else {
LOAD_GLES(glBlendFunc);
LOAD_GLES2_OR_OES(glBlendFuncSeparate);
errorGL();
// There are some limitations in GLES1.1 Blend functions
switch(sfactor) {
#if 0
case GL_SRC_COLOR:
if (gles_glBlendFuncSeparate) {
gles_glBlendFuncSeparate(sfactor, dfactor, sfactor, dfactor);
return;
}
sfactor = GL_ONE; // approx...
break;
case GL_ONE_MINUS_SRC_COLOR:
if (gles_glBlendFuncSeparate) {
gles_glBlendFuncSeparate(sfactor, dfactor, sfactor, dfactor);
return;
}
sfactor = GL_ONE; // not sure it make sense...
break;
#endif
// here, we need support for glBlendColor...
case GL_CONSTANT_COLOR:
case GL_CONSTANT_ALPHA:
if(hardext.blendcolor==0)
sfactor = GL_ONE;
break;
case GL_ONE_MINUS_CONSTANT_COLOR:
case GL_ONE_MINUS_CONSTANT_ALPHA:
if(hardext.blendcolor==0)
sfactor = GL_ZERO;
break;
default:
break;
}
switch(dfactor) {
#if 0
case GL_DST_COLOR:
sfactor = GL_ONE; // approx...
break;
case GL_ONE_MINUS_DST_COLOR:
sfactor = GL_ZERO; // not sure it make sense...
break;
#endif
// here, we need support for glBlendColor...
case GL_CONSTANT_COLOR:
case GL_CONSTANT_ALPHA:
if(hardext.blendcolor==0)
sfactor = GL_ONE;
break;
case GL_ONE_MINUS_CONSTANT_COLOR:
case GL_ONE_MINUS_CONSTANT_ALPHA:
if(hardext.blendcolor==0)
sfactor = GL_ZERO;
break;
default:
break;
}
if ((globals4es.blendhack) && (sfactor==GL_SRC_ALPHA) && (dfactor==GL_ONE)) {
// special case, as seen in Xash3D, but it breaks torus_trooper, so behind a parameter
sfactor = GL_ONE;
}
#ifdef ODROID
if(gles_glBlendFunc)
#endif
gles_glBlendFunc(sfactor, dfactor);
}
}
AliasExport(void,glBlendFunc,,(GLenum sfactor, GLenum dfactor));
void APIENTRY_GL4ES gl4es_glBlendEquation(GLenum mode) {
if(!glstate->list.pending)
PUSH_IF_COMPILING(glBlendEquation)
if(glstate->blendeqrgb==mode
&& glstate->blendeqalpha==mode)
return;
glstate->blendeqrgb = mode;
glstate->blendeqalpha = mode;
if(globals4es.shaderblend) {
int rgb = fpeBlendEq(mode);
int alpha = fpeBlendEq(mode);
if(rgb<0 || alpha<0) {
errorShim(GL_INVALID_VALUE);
return;
}
glstate->fpe_state->blendeqrgb = rgb;
glstate->fpe_state->blendeqalpha = alpha;
} else {
LOAD_GLES2_OR_OES(glBlendEquation);
errorGL();
#ifdef ODROID
if(gles_glBlendEquation)
#endif
gles_glBlendEquation(mode);
}
}
AliasExport(void,glBlendEquation,,(GLenum mode));
AliasExport(void,glBlendEquation,EXT,(GLenum mode));
+12
View File
@@ -0,0 +1,12 @@
#ifndef _GL4ES_BLEND_H_
#define _GL4ES_BLEND_H_
#include "gles.h"
void APIENTRY_GL4ES gl4es_glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
void APIENTRY_GL4ES gl4es_glBlendFuncSeparate(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
void APIENTRY_GL4ES gl4es_glBlendEquationSeparate(GLenum modeRGB, GLenum modeA);
void APIENTRY_GL4ES gl4es_glBlendFunc(GLenum sfactor, GLenum dfactor);
void APIENTRY_GL4ES gl4es_glBlendEquation(GLenum mode);
#endif //_GL4ES_BLEND_H_
+417
View File
@@ -0,0 +1,417 @@
/* Blit utility function */
#include "blit.h"
#include <math.h>
#include "fpe.h"
#include "gl4es.h"
#include "glstate.h"
#include "init.h"
#include "loader.h"
#include "logs.h"
#ifdef TEXSTREAM
# ifndef GL_TEXTURE_STREAM_IMG
# define GL_TEXTURE_STREAM_IMG 0x8C0D
# endif
#include "../glx/streaming.h"
#endif
// hacky viewport temporary changes
void pushViewport(GLint x, GLint y, GLsizei width, GLsizei height);
void popViewport();
void gl4es_blitTexture_gles1(GLuint texture,
GLfloat sx, GLfloat sy,
GLfloat width, GLfloat height,
GLfloat nwidth, GLfloat nheight,
GLfloat zoomx, GLfloat zoomy,
GLfloat vpwidth, GLfloat vpheight,
GLfloat x, GLfloat y, GLint mode) {
LOAD_GLES(glClientActiveTexture);
GLfloat old_projection[16], old_modelview[16], old_texture[16];
int customvp = (vpwidth>0.0);
int drawtexok = (hardext.drawtex) && (zoomx==1.0f) && (zoomy==1.0f);
GLuint old_cli = glstate->texture.client;
if (old_cli!=0) gles_glClientActiveTexture(GL_TEXTURE0);
gl4es_glDisable(GL_LIGHTING);
gl4es_glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
gl4es_glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
switch (mode) {
case BLIT_OPAQUE:
gl4es_glDisable(GL_ALPHA_TEST);
gl4es_glDisable(GL_BLEND);
break;
case BLIT_ALPHA:
gl4es_glEnable(GL_ALPHA_TEST);
gl4es_glAlphaFunc(GL_GREATER, 0.0f);
break;
case BLIT_COLOR:
break;
}
if(drawtexok) {
LOAD_GLES_OES(glDrawTexf);
LOAD_GLES(glTexParameteriv);
// setup texture first
int sourceRect[4] = {sx, sy, width, height};
gles_glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, sourceRect);
// take x/y of ViewPort into account
GLfloat dx = (customvp)?0.0f:glstate->raster.viewport.x;
GLfloat dy = (customvp)?0.0f:glstate->raster.viewport.y;
//TODO: do something with width / height of ViewPort?
// then draw it
gles_glDrawTexf(x+dx, y+dy, 0.0f, width, height);
} else {
LOAD_GLES(glVertexPointer);
LOAD_GLES(glTexCoordPointer);
LOAD_GLES(glDrawArrays);
GLfloat w2 = 2.0f / (customvp?vpwidth:glstate->raster.viewport.width);
GLfloat h2 = 2.0f / (customvp?vpheight:glstate->raster.viewport.height);
GLfloat blit_x1=roundf(x);
GLfloat blit_x2=roundf(x+width*zoomx);
GLfloat blit_y1=roundf(y);
GLfloat blit_y2=roundf(y+height*zoomy);
GLfloat blit_vert[] = {
blit_x1*w2-1.0f, blit_y1*h2-1.0f,
blit_x2*w2-1.0f, blit_y1*h2-1.0f,
blit_x2*w2-1.0f, blit_y2*h2-1.0f,
blit_x1*w2-1.0f, blit_y2*h2-1.0f
};
GLfloat sw = sx/nwidth;
GLfloat sh = sy/nheight;
GLfloat rw = (sx+width)/nwidth;
GLfloat rh = (sy+height)/nheight;
GLfloat blit_tex[] = {
sw, sh,
rw, sh,
rw, rh,
sw, rh
};
gl4es_glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT | GL_CLIENT_PIXEL_STORE_BIT);
gl4es_glGetFloatv(GL_TEXTURE_MATRIX, old_texture);
gl4es_glGetFloatv(GL_PROJECTION_MATRIX, old_projection);
gl4es_glGetFloatv(GL_MODELVIEW_MATRIX, old_modelview);
gl4es_glMatrixMode(GL_TEXTURE);
gl4es_glLoadIdentity();
gl4es_glMatrixMode(GL_PROJECTION);
gl4es_glLoadIdentity();
gl4es_glMatrixMode(GL_MODELVIEW);
gl4es_glLoadIdentity();
if(customvp)
pushViewport(0,0,vpwidth, vpheight);
fpe_glEnableClientState(GL_VERTEX_ARRAY);
gles_glVertexPointer(2, GL_FLOAT, 0, blit_vert);
fpe_glEnableClientState(GL_TEXTURE_COORD_ARRAY);
gles_glTexCoordPointer(2, GL_FLOAT, 0, blit_tex);
for (int a=1; a <hardext.maxtex; a++)
if(glstate->gleshard->vertexattrib[ATT_MULTITEXCOORD0+a].enabled) {
gles_glClientActiveTexture(GL_TEXTURE0 + a);
fpe_glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
gles_glClientActiveTexture(GL_TEXTURE0);
fpe_glDisableClientState(GL_COLOR_ARRAY);
fpe_glDisableClientState(GL_NORMAL_ARRAY);
gles_glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
if(customvp)
popViewport();
gl4es_glPopClientAttrib();
gl4es_glMatrixMode(GL_TEXTURE);
gl4es_glLoadMatrixf(old_texture);
gl4es_glMatrixMode(GL_MODELVIEW);
gl4es_glLoadMatrixf(old_modelview);
gl4es_glMatrixMode(GL_PROJECTION);
gl4es_glLoadMatrixf(old_projection);
}
if (old_cli!=0) gles_glClientActiveTexture(GL_TEXTURE0+old_cli);
}
const char _blit_vsh[] = "#version 100 \n" \
"attribute highp vec2 aPosition; \n" \
"attribute highp vec2 aTexCoord; \n" \
"varying mediump vec2 vTexCoord; \n" \
"void main(){ \n" \
"gl_Position = vec4(aPosition.x, aPosition.y, 0.0, 1.0);\n" \
"vTexCoord = aTexCoord; \n" \
"} \n";
const char _blit_fsh[] = "#version 100 \n" \
"uniform sampler2D uTex; \n" \
"varying mediump vec2 vTexCoord; \n" \
"void main(){ \n" \
"gl_FragColor = texture2D(uTex, vTexCoord); \n" \
"} \n";
const char _blit_vsh_alpha[] = "#version 100 \n" \
"attribute highp vec2 aPosition; \n" \
"attribute highp vec2 aTexCoord; \n" \
"varying mediump vec2 vTexCoord; \n" \
"void main(){ \n" \
"gl_Position = vec4(aPosition.x, aPosition.y, 0.0, 1.0);\n" \
"vTexCoord = aTexCoord; \n" \
"} \n";
const char _blit_fsh_alpha[] = "#version 100 \n" \
"uniform sampler2D uTex; \n" \
"varying mediump vec2 vTexCoord; \n" \
"void main(){ \n" \
"lowp vec4 p = texture2D(uTex, vTexCoord); \n" \
"if (p.a==0.0) discard; \n" \
"gl_FragColor = p; \n" \
"} \n";
void gl4es_blitTexture_gles2(GLuint texture,
GLfloat sx, GLfloat sy,
GLfloat width, GLfloat height,
GLfloat nwidth, GLfloat nheight,
GLfloat zoomx, GLfloat zoomy,
GLfloat vpwidth, GLfloat vpheight,
GLfloat x, GLfloat y, GLint mode) {
LOAD_GLES(glDrawArrays);
if(!glstate->blit) {
LOAD_GLES2(glCreateShader);
LOAD_GLES2(glShaderSource);
LOAD_GLES2(glCompileShader);
LOAD_GLES2(glGetShaderiv);
LOAD_GLES2(glBindAttribLocation);
LOAD_GLES2(glAttachShader);
LOAD_GLES2(glCreateProgram);
LOAD_GLES2(glLinkProgram);
LOAD_GLES2(glGetProgramiv);
LOAD_GLES(glGetUniformLocation);
LOAD_GLES2(glUniform1i);
LOAD_GLES2(glUseProgram);
glstate->blit = (glesblit_t*)malloc(sizeof(glesblit_t));
memset(glstate->blit, 0, sizeof(glesblit_t));
GLint success;
const char *src[1];
src[0] = _blit_fsh;
glstate->blit->pixelshader = gles_glCreateShader( GL_FRAGMENT_SHADER );
gles_glShaderSource( glstate->blit->pixelshader, 1, (const char**) src, NULL );
gles_glCompileShader( glstate->blit->pixelshader );
gles_glGetShaderiv( glstate->blit->pixelshader, GL_COMPILE_STATUS, &success );
if (!success)
{
LOAD_GLES(glGetShaderInfoLog);
char log[400];
gles_glGetShaderInfoLog(glstate->blit->pixelshader_alpha, 399, NULL, log);
SHUT_LOGE("Failed to produce blit fragment shader.\n%s", log);
free(glstate->blit);
glstate->blit = NULL;
}
src[0] = _blit_fsh_alpha;
glstate->blit->pixelshader_alpha = gles_glCreateShader( GL_FRAGMENT_SHADER );
gles_glShaderSource( glstate->blit->pixelshader_alpha, 1, (const char**) src, NULL );
gles_glCompileShader( glstate->blit->pixelshader_alpha );
gles_glGetShaderiv( glstate->blit->pixelshader_alpha, GL_COMPILE_STATUS, &success );
if (!success)
{
LOAD_GLES(glGetShaderInfoLog);
char log[400];
gles_glGetShaderInfoLog(glstate->blit->pixelshader_alpha, 399, NULL, log);
SHUT_LOGE("Failed to produce blit with alpha fragment shader.\n%s", log);
free(glstate->blit);
glstate->blit = NULL;
}
src[0] = _blit_vsh;
glstate->blit->vertexshader = gles_glCreateShader( GL_VERTEX_SHADER );
gles_glShaderSource( glstate->blit->vertexshader, 1, (const char**) src, NULL );
gles_glCompileShader( glstate->blit->vertexshader );
gles_glGetShaderiv( glstate->blit->vertexshader, GL_COMPILE_STATUS, &success );
if( !success )
{
LOAD_GLES(glGetShaderInfoLog);
char log[400];
gles_glGetShaderInfoLog(glstate->blit->pixelshader_alpha, 399, NULL, log);
SHUT_LOGE("Failed to produce blit vertex shader.\n%s", log);
free(glstate->blit);
glstate->blit = NULL;
}
src[0] = _blit_vsh_alpha;
glstate->blit->vertexshader_alpha = gles_glCreateShader( GL_VERTEX_SHADER );
gles_glShaderSource( glstate->blit->vertexshader_alpha, 1, (const char**) src, NULL );
gles_glCompileShader( glstate->blit->vertexshader_alpha );
gles_glGetShaderiv( glstate->blit->vertexshader_alpha, GL_COMPILE_STATUS, &success );
if( !success )
{
LOAD_GLES(glGetShaderInfoLog);
char log[400];
gles_glGetShaderInfoLog(glstate->blit->pixelshader_alpha, 399, NULL, log);
SHUT_LOGE("Failed to produce blit with alpha vertex shader.\n%s", log);
free(glstate->blit);
glstate->blit = NULL;
}
glstate->blit->program = gles_glCreateProgram();
gles_glBindAttribLocation( glstate->blit->program, 0, "aPosition" );
gles_glBindAttribLocation( glstate->blit->program, 1, "aTexCoord" );
gles_glAttachShader( glstate->blit->program, glstate->blit->pixelshader );
gles_glAttachShader( glstate->blit->program, glstate->blit->vertexshader );
gles_glLinkProgram( glstate->blit->program );
gles_glGetProgramiv( glstate->blit->program, GL_LINK_STATUS, &success );
if( !success )
{
SHUT_LOGE("Failed to link blit program.\n");
free(glstate->blit);
glstate->blit = NULL;
}
GLuint oldprog = glstate->gleshard->program;
gles_glUseProgram(glstate->blit->program);
gles_glUniform1i( gles_glGetUniformLocation( glstate->blit->program, "uTex" ), 0 );
glstate->blit->program_alpha = gles_glCreateProgram();
gles_glBindAttribLocation( glstate->blit->program_alpha, 0, "aPosition" );
gles_glBindAttribLocation( glstate->blit->program_alpha, 1, "aTexCoord" );
gles_glAttachShader( glstate->blit->program_alpha, glstate->blit->pixelshader_alpha );
gles_glAttachShader( glstate->blit->program_alpha, glstate->blit->vertexshader_alpha );
gles_glLinkProgram( glstate->blit->program_alpha );
gles_glGetProgramiv( glstate->blit->program_alpha, GL_LINK_STATUS, &success );
if( !success )
{
SHUT_LOGE("Failed to link blit program.\n");
free(glstate->blit);
glstate->blit = NULL;
}
gles_glUseProgram(glstate->blit->program_alpha);
gles_glUniform1i( gles_glGetUniformLocation( glstate->blit->program_alpha, "uTex" ), 0 );
gles_glUseProgram(oldprog);
}
int customvp = (vpwidth>0.0);
GLfloat w2 = 2.0f / (customvp?vpwidth:glstate->raster.viewport.width);
GLfloat h2 = 2.0f / (customvp?vpheight:glstate->raster.viewport.height);
GLfloat blit_x1=roundf(x);
GLfloat blit_x2=roundf(x+width*zoomx);
GLfloat blit_y1=roundf(y);
GLfloat blit_y2=roundf(y+height*zoomy);
GLfloat *vert = glstate->blit->vert;
GLfloat *tex = glstate->blit->tex;
vert[0] = blit_x1*w2-1.0f; vert[1] = blit_y1*h2-1.0f;
vert[2] = blit_x2*w2-1.0f; vert[3] = vert[1];
vert[4] = vert[2]; vert[5] = blit_y2*h2-1.0f;
vert[6] = vert[0]; vert[7] = vert[5];
GLfloat sw = sx/nwidth;
GLfloat sh = sy/nheight;
GLfloat rw = (sx+width)/nwidth;
GLfloat rh = (sy+height)/nheight;
tex[0] = sw; tex[1] = sh;
tex[2] = rw; tex[3] = sh;
tex[4] = rw; tex[5] = rh;
tex[6] = sw; tex[7] = rh;
gl4es_glDisable(GL_BLEND);
int alpha = 0;
switch (mode) {
case BLIT_OPAQUE:
//gl4es_glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
break;
case BLIT_ALPHA:
alpha = 1;
break;
case BLIT_COLOR:
//gl4es_glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
break;
}
realize_blitenv(alpha);
gles_glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
void gl4es_blitTexture(GLuint texture,
GLfloat sx, GLfloat sy,
GLfloat width, GLfloat height,
GLfloat nwidth, GLfloat nheight,
GLfloat zoomx, GLfloat zoomy,
GLfloat vpwidth, GLfloat vpheight,
GLfloat x, GLfloat y, GLint mode) {
//printf("blitTexture(%d, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %f, %d) customvp=%d, vp=%d/%d/%d/%d\n", texture, sx, sy, width, height, nwidth, nheight, zoomx, zoomy, vpwidth, vpheight, x, y, mode, (vpwidth>0.0), glstate->raster.viewport.x, glstate->raster.viewport.y, glstate->raster.viewport.width, glstate->raster.viewport.height);
LOAD_GLES(glBindTexture);
LOAD_GLES(glActiveTexture);
LOAD_GLES(glEnable);
LOAD_GLES(glDisable);
realize_textures(1);
gl4es_glPushAttrib(GL_TEXTURE_BIT | GL_ENABLE_BIT | GL_TRANSFORM_BIT | GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT);
if(glstate->gleshard->active) {
glstate->gleshard->active = 0;
gles_glActiveTexture(GL_TEXTURE0);
}
GLint depthwrite = glstate->depth.mask;
gl4es_glDisable(GL_DEPTH_TEST);
gl4es_glDisable(GL_CULL_FACE);
gl4es_glDisable(GL_STENCIL_TEST);
if(depthwrite)
gl4es_glDepthMask(GL_FALSE);
#ifdef TEXSTREAM
if(glstate->bound_stream[0] && hardext.esversion==1) {
//printf("TMU%d, turning off Streaming (blit)\n", 0);
gles_glDisable(GL_TEXTURE_STREAM_IMG);
DeactivateStreaming();
}
#endif
int tmp = glstate->enable.texture[0];
if(glstate->actual_tex2d[0] != texture)
gles_glBindTexture(GL_TEXTURE_2D, texture);
if(hardext.esversion==1) {
if(!IS_TEX2D(tmp))
gles_glEnable(GL_TEXTURE_2D);
if(IS_CUBE_MAP(tmp))
gles_glDisable(GL_TEXTURE_CUBE_MAP);
gl4es_blitTexture_gles1(texture, sx, sy, width, height,
nwidth, nheight, zoomx, zoomy,
vpwidth, vpheight, x, y, mode);
if(!IS_TEX2D(tmp))
gles_glDisable(GL_TEXTURE_2D);
if(IS_CUBE_MAP(tmp))
gles_glEnable(GL_TEXTURE_CUBE_MAP);
} else {
gl4es_blitTexture_gles2(texture, sx, sy, width, height,
nwidth, nheight, zoomx, zoomy,
vpwidth, vpheight, x, y, mode);
}
// All the previous states are Pushed / Poped anyway...
#ifdef TEXSTREAM
if(glstate->bound_stream[0] && hardext.esversion==1) {
//printf("TMU%d, turning ON Streaming (blit)\n", 0);
gltexture_t *tex = glstate->texture.bound[0][ENABLED_TEX2D];
ActivateStreaming(tex->streamingID);
gles_glEnable(GL_TEXTURE_STREAM_IMG);
} else
#endif
if (glstate->actual_tex2d[0] != texture)
gles_glBindTexture(GL_TEXTURE_2D, glstate->actual_tex2d[0]);
if(depthwrite)
gl4es_glDepthMask(GL_TRUE);
gl4es_glPopAttrib();
}
+18
View File
@@ -0,0 +1,18 @@
#ifndef _GL4ES_BLIT_H_
#define _GL4ES_BLIT_H_
#include "gles.h"
#define BLIT_ALPHA 0
#define BLIT_OPAQUE 1
#define BLIT_COLOR 2
void gl4es_blitTexture(GLuint texture,
GLfloat sx, GLfloat sy,
GLfloat width, GLfloat height,
GLfloat nwidth, GLfloat nheight,
GLfloat zoomx, GLfloat zoomy,
GLfloat vpwidth, GLfloat vpheight,
GLfloat x, GLfloat y, GLint mode);
#endif // _GL4ES_BLIT_H_
+942
View File
@@ -0,0 +1,942 @@
#include "buffers.h"
#include "khash.h"
#include "../glx/hardext.h"
#include "attributes.h"
#include "debug.h"
#include "gl4es.h"
#include "glstate.h"
#include "logs.h"
#include "init.h"
#include "loader.h"
//#define DEBUG
#ifdef DEBUG
#define DBG(a) a
#else
#define DBG(a)
#endif
KHASH_MAP_IMPL_INT(buff, glbuffer_t *);
KHASH_MAP_IMPL_INT(glvao, glvao_t*);
static GLuint lastbuffer = 1;
// Utility function to bind / unbind a particular buffer
glbuffer_t** BUFF(GLenum target) {
switch(target) {
case GL_ARRAY_BUFFER:
return &glstate->vao->vertex;
break;
case GL_ELEMENT_ARRAY_BUFFER:
return &glstate->vao->elements;
break;
case GL_PIXEL_PACK_BUFFER:
return &glstate->vao->pack;
break;
case GL_PIXEL_UNPACK_BUFFER:
return &glstate->vao->unpack;
break;
default:
LOGD("Warning, unknown buffer target 0x%04X\n", target);
}
return (glbuffer_t**)NULL;
}
void unbind_buffer(GLenum target) {
glbuffer_t **t = BUFF(target);
if (t)
*t=(glbuffer_t*)NULL;
}
void bind_buffer(GLenum target, glbuffer_t* buff) {
glbuffer_t ** t = BUFF(target);
if (t)
*t = buff;
}
glbuffer_t* getbuffer_buffer(GLenum target) {
glbuffer_t ** t = BUFF(target);
if (t)
return *t;
return NULL;
}
glbuffer_t* getbuffer_id(GLuint buffer) {
if(!buffer)
return NULL;
khint_t k;
khash_t(buff) *list = glstate->buffers;
k = kh_get(buff, list, buffer);
if (k == kh_end(list))
return NULL;
return kh_value(list, k);
}
int buffer_target(GLenum target) {
if (target==GL_ARRAY_BUFFER)
return 1;
if (target==GL_ELEMENT_ARRAY_BUFFER)
return 1;
if (target==GL_PIXEL_PACK_BUFFER)
return 1;
if (target==GL_PIXEL_UNPACK_BUFFER)
return 1;
return 0;
}
void rebind_real_buff_arrays(int old_buffer, int new_buffer) {
for (int j = 0; j < hardext.maxvattrib; j++) {
if (glstate->vao->vertexattrib[j].real_buffer == old_buffer) {
glstate->vao->vertexattrib[j].real_buffer = new_buffer;
/*if(!new_buffer)
glstate->vao->vertexattrib[j].real_pointer = 0;*/
}
}
}
void APIENTRY_GL4ES gl4es_glGenBuffers(GLsizei n, GLuint * buffers) {
DBG(printf("glGenBuffers(%i, %p)\n", n, buffers);)
noerrorShim();
if (n<1) {
errorShim(GL_INVALID_VALUE);
return;
}
khash_t(buff) *list = glstate->buffers;
for (int i=0; i<n; i++) { // create buffer, and check uniqueness...
int b;
while(getbuffer_id(b=lastbuffer++));
buffers[i] = b;
// create the buffer
khint_t k;
int ret;
k = kh_put(buff, list, b, &ret);
glbuffer_t *buff = kh_value(list, k) = malloc(sizeof(glbuffer_t));
buff->buffer = b;
buff->type = 0; // no target for now
buff->data = NULL;
buff->usage = GL_STATIC_DRAW;
buff->size = 0;
buff->access = GL_READ_WRITE;
buff->mapped = 0;
buff->real_buffer = 0;
}
}
void APIENTRY_GL4ES gl4es_glBindBuffer(GLenum target, GLuint buffer) {
DBG(printf("glBindBuffer(%s, %u)\n", PrintEnum(target), buffer);)
// this flush is probably not needed as long as real VBO are not used
FLUSH_BEGINEND;
khint_t k;
int ret;
khash_t(buff) *list = glstate->buffers;
if (!buffer_target(target)) {
errorShim(GL_INVALID_ENUM);
return;
}
// if buffer = 0 => unbind buffer!
if (buffer == 0) {
// unbind buffer
bindBuffer(target, 0);
unbind_buffer(target);
} else {
// search for an existing buffer
k = kh_get(buff, list, buffer);
glbuffer_t *buff = NULL;
if (k == kh_end(list)){
k = kh_put(buff, list, buffer, &ret);
buff = kh_value(list, k) = malloc(sizeof(glbuffer_t));
buff->buffer = buffer;
buff->type = target;
buff->data = NULL;
buff->usage = GL_STATIC_DRAW;
buff->size = 0;
buff->access = GL_READ_WRITE;
buff->mapped = 0;
buff->real_buffer = 0;
} else {
buff = kh_value(list, k);
buff->type = target; //TODO: check if old binding?
}
bind_buffer(target, buff);
}
noerrorShim();
}
void APIENTRY_GL4ES gl4es_glBufferData(GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage) {
DBG(printf("glBufferData(%s, %zi, %p, %s)\n", PrintEnum(target), size, data, PrintEnum(usage));)
if (!buffer_target(target)) {
errorShim(GL_INVALID_ENUM);
return;
}
glbuffer_t *buff = getbuffer_buffer(target);
if (buff==NULL) {
errorShim(GL_INVALID_OPERATION);
LOGE("Warning, null buffer for target=0x%04X for glBufferData\n", target);
return;
}
if(target==GL_ARRAY_BUFFER)
VaoSharedClear(glstate->vao);
int go_real = 0;
if( (target==GL_ARRAY_BUFFER || target==GL_ELEMENT_ARRAY_BUFFER)
&& (usage==GL_STREAM_DRAW || usage==GL_STATIC_DRAW || usage==GL_DYNAMIC_DRAW) && globals4es.usevbo)
go_real = 1;
if(buff->real_buffer && !go_real) {
rebind_real_buff_arrays(buff->real_buffer, 0);
deleteSingleBuffer(buff->real_buffer);
// what about VA already pointing there?
buff->real_buffer = 0;
}
if(go_real) {
if(!buff->real_buffer) {
LOAD_GLES(glGenBuffers);
gles_glGenBuffers(1, &buff->real_buffer);
}
LOAD_GLES(glBufferData);
LOAD_GLES(glBindBuffer);
bindBuffer(target, buff->real_buffer);
gles_glBufferData(target, size, data, usage);
DBG(printf(" => real VBO %d\n", buff->real_buffer);)
}
if (buff->data && buff->size<size) {
free(buff->data);
buff->data = NULL;
}
if(!buff->data)
buff->data = malloc(size);
buff->size = size;
buff->usage = usage;
DBG(printf("\t buff->data = %p (size=%zd)\n", buff->data, size);)
buff->access = GL_READ_WRITE;
if (data)
memcpy(buff->data, data, size);
// update binded VA
for (int i=0; i<hardext.maxvattrib; ++i) {
vertexattrib_t *v = &glstate->vao->vertexattrib[i];
if( v->buffer == buff ) {
v->real_buffer = v->buffer->real_buffer;
// do not update real_pointer, as it's the relative start in the buffer
}
}
noerrorShim();
}
void APIENTRY_GL4ES gl4es_glNamedBufferData(GLuint buffer, GLsizeiptr size, const GLvoid * data, GLenum usage) {
DBG(printf("glNamedBufferData(%u, %zi, %p, %s)\n", buffer, size, data, PrintEnum(usage));)
glbuffer_t *buff = getbuffer_id(buffer);
if (buff==NULL) {
DBG(printf("Named Buffer not found\n");)
errorShim(GL_INVALID_OPERATION);
return;
}
if (buff->data) {
free(buff->data);
}
int go_real = 0;
if( (buff->type==GL_ARRAY_BUFFER || buff->type==GL_ELEMENT_ARRAY_BUFFER)
&& (usage==GL_STREAM_DRAW || usage==GL_STATIC_DRAW || usage==GL_DYNAMIC_DRAW) && globals4es.usevbo)
go_real = 1;
if(buff->real_buffer && !go_real) {
deleteSingleBuffer(buff->real_buffer);
// what about VA already pointing there?
buff->real_buffer = 0;
}
if(go_real) {
if(!buff->real_buffer) {
LOAD_GLES(glGenBuffers);
gles_glGenBuffers(1, &buff->real_buffer);
}
LOAD_GLES(glBufferData);
LOAD_GLES(glBindBuffer);
bindBuffer(buff->type, buff->real_buffer);
gles_glBufferData(buff->type, size, data, usage);
}
buff->size = size;
buff->usage = usage;
buff->data = malloc(size);
buff->access = GL_READ_WRITE;
if (data)
memcpy(buff->data, data, size);
// update binded VA
for (int i=0; i<hardext.maxvattrib; ++i) {
vertexattrib_t *v = &glstate->vao->vertexattrib[i];
if( v->buffer == buff ) {
v->real_buffer = v->buffer->real_buffer;
// do not update real_pointer, as it's the relative start in the buffer
}
}
noerrorShim();
}
void APIENTRY_GL4ES gl4es_glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
DBG(printf("glBufferSubData(%s, %p, %zi, %p)\n", PrintEnum(target), (void*)offset, size, data);)
if (!buffer_target(target)) {
errorShim(GL_INVALID_ENUM);
return;
}
glbuffer_t *buff = getbuffer_buffer(target);
if (buff==NULL) {
errorShim(GL_INVALID_OPERATION);
DBG(printf("LIBGL: Warning, null buffer for target=0x%04X for glBufferSubData\n", target);)
return;
}
if(target==GL_ARRAY_BUFFER)
VaoSharedClear(glstate->vao);
if (offset<0 || size<0 || offset+size>buff->size) {
errorShim(GL_INVALID_VALUE);
return;
}
if((target==GL_ARRAY_BUFFER || target==GL_ELEMENT_ARRAY_BUFFER) && buff->real_buffer) {
LOAD_GLES(glBufferSubData);
LOAD_GLES(glBindBuffer);
bindBuffer(target, buff->real_buffer);
gles_glBufferSubData(target, offset, size, data);
}
memcpy((char*)buff->data + offset, data, size);
noerrorShim();
}
void APIENTRY_GL4ES gl4es_glNamedBufferSubData(GLuint buffer, GLintptr offset, GLsizeiptr size, const GLvoid * data) {
DBG(printf("glNamedBufferSubData(%u, %p, %zi, %p)\n", buffer, (void*)offset, size, data);)
glbuffer_t *buff = getbuffer_id(buffer);
if (buff==NULL) {
errorShim(GL_INVALID_OPERATION);
return;
}
if (offset<0 || size<0 || offset+size>buff->size) {
errorShim(GL_INVALID_VALUE);
return;
}
if((buff->type==GL_ARRAY_BUFFER || buff->type==GL_ELEMENT_ARRAY_BUFFER) && buff->real_buffer) {
LOAD_GLES(glBufferSubData);
LOAD_GLES(glBindBuffer);
bindBuffer(buff->type, buff->real_buffer);
gles_glBufferSubData(buff->type, offset, size, data);
}
memcpy((char*)buff->data + offset, data, size);
noerrorShim();
}
void APIENTRY_GL4ES gl4es_glDeleteBuffers(GLsizei n, const GLuint * buffers) {
DBG(printf("glDeleteBuffers(%i, %p)\n", n, buffers);)
if(!glstate) return;
FLUSH_BEGINEND;
VaoSharedClear(glstate->vao);
khash_t(buff) *list = glstate->buffers;
if (list) {
khint_t k;
glbuffer_t *buff;
for (int i = 0; i < n; i++) {
GLuint t = buffers[i];
DBG(printf("\t deleting %d\n", t);)
if (t) { // don't allow to remove default one
k = kh_get(buff, list, t);
if (k != kh_end(list)) {
buff = kh_value(list, k);
if(buff->real_buffer) {
rebind_real_buff_arrays(buff->real_buffer, 0); // unbind
LOAD_GLES(glDeleteBuffers);
deleteSingleBuffer(buff->real_buffer);
}
if (glstate->vao->vertex == buff)
glstate->vao->vertex = NULL;
if (glstate->vao->elements == buff)
glstate->vao->elements = NULL;
if (glstate->vao->pack == buff)
glstate->vao->pack = NULL;
if (glstate->vao->unpack == buff)
glstate->vao->unpack = NULL;
for (int j = 0; j < hardext.maxvattrib; j++)
if (glstate->vao->vertexattrib[j].buffer == buff) {
glstate->vao->vertexattrib[j].buffer = NULL;
glstate->vao->vertexattrib[j].real_buffer = 0;
glstate->vao->vertexattrib[j].real_pointer = 0;
}
DBG(printf("\t buff->data = %p\n", buff->data);)
if (buff->data) free(buff->data);
kh_del(buff, list, k);
free(buff);
}
}
}
}
DBG(printf("\t done\n");)
noerrorShim();
}
GLboolean APIENTRY_GL4ES gl4es_glIsBuffer(GLuint buffer) {
DBG(printf("glIsBuffer(%u)\n", buffer);)
khash_t(buff) *list = glstate->buffers;
khint_t k;
noerrorShim();
if (list) {
k = kh_get(buff, list, buffer);
if (k != kh_end(list)) {
return GL_TRUE;
}
}
return GL_FALSE;
}
static void bufferGetParameteriv(glbuffer_t* buff, GLenum value, GLint * data) {
noerrorShim();
switch (value) {
case GL_BUFFER_ACCESS:
data[0] = buff->access;
break;
case GL_BUFFER_ACCESS_FLAGS:
data[0] = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
break;
case GL_BUFFER_MAPPED:
data[0]=(buff->mapped)?GL_TRUE:GL_FALSE;
break;
case GL_BUFFER_MAP_LENGTH:
data[0]=(buff->mapped)?buff->size:0;
break;
case GL_BUFFER_MAP_OFFSET:
data[0]=0;
break;
case GL_BUFFER_SIZE:
data[0] = buff->size;
break;
case GL_BUFFER_USAGE:
data[0] = buff->usage;
break;
default:
errorShim(GL_INVALID_ENUM);
/* TODO Error if something else */
}
}
void APIENTRY_GL4ES gl4es_glGetBufferParameteriv(GLenum target, GLenum value, GLint * data) {
DBG(printf("glGetBufferParameteriv(%s, %s, %p)\n", PrintEnum(target), PrintEnum(value), data);)
if (!buffer_target(target)) {
errorShim(GL_INVALID_ENUM);
return;
}
glbuffer_t* buff = getbuffer_buffer(target);
if (buff==NULL) {
errorShim(GL_INVALID_OPERATION);
return; // Should generate an error!
}
bufferGetParameteriv(buff, value, data);
}
void APIENTRY_GL4ES gl4es_glGetNamedBufferParameteriv(GLuint buffer, GLenum value, GLint * data) {
DBG(printf("glGetNamedBufferParameteriv(%u, %s, %p)\n", buffer, PrintEnum(value), data);)
glbuffer_t* buff = getbuffer_id(buffer);
if (buff==NULL) {
errorShim(GL_INVALID_OPERATION);
return; // Should generate an error!
}
bufferGetParameteriv(buff, value, data);
}
void* APIENTRY_GL4ES gl4es_glMapBuffer(GLenum target, GLenum access) {
DBG(printf("glMapBuffer(%s, %s)\n", PrintEnum(target), PrintEnum(access));)
if (!buffer_target(target)) {
errorShim(GL_INVALID_ENUM);
return (void*)NULL;
}
if(target==GL_ARRAY_BUFFER)
VaoSharedClear(glstate->vao);
glbuffer_t *buff = getbuffer_buffer(target);
if (buff==NULL) {
errorShim(GL_INVALID_VALUE);
return NULL;
}
if(buff->mapped) {
errorShim(GL_INVALID_OPERATION);
return NULL;
}
buff->access = access; // not used
buff->mapped = 1;
buff->ranged = 0;
noerrorShim();
return buff->data; // Not nice, should do some copy or something probably
}
void* APIENTRY_GL4ES gl4es_glMapNamedBuffer(GLuint buffer, GLenum access) {
DBG(printf("glMapNamedBuffer(%u, %s)\n", buffer, PrintEnum(access));)
glbuffer_t *buff = getbuffer_id(buffer);
if (buff==NULL) {
errorShim(GL_INVALID_VALUE);
return NULL;
}
if(buff->mapped) {
errorShim(GL_INVALID_OPERATION);
return NULL;
}
buff->access = access; // not used
buff->mapped = 1;
buff->ranged = 0;
noerrorShim();
return buff->data; // Not nice, should do some copy or something probably
}
GLboolean APIENTRY_GL4ES gl4es_glUnmapBuffer(GLenum target) {
DBG(printf("glUnmapBuffer(%s)\n", PrintEnum(target));)
if(glstate->list.compiling) {errorShim(GL_INVALID_OPERATION); return GL_FALSE;}
FLUSH_BEGINEND;
if (!buffer_target(target)) {
errorShim(GL_INVALID_ENUM);
return GL_FALSE;
}
if(target==GL_ARRAY_BUFFER)
VaoSharedClear(glstate->vao);
glbuffer_t *buff = getbuffer_buffer(target);
if (buff==NULL) {
errorShim(GL_INVALID_VALUE);
return GL_FALSE;
}
noerrorShim();
if(buff->real_buffer && (buff->type==GL_ARRAY_BUFFER || buff->type==GL_ELEMENT_ARRAY_BUFFER) && buff->mapped && !buff->ranged && (buff->access==GL_WRITE_ONLY || buff->access==GL_READ_WRITE)) {
LOAD_GLES(glBufferSubData);
LOAD_GLES(glBindBuffer);
bindBuffer(buff->type, buff->real_buffer);
gles_glBufferSubData(buff->type, 0, buff->size, buff->data);
}
if(buff->real_buffer && (buff->type==GL_ARRAY_BUFFER || buff->type==GL_ELEMENT_ARRAY_BUFFER) && buff->mapped && buff->ranged && (buff->access&GL_MAP_WRITE_BIT_EXT) && !(buff->access&GL_MAP_FLUSH_EXPLICIT_BIT_EXT)) {
LOAD_GLES(glBufferSubData);
bindBuffer(buff->type, buff->real_buffer);
gles_glBufferSubData(buff->type, buff->offset, buff->length, (void*)((uintptr_t)buff->data+buff->offset));
}
if (buff->mapped) {
buff->mapped = 0;
buff->ranged = 0;
return GL_TRUE;
}
return GL_FALSE;
}
GLboolean APIENTRY_GL4ES gl4es_glUnmapNamedBuffer(GLuint buffer) {
DBG(printf("glUnmapNamedBuffer(%u)\n", buffer);)
if(glstate->list.compiling) {errorShim(GL_INVALID_OPERATION); return GL_FALSE;}
FLUSH_BEGINEND;
glbuffer_t *buff = getbuffer_id(buffer);
if (buff==NULL)
return GL_FALSE; // Should generate an error!
noerrorShim();
if(buff->real_buffer && (buff->type==GL_ARRAY_BUFFER || buff->type==GL_ELEMENT_ARRAY_BUFFER) && buff->mapped && (buff->access==GL_WRITE_ONLY || buff->access==GL_READ_WRITE)) {
LOAD_GLES(glBufferSubData);
LOAD_GLES(glBindBuffer);
bindBuffer(buff->type, buff->real_buffer);
gles_glBufferSubData(buff->type, 0, buff->size, buff->data);
}
if(buff->real_buffer && (buff->type==GL_ARRAY_BUFFER || buff->type==GL_ELEMENT_ARRAY_BUFFER) && buff->mapped && buff->ranged && (buff->access&GL_MAP_WRITE_BIT_EXT) && !(buff->access&GL_MAP_FLUSH_EXPLICIT_BIT_EXT)) {
LOAD_GLES(glBufferSubData);
LOAD_GLES(glBindBuffer);
bindBuffer(buff->type, buff->real_buffer);
gles_glBufferSubData(buff->type, buff->offset, buff->length, (void*)((uintptr_t)buff->data+buff->offset));
}
if (buff->mapped) {
buff->mapped = 0;
buff->ranged = 0;
return GL_TRUE;
}
return GL_FALSE;
}
void APIENTRY_GL4ES gl4es_glGetBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid * data) {
DBG(printf("glGetBufferSubData(%s, %p, %zi, %p)\n", PrintEnum(target), (void*)offset, size, data);)
if (!buffer_target(target)) {
errorShim(GL_INVALID_ENUM);
return;
}
glbuffer_t *buff = getbuffer_buffer(target);
if (buff==NULL)
return; // Should generate an error!
// TODO, check parameter consistancie
memcpy(data, (char*)buff->data+offset, size);
noerrorShim();
}
void APIENTRY_GL4ES gl4es_glGetNamedBufferSubData(GLuint buffer, GLintptr offset, GLsizeiptr size, GLvoid * data) {
DBG(printf("glGetNamedBufferSubData(%u, %p, %zi, %p)\n", buffer, (void*)offset, size, data);)
glbuffer_t *buff = getbuffer_id(buffer);
if (buff==NULL)
return; // Should generate an error!
// TODO, check parameter consistancie
memcpy(data, (char*)buff->data+offset, size);
noerrorShim();
}
void APIENTRY_GL4ES gl4es_glGetBufferPointerv(GLenum target, GLenum pname, GLvoid ** params) {
DBG(printf("glGetBufferPointerv(%s, %s, %p)\n", PrintEnum(target), PrintEnum(pname), params);)
if (!buffer_target(target)) {
errorShim(GL_INVALID_ENUM);
return;
}
glbuffer_t *buff = getbuffer_buffer(target);
if (buff==NULL)
return; // Should generate an error!
if (pname != GL_BUFFER_MAP_POINTER) {
errorShim(GL_INVALID_ENUM);
return;
}
if (!buff->mapped) {
params[0] = NULL;
} else {
params[0] = buff->data;
}
}
void APIENTRY_GL4ES gl4es_glGetNamedBufferPointerv(GLuint buffer, GLenum pname, GLvoid ** params) {
DBG(printf("glGetNamedBufferPointerv(%u, %s, %p)\n", buffer, PrintEnum(pname), params);)
glbuffer_t *buff = getbuffer_id(buffer);
if (buff==NULL)
return; // Should generate an error!
if (pname != GL_BUFFER_MAP_POINTER) {
errorShim(GL_INVALID_ENUM);
return;
}
if (!buff->mapped) {
params[0] = NULL;
} else {
params[0] = buff->data;
}
}
void* APIENTRY_GL4ES gl4es_glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)
{
DBG(printf("glMapBufferRange(%s, %p, %zd, 0x%x)\n", PrintEnum(target), (void*)offset, length, access);)
if (!buffer_target(target)) {
errorShim(GL_INVALID_ENUM);
return NULL;
}
glbuffer_t *buff = getbuffer_buffer(target);
if (buff==NULL) {
errorShim(GL_INVALID_VALUE);
return NULL; // Should generate an error!
}
if(buff->mapped) {
errorShim(GL_INVALID_OPERATION);
return NULL;
}
buff->access = access;
buff->mapped = 1;
buff->ranged = 1;
buff->offset = offset;
buff->length = length;
noerrorShim();
uintptr_t ret = (uintptr_t)buff->data;
ret += offset;
return (void*)ret;
}
void APIENTRY_GL4ES gl4es_glFlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length)
{
DBG(printf("glFlushMappedBufferRange(%s, %p, %zd)\n", PrintEnum(target), (void*)offset, length);)
if (!buffer_target(target)) {
errorShim(GL_INVALID_ENUM);
return;
}
if(target==GL_ARRAY_BUFFER)
VaoSharedClear(glstate->vao);
glbuffer_t *buff = getbuffer_buffer(target);
if(!buff) {
errorShim(GL_INVALID_VALUE);
return;
}
if(!buff->mapped || !buff->ranged || !(buff->access&GL_MAP_FLUSH_EXPLICIT_BIT_EXT)) {
errorShim(GL_INVALID_OPERATION);
return;
}
if(buff->real_buffer && (buff->type==GL_ARRAY_BUFFER || buff->type==GL_ELEMENT_ARRAY_BUFFER) && (buff->access&GL_MAP_WRITE_BIT_EXT)) {
LOAD_GLES(glBufferSubData);
bindBuffer(buff->type, buff->real_buffer);
gles_glBufferSubData(buff->type, buff->offset+offset, length, (void*)((uintptr_t)buff->data+buff->offset+offset));
}
}
void APIENTRY_GL4ES gl4es_glCopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size)
{
DBG(printf("glCopyBufferSubData(%s, %s, %p, %p, %zd)\n", PrintEnum(readTarget), PrintEnum(writeTarget), (void*)readOffset, (void*)writeOffset, size);)
//TODO: Add GL_COPY_READ_BUFFER and GL_COPY_WRITE_BUFFER (and GL_QUERY_BUFFER?)
glbuffer_t *readbuff = getbuffer_buffer(readTarget);
glbuffer_t *writebuff = getbuffer_buffer(writeTarget);
if(!readbuff || !writebuff) {
errorShim(GL_INVALID_VALUE);
return;
}
if(writebuff->ranged && !(writebuff->access&GL_MAP_PERSISTENT_BIT)) {
errorShim(GL_INVALID_OPERATION);
return;
}
// TODO: check memory overlap and overread/overwrite
memcpy((char*)writebuff->data+writeOffset, (char*)readbuff->data+readOffset, size);
if(writebuff->real_buffer && (writebuff->type==GL_ARRAY_BUFFER || writebuff->type==GL_ELEMENT_ARRAY_BUFFER) && writebuff->mapped && (writebuff->access==GL_WRITE_ONLY || writebuff->access==GL_READ_WRITE)) {
LOAD_GLES(glBufferSubData);
bindBuffer(writebuff->type, writebuff->real_buffer);
gles_glBufferSubData(writebuff->type, writeOffset, size, (char*)writebuff->data+writeOffset);
}
noerrorShim();
}
void bindBuffer(GLenum target, GLuint buffer)
{
LOAD_GLES(glBindBuffer);
if(target==GL_ARRAY_BUFFER) {
if(glstate->bind_buffer.array == buffer)
return;
DBG(printf("Bind buffer %d to GL_ARRAY_BUFFER\n", buffer);)
glstate->bind_buffer.array = buffer;
gles_glBindBuffer(target, buffer);
} else if (target==GL_ELEMENT_ARRAY_BUFFER) {
glstate->bind_buffer.want_index = buffer;
if(glstate->bind_buffer.index == buffer)
return;
glstate->bind_buffer.index = buffer;
DBG(printf("Bind buffer %d to GL_ELEMENT_ARRAY_BUFFER\n", buffer);)
gles_glBindBuffer(target, buffer);
} else {
LOGE("Warning, unhandled Buffer type %s in bindBuffer\n", PrintEnum(target));
return;
}
glstate->bind_buffer.used = (glstate->bind_buffer.index && glstate->bind_buffer.array)?1:0;
}
GLuint wantBufferIndex(GLuint buffer)
{
GLuint ret = glstate->bind_buffer.want_index;
glstate->bind_buffer.want_index = buffer;
return ret;
}
void realize_bufferIndex()
{
LOAD_GLES(glBindBuffer);
if(glstate->bind_buffer.index != glstate->bind_buffer.want_index) {
glstate->bind_buffer.index = glstate->bind_buffer.want_index;
gles_glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glstate->bind_buffer.index);
DBG(printf("Bind buffer %d to GL_ELEMENT_ARRAY_BUFFER\n", glstate->bind_buffer.index);)
glstate->bind_buffer.used = (glstate->bind_buffer.index && glstate->bind_buffer.array)?1:0;
}
}
void deleteSingleBuffer(GLuint buffer) {
LOAD_GLES(glDeleteBuffers);
if(glstate->bind_buffer.index == buffer) glstate->bind_buffer.index = 0;
else if(glstate->bind_buffer.want_index == buffer) glstate->bind_buffer.want_index = 0;
else if(glstate->bind_buffer.array == buffer) glstate->bind_buffer.array = 0;
gles_glDeleteBuffers(1, &buffer);
}
void unboundBuffers()
{
if(!glstate->bind_buffer.used)
return;
LOAD_GLES(glBindBuffer);
if(glstate->bind_buffer.array) {
glstate->bind_buffer.array = 0;
gles_glBindBuffer(GL_ARRAY_BUFFER, 0);
DBG(printf("Bind buffer %d to GL_ARRAY_BUFFER\n", 0);)
}
if(glstate->bind_buffer.index) {
glstate->bind_buffer.index = 0;
glstate->bind_buffer.want_index = 0;
gles_glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
DBG(printf("Bind buffer %d to GL_ELEMENT_ARRAY_BUFFER\n", 0);)
}
glstate->bind_buffer.used = 0;
}
//Direct wrapper
AliasExport(void,glGenBuffers,,(GLsizei n, GLuint * buffers));
AliasExport(void,glBindBuffer,,(GLenum target, GLuint buffer));
AliasExport(void,glBufferData,,(GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage));
AliasExport(void,glBufferSubData,,(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data));
AliasExport(void,glDeleteBuffers,,(GLsizei n, const GLuint * buffers));
AliasExport(GLboolean,glIsBuffer,,(GLuint buffer));
AliasExport(void,glGetBufferParameteriv,,(GLenum target, GLenum value, GLint * data));
AliasExport(void*,glMapBuffer,,(GLenum target, GLenum access));
AliasExport(GLboolean,glUnmapBuffer,,(GLenum target));
AliasExport(void,glGetBufferSubData,,(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid * data));
AliasExport(void,glGetBufferPointerv,,(GLenum target, GLenum pname, GLvoid ** params));
AliasExport(void*,glMapBufferRange,,(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access));
AliasExport(void,glFlushMappedBufferRange,,(GLenum target, GLintptr offset, GLsizeiptr length));
AliasExport(void,glCopyBufferSubData,,(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size));
//ARB wrapper
#ifndef AMIGAOS4
AliasExport(void,glGenBuffers,ARB,(GLsizei n, GLuint * buffers));
AliasExport(void,glBindBuffer,ARB,(GLenum target, GLuint buffer));
AliasExport(void,glBufferData,ARB,(GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage));
AliasExport(void,glBufferSubData,ARB,(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data));
AliasExport(void,glDeleteBuffers,ARB,(GLsizei n, const GLuint * buffers));
AliasExport(GLboolean,glIsBuffer,ARB,(GLuint buffer));
AliasExport(void,glGetBufferParameteriv,ARB,(GLenum target, GLenum value, GLint * data));
AliasExport(void*,glMapBuffer,ARB,(GLenum target, GLenum access));
AliasExport(GLboolean,glUnmapBuffer,ARB,(GLenum target));
AliasExport(void,glGetBufferSubData,ARB,(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid * data));
AliasExport(void,glGetBufferPointerv,ARB,(GLenum target, GLenum pname, GLvoid ** params));
#endif
//Direct Access
AliasExport(void,glNamedBufferData,,(GLuint buffer, GLsizeiptr size, const GLvoid * data, GLenum usage));
AliasExport(void,glNamedBufferSubData,,(GLuint buffer, GLintptr offset, GLsizeiptr size, const GLvoid * data));
AliasExport(void,glGetNamedBufferParameteriv,,(GLuint buffer, GLenum value, GLint * data));
AliasExport(void*,glMapNamedBuffer,,(GLuint buffer, GLenum access));
AliasExport(GLboolean,glUnmapNamedBuffer,,(GLuint buffer));
AliasExport(void,glGetNamedBufferSubData,,(GLuint buffer, GLintptr offset, GLsizeiptr size, GLvoid * data));
AliasExport(void,glGetNamedBufferPointerv,,(GLuint buffer, GLenum pname, GLvoid ** params));
AliasExport(void,glNamedBufferData,EXT,(GLuint buffer, GLsizeiptr size, const GLvoid * data, GLenum usage));
AliasExport(void,glNamedBufferSubData,EXT,(GLuint buffer, GLintptr offset, GLsizeiptr size, const GLvoid * data));
AliasExport(void,glGetNamedBufferParameteriv,EXT,(GLuint buffer, GLenum value, GLint * data));
AliasExport(void*,glMapNamedBuffer,EXT,(GLuint buffer, GLenum access));
AliasExport(GLboolean,glUnmapNamedBuffer,EXT,(GLuint buffer));
AliasExport(void,glGetNamedBufferSubData,EXT,(GLuint buffer, GLintptr offset, GLsizeiptr size, GLvoid * data));
AliasExport(void,glGetNamedBufferPointerv,EXT,(GLuint buffer, GLenum pname, GLvoid ** params));
// VAO ****************
static GLuint lastvao = 1;
void APIENTRY_GL4ES gl4es_glGenVertexArrays(GLsizei n, GLuint *arrays) {
DBG(printf("glGenVertexArrays(%i, %p)\n", n, arrays);)
noerrorShim();
if (n<1) {
errorShim(GL_INVALID_VALUE);
return;
}
for (int i=0; i<n; i++) { // TODO: create VAO here and check unicity
arrays[i] = lastvao++;
}
}
void APIENTRY_GL4ES gl4es_glBindVertexArray(GLuint array) {
DBG(printf("glBindVertexArray(%u)\n", array);)
FLUSH_BEGINEND;
khint_t k;
int ret;
khash_t(glvao) *list = glstate->vaos;
// if array = 0 => unbind buffer!
if (array == 0) {
// unbind buffer
glstate->vao = glstate->defaultvao;
} else {
// search for an existing buffer
k = kh_get(glvao, list, array);
glvao_t *glvao = NULL;
if (k == kh_end(list)){
k = kh_put(glvao, list, array, &ret);
glvao = kh_value(list, k) = malloc(sizeof(glvao_t));
// new vao is binded to nothing
VaoInit(glvao);
// Copy current status to new VAO
glvao->vertex = glstate->vao->vertex;
glvao->elements = glstate->vao->elements;
glvao->pack = glstate->vao->pack;
glvao->unpack = glstate->vao->unpack;
glvao->maxtex = glstate->vao->maxtex;
// just put is number
glvao->array = array;
} else {
glvao = kh_value(list, k);
}
glstate->vao = glvao;
}
noerrorShim();
}
void APIENTRY_GL4ES gl4es_glDeleteVertexArrays(GLsizei n, const GLuint *arrays) {
DBG(printf("glDeleteVertexArrays(%i, %p)\n", n, arrays);)
if(!glstate) return;
FLUSH_BEGINEND;
khash_t(glvao) *list = glstate->vaos;
if (list) {
khint_t k;
glvao_t *glvao;
for (int i = 0; i < n; i++) {
GLuint t = arrays[i];
if (t) { // don't allow to remove the default one
k = kh_get(glvao, list, t);
if (k != kh_end(list)) {
glvao = kh_value(list, k);
VaoSharedClear(glvao);
kh_del(glvao, list, k);
//free(glvao); //let the use delete those
}
}
}
}
noerrorShim();
}
GLboolean APIENTRY_GL4ES gl4es_glIsVertexArray(GLuint array) {
DBG(printf("glIsVertexArray(%u)\n", array);)
if(!glstate)
return GL_FALSE;
khash_t(glvao) *list = glstate->vaos;
khint_t k;
noerrorShim();
if (list) {
k = kh_get(glvao, list, array);
if (k != kh_end(list)) {
return GL_TRUE;
}
}
return GL_FALSE;
}
void VaoSharedClear(glvao_t *vao) {
if(vao==NULL || vao->shared_arrays==NULL)
return;
if(!(--(*vao->shared_arrays))) {
free(vao->vert.ptr);
free(vao->color.ptr);
free(vao->secondary.ptr);
free(vao->normal.ptr);
for (int i=0; i<hardext.maxtex; i++)
free(vao->tex[i].ptr);
free(vao->shared_arrays);
}
vao->vert.ptr = NULL;
vao->color.ptr = NULL;
vao->secondary.ptr = NULL;
vao->normal.ptr = NULL;
for (int i=0; i<hardext.maxtex; i++)
vao->tex[i].ptr = NULL;
vao->shared_arrays = NULL;
}
void VaoInit(glvao_t *vao) {
memset(vao, 0, sizeof(glvao_t));
for (int i=0; i<hardext.maxvattrib; i++) {
vao->vertexattrib[i].size = 4;
vao->vertexattrib[i].type = GL_FLOAT;
}
}
//Direct wrapper
AliasExport(void,glGenVertexArrays,,(GLsizei n, GLuint *arrays));
AliasExport(void,glBindVertexArray,,(GLuint array));
AliasExport(void,glDeleteVertexArrays,,(GLsizei n, const GLuint *arrays));
AliasExport(GLboolean,glIsVertexArray,,(GLuint array));
+243
View File
@@ -0,0 +1,243 @@
#ifndef _GL4ES_BUFFERS_H_
#define _GL4ES_BUFFERS_H_
#include "khash.h"
#include "../config.h"
#include "gles.h"
// VBO *****************
typedef struct {
GLuint buffer;
GLuint real_buffer;
GLenum type;
GLsizeiptr size;
GLenum usage;
GLint access;
int mapped;
int ranged;
GLintptr offset;
GLsizeiptr length;
GLvoid *data;
} glbuffer_t;
KHASH_MAP_DECLARE_INT(buff, glbuffer_t *);
void APIENTRY_GL4ES gl4es_glGenBuffers(GLsizei n, GLuint * buffers);
void APIENTRY_GL4ES gl4es_glBindBuffer(GLenum target, GLuint buffer);
void APIENTRY_GL4ES gl4es_glBufferData(GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage);
void APIENTRY_GL4ES gl4es_glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
void APIENTRY_GL4ES gl4es_glDeleteBuffers(GLsizei n, const GLuint * buffers);
GLboolean APIENTRY_GL4ES gl4es_glIsBuffer(GLuint buffer);
void APIENTRY_GL4ES gl4es_glGetBufferParameteriv(GLenum target, GLenum value, GLint * data);
void* APIENTRY_GL4ES gl4es_glMapBuffer(GLenum target, GLenum access);
GLboolean APIENTRY_GL4ES gl4es_glUnmapBuffer(GLenum target);
void APIENTRY_GL4ES gl4es_glGetBufferPointerv(GLenum target, GLenum pname, GLvoid ** params);
void APIENTRY_GL4ES gl4es_glGetBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid * data);
void* APIENTRY_GLES gl4es_glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
void APIENTRY_GL4ES gl4es_glFlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length);
void APIENTRY_GL4ES gl4es_glCopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
void APIENTRY_GL4ES glGenBuffers(GLsizei n, GLuint * buffers);
void APIENTRY_GL4ES glBindBuffer(GLenum target, GLuint buffer);
void APIENTRY_GL4ES glBufferData(GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage);
void APIENTRY_GL4ES glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
void APIENTRY_GL4ES glDeleteBuffers(GLsizei n, const GLuint * buffers);
GLboolean APIENTRY_GL4ES glIsBuffer(GLuint buffer);
void APIENTRY_GL4ES glGetBufferParameteriv(GLenum target, GLenum value, GLint * data);
void* APIENTRY_GL4ES glMapBuffer(GLenum target, GLenum access);
GLboolean APIENTRY_GL4ES glUnmapBuffer(GLenum target);
void APIENTRY_GL4ES glGetBufferPointerv(GLenum target, GLenum pname, GLvoid ** params);
void APIENTRY_GL4ES glGetBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid * data);
void* APIENTRY_GL4ES glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
void APIENTRY_GL4ES glFlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length);
void APIENTRY_GL4ES glGenBuffersARB(GLsizei n, GLuint * buffers);
void APIENTRY_GL4ES glBindBufferARB(GLenum target, GLuint buffer);
void APIENTRY_GL4ES glBufferDataARB(GLenum target, GLsizeiptr size, const GLvoid * data, GLenum usage);
void APIENTRY_GL4ES glBufferSubDataARB(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid * data);
void APIENTRY_GL4ES glDeleteBuffersARB(GLsizei n, const GLuint * buffers);
GLboolean APIENTRY_GL4ES glIsBufferARB(GLuint buffer);
void APIENTRY_GL4ES glGetBufferParameterivARB(GLenum target, GLenum value, GLint * data);
void* APIENTRY_GL4ES glMapBufferARB(GLenum target, GLenum access);
GLboolean APIENTRY_GL4ES glUnmapBufferARB(GLenum target);
void APIENTRY_GL4ES glGetBufferSubDataARB(GLenum target, GLintptr offset, GLsizeiptr size, GLvoid * data);
void APIENTRY_GL4ES glGetBufferPointervARB(GLenum target, GLenum pname, GLvoid ** params);
// internal actual BindBuffer with cache
void bindBuffer(GLenum target, GLuint buffer);
// delete a single buffer (and erase it from the cache)
void deleteSingleBuffer(GLuint buffer);
// unbound all buffer
void unboundBuffers();
// update wanted Index Buffer
GLuint wantBufferIndex(GLuint buffer);
// Bind the wanted index buffer if needed
void realize_bufferIndex();
// Pointer..... ****** => map them in vertexattrib (even with GLES1.1). So no more pointer_state_t, use vertexattrib_t
// and map .enabled to .vaarray
// This map correspond to ARB_vertex_program map
typedef enum {
ARB_VERTEX = 0,
//ARB_WEIGHT
ARB_NORMAL = 2,
ARB_COLOR,
ARB_SECONDARY,
ARB_FOGCOORD,
// 6 and 7 are nothing specifics
ARB_MULTITEXCOORD0 = 8,
ARB_MULTITEXCOORD1,
ARB_MULTITEXCOORD2,
ARB_MULTITEXCOORD3,
ARB_MULTITEXCOORD4,
ARB_MULTITEXCOORD5,
ARB_MULTITEXCOORD6,
ARB_MULTITEXCOORD7,
ARB_MULTITEXCOORD8,
ARB_MULTITEXCOORD9,
ARB_MULTITEXCOORD10,
ARB_MULTITEXCOORD11,
ARB_MULTITEXCOORD12,
ARB_MULTITEXCOORD13,
ARB_MULTITEXCOORD14,
ARB_MULTITEXCOORD15,
//ARB_POINTSIZE, //this one is supported by GLES hardware
ARB_MAX
} reserved_attrib_t;
// This map correspond tries to fit as much as possible in 8 VA
typedef enum {
COMP_VERTEX = 0,
COMP_FOGCOORD,
COMP_NORMAL,
COMP_COLOR,
COMP_SECONDARY,
COMP_MULTITEXCOORD0,
COMP_MULTITEXCOORD1,
COMP_MULTITEXCOORD2,
COMP_MULTITEXCOORD3,
COMP_MULTITEXCOORD4,
COMP_MULTITEXCOORD5,
COMP_MULTITEXCOORD6,
COMP_MULTITEXCOORD7,
COMP_MULTITEXCOORD8,
COMP_MULTITEXCOORD9,
COMP_MULTITEXCOORD10,
COMP_MULTITEXCOORD11,
COMP_MULTITEXCOORD12,
COMP_MULTITEXCOORD13,
COMP_MULTITEXCOORD14,
COMP_MULTITEXCOORD15,
//COMP_WEIGHT
//COMP_POINTSIZE, //this one is supported by GLES hardware
COMP_MAX
} compressed_attrib_t;
#define ATT_VERTEX ((hardext.maxvattrib>8)?ARB_VERTEX:COMP_VERTEX)
#define ATT_NORMAL ((hardext.maxvattrib>8)?ARB_NORMAL:COMP_NORMAL)
#define ATT_COLOR ((hardext.maxvattrib>8)?ARB_COLOR:COMP_COLOR)
#define ATT_SECONDARY ((hardext.maxvattrib>8)?ARB_SECONDARY:COMP_SECONDARY)
#define ATT_FOGCOORD ((hardext.maxvattrib>8)?ARB_FOGCOORD:COMP_FOGCOORD)
#define ATT_MULTITEXCOORD0 ((hardext.maxvattrib>8)?ARB_MULTITEXCOORD0:COMP_MULTITEXCOORD0)
#define ATT_MULTITEXCOORD1 ((hardext.maxvattrib>8)?ARB_MULTITEXCOORD1:COMP_MULTITEXCOORD1)
#define ATT_MULTITEXCOORD2 ((hardext.maxvattrib>8)?ARB_MULTITEXCOORD2:COMP_MULTITEXCOORD2)
#define ATT_MULTITEXCOORD3 ((hardext.maxvattrib>8)?ARB_MULTITEXCOORD3:COMP_MULTITEXCOORD3)
#define ATT_MULTITEXCOORD4 ((hardext.maxvattrib>8)?ARB_MULTITEXCOORD4:COMP_MULTITEXCOORD4)
#define ATT_MULTITEXCOORD5 ((hardext.maxvattrib>8)?ARB_MULTITEXCOORD5:COMP_MULTITEXCOORD5)
#define ATT_MULTITEXCOORD6 ((hardext.maxvattrib>8)?ARB_MULTITEXCOORD6:COMP_MULTITEXCOORD6)
#define ATT_MULTITEXCOORD7 ((hardext.maxvattrib>8)?ARB_MULTITEXCOORD7:COMP_MULTITEXCOORD7)
#define ATT_MULTITEXCOORD8 ((hardext.maxvattrib>8)?ARB_MULTITEXCOORD8:COMP_MULTITEXCOORD8)
#define ATT_MULTITEXCOORD9 ((hardext.maxvattrib>8)?ARB_MULTITEXCOORD9:COMP_MULTITEXCOORD9)
#define ATT_MULTITEXCOORD10 ((hardext.maxvattrib>8)?ARB_MULTITEXCOORD10:COMP_MULTITEXCOORD10)
#define ATT_MULTITEXCOORD11 ((hardext.maxvattrib>8)?ARB_MULTITEXCOORD11:COMP_MULTITEXCOORD11)
#define ATT_MULTITEXCOORD12 ((hardext.maxvattrib>8)?ARB_MULTITEXCOORD12:COMP_MULTITEXCOORD12)
#define ATT_MULTITEXCOORD13 ((hardext.maxvattrib>8)?ARB_MULTITEXCOORD13:COMP_MULTITEXCOORD13)
#define ATT_MULTITEXCOORD14 ((hardext.maxvattrib>8)?ARB_MULTITEXCOORD14:COMP_MULTITEXCOORD14)
#define ATT_MULTITEXCOORD15 ((hardext.maxvattrib>8)?ARB_MULTITEXCOORD15:COMP_MULTITEXCOORD15)
#define ATT_MAX ARB_MAX
#define NB_VA (ATT_MAX)
// glLockArrays should lock all arrays, but Quake3 do change values on Color and Textures UV, so limit Lock to 3D" Coords arrays
#define NB_LOCKVA (ATT_NORMAL+1)
// Vertex Attrib.. ***
typedef struct {
GLint size;
GLenum type;
GLsizei stride;
const GLvoid* pointer;
int enabled;
int normalized;
glbuffer_t *buffer; // reference buffer
GLint divisor;
GLuint real_buffer; // If there is a real VBO binded
const GLvoid* real_pointer; // the pointer related to real VBO
int integer;
} vertexattrib_t;
typedef struct {
GLfloat *ptr;
vertexattrib_t state;
int enabled;
} pointer_cache_t;
// VAO ****************
typedef struct {
GLuint array;
// buffer state
glbuffer_t *vertex;
glbuffer_t *elements;
glbuffer_t *pack;
glbuffer_t *unpack;
// locked arrays
int locked;
GLsizei count;
GLint first;
int locked_mapped[NB_VA];
int maxtex; // upper limit enabled tex_coord
// VAO optimisation: keep a shared copy of the digested datas (unless the vao is the default one)
int *shared_arrays;
pointer_cache_t vert;
pointer_cache_t normal;
pointer_cache_t color;
pointer_cache_t secondary;
pointer_cache_t fog;
pointer_cache_t tex[MAX_TEX];
int cache_count;
// Vertex Attrib
vertexattrib_t vertexattrib[MAX_VATTRIB];
// TODO: Cache VA also?
} glvao_t;
void VaoSharedClear(glvao_t *vao);
void VaoInit(glvao_t *vao);
KHASH_MAP_DECLARE_INT(glvao, glvao_t*);
void APIENTRY_GL4ES gl4es_glGenVertexArrays(GLsizei n, GLuint *arrays);
void APIENTRY_GL4ES gl4es_glBindVertexArray(GLuint array);
void APIENTRY_GL4ES gl4es_glDeleteVertexArrays(GLsizei n, const GLuint *arrays);
GLboolean APIENTRY_GL4ES gl4es_glIsVertexArray(GLuint array);
void APIENTRY_GL4ES glGenVertexArrays(GLsizei n, GLuint *arrays);
void APIENTRY_GL4ES glBindVertexArray(GLuint array);
void APIENTRY_GL4ES glDeleteVertexArrays(GLsizei n, const GLuint *arrays);
GLboolean APIENTRY_GL4ES glIsVertexArray(GLuint array);
void APIENTRY_GL4ES gl4es_glNamedBufferData(GLuint buffer, GLsizeiptr size, const GLvoid * data, GLenum usage);
void APIENTRY_GL4ES gl4es_glNamedBufferSubData(GLuint buffer, GLintptr offset, GLsizeiptr size, const GLvoid * data);
void APIENTRY_GL4ES gl4es_glGetNamedBufferParameteriv(GLuint buffer, GLenum value, GLint * data);
void* APIENTRY_GL4ES gl4es_glMapNamedBuffer(GLuint buffer, GLenum access);
GLboolean APIENTRY_GL4ES gl4es_glUnmapNamedBuffer(GLuint buffer);
void APIENTRY_GL4ES gl4es_glGetNamedBufferSubData(GLuint buffer, GLintptr offset, GLsizeiptr size, GLvoid * data);
void APIENTRY_GL4ES gl4es_glGetNamedBufferPointerv(GLuint buffer, GLenum pname, GLvoid ** params);
#endif // _GL4ES_BUFFERS_H_
+9
View File
@@ -0,0 +1,9 @@
#include <stdio.h>
#include "build_info.h"
#include "logs.h"
#include "../../version.h"
void print_build_infos()
{
SHUT_LOGD("v%d.%d.%d built on %s %s\n", MAJOR, MINOR, REVISION, __DATE__, __TIME__);
}
+6
View File
@@ -0,0 +1,6 @@
#ifndef _GL4ES_BUILD_INFO_H_
#define _GL4ES_BUILD_INFO_H_
void print_build_infos();
#endif // _GL4ES_BUILD_INFO_H_
+935
View File
@@ -0,0 +1,935 @@
#ifndef _GL4ES_CONST_H_
#define _GL4ES_CONST_H_
#define GL_QUADS 7
#define GL_QUAD_STRIP 8
#define GL_POLYGON 9
#define GL_MAJOR_VERSION 0x821B
#define GL_MINOR_VERSION 0x821C
#define GL_DOUBLEBUFFER 0x0C32
/* texture mapping */
#define GL_TEXTURE_ENV 0x2300
#define GL_TEXTURE_ENV_MODE 0x2200
#define GL_TEXTURE_1D 0x0DE0
#define GL_TEXTURE_2D 0x0DE1
#define GL_TEXTURE_3D 0x806F
#define GL_TEXTURE_WRAP_S 0x2802
#define GL_TEXTURE_WRAP_T 0x2803
#define GL_TEXTURE_WRAP_R 0x8072
#define GL_TEXTURE_MAG_FILTER 0x2800
#define GL_TEXTURE_MIN_FILTER 0x2801
#define GL_TEXTURE_ENV_COLOR 0x2201
#define GL_TEXTURE_GEN_S 0x0C60
#define GL_TEXTURE_GEN_T 0x0C61
#define GL_TEXTURE_GEN_MODE 0x2500
#define GL_TEXTURE_BORDER_COLOR 0x1004
#define GL_TEXTURE_BORDER 0x1005
#define GL_TEXTURE_WIDTH 0x1000
#define GL_TEXTURE_HEIGHT 0x1001
#define GL_TEXTURE_BORDER 0x1005
#define GL_TEXTURE_COMPONENTS 0x1003
#define GL_TEXTURE_RED_SIZE 0x805C
#define GL_TEXTURE_GREEN_SIZE 0x805D
#define GL_TEXTURE_BLUE_SIZE 0x805E
#define GL_TEXTURE_ALPHA_SIZE 0x805F
#define GL_TEXTURE_LUMINANCE_SIZE 0x8060
#define GL_TEXTURE_INTENSITY_SIZE 0x8061
#define GL_NEAREST_MIPMAP_NEAREST 0x2700
#define GL_NEAREST_MIPMAP_LINEAR 0x2702
#define GL_LINEAR_MIPMAP_NEAREST 0x2701
#define GL_LINEAR_MIPMAP_LINEAR 0x2703
#define GL_OBJECT_LINEAR 0x2401
#define GL_OBJECT_PLANE 0x2501
#define GL_EYE_LINEAR 0x2400
#define GL_EYE_PLANE 0x2502
#define GL_SPHERE_MAP 0x2402
#define GL_NORMAL_MAP 0x8511
#define GL_REFLECTION_MAP 0x8512
#define GL_DECAL 0x2101
#define GL_MODULATE 0x2100
#define GL_NEAREST 0x2600
#define GL_REPEAT 0x2901
#define GL_CLAMP 0x2900
#define GL_S 0x2000
#define GL_T 0x2001
#define GL_R 0x2002
#define GL_Q 0x2003
#define GL_TEXTURE_GEN_R 0x0C62
#define GL_TEXTURE_GEN_Q 0x0C63
#define GL_PROXY_TEXTURE_1D 0x8063
#define GL_PROXY_TEXTURE_2D 0x8064
#define GL_PROXY_TEXTURE_3D 0x8070
#define GL_TEXTURE_MIN_LOD 0x813A
#define GL_TEXTURE_MAX_LOD 0x813B
#define GL_TEXTURE_FILTER_CONTROL 0x8500
#define GL_TEXTURE_LOD_BIAS 0x8501
#define GL_TEXTURE_CUBE_MAP 0x8513
#define GL_TEXTURE_GEN_STR 0x8D60
#define GL_CLAMP_TO_BORDER 0x812D
#define GL_MAX_TEXTURE_COORDS 0x8871
#define GL_TEXTURE_COMPARE_MODE 0x884C
// GL_ARB_point_sprite
#define GL_POINT_SPRITE 0x8861
#define GL_COORD_REPLACE 0x8862
// GL_ARB_texture_rectangle
#define GL_TEXTURE_RECTANGLE_ARB 0x84F5
#define GL_TEXTURE_BINDING_RECTANGLE_ARB 0x84F6
#define GL_PROXY_TEXTURE_RECTANGLE_ARB 0x84F7
#define GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB 0x84F8
#define GL_LINE_SMOOTH 0x0B20
#define GL_LINE_STIPPLE 0x0B24
#define GL_LINE_STIPPLE_PATTERN 0x0B25
#define GL_LINE_STIPPLE_REPEAT 0x0B26
#define GL_LINE_WIDTH 0x0B21
#define GL_LINE_WIDTH_GRANULARITY 0x0B23
#define GL_LINE_WIDTH_RANGE 0x0B22
#define GL_OBJECT_LINEAR 0x2401
#define GL_OBJECT_PLANE 0x2501
#define GL_EYE_LINEAR 0x2400
#define GL_EYE_PLANE 0x2502
#define GL_SPHERE_MAP 0x2402
#define GL_CURRENT_BIT 0x00001
#define GL_POINT_BIT 0x00002
#define GL_LINE_BIT 0x00004
#define GL_POLYGON_BIT 0x00008
#define GL_POLYGON_STIPPLE_BIT 0x00010
#define GL_PIXEL_MODE_BIT 0x00020
#define GL_LIGHTING_BIT 0x00040
#define GL_FOG_BIT 0x00080
// some of these are already defined in GLES
// #define GL_DEPTH_BUFFER_BIT 0x00100
#define GL_ACCUM_BUFFER_BIT 0x00200
// #define GL_STENCIL_BUFFER_BIT 0x00400
#define GL_VIEWPORT_BIT 0x00800
#define GL_TRANSFORM_BIT 0x01000
#define GL_ENABLE_BIT 0x02000
// #define GL_COLOR_BUFFER_BIT 0x04000
#define GL_HINT_BIT 0x08000
#define GL_EVAL_BIT 0x10000
#define GL_LIST_BIT 0x20000
#define GL_TEXTURE_BIT 0x40000
#define GL_SCISSOR_BIT 0x80000
#define GL_ALL_ATTRIB_BITS 0xFFFFF
#define GL_MULTISAMPLE_BIT 0x20000000
#define GL_CLIENT_PIXEL_STORE_BIT 0x00000001
#define GL_CLIENT_VERTEX_ARRAY_BIT 0x00000002
#define GL_ALL_CLIENT_ATTRIB_BITS 0xFFFFFFFF
#define GL_CLIENT_ALL_ATTRIB_BITS 0xFFFFFFFF
// secondary color
#define GL_SECONDARY_COLOR_ARRAY_SIZE 0x845A
#define GL_SECONDARY_COLOR_ARRAY_TYPE 0x845B
#define GL_SECONDARY_COLOR_ARRAY_STRIDE 0x845C
#define GL_SECONDARY_COLOR_ARRAY_POINTER 0x845D
#define GL_SECONDARY_COLOR_ARRAY 0x845E
#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C
#define GL_COLOR_SUM 0x8458
#define GL_CURRENT_SECONDARY_COLOR 0x8459
// pixel formats
#define GL_COLOR_INDEX 0x1900
#define GL_RED 0x1903
#define GL_R3_G3_B2 0x2A10
#define GL_RG 0x8227
#define GL_BGR 0x80E0
#define GL_BGRA 0x80E1
#define GL_UNSIGNED_BYTE_3_3_2 0x8032
#define GL_UNSIGNED_BYTE_2_3_3_REV 0x8362
#define GL_UNSIGNED_SHORT_5_6_5 0x8363
#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364
#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033
#define GL_UNSIGNED_SHORT_4_4_4_4_REV 0x8365
#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034
#define GL_UNSIGNED_SHORT_1_5_5_5_REV 0x8366
#define GL_UNSIGNED_INT_8_8_8_8 0x8035
#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
#define GL_UNSIGNED_INT_10_10_10_2 0x8036
#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
#define GL_R8 0x8229
#define GL_RGB8 0x8051
#define GL_RGB5 0x8050
#define GL_RGB4 0x804F
#define GL_RGBA8 0x8058
#define GL_RGBA16 0x805B
#define GL_ALPHA4 0x803B
#define GL_ALPHA8 0x803C
#define GL_ALPHA12 0x803D
#define GL_ALPHA16 0x803E
#define GL_ALPHA16F 0x881C
#define GL_ALPHA32F 0x8816
#define GL_LUMINANCE4 0x803F
#define GL_LUMINANCE8 0x8040
#define GL_LUMINANCE12 0x8041
#define GL_LUMINANCE16 0x8042
#define GL_LUMINANCE16F 0x881E
#define GL_LUMINANCE32F 0x8818
#define GL_LUMINANCE4_ALPHA4 0x8043
#define GL_LUMINANCE6_ALPHA2 0x8044
#define GL_LUMINANCE8_ALPHA8 0x8045
#define GL_LUMINANCE12_ALPHA4 0x8046
#define GL_LUMINANCE12_ALPHA12 0x8047
#define GL_LUMINANCE16_ALPHA16 0x8048
#define GL_LUMINANCE_ALPHA16F 0x881F
#define GL_LUMINANCE_ALPHA32F 0x8819
#define GL_INTENSITY 0x8049
#define GL_INTENSITY4 0x804A
#define GL_INTENSITY8 0x804B
#define GL_INTENSITY12 0x804C
#define GL_INTENSITY16 0x804D
#define GL_INTENSITY16F 0x881D
#define GL_INTENSITY32F 0x8817
#define GL_RGB10_A2 0x8059
#define GL_RGBA16F 0x881A
#define GL_RGB16F 0x881B
#define GL_RGBA32F 0x8814
#define GL_RGB32F 0x8815
#define GL_LUMINANCE16_ALPHA16 0x8048
#define GL_RGB16 0x8054
#define GL_RGBA4 0x8056
#define GL_RGB5_A1 0x8057
#define GL_COMPRESSED_ALPHA 0x84E9
#define GL_COMPRESSED_LUMINANCE 0x84EA
#define GL_COMPRESSED_LUMINANCE_ALPHA 0x84EB
#define GL_COMPRESSED_INTENSITY 0x84EC
#define GL_COMPRESSED_RGB 0x84ED
#define GL_COMPRESSED_RGBA 0x84EE
#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3
#define GL_HALF_FLOAT_OES 0x8D61
#define GL_RGB565 0x8D62
// types
#define GL_BYTE 0x1400
#define GL_UNSIGNED_BYTE 0x1401
#define GL_SHORT 0x1402
#define GL_UNSIGNED_SHORT 0x1403
#define GL_INT 0x1404
#define GL_UNSIGNED_INT 0x1405
#define GL_FLOAT 0x1406
#define GL_2_BYTES 0x1407
#define GL_3_BYTES 0x1408
#define GL_4_BYTES 0x1409
#define GL_DOUBLE 0x140A
#define GL_HALF_FLOAT 0x140B
#define GL_BITMAP 0x1A00
#define GL_COMPILE 0x1300
#define GL_COMPILE_AND_EXECUTE 0x1301
// fog
#define GL_FOG 0x0B60
#define GL_FOG_MODE 0x0B65
#define GL_FOG_DENSITY 0x0B62
#define GL_FOG_COLOR 0x0B66
#define GL_FOG_INDEX 0x0B61
#define GL_FOG_START 0x0B63
#define GL_FOG_END 0x0B64
#define GL_LINEAR 0x2601
#define GL_EXP 0x0800
#define GL_EXP2 0x0801
#define GL_FOG_COORDINATE_SOURCE 0x8450
#define GL_FOG_COORD_SRC GL_FOG_COORDINATE_SOURCE
#define GL_FRAGMENT_DEPTH 0x8452
#define GL_FOG_COORDINATE 0x8451
#define GL_FOG_COORD GL_FOG_COORDINATE
#define GL_CURRENT_FOG_COORD 0x8453
#define GL_FOG_COORD_ARRAY_TYPE 0x8454
#define GL_FOG_COORD_ARRAY_STRIDE 0x8455
#define GL_FOG_COORD_ARRAY_POINTER 0x8456
#define GL_FOG_COORD_ARRAY 0x8457
#define GL_FOG_COORD_ARRAY_BUFFER_BINDING 0x889D
// lighting
#define GL_LIGHTING 0x0B50
#define GL_LIGHT0 0x4000
#define GL_LIGHT1 0x4001
#define GL_LIGHT2 0x4002
#define GL_LIGHT3 0x4003
#define GL_LIGHT4 0x4004
#define GL_LIGHT5 0x4005
#define GL_LIGHT6 0x4006
#define GL_LIGHT7 0x4007
#define GL_SPOT_EXPONENT 0x1205
#define GL_SPOT_CUTOFF 0x1206
#define GL_CONSTANT_ATTENUATION 0x1207
#define GL_LINEAR_ATTENUATION 0x1208
#define GL_QUADRATIC_ATTENUATION 0x1209
#define GL_AMBIENT 0x1200
#define GL_DIFFUSE 0x1201
#define GL_SPECULAR 0x1202
#define GL_SHININESS 0x1601
#define GL_EMISSION 0x1600
#define GL_POSITION 0x1203
#define GL_SPOT_DIRECTION 0x1204
#define GL_AMBIENT_AND_DIFFUSE 0x1602
#define GL_COLOR_INDEXES 0x1603
#define GL_LIGHT_MODEL_TWO_SIDE 0x0B52
#define GL_LIGHT_MODEL_LOCAL_VIEWER 0x0B51
#define GL_LIGHT_MODEL_AMBIENT 0x0B53
#define GL_FRONT_AND_BACK 0x0408
#define GL_SHADE_MODEL 0x0B54
#define GL_FLAT 0x1D00
#define GL_SMOOTH 0x1D01
#define GL_COLOR_MATERIAL 0x0B57
#define GL_COLOR_MATERIAL_FACE 0x0B55
#define GL_COLOR_MATERIAL_PARAMETER 0x0B56
#define GL_NORMALIZE 0x0BA1
#define GL_DRAW_BUFFER 0x0C01
#define GL_LIGHT_MODEL_COLOR_CONTROL 0x81F8
#define GL_SINGLE_COLOR 0x81F9
#define GL_SEPARATE_SPECULAR_COLOR 0x81FA
// stencil
#define GL_STENCIL_BACK_FUNC 0x8800
#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4
#define GL_STENCIL_BACK_REF 0x8CA3
#define GL_STENCIL_BACK_WRITEMASK 0x8CA5
#define GL_STENCIL_BACK_FAIL 0x8801
#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802
#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803
// pixel transfer
#define GL_MAP_COLOR 0x0D10
#define GL_MAP_STENCIL 0x0D11
#define GL_INDEX_SHIFT 0x0D12
#define GL_INDEX_OFFSET 0x0D13
#define GL_RED_SCALE 0x0D14
#define GL_RED_BIAS 0x0D15
#define GL_GREEN_SCALE 0x0D18
#define GL_GREEN_BIAS 0x0D19
#define GL_BLUE_SCALE 0x0D1A
#define GL_BLUE_BIAS 0x0D1B
#define GL_ALPHA_SCALE 0x0D1C
#define GL_ALPHA_BIAS 0x0D1D
#define GL_DEPTH_SCALE 0x0D1E
#define GL_DEPTH_BIAS 0x0D1F
#define GL_PIXEL_MAP_S_TO_S_SIZE 0x0CB1
#define GL_PIXEL_MAP_I_TO_I_SIZE 0x0CB0
#define GL_PIXEL_MAP_I_TO_R_SIZE 0x0CB2
#define GL_PIXEL_MAP_I_TO_G_SIZE 0x0CB3
#define GL_PIXEL_MAP_I_TO_B_SIZE 0x0CB4
#define GL_PIXEL_MAP_I_TO_A_SIZE 0x0CB5
#define GL_PIXEL_MAP_R_TO_R_SIZE 0x0CB6
#define GL_PIXEL_MAP_G_TO_G_SIZE 0x0CB7
#define GL_PIXEL_MAP_B_TO_B_SIZE 0x0CB8
#define GL_PIXEL_MAP_A_TO_A_SIZE 0x0CB9
#define GL_PIXEL_MAP_S_TO_S 0x0C71
#define GL_PIXEL_MAP_I_TO_I 0x0C70
#define GL_PIXEL_MAP_I_TO_R 0x0C72
#define GL_PIXEL_MAP_I_TO_G 0x0C73
#define GL_PIXEL_MAP_I_TO_B 0x0C74
#define GL_PIXEL_MAP_I_TO_A 0x0C75
#define GL_PIXEL_MAP_R_TO_R 0x0C76
#define GL_PIXEL_MAP_G_TO_G 0x0C77
#define GL_PIXEL_MAP_B_TO_B 0x0C78
#define GL_PIXEL_MAP_A_TO_A 0x0C79
#define GL_PACK_ALIGNMENT 0x0D05
#define GL_PACK_LSB_FIRST 0x0D01
#define GL_PACK_ROW_LENGTH 0x0D02
#define GL_PACK_SKIP_PIXELS 0x0D04
#define GL_PACK_SKIP_ROWS 0x0D03
#define GL_PACK_SWAP_BYTES 0x0D00
#define GL_UNPACK_ALIGNMENT 0x0CF5
#define GL_UNPACK_LSB_FIRST 0x0CF1
#define GL_UNPACK_ROW_LENGTH 0x0CF2
#define GL_UNPACK_SKIP_PIXELS 0x0CF4
#define GL_UNPACK_SKIP_ROWS 0x0CF3
#define GL_UNPACK_SWAP_BYTES 0x0CF0
#define GL_UNPACK_IMAGE_HEIGHT 0x806E
#define GL_PACK_IMAGE_HEIGHT 0x806C
#define GL_ZOOM_X 0x0D16
#define GL_ZOOM_Y 0x0D17
#define GL_MAX_PIXEL_MAP_TABLE 0x0D34
#define GL_TEXTURE_BASE_LEVEL 0x813C
// blending
#define GL_BLEND 0x0BE2
#define GL_BLEND_SRC 0x0BE1
#define GL_BLEND_DST 0x0BE0
#define GL_SRC_COLOR 0x0300
#define GL_ONE_MINUS_SRC_COLOR 0x0301
#define GL_SRC_ALPHA 0x0302
#define GL_ONE_MINUS_SRC_ALPHA 0x0303
#define GL_DST_ALPHA 0x0304
#define GL_ONE_MINUS_DST_ALPHA 0x0305
#define GL_DST_COLOR 0x0306
#define GL_ONE_MINUS_DST_COLOR 0x0307
#define GL_SRC_ALPHA_SATURATE 0x0308
#define GL_CONSTANT_COLOR 0x8001
#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002
#define GL_CONSTANT_ALPHA 0x8003
#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004
#define GL_DOT3_RGB_EXT 0x8740
#define GL_DOT3_RGBA_EXT 0x8741
#define GL_BLEND_DST_RGB 0x80C8
#define GL_BLEND_SRC_RGB 0x80C9
#define GL_BLEND_DST_ALPHA 0x80CA
#define GL_BLEND_SRC_ALPHA 0x80CB
// glGet
#define GL_AUX_BUFFERS 0x0C00
#define GL_MAX_ELEMENTS_VERTICES 0x80E8
#define GL_MAX_ELEMENTS_INDICES 0x80E9
#define GL_POINT_SIZE_RANGE 0x0B12
#define GL_RENDER_MODE 0x0C40
#define GL_NAME_STACK_DEPTH 0x0D70
#define GL_MAX_NAME_STACK_DEPTH 0x0D37
#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
#define GL_TRANSPOSE_MODELVIEW_MATRIX 0x84E3
#define GL_TRANSPOSE_PROJECTION_MATRIX 0x84E4
#define GL_TRANSPOSE_TEXTURE_MATRIX 0x84E5
#define GL_TRANSPOSE_COLOR_MATRIX 0x84E6
#define GL_INDEX_ARRAY_POINTER 0x8091
#define GL_EDGE_FLAG_ARRAY_POINTER 0x8093
#define GL_FEEDBACK_BUFFER_POINTER 0x0DF0
#define GL_SELECTION_BUFFER_POINTER 0x0DF3
// evaluators
#define GL_AUTO_NORMAL 0x0D80
#define GL_MAP1_COLOR_4 0x0D90
#define GL_MAP1_INDEX 0x0D91
#define GL_MAP1_NORMAL 0x0D92
#define GL_MAP1_TEXTURE_COORD_1 0x0D93
#define GL_MAP1_TEXTURE_COORD_2 0x0D94
#define GL_MAP1_TEXTURE_COORD_3 0x0D95
#define GL_MAP1_TEXTURE_COORD_4 0x0D96
#define GL_MAP1_VERTEX_3 0x0D97
#define GL_MAP1_VERTEX_4 0x0D98
#define GL_MAP2_COLOR_4 0x0DB0
#define GL_MAP2_INDEX 0x0DB1
#define GL_MAP2_NORMAL 0x0DB2
#define GL_MAP2_TEXTURE_COORD_1 0x0DB3
#define GL_MAP2_TEXTURE_COORD_2 0x0DB4
#define GL_MAP2_TEXTURE_COORD_3 0x0DB5
#define GL_MAP2_TEXTURE_COORD_4 0x0DB6
#define GL_MAP2_VERTEX_3 0x0DB7
#define GL_MAP2_VERTEX_4 0x0DB8
#define GL_MAP1_GRID_DOMAIN 0x0DD0
#define GL_MAP1_GRID_SEGMENTS 0x0DD1
#define GL_MAP2_GRID_DOMAIN 0x0DD2
#define GL_MAP2_GRID_SEGMENTS 0x0DD3
#define GL_COEFF 0x0A00
#define GL_ORDER 0x0A01
#define GL_DOMAIN 0x0A02
#define GL_MAX_LIST_NESTING 0x0B31
/* polygons */
#define GL_POINT 0x1B00
#define GL_LINE 0x1B01
#define GL_FILL 0x1B02
#define GL_CW 0x0900
#define GL_CCW 0x0901
#define GL_FRONT 0x0404
#define GL_BACK 0x0405
#define GL_POLYGON_MODE 0x0B40
#define GL_POLYGON_SMOOTH 0x0B41
#define GL_POLYGON_STIPPLE 0x0B42
#define GL_EDGE_FLAG 0x0B43
#define GL_CULL_FACE 0x0B44
#define GL_CULL_FACE_MODE 0x0B45
#define GL_FRONT_FACE 0x0B46
#define GL_POLYGON_OFFSET_FACTOR 0x8038
#define GL_POLYGON_OFFSET_UNITS 0x2A00
#define GL_POLYGON_OFFSET_POINT 0x2A01
#define GL_POLYGON_OFFSET_LINE 0x2A02
/* Shader Source */
#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
#define GL_COMPILE_STATUS 0x8B81
#define GL_INFO_LOG_LENGTH 0x8B84
#define GL_SHADER_SOURCE_LENGTH 0x8B88
#define GL_SHADER_COMPILER 0x8DFA
/* Shader Binary */
#define GL_SHADER_BINARY_FORMATS 0x8DF8
#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9
/* Shader Precision-Specified Types */
#define GL_LOW_FLOAT 0x8DF0
#define GL_MEDIUM_FLOAT 0x8DF1
#define GL_HIGH_FLOAT 0x8DF2
#define GL_LOW_INT 0x8DF3
#define GL_MEDIUM_INT 0x8DF4
#define GL_HIGH_INT 0x8DF5
/* Texture Parameters */
#define GL_TEXTURE_INTERNAL_FORMAT 0x1003
#define GL_TEXTURE_RED_SIZE 0x805C
#define GL_TEXTURE_GREEN_SIZE 0x805D
#define GL_TEXTURE_BLUE_SIZE 0x805E
#define GL_TEXTURE_ALPHA_SIZE 0x805F
#define GL_TEXTURE_LUMINANCE_SIZE 0x8060
#define GL_TEXTURE_INTENSITY_SIZE 0x8061
#define GL_TEXTURE_RED_TYPE 0x8C10
#define GL_TEXTURE_GREEN_TYPE 0x8C11
#define GL_TEXTURE_BLUE_TYPE 0x8C12
#define GL_TEXTURE_ALPHA_TYPE 0x8C13
#define GL_TEXTURE_DEPTH_TYPE 0x8C16
#define GL_TEXTURE_DEPTH 0x8071
#define GL_TEXTURE_DEPTH_SIZE 0x884A
#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE 0x86A0
#define GL_TEXTURE_COMPRESSED 0x86A1
#define GL_TEXTURE_MAX_LEVEL 0x813D
/* Compressed Textures */
#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
#define GL_TEXTURE_COMPRESSION_HINT 0x84EF
/* S3TC with sRGB */
#define GL_COMPRESSED_SRGB_S3TC_DXT1_EXT 0x8C4C
#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT 0x8C4D
#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT 0x8C4E
#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F
/* Render Mode */
#define GL_SELECT 0x1c02
#define GL_RENDER 0x1C00
/* Interleaved Array */
#define GL_V2F 0x2A20
#define GL_V3F 0x2A21
#define GL_C4UB_V2F 0x2A22
#define GL_C4UB_V3F 0x2A23
#define GL_C3F_V3F 0x2A24
#define GL_N3F_V3F 0x2A25
#define GL_C4F_N3F_V3F 0x2A26
#define GL_T2F_V3F 0x2A27
#define GL_T4F_V4F 0x2A28
#define GL_T2F_C4UB_V3F 0x2A29
#define GL_T2F_C3F_V3F 0x2A2A
#define GL_T2F_N3F_V3F 0x2A2B
#define GL_T2F_C4F_N3F_V3F 0x2A2C
#define GL_T4F_C4F_N3F_V4F 0x2A2D
/* Buffers Array */
#define GL_BUFFER_SIZE 0x8764
#define GL_BUFFER_USAGE 0x8765
#define GL_QUERY_COUNTER_BITS 0x8864
#define GL_CURRENT_QUERY 0x8865
#define GL_QUERY_RESULT 0x8866
#define GL_QUERY_RESULT_AVAILABLE 0x8867
#define GL_ARRAY_BUFFER 0x8892
#define GL_ELEMENT_ARRAY_BUFFER 0x8893
#define GL_ARRAY_BUFFER_BINDING 0x8894
#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895
#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
#define GL_READ_ONLY 0x88B8
#define GL_WRITE_ONLY 0x88B9
#define GL_READ_WRITE 0x88BA
#define GL_BUFFER_ACCESS 0x88BB
#define GL_BUFFER_MAPPED 0x88BC
#define GL_BUFFER_MAP_POINTER 0x88BD
#define GL_STREAM_DRAW 0x88E0
#define GL_STREAM_READ 0x88E1
#define GL_STREAM_COPY 0x88E2
#define GL_STATIC_DRAW 0x88E4
#define GL_STATIC_READ 0x88E5
#define GL_STATIC_COPY 0x88E6
#define GL_DYNAMIC_DRAW 0x88E8
#define GL_DYNAMIC_READ 0x88E9
#define GL_DYNAMIC_COPY 0x88EA
#define GL_SRC1_ALPHA 0x8589
#define GL_VERTEX_ARRAY_BUFFER_BINDING 0x8896
#define GL_NORMAL_ARRAY_BUFFER_BINDING 0x8897
#define GL_COLOR_ARRAY_BUFFER_BINDING 0x8898
#define GL_INDEX_ARRAY_BUFFER_BINDING 0x8899
#define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING 0x889A
#define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING 0x889B
#define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING 0x889C
#define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING 0x889D
#define GL_WEIGHT_ARRAY_BUFFER_BINDING 0x889E
#define GL_MAP_READ_BIT 0x0001
#define GL_MAP_WRITE_BIT 0x0002
#define GL_BUFFER_ACCESS_FLAGS 0x911F
#define GL_BUFFER_MAP_LENGTH 0x9120
#define GL_BUFFER_MAP_OFFSET 0x9121
#define GL_READ_ONLY 0x88B8
#define GL_WRITE_ONLY 0x88B9
#define GL_READ_WRITE 0x88BA
#define GL_PIXEL_PACK_BUFFER 0x88EB
#define GL_PIXEL_UNPACK_BUFFER 0x88EC
#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF
#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED
#define GL_CURRENT_VERTEX_ATTRIB 0x8626
#define GL_MAP_PERSISTENT_BIT 0x00000040
#define GL_QUERY_BUFFER_BINDING_AMD 0x9193
#define GL_COPY_READ_BUFFER_BINDING 0x8F36
#define GL_COPY_READ_BUFFER GL_COPY_READ_BUFFER_BINDING
#define GL_COPY_WRITE_BUFFER_BINDING 0x8F37
#define GL_COPY_WRITE_BUFFER GL_COPY_WRITE_BUFFER_BINDING
/* Framebuffers */
#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210
#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211
#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212
#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213
#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214
#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215
#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216
#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217
#define GL_FRAMEBUFFER_DEFAULT 0x8218
#define GL_FRAMEBUFFER_UNDEFINED 0x8219
#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
#define GL_MAX_RENDERBUFFER_SIZE 0x84E8
#define GL_DEPTH_STENCIL 0x84F9
#define GL_UNSIGNED_INT_24_8 0x84FA
#define GL_DEPTH24_STENCIL8 0x88F0
#define GL_TEXTURE_STENCIL_SIZE 0x88F1
#define GL_TEXTURE_RED_TYPE 0x8C10
#define GL_TEXTURE_GREEN_TYPE 0x8C11
#define GL_TEXTURE_BLUE_TYPE 0x8C12
#define GL_TEXTURE_ALPHA_TYPE 0x8C13
#define GL_TEXTURE_DEPTH_TYPE 0x8C16
#define GL_UNSIGNED_NORMALIZED 0x8C17
#define GL_FRAMEBUFFER_BINDING 0x8CA6
#define GL_DRAW_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING
#define GL_RENDERBUFFER_BINDING 0x8CA7
#define GL_READ_FRAMEBUFFER 0x8CA8
#define GL_DRAW_FRAMEBUFFER 0x8CA9
#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA
#define GL_RENDERBUFFER_SAMPLES 0x8CAB
#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0
#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1
#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4
#define GL_FRAMEBUFFER_COMPLETE 0x8CD5
#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6
#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER 0x8CDB
#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC
#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF
#define GL_COLOR_ATTACHMENT0 0x8CE0
#define GL_COLOR_ATTACHMENT1 0x8CE1
#define GL_COLOR_ATTACHMENT2 0x8CE2
#define GL_COLOR_ATTACHMENT3 0x8CE3
#define GL_COLOR_ATTACHMENT4 0x8CE4
#define GL_COLOR_ATTACHMENT5 0x8CE5
#define GL_COLOR_ATTACHMENT6 0x8CE6
#define GL_COLOR_ATTACHMENT7 0x8CE7
#define GL_COLOR_ATTACHMENT8 0x8CE8
#define GL_COLOR_ATTACHMENT9 0x8CE9
#define GL_COLOR_ATTACHMENT10 0x8CEA
#define GL_COLOR_ATTACHMENT11 0x8CEB
#define GL_COLOR_ATTACHMENT12 0x8CEC
#define GL_COLOR_ATTACHMENT13 0x8CED
#define GL_COLOR_ATTACHMENT14 0x8CEE
#define GL_COLOR_ATTACHMENT15 0x8CEF
#define GL_DEPTH_ATTACHMENT 0x8D00
#define GL_STENCIL_ATTACHMENT 0x8D20
#define GL_FRAMEBUFFER 0x8D40
#define GL_RENDERBUFFER 0x8D41
#define GL_RENDERBUFFER_WIDTH 0x8D42
#define GL_RENDERBUFFER_HEIGHT 0x8D43
#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44
#define GL_STENCIL_INDEX1 0x8D46
#define GL_STENCIL_INDEX4 0x8D47
#define GL_STENCIL_INDEX8 0x8D48
#define GL_STENCIL_INDEX16 0x8D49
#define GL_RENDERBUFFER_RED_SIZE 0x8D50
#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51
#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52
#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53
#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54
#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55
#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56
#define GL_MAX_SAMPLES 0x8D57
#define GL_INDEX 0x8222
#define GL_TEXTURE_LUMINANCE_TYPE 0x8C14
#define GL_TEXTURE_INTENSITY_TYPE 0x8C15
#define GL_DEPTH_COMPONENT32 0x81A7
#define GL_DEPTH_COMPONENT24 0x81A6
#define GL_DEPTH_COMPONENT16 0x81A5
#define GL_DEPTH_COMPONENT 0x1902
#define GL_MAX_DRAW_BUFFERS_ARB 0x8824
// point sprite extension
#define GL_POINT_SPRITE_COORD_ORIGIN 0x8CA0
#define GL_LOWER_LEFT 0x8CA1
#define GL_UPPER_LEFT 0x8CA2
#define GL_PROGRAM_POINT_SIZE 0x8642
// clear buffer
#define GL_COLOR 0x1800
#define GL_DEPTH 0x1801
#define GL_STENCIL 0x1802
// direct state
#define GL_MATRIX0_ARB 0x88C0
#define GL_PROGRAM_MATRIX_EXT 0x8E2D
#define GL_TRANSPOSE_PROGRAM_MATRIX_EXT 0x8E2E
#define GL_PROGRAM_MATRIX_STACK_DEPTH_EXT 0x8E2F
#define GL_CURRENT_MATRIX_STACK_DEPTH_ARB 0x8640
#define GL_TRANSPOSE_CURRENT_MATRIX_ARB 0x88B7
#define GL_CURRENT_MATRIX_ARB 0x8641
#define GL_TEXTURE_BUFFER_FORMAT_EXT 0x8C2E
#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT 0x8C2D
#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
#define GL_TEXTURE_BINDING_BUFFER_EXT 0x8C2C
#define GL_TEXTURE_BINDING_1D 0x8068
#define GL_TEXTURE_BINDING_2D 0x8069
#define GL_TEXTURE_BINDING_3D 0x806A
#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D
#define GL_TEXTURE_BINDING_1D_ARRAY 0x8C1C
#define GL_CURRENT_RASTER_TEXTURE_COORDS 0x0B06
#define GL_TEXTURE_COORD_ARRAY_COUNT 0x808B
// cube mapping
#define GL_TEXTURE_CUBE_MAP 0x8513
#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514
#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515
#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516
#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517
#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518
#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519
#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A
#define GL_PROXY_TEXTURE_CUBE_MAP 0x851B
#define GL_AX_CUBE_MAP_TEXTURE_SIZE 0x851C
// Shaders
#define GL_FRAGMENT_SHADER 0x8B30
#define GL_VERTEX_SHADER 0x8B31
#define GL_MAX_VERTEX_ATTRIBS 0x8869
#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB
#define GL_MAX_VARYING_VECTORS 0x8DFC
#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C
#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872
#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD
#define GL_SHADER_TYPE 0x8B4F
#define GL_DELETE_STATUS 0x8B80
#define GL_LINK_STATUS 0x8B82
#define GL_VALIDATE_STATUS 0x8B83
#define GL_ATTACHED_SHADERS 0x8B85
#define GL_ACTIVE_UNIFORMS 0x8B86
#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
#define GL_ACTIVE_ATTRIBUTES 0x8B89
#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
#define GL_SHADING_LANGUAGE_VERSION 0x8B8C
#define GL_CURRENT_PROGRAM 0x8B8D
// Shaders extensions
#define GL_PROGRAM_BINARY_LENGTH 0x8741
#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE
#define GL_PROGRAM_BINARY_FORMATS 0x87FF
#define GL_PROGRAM_OBJECT_ARB 0x8B40
// Vertex Arrays
#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622
#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623
#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624
#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625
#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A
#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645
#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F
// Uniform Types
#define GL_FLOAT_VEC2 0x8B50
#define GL_FLOAT_VEC3 0x8B51
#define GL_FLOAT_VEC4 0x8B52
#define GL_INT_VEC2 0x8B53
#define GL_INT_VEC3 0x8B54
#define GL_INT_VEC4 0x8B55
#define GL_BOOL 0x8B56
#define GL_BOOL_VEC2 0x8B57
#define GL_BOOL_VEC3 0x8B58
#define GL_BOOL_VEC4 0x8B59
#define GL_FLOAT_MAT2 0x8B5A
#define GL_FLOAT_MAT3 0x8B5B
#define GL_FLOAT_MAT4 0x8B5C
#define GL_SAMPLER_2D 0x8B5E
#define GL_SAMPLER_CUBE 0x8B60
// Getter
#define GL_NUM_EXTENSIONS 0x821D
// Anisotropic
#define GL_TEXTURE_MAX_ANISOTROPY 0x84FE
#define GL_MAX_TEXTURE_MAX_ANISOTROPY 0x84FF
// ATI_texture_env_combine3
#define GL_MODULATE_ADD_ATI 0x8744
#define GL_MODULATE_SIGNED_ADD_ATI 0x8745
#define GL_MODULATE_SUBTRACT_ATI 0x8746
// ATIX_texture_env_route
#define GL_SECONDARY_COLOR_ATIX 0x8747
#define GL_TEXTURE_OUTPUT_RGB_ATIX 0x8748
#define GL_TEXTURE_OUTPUT_ALPHA_ATIX 0x8749
//GL_NV_texture_env_combine4
#define GL_COMBINE4 0x8503
#define GL_SRC3_RGB 0x8583
#define GL_SRC3_ALPHA 0x858B
#define GL_OPERAND3_RGB 0x8593
#define GL_OPERAND3_ALPHA 0x859B
//GL_NV_fog_distance
#define GL_FOG_DISTANCE_MODE_NV 0x855A
#define GL_EYE_RADIAL_NV 0x855B
#define GL_EYE_PLANE_ABSOLUTE_NV 0x855C
//GL_ARB_instanced_arrays
#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE
//GL_OES_get_program_binary
#define GL_PROGRAM_BINARY_LENGTH_OES 0x8741
#define GL_NUM_PROGRAM_BINARY_FORMATS_OES 0x87FE
#define GL_PROGRAM_BINARY_FORMATS_OES 0x87FF
//Clamp color
#define GL_CLAMP_READ_COLOR 0x891C
//GL_ARB_vertex_program
#define GL_MATRIX0_ARB 0x88C0
#define GL_MATRIX1_ARB 0x88C1
#define GL_MATRIX2_ARB 0x88C2
#define GL_MATRIX3_ARB 0x88C3
#define GL_MATRIX4_ARB 0x88C4
#define GL_MATRIX5_ARB 0x88C5
#define GL_MATRIX6_ARB 0x88C6
#define GL_MATRIX7_ARB 0x88C7
#define GL_MATRIX8_ARB 0x88C8
#define GL_MATRIX9_ARB 0x88C9
#define GL_MATRIX10_ARB 0x88CA
#define GL_MATRIX11_ARB 0x88CB
#define GL_MATRIX12_ARB 0x88CC
#define GL_MATRIX13_ARB 0x88CD
#define GL_MATRIX14_ARB 0x88CE
#define GL_MATRIX15_ARB 0x88CF
#define GL_MATRIX16_ARB 0x88D0
#define GL_MATRIX17_ARB 0x88D1
#define GL_MATRIX18_ARB 0x88D2
#define GL_MATRIX19_ARB 0x88D3
#define GL_MATRIX20_ARB 0x88D4
#define GL_MATRIX21_ARB 0x88D5
#define GL_MATRIX22_ARB 0x88D6
#define GL_MATRIX23_ARB 0x88D7
#define GL_MATRIX24_ARB 0x88D8
#define GL_MATRIX25_ARB 0x88D9
#define GL_MATRIX26_ARB 0x88DA
#define GL_MATRIX27_ARB 0x88DB
#define GL_MATRIX28_ARB 0x88DC
#define GL_MATRIX29_ARB 0x88DD
#define GL_MATRIX30_ARB 0x88DE
#define GL_MATRIX31_ARB 0x88DF
#define GL_PROGRAM_ERROR_STRING_ARB 0x8874
#define GL_PROGRAM_ERROR_POSITION_ARB 0x864B
#define GL_CURRENT_MATRIX_ARB 0x8641
#define GL_TRANSPOSE_CURRENT_MATRIX_ARB 0x88B7
#define GL_CURRENT_MATRIX_STACK_DEPTH_ARB 0x8640
#define GL_MAX_VERTEX_ATTRIBS_ARB 0x8869
#define GL_MAX_PROGRAM_MATRICES_ARB 0x862F
#define GL_MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB 0x862E
#define GL_PROGRAM_STRING_ARB 0x8628
#define GL_PROGRAM_LENGTH_ARB 0x8627
#define GL_PROGRAM_FORMAT_ARB 0x8876
#define GL_PROGRAM_BINDING_ARB 0x8677
#define GL_PROGRAM_INSTRUCTIONS_ARB 0x88A0
#define GL_MAX_PROGRAM_INSTRUCTIONS_ARB 0x88A1
#define GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A2
#define GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A3
#define GL_PROGRAM_TEMPORARIES_ARB 0x88A4
#define GL_MAX_PROGRAM_TEMPORARIES_ARB 0x88A5
#define GL_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A6
#define GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A7
#define GL_PROGRAM_PARAMETERS_ARB 0x88A8
#define GL_MAX_PROGRAM_PARAMETERS_ARB 0x88A9
#define GL_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AA
#define GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AB
#define GL_PROGRAM_ATTRIBS_ARB 0x88AC
#define GL_MAX_PROGRAM_ATTRIBS_ARB 0x88AD
#define GL_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AE
#define GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AF
#define GL_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B0
#define GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B1
#define GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B2
#define GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B3
#define GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB 0x88B4
#define GL_MAX_PROGRAM_ENV_PARAMETERS_ARB 0x88B5
#define GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB 0x88B6
#define GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB 0x8645
#define GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB 0x8622
#define GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB 0x8623
#define GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB 0x8624
#define GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB 0x8625
#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB 0x886A
#define GL_CURRENT_VERTEX_ATTRIB_ARB 0x8626
#define GL_PROGRAM_FORMAT_ASCII_ARB 0x8875
#define GL_VERTEX_PROGRAM_POINT_SIZE_ARB 0x8642
#define GL_VERTEX_PROGRAM_TWO_SIDE_ARB 0x8643
#define GL_COLOR_SUM_ARB 0x8458
#define GL_VERTEX_PROGRAM_ARB 0x8620
// ARB_fragment_program
#define GL_MAX_TEXTURE_COORDS_ARB 0x8871
#define GL_MAX_TEXTURE_IMAGE_UNITS_ARB 0x8872
#define GL_PROGRAM_ALU_INSTRUCTIONS_ARB 0x8805
#define GL_PROGRAM_TEX_INSTRUCTIONS_ARB 0x8806
#define GL_PROGRAM_TEX_INDIRECTIONS_ARB 0x8807
#define GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x8808
#define GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x8809
#define GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x880A
#define GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB 0x880B
#define GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB 0x880C
#define GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB 0x880D
#define GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x880E
#define GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x880F
#define GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x8810
#define GL_FRAGMENT_PROGRAM_ARB 0x8804
// EXT_draw_buffers
#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF
// Sampler
#define GL_SAMPLER_BINDING 0x8919
#define GL_TEXTURE_COMPARE_FUNC 0x884D
#define GL_COMPARE_REF_TO_TEXTURE 0x884E
#define GL_NONE 0x0
// Queries
#define GL_TIME_ELAPSED 0x88BF
#define GL_TIMESTAMP 0x8E28
#define GL_SAMPLES_PASSED 0x8914
#define GL_ANY_SAMPLES_PASSED 0x8C2F
#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A
#define GL_PRIMITIVES_GENERATED 0x8C87
#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88
#define GL_QUERY_RESULT_NO_WAIT 0x9194
// Blend
#define GL_FUNC_ADD 0x8006
#define GL_FUNC_SUBTRACT 0x800A
#define GL_FUNC_REVERSE_SUBTRACT 0x800B
#define GL_MIN 0x8007
#define GL_MAX 0x8008
#endif // _GL4ES_CONST_H_
+430
View File
@@ -0,0 +1,430 @@
#include "debug.h"
#include <string.h>
#include "wrap/gles.h"
#include "const.h"
#include "loader.h"
#include "logs.h"
#include "gl4es.h"
#include "gles.h"
#define p(a) \
case a: return #a
const char* PrintEnum(GLenum what) {
static char fallback[64];
switch(what)
{
// error
p(GL_INVALID_ENUM);
p(GL_INVALID_VALUE);
p(GL_INVALID_OPERATION);
// target
p(GL_TEXTURE_1D);
p(GL_TEXTURE_2D);
p(GL_TEXTURE_3D);
p(GL_TEXTURE_RECTANGLE_ARB);
p(GL_FRAMEBUFFER);
p(GL_RENDERBUFFER);
p(GL_PROXY_TEXTURE_1D);
p(GL_PROXY_TEXTURE_2D);
p(GL_PROXY_TEXTURE_3D);
p(GL_READ_FRAMEBUFFER);
p(GL_DRAW_FRAMEBUFFER);
p(GL_TEXTURE_CUBE_MAP);
p(GL_TEXTURE_CUBE_MAP_POSITIVE_X);
p(GL_TEXTURE_CUBE_MAP_NEGATIVE_X);
p(GL_TEXTURE_CUBE_MAP_POSITIVE_Y);
p(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y);
p(GL_TEXTURE_CUBE_MAP_POSITIVE_Z);
p(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
// format
p(GL_COLOR_INDEX);
p(GL_RED);
p(GL_R);
p(GL_R8);
p(GL_R3_G3_B2);
p(GL_RGB);
p(GL_BGR);
p(GL_RGB8);
p(GL_RGB5);
p(GL_RGB16);
p(GL_RGB16F);
p(GL_RGB32F);
p(GL_BGRA);
p(GL_RGBA);
p(GL_RGBA4);
p(GL_RGB5_A1);
p(GL_RGB10_A2);
p(GL_RGBA8);
p(GL_RGBA16);
p(GL_RGBA16F);
p(GL_RGBA32F);
p(GL_COMPRESSED_RGB_S3TC_DXT1_EXT);
p(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT);
p(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT);
p(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT);
p(GL_LUMINANCE8_ALPHA8);
p(GL_LUMINANCE_ALPHA);
p(GL_LUMINANCE4_ALPHA4);
p(GL_LUMINANCE16_ALPHA16);
p(GL_LUMINANCE_ALPHA16F);
p(GL_LUMINANCE_ALPHA32F);
p(GL_LUMINANCE);
p(GL_ALPHA);
p(GL_LUMINANCE8);
p(GL_LUMINANCE16);
p(GL_LUMINANCE16F);
p(GL_LUMINANCE32F);
p(GL_ALPHA8);
p(GL_ALPHA16F);
p(GL_ALPHA32F);
p(GL_COMPRESSED_ALPHA);
p(GL_COMPRESSED_LUMINANCE);
p(GL_COMPRESSED_LUMINANCE_ALPHA);
p(GL_COMPRESSED_RGB);
p(GL_COMPRESSED_RGBA);
p(GL_HALF_FLOAT);
p(GL_INTENSITY);
p(GL_INTENSITY8);
p(GL_INTENSITY16F);
p(GL_INTENSITY32F);
p(GL_DEPTH_STENCIL);
// type
p(GL_BYTE);
p(GL_UNSIGNED_BYTE);
p(GL_UNSIGNED_BYTE_2_3_3_REV);
p(GL_UNSIGNED_BYTE_3_3_2);
p(GL_UNSIGNED_INT);
p(GL_UNSIGNED_SHORT);
p(GL_UNSIGNED_SHORT_5_5_5_1);
p(GL_UNSIGNED_SHORT_1_5_5_5_REV);
p(GL_UNSIGNED_SHORT_4_4_4_4);
p(GL_UNSIGNED_SHORT_4_4_4_4_REV);
p(GL_UNSIGNED_SHORT_5_6_5);
p(GL_UNSIGNED_SHORT_5_6_5_REV);
p(GL_UNSIGNED_INT_8_8_8_8_REV);
p(GL_UNSIGNED_INT_8_8_8_8);
p(GL_FLOAT);
p(GL_DOUBLE);
p(GL_UNSIGNED_INT_24_8);
// texture infos
p(GL_TEXTURE_WIDTH);
p(GL_TEXTURE_HEIGHT);
p(GL_TEXTURE_COMPRESSED);
p(GL_TEXTURE_BORDER);
p(GL_TEXTURE_INTERNAL_FORMAT);
p(GL_MAX_TEXTURE_SIZE);
p(GL_MAX_TEXTURE_COORDS);
// texture pack/unpack
p(GL_UNPACK_ALIGNMENT);
p(GL_UNPACK_ROW_LENGTH);
p(GL_UNPACK_SKIP_PIXELS);
p(GL_UNPACK_SKIP_ROWS);
p(GL_PACK_ALIGNMENT);
p(GL_PACK_ROW_LENGTH);
p(GL_PACK_SKIP_PIXELS);
p(GL_PACK_SKIP_ROWS);
// framebuffer
p(GL_COLOR_ATTACHMENT0);
p(GL_COLOR_ATTACHMENT1);
p(GL_COLOR_ATTACHMENT2);
p(GL_COLOR_ATTACHMENT3);
p(GL_COLOR_ATTACHMENT4);
p(GL_DEPTH_ATTACHMENT);
p(GL_DEPTH_STENCIL_ATTACHMENT);
p(GL_STENCIL_ATTACHMENT);
p(GL_DEPTH_COMPONENT);
p(GL_DEPTH24_STENCIL8);
p(GL_MAX_DRAW_BUFFERS_ARB);
p(GL_DRAW_FRAMEBUFFER_BINDING);
p(GL_READ_FRAMEBUFFER_BINDING);
// VBO
p(GL_STATIC_DRAW);
p(GL_STREAM_DRAW);
p(GL_READ_WRITE);
p(GL_ARRAY_BUFFER);
p(GL_ELEMENT_ARRAY_BUFFER);
p(GL_PIXEL_PACK_BUFFER);
p(GL_PIXEL_UNPACK_BUFFER);
p(GL_WRITE_ONLY);
// Texture
p(GL_TEXTURE0);
p(GL_TEXTURE1);
p(GL_TEXTURE2);
p(GL_TEXTURE3);
p(GL_TEXTURE4);
p(GL_TEXTURE5);
p(GL_TEXTURE6);
p(GL_TEXTURE7);
p(GL_TEXTURE8);
p(GL_TEXTURE9);
p(GL_TEXTURE10);
p(GL_TEXTURE11);
p(GL_TEXTURE12);
p(GL_TEXTURE13);
p(GL_TEXTURE14);
p(GL_TEXTURE15);
p(GL_TEXTURE_WRAP_S);
p(GL_TEXTURE_WRAP_T);
p(GL_LINEAR);
p(GL_NEAREST);
p(GL_NEAREST_MIPMAP_NEAREST);
p(GL_NEAREST_MIPMAP_LINEAR);
p(GL_LINEAR_MIPMAP_NEAREST);
p(GL_LINEAR_MIPMAP_LINEAR);
p(GL_TEXTURE_MAX_LEVEL);
p(GL_TEXTURE_BASE_LEVEL);
p(GL_TEXTURE_MIN_FILTER);
p(GL_TEXTURE_MAG_FILTER);
p(GL_CLAMP_TO_EDGE);
p(GL_REPEAT);
p(GL_MIRRORED_REPEAT_OES);
p(GL_GENERATE_MIPMAP);
// mode
p(GL_POINTS);
p(GL_LINES);
p(GL_LINE_LOOP);
p(GL_LINE_STRIP);
p(GL_TRIANGLES);
p(GL_TRIANGLE_STRIP);
p(GL_TRIANGLE_FAN);
p(GL_QUADS);
p(GL_QUAD_STRIP);
p(GL_POLYGON);
// texgen
p(GL_S);
p(GL_T);
p(GL_Q);
p(GL_TEXTURE_GEN_MODE);
p(GL_OBJECT_LINEAR);
p(GL_EYE_LINEAR);
p(GL_SPHERE_MAP);
p(GL_NORMAL_MAP);
p(GL_REFLECTION_MAP);
p(GL_TEXTURE_GEN_S);
p(GL_TEXTURE_GEN_T);
p(GL_TEXTURE_GEN_R);
p(GL_TEXTURE_GEN_Q);
// matrix mode
p(GL_PROJECTION);
p(GL_MODELVIEW);
p(GL_TEXTURE);
// blend
p(GL_SRC_ALPHA);
p(GL_DST_ALPHA);
p(GL_ONE_MINUS_SRC_ALPHA);
p(GL_ONE_MINUS_DST_ALPHA);
// lights
p(GL_LIGHT0);
p(GL_LIGHT1);
p(GL_LIGHT2);
p(GL_LIGHT3);
p(GL_LIGHT4);
p(GL_LIGHT5);
p(GL_LIGHT6);
p(GL_LIGHT7);
p(GL_AMBIENT);
p(GL_DIFFUSE);
p(GL_SPECULAR);
p(GL_POSITION);
p(GL_SPOT_DIRECTION);
p(GL_SPOT_EXPONENT);
p(GL_SPOT_CUTOFF);
p(GL_CONSTANT_ATTENUATION);
p(GL_LINEAR_ATTENUATION);
p(GL_QUADRATIC_ATTENUATION);
// Misc enabled
p(GL_LIGHTING);
p(GL_NORMALIZE);
p(GL_CULL_FACE);
p(GL_DEPTH_TEST);
p(GL_RESCALE_NORMAL);
p(GL_ALPHA_TEST);
p(GL_ALPHA_TEST_FUNC);
p(GL_BLEND);
p(GL_BLEND_SRC);
p(GL_BLEND_DST);
p(GL_LOGIC_OP_MODE);
p(GL_SCISSOR_TEST);
p(GL_STENCIL_TEST);
// uniform type
p(GL_FLOAT_VEC2);
p(GL_FLOAT_VEC3);
p(GL_FLOAT_VEC4);
p(GL_INT_VEC2);
p(GL_INT_VEC3);
p(GL_INT_VEC4);
p(GL_BOOL);
p(GL_BOOL_VEC2);
p(GL_BOOL_VEC3);
p(GL_BOOL_VEC4);
p(GL_FLOAT_MAT2);
p(GL_FLOAT_MAT3);
p(GL_FLOAT_MAT4);
p(GL_SAMPLER_2D);
p(GL_SAMPLER_CUBE);
// Shaders
p(GL_FRAGMENT_SHADER);
p(GL_VERTEX_SHADER);
p(GL_MAX_VERTEX_ATTRIBS);
p(GL_MAX_VERTEX_UNIFORM_VECTORS);
p(GL_MAX_VARYING_VECTORS);
p(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS);
p(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS);
p(GL_MAX_TEXTURE_IMAGE_UNITS);
p(GL_MAX_FRAGMENT_UNIFORM_VECTORS);
p(GL_SHADER_TYPE);
p(GL_DELETE_STATUS);
p(GL_LINK_STATUS);
p(GL_COMPILE_STATUS);
p(GL_VALIDATE_STATUS);
p(GL_ATTACHED_SHADERS);
p(GL_ACTIVE_UNIFORMS);
p(GL_ACTIVE_UNIFORM_MAX_LENGTH);
p(GL_ACTIVE_ATTRIBUTES);
p(GL_ACTIVE_ATTRIBUTE_MAX_LENGTH);
p(GL_SHADING_LANGUAGE_VERSION);
p(GL_CURRENT_PROGRAM);
p(GL_PROGRAM_BINARY_LENGTH);
p(GL_NUM_PROGRAM_BINARY_FORMATS);
p(GL_PROGRAM_BINARY_FORMATS);
p(GL_INFO_LOG_LENGTH);
// Client State
p(GL_VERTEX_ARRAY);
p(GL_COLOR_ARRAY);
p(GL_NORMAL_ARRAY);
p(GL_TEXTURE_COORD_ARRAY);
p(GL_SECONDARY_COLOR_ARRAY);
p(GL_FOG_COORD_ARRAY);
// TexEnv
p(GL_POINT_SPRITE);
p(GL_COORD_REPLACE);
p(GL_TEXTURE_FILTER_CONTROL);
p(GL_TEXTURE_LOD_BIAS);
p(GL_TEXTURE_ENV);
p(GL_TEXTURE_ENV_MODE);
p(GL_MODULATE);
p(GL_ADD);
p(GL_DECAL);
p(GL_REPLACE);
p(GL_COMBINE);
p(GL_COMBINE_RGB);
p(GL_ADD_SIGNED);
p(GL_INTERPOLATE);
p(GL_SUBTRACT);
p(GL_DOT3_RGB);
p(GL_DOT3_RGBA);
p(GL_COMBINE_ALPHA);
p(GL_SRC0_RGB);
p(GL_SRC1_RGB);
p(GL_SRC2_RGB);
p(GL_CONSTANT);
p(GL_PRIMARY_COLOR);
p(GL_PREVIOUS);
p(GL_SRC0_ALPHA);
p(GL_SRC1_ALPHA);
p(GL_SRC2_ALPHA);
p(GL_OPERAND0_RGB);
p(GL_OPERAND1_RGB);
p(GL_OPERAND2_RGB);
p(GL_SRC_COLOR);
p(GL_ONE_MINUS_SRC_COLOR);
p(GL_OPERAND0_ALPHA);
p(GL_OPERAND1_ALPHA);
p(GL_OPERAND2_ALPHA);
p(GL_RGB_SCALE);
p(GL_ALPHA_SCALE);
p(GL_TEXTURE_ENV_COLOR);
// misc
p(GL_NUM_EXTENSIONS);
// ARB_program
p(GL_VERTEX_PROGRAM_ARB);
p(GL_FRAGMENT_PROGRAM_ARB);
p(GL_PROGRAM_FORMAT_ASCII_ARB);
p(GL_PROGRAM_LENGTH_ARB);
p(GL_PROGRAM_FORMAT_ARB);
p(GL_PROGRAM_BINDING_ARB);
p(GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB);
p(GL_MAX_PROGRAM_ENV_PARAMETERS_ARB);
p(GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB);
p(GL_MAX_PROGRAM_ATTRIBS_ARB);
p(GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB);
p(GL_MAX_PROGRAM_INSTRUCTIONS_ARB);
p(GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB);
p(GL_MAX_PROGRAM_TEMPORARIES_ARB);
p(GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB);
p(GL_MAX_PROGRAM_PARAMETERS_ARB);
p(GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB);
p(GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB);
p(GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB);
p(GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB);
p(GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB);
p(GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB);
p(GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB);
p(GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB);
p(GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB);
p(GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB);
p(GL_PROGRAM_INSTRUCTIONS_ARB);
p(GL_PROGRAM_NATIVE_TEMPORARIES_ARB);
p(GL_PROGRAM_TEMPORARIES_ARB);
p(GL_PROGRAM_NATIVE_PARAMETERS_ARB);
p(GL_PROGRAM_PARAMETERS_ARB);
p(GL_PROGRAM_NATIVE_ATTRIBS_ARB);
p(GL_PROGRAM_ATTRIBS_ARB);
p(GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB);
p(GL_PROGRAM_ADDRESS_REGISTERS_ARB);
p(GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB);
p(GL_PROGRAM_ALU_INSTRUCTIONS_ARB);
p(GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB);
p(GL_PROGRAM_TEX_INSTRUCTIONS_ARB);
p(GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB);
p(GL_PROGRAM_TEX_INDIRECTIONS_ARB);
default:
sprintf(fallback, "0x%04X", what);
}
return fallback;
}
const char* PrintEGLError(int onlyerror) {
#ifdef NOEGL
return "";
#else
LOAD_EGL(eglGetError);
static char fallback[64];
GLenum what = egl_eglGetError();
if(onlyerror && what==EGL_SUCCESS)
return NULL;
switch(what)
{
p(EGL_SUCCESS);
p(EGL_NOT_INITIALIZED);
p(EGL_BAD_ACCESS);
p(EGL_BAD_ALLOC);
p(EGL_BAD_ATTRIBUTE);
p(EGL_BAD_CONTEXT);
p(EGL_BAD_CONFIG);
p(EGL_BAD_CURRENT_SURFACE);
p(EGL_BAD_DISPLAY);
p(EGL_BAD_SURFACE);
p(EGL_BAD_MATCH);
p(EGL_BAD_PARAMETER);
p(EGL_BAD_NATIVE_PIXMAP);
p(EGL_BAD_NATIVE_WINDOW);
p(EGL_CONTEXT_LOST);
default:
sprintf(fallback, "0x%04X", what);
}
return fallback;
#endif
}
void CheckGLError(int fwd) {
LOAD_GLES(glGetError);
GLenum err=gles_glGetError();
if(err!=GL_NO_ERROR) {
printf("LIBGL: glGetError(): %s\n", PrintEnum(err));
if(fwd)
errorShim(err);
}
}
+12
View File
@@ -0,0 +1,12 @@
#ifndef _GL4ES_DEBUG_H_
#define _GL4ES_DEBUG_H_
#include "gles.h"
const char* PrintEnum(GLenum what);
const char* PrintEGLError(int onlyerror);
void CheckGLError(int fwd);
#endif // _GL4ES_DEBUG_H_
+341
View File
@@ -0,0 +1,341 @@
#include <stdint.h>
#include <stddef.h>
/*
DXT1/DXT3/DXT5 texture decompression
The original code is from Benjamin Dobell, see below for details. Compared to
the original this one adds DXT3 decompression, is valid C89, and is x64
compatible as it uses fixed size integers everywhere. It also uses a different
PackRGBA order.
---
Copyright (c) 2012, Matth�us G. "Anteru" Chajdas (http://anteru.net)
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
---
Copyright (C) 2009 Benjamin Dobell, Glass Echidna
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
---
*/
static uint32_t PackRGBA (uint8_t r, uint8_t g, uint8_t b, uint8_t a)
{
return r | (g << 8) | (b << 16) | (a << 24);
}
static void DecompressBlockDXT1Internal (const uint8_t* block,
uint32_t* output,
uint32_t outputStride,
int transparent0, int* simpleAlpha, int *complexAlpha,
const uint8_t* alphaValues)
{
uint32_t temp, code;
uint16_t color0, color1;
uint8_t r0, g0, b0, r1, g1, b1;
int i, j;
color0 = *(const uint16_t*)(block);
color1 = *(const uint16_t*)(block + 2);
temp = (color0 >> 11) * 255 + 16;
r0 = (uint8_t)((temp/32 + temp)/32);
temp = ((color0 & 0x07E0) >> 5) * 255 + 32;
g0 = (uint8_t)((temp/64 + temp)/64);
temp = (color0 & 0x001F) * 255 + 16;
b0 = (uint8_t)((temp/32 + temp)/32);
temp = (color1 >> 11) * 255 + 16;
r1 = (uint8_t)((temp/32 + temp)/32);
temp = ((color1 & 0x07E0) >> 5) * 255 + 32;
g1 = (uint8_t)((temp/64 + temp)/64);
temp = (color1 & 0x001F) * 255 + 16;
b1 = (uint8_t)((temp/32 + temp)/32);
code = *(const uint32_t*)(block + 4);
if (color0 > color1) {
for (j = 0; j < 4; ++j) {
for (i = 0; i < 4; ++i) {
uint32_t finalColor, positionCode;
uint8_t alpha;
alpha = alphaValues [j*4+i];
finalColor = 0;
positionCode = (code >> 2*(4*j+i)) & 0x03;
switch (positionCode) {
case 0:
finalColor = PackRGBA(r0, g0, b0, alpha);
break;
case 1:
finalColor = PackRGBA(r1, g1, b1, alpha);
break;
case 2:
finalColor = PackRGBA((2*r0+r1)/3, (2*g0+g1)/3, (2*b0+b1)/3, alpha);
break;
case 3:
finalColor = PackRGBA((r0+2*r1)/3, (g0+2*g1)/3, (b0+2*b1)/3, alpha);
break;
}
if(!alpha)
*simpleAlpha = 1;
else if(alpha<0xff)
*complexAlpha = 1;
output [j*outputStride + i] = finalColor;
}
}
} else {
for (j = 0; j < 4; ++j) {
for (i = 0; i < 4; ++i) {
uint32_t finalColor, positionCode;
uint8_t alpha;
alpha = alphaValues [j*4+i];
finalColor = 0;
positionCode = (code >> 2*(4*j+i)) & 0x03;
switch (positionCode) {
case 0:
finalColor = PackRGBA(r0, g0, b0, alpha);
break;
case 1:
finalColor = PackRGBA(r1, g1, b1, alpha);
break;
case 2:
finalColor = PackRGBA((r0+r1)/2, (g0+g1)/2, (b0+b1)/2, alpha);
break;
case 3:
if(transparent0) alpha=0;
finalColor = PackRGBA(0, 0, 0, alpha);
break;
}
if(!alpha)
*simpleAlpha = 1;
else if(alpha<0xff)
*complexAlpha = 1;
output [j*outputStride + i] = finalColor;
}
}
}
}
/*
void DecompressBlockDXT1(): Decompresses one block of a DXT1 texture and stores the resulting pixels at the appropriate offset in 'image'.
uint32_t x: x-coordinate of the first pixel in the block.
uint32_t y: y-coordinate of the first pixel in the block.
uint32_t width: width of the texture being decompressed.
const uint8_t *blockStorage: pointer to the block to decompress.
uint32_t *image: pointer to image where the decompressed pixel data should be stored.
*/
void DecompressBlockDXT1(uint32_t x, uint32_t y, uint32_t width,
const uint8_t* blockStorage,
int transparent0, int* simpleAlpha, int *complexAlpha,
uint32_t* image)
{
static const uint8_t const_alpha [] = {
255, 255, 255, 255,
255, 255, 255, 255,
255, 255, 255, 255,
255, 255, 255, 255
};
DecompressBlockDXT1Internal (blockStorage,
image + x + (y * width), width, transparent0, simpleAlpha, complexAlpha, const_alpha);
}
/*
void DecompressBlockDXT5(): Decompresses one block of a DXT5 texture and stores the resulting pixels at the appropriate offset in 'image'.
uint32_t x: x-coordinate of the first pixel in the block.
uint32_t y: y-coordinate of the first pixel in the block.
uint32_t width: width of the texture being decompressed.
const uint8_t *blockStorage: pointer to the block to decompress.
uint32_t *image: pointer to image where the decompressed pixel data should be stored.
*/
void DecompressBlockDXT5(uint32_t x, uint32_t y, uint32_t width,
const uint8_t* blockStorage,
int transparent0, int* simpleAlpha, int *complexAlpha,
uint32_t* image)
{
uint8_t alpha0, alpha1;
const uint8_t* bits;
uint32_t alphaCode1;
uint16_t alphaCode2;
uint16_t color0, color1;
uint8_t r0, g0, b0, r1, g1, b1;
int i, j;
uint32_t temp, code;
alpha0 = *(blockStorage);
alpha1 = *(blockStorage + 1);
bits = blockStorage + 2;
alphaCode1 = bits[2] | (bits[3] << 8) | (bits[4] << 16) | (bits[5] << 24);
alphaCode2 = bits[0] | (bits[1] << 8);
color0 = *(const uint16_t*)(blockStorage + 8);
color1 = *(const uint16_t*)(blockStorage + 10);
temp = (color0 >> 11) * 255 + 16;
r0 = (uint8_t)((temp/32 + temp)/32);
temp = ((color0 & 0x07E0) >> 5) * 255 + 32;
g0 = (uint8_t)((temp/64 + temp)/64);
temp = (color0 & 0x001F) * 255 + 16;
b0 = (uint8_t)((temp/32 + temp)/32);
temp = (color1 >> 11) * 255 + 16;
r1 = (uint8_t)((temp/32 + temp)/32);
temp = ((color1 & 0x07E0) >> 5) * 255 + 32;
g1 = (uint8_t)((temp/64 + temp)/64);
temp = (color1 & 0x001F) * 255 + 16;
b1 = (uint8_t)((temp/32 + temp)/32);
code = *(const uint32_t*)(blockStorage + 12);
for (j = 0; j < 4; j++) {
for (i = 0; i < 4; i++) {
uint8_t finalAlpha;
int alphaCode, alphaCodeIndex;
uint8_t colorCode;
uint32_t finalColor;
alphaCodeIndex = 3*(4*j+i);
if (alphaCodeIndex <= 12) {
alphaCode = (alphaCode2 >> alphaCodeIndex) & 0x07;
} else if (alphaCodeIndex == 15) {
alphaCode = (alphaCode2 >> 15) | ((alphaCode1 << 1) & 0x06);
} else /* alphaCodeIndex >= 18 && alphaCodeIndex <= 45 */ {
alphaCode = (alphaCode1 >> (alphaCodeIndex - 16)) & 0x07;
}
if (alphaCode == 0) {
finalAlpha = alpha0;
} else if (alphaCode == 1) {
finalAlpha = alpha1;
} else {
if (alpha0 > alpha1) {
finalAlpha = (uint8_t)(((8-alphaCode)*alpha0 + (alphaCode-1)*alpha1)/7);
} else {
if (alphaCode == 6) {
finalAlpha = 0;
} else if (alphaCode == 7) {
finalAlpha = 255;
} else {
finalAlpha = (uint8_t)(((6-alphaCode)*alpha0 + (alphaCode-1)*alpha1)/5);
}
}
}
colorCode = (code >> 2*(4*j+i)) & 0x03;
finalColor = 0;
switch (colorCode) {
case 0:
finalColor = PackRGBA(r0, g0, b0, finalAlpha);
break;
case 1:
finalColor = PackRGBA(r1, g1, b1, finalAlpha);
break;
case 2:
finalColor = PackRGBA((2*r0+r1)/3, (2*g0+g1)/3, (2*b0+b1)/3, finalAlpha);
break;
case 3:
finalColor = PackRGBA((r0+2*r1)/3, (g0+2*g1)/3, (b0+2*b1)/3, finalAlpha);
break;
}
if(finalAlpha==0) *simpleAlpha = 1;
else if(finalAlpha<0xff) *complexAlpha = 1;
image [i + x + (width* (y+j))] = finalColor;
}
}
}
/*
void DecompressBlockDXT3(): Decompresses one block of a DXT3 texture and stores the resulting pixels at the appropriate offset in 'image'.
uint32_t x: x-coordinate of the first pixel in the block.
uint32_t y: y-coordinate of the first pixel in the block.
uint32_t height: height of the texture being decompressed.
const uint8_t *blockStorage: pointer to the block to decompress.
uint32_t *image: pointer to image where the decompressed pixel data should be stored.
*/
void DecompressBlockDXT3(uint32_t x, uint32_t y, uint32_t width,
const uint8_t* blockStorage,
int transparent0, int* simpleAlpha, int *complexAlpha,
uint32_t* image)
{
int i;
uint8_t alphaValues [16] = { 0 };
for (i = 0; i < 4; ++i) {
const uint16_t* alphaData = (const uint16_t*) (blockStorage);
alphaValues [i*4 + 0] = (((*alphaData) >> 0) & 0xF ) * 17;
alphaValues [i*4 + 1] = (((*alphaData) >> 4) & 0xF ) * 17;
alphaValues [i*4 + 2] = (((*alphaData) >> 8) & 0xF ) * 17;
alphaValues [i*4 + 3] = (((*alphaData) >> 12) & 0xF) * 17;
blockStorage += 2;
}
DecompressBlockDXT1Internal (blockStorage,
image + x + (y * width), width, transparent0, simpleAlpha, complexAlpha, alphaValues);
}
// Texture DXT1 / DXT5 compression
// Using STB "on file" library
// go there https://github.com/nothings/stb
// for more details and other libs
#define STB_DXT_IMPLEMENTATION
#include "stb_dxt_104.h"
+21
View File
@@ -0,0 +1,21 @@
#ifndef _GL4ES_DECOMPRESS_H_
#define _GL4ES_DECOMPRESS_H_
#include <stdint.h>
void DecompressBlockDXT1(uint32_t x, uint32_t y, uint32_t width,
const uint8_t* blockStorage,
int transparent0, int* simpleAlpha, int *complexAlpha,
uint32_t* image);
void DecompressBlockDXT3(uint32_t x, uint32_t y, uint32_t width,
const uint8_t* blockStorage,
int transparent0, int* simpleAlpha, int *complexAlpha,
uint32_t* image);
void DecompressBlockDXT5(uint32_t x, uint32_t y, uint32_t width,
const uint8_t* blockStorage,
int transparent0, int* simpleAlpha, int *complexAlpha,
uint32_t* image);
#endif // _GL4ES_DECOMPRESS_H_
+72
View File
@@ -0,0 +1,72 @@
#include "depth.h"
#include "gl4es.h"
#include "glstate.h"
#include "loader.h"
void APIENTRY_GL4ES gl4es_glDepthFunc(GLenum func) {
if(glstate->list.compiling) {
PUSH_IF_COMPILING(glDepthFunc);
}
noerrorShim();
if (glstate->depth.func == func)
return;
FLUSH_BEGINEND;
glstate->depth.func = func;
LOAD_GLES(glDepthFunc);
errorGL();
gles_glDepthFunc(func);
}
void APIENTRY_GL4ES gl4es_glDepthMask(GLboolean flag) {
if(glstate->list.compiling) {
PUSH_IF_COMPILING(glDepthMask);
}
noerrorShim();
if (glstate->depth.mask == flag)
return;
FLUSH_BEGINEND;
glstate->depth.mask = flag;
LOAD_GLES(glDepthMask);
errorGL();
gles_glDepthMask(flag);
}
GLfloat clamp(GLfloat a) {
return (a<0.f)?0.f:((a>1.f)?1.f:a);
}
void APIENTRY_GL4ES gl4es_glDepthRangef(GLclampf Near, GLclampf Far) {
Near = clamp(Near);
Far = clamp(Far);
if(glstate->list.compiling) {
PUSH_IF_COMPILING(glDepthRangef);
}
noerrorShim();
if ((glstate->depth.Near == Near) && (glstate->depth.Far == Far))
return;
FLUSH_BEGINEND;
glstate->depth.Near = Near;
glstate->depth.Far = Far;
LOAD_GLES(glDepthRangef);
errorGL();
gles_glDepthRangef(Near, Far);
}
void APIENTRY_GL4ES gl4es_glClearDepthf(GLclampf depth) {
depth = clamp(depth);
if(glstate->list.compiling) {
PUSH_IF_COMPILING(glClearDepthf);
}
noerrorShim();
glstate->depth.clear = depth;
LOAD_GLES(glClearDepthf);
errorGL();
gles_glClearDepthf(depth);
}
AliasExport(void,glDepthFunc,,(GLenum func));
AliasExport(void,glDepthMask,,(GLboolean flag));
AliasExport(void,glDepthRangef,,(GLclampf nearVal, GLclampf farVal));
AliasExport(void,glClearDepthf,,(GLclampf depth));
+11
View File
@@ -0,0 +1,11 @@
#ifndef _GL4ES_DEPTH_H_
#define _GL4ES_DEPTH_H_
#include "gles.h"
void APIENTRY_GL4ES gl4es_glDepthFunc(GLenum func);
void APIENTRY_GL4ES gl4es_glDepthMask(GLboolean flag);
void APIENTRY_GL4ES gl4es_glDepthRangef(GLclampf nearVal, GLclampf farVal);
void APIENTRY_GL4ES gl4es_glClearDepthf(GLclampf depth);
#endif // _GL4ES_DEPTH_H_
+655
View File
@@ -0,0 +1,655 @@
#include "directstate.h"
#include <stdio.h>
#include "wrap/gl4es.h"
#include "gles.h"
#include "stack.h"
#include "texgen.h"
#include "debug.h"
//#define DEBUG
#ifdef DEBUG
#define DBG(a) a
#else
#define DBG(a)
#endif
// Client State
void APIENTRY_GL4ES gl4es_glClientAttribDefault(GLbitfield mask) {
if (mask & GL_CLIENT_PIXEL_STORE_BIT) {
gl4es_glPixelStorei(GL_PACK_ALIGNMENT, 0);
gl4es_glPixelStorei(GL_UNPACK_ALIGNMENT, 0);
gl4es_glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
gl4es_glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
gl4es_glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
gl4es_glPixelStorei(GL_PACK_ROW_LENGTH, 0);
gl4es_glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
gl4es_glPixelStorei(GL_PACK_SKIP_ROWS, 0);
}
#define enable_disable(pname, enabled) \
if (enabled) gl4es_glEnableClientState(pname); \
else gl4es_glDisableClientState(pname)
if (mask & GL_CLIENT_VERTEX_ARRAY_BIT) {
int client = glstate->texture.client;
enable_disable(GL_VERTEX_ARRAY, false);
enable_disable(GL_NORMAL_ARRAY, false);
enable_disable(GL_COLOR_ARRAY, false);
enable_disable(GL_SECONDARY_COLOR_ARRAY, false);
for (int a=0; a<MAX_TEX; a++) {
gl4es_glClientActiveTexture(GL_TEXTURE0+a);
enable_disable(GL_TEXTURE_COORD_ARRAY, false);
}
#undef enable_disable
if (glstate->texture.client != client) gl4es_glClientActiveTexture(GL_TEXTURE0+client);
}
}
void APIENTRY_GL4ES gl4es_glPushClientAttribDefault(GLbitfield mask) {
gl4es_glPushClientAttrib(mask);
gl4es_glClientAttribDefault(mask);
}
// Matrix
#define mat(f) \
GLenum old_mat; \
gl4es_glGetIntegerv(GL_MATRIX_MODE, (GLint *) &old_mat); \
gl4es_glMatrixMode(matrixMode); \
gl4es_##f; \
gl4es_glMatrixMode(old_mat)
void APIENTRY_GL4ES gl4es_glMatrixLoadf(GLenum matrixMode, const GLfloat *m) {
mat(glLoadMatrixf(m));
}
void APIENTRY_GL4ES gl4es_glMatrixLoadd(GLenum matrixMode, const GLdouble *m) {
mat(glLoadMatrixd(m));
}
void APIENTRY_GL4ES gl4es_glMatrixMultf(GLenum matrixMode, const GLfloat *m) {
mat(glMultMatrixf(m));
}
void APIENTRY_GL4ES gl4es_glMatrixMultd(GLenum matrixMode, const GLdouble *m) {
mat(glMultMatrixd(m));
}
void APIENTRY_GL4ES gl4es_glMatrixLoadIdentity(GLenum matrixMode) {
mat(glLoadIdentity());
}
void APIENTRY_GL4ES gl4es_glMatrixRotatef(GLenum matrixMode, GLfloat angle, GLfloat x, GLfloat y, GLfloat z) {
mat(glRotatef(angle, x, y, z));
}
void APIENTRY_GL4ES gl4es_glMatrixRotated(GLenum matrixMode, GLdouble angle, GLdouble x, GLdouble y, GLdouble z) {
mat(glRotated(angle, x, y, z));
}
void APIENTRY_GL4ES gl4es_glMatrixScalef(GLenum matrixMode, GLfloat x, GLfloat y, GLfloat z) {
mat(glScalef(x, y, z));
}
void APIENTRY_GL4ES gl4es_glMatrixScaled(GLenum matrixMode, GLdouble x, GLdouble y, GLdouble z) {
mat(glScaled(x, y, z));
}
void APIENTRY_GL4ES gl4es_glMatrixTranslatef(GLenum matrixMode, GLfloat x, GLfloat y, GLfloat z) {
mat(glTranslatef(x, y, z));
}
void APIENTRY_GL4ES gl4es_glMatrixTranslated(GLenum matrixMode, GLdouble x, GLdouble y, GLdouble z) {
mat(glTranslated(x, y, z));
}
void APIENTRY_GL4ES gl4es_glMatrixOrtho(GLenum matrixMode, GLdouble l, GLdouble r, GLdouble b, GLdouble t, GLdouble n, GLdouble f) {
mat(glOrtho(l, r, b ,t, n, f));
}
void APIENTRY_GL4ES gl4es_glMatrixFrustum(GLenum matrixMode, GLdouble l, GLdouble r, GLdouble b, GLdouble t, GLdouble n, GLdouble f) {
mat(glFrustum(l, r, b, t, n, f));
}
void APIENTRY_GL4ES gl4es_glMatrixPush(GLenum matrixMode) {
mat(glPushMatrix());
}
void APIENTRY_GL4ES gl4es_glMatrixPop(GLenum matrixMode) {
mat(glPopMatrix());
}
void APIENTRY_GL4ES gl4es_glMatrixLoadTransposef(GLenum matrixMode, const GLfloat *m) {
mat(glLoadTransposeMatrixf(m));
}
void APIENTRY_GL4ES gl4es_glMatrixLoadTransposed(GLenum matrixMode, const GLdouble *m) {
mat(glLoadTransposeMatrixd(m));
}
void APIENTRY_GL4ES gl4es_glMatrixMultTransposef(GLenum matrixMode, const GLfloat *m) {
mat(glMultTransposeMatrixf(m));
}
void APIENTRY_GL4ES gl4es_glMatrixMultTransposed(GLenum matrixMode, const GLdouble *m) {
mat(glMultTransposeMatrixd(m));
}
#undef mat
// Textures
#define text(f) \
gl4es_glBindTexture(target, texture); \
gl4es_##f
void APIENTRY_GL4ES gl4es_glTextureParameteri(GLuint texture, GLenum target, GLenum pname, GLint param) {
text(glTexParameteri(target, pname, param));
}
void APIENTRY_GL4ES gl4es_glTextureParameteriv(GLuint texture, GLenum target, GLenum pname, const GLint *param) {
text(glTexParameteriv(target, pname, param));
}
void APIENTRY_GL4ES gl4es_glTextureParameterf(GLuint texture, GLenum target, GLenum pname, GLfloat param) {
text(glTexParameterf(target, pname, param));
}
void APIENTRY_GL4ES gl4es_glTextureParameterfv(GLuint texture, GLenum target, GLenum pname, const GLfloat *param) {
text(glTexParameterfv(target, pname, param));
}
void APIENTRY_GL4ES gl4es_glTextureImage1D(GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels) {
text(glTexImage1D(target, level, internalformat, width, border, format, type, pixels));
}
void APIENTRY_GL4ES gl4es_glTextureImage2D(GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels) {
text(glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels));
}
void APIENTRY_GL4ES gl4es_glTextureSubImage1D(GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels) {
text(glTexSubImage1D(target, level, xoffset, width, format, type, pixels));
}
void APIENTRY_GL4ES gl4es_glTextureSubImage2D(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels) {
text(glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels));
}
void APIENTRY_GL4ES gl4es_glCopyTextureImage1D(GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border) {
text(glCopyTexImage1D(target, level, internalformat, x, y, width, border));
}
void APIENTRY_GL4ES gl4es_glCopyTextureImage2D(GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) {
text(glCopyTexImage2D(target, level, internalformat, x, y, width, height, border));
}
void APIENTRY_GL4ES gl4es_glCopyTextureSubImage1D(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width) {
text(glCopyTexSubImage1D(target, level, xoffset, x, y, width));
}
void APIENTRY_GL4ES gl4es_glCopyTextureSubImage2D(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) {
text(glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height));
}
void APIENTRY_GL4ES gl4es_glGetTextureImage(GLuint texture, GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels) {
text(glGetTexImage(target, level, format, type, pixels));
}
void APIENTRY_GL4ES gl4es_glGetTextureParameterfv(GLuint texture, GLenum target, GLenum pname, GLfloat *params) {
text(glGetTexParameterfv(target, pname, params));
}
void APIENTRY_GL4ES gl4es_glGetTextureParameteriv(GLuint texture, GLenum target, GLenum pname, GLint *params) {
text(glGetTexParameteriv(target, pname, params));
}
void APIENTRY_GL4ES gl4es_glGetTextureLevelParameterfv(GLuint texture, GLenum target, GLint level, GLenum pname, GLfloat *params) {
text(glGetTexLevelParameterfv(target, level, pname, params));
}
void APIENTRY_GL4ES gl4es_glGetTextureLevelParameteriv(GLuint texture, GLenum target, GLint level, GLenum pname, GLint *params) {
text(glGetTexLevelParameteriv(target, level, pname, params));
}
// Texture 3D
void APIENTRY_GL4ES gl4es_glTextureImage3D(GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels) {
text(glTexImage3D(target, level, internalformat, width, height, depth, border, format, type, pixels));
}
void APIENTRY_GL4ES gl4es_glTextureSubImage3D(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels) {
text(glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels));
}
void APIENTRY_GL4ES gl4es_glCopyTextureSubImage3D(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) {
text(glCopyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height));
}
// Compressed texture
void APIENTRY_GL4ES gl4es_glCompressedTextureImage3D(GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data) {
text(glCompressedTexImage3D(target, level, internalformat, width, height, depth, border, imageSize, data));
}
void APIENTRY_GL4ES gl4es_glCompressedTextureImage2D(GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data) {
text(glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data));
}
void APIENTRY_GL4ES gl4es_glCompressedTextureImage1D(GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data) {
text(glCompressedTexImage1D(target, level, internalformat, width, border, imageSize, data));
}
void APIENTRY_GL4ES gl4es_glCompressedTextureSubImage3D(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data) {
text(glCompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data));
}
void APIENTRY_GL4ES gl4es_glCompressedTextureSubImage2D(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data) {
text(glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data));
}
void APIENTRY_GL4ES gl4es_glCompressedTextureSubImage1D(GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data) {
text(glCompressedTexSubImage1D(target, level, xoffset, width, format, imageSize, data));
}
void APIENTRY_GL4ES gl4es_glGetCompressedTextureImage(GLuint texture, GLenum target, GLint level, GLvoid *img) {
text(glGetCompressedTexImage(target, level, img));
}
#undef text
#define text(f) \
GLenum old_tex = glstate->texture.active; \
if(texunit != old_tex) gl4es_glActiveTexture(texunit); \
gl4es_##f; \
if(texunit != old_tex) gl4es_glActiveTexture(old_tex)
#define texc(f) \
GLenum old_tex = glstate->texture.client; \
if(texunit != old_tex) gl4es_glClientActiveTexture(texunit); \
gl4es_##f; \
if(texunit != old_tex) gl4es_glClientActiveTexture(old_tex)
void APIENTRY_GL4ES gl4es_glBindMultiTexture(GLenum texunit, GLenum target, GLuint texture) {
text(glBindTexture(target, texture));
}
void APIENTRY_GL4ES gl4es_glMultiTexCoordPointer(GLenum texunit, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer) {
texc(glTexCoordPointer(size, type, stride, pointer));
}
void APIENTRY_GL4ES gl4es_glMultiTexEnvf(GLenum texunit, GLenum target, GLenum pname, GLfloat param) {
text(glTexEnvf(target, pname, param));
}
void APIENTRY_GL4ES gl4es_glMultiTexEnvfv(GLenum texunit, GLenum target, GLenum pname, const GLfloat *params) {
text(glTexEnvfv(target, pname, params));
}
void APIENTRY_GL4ES gl4es_glMultiTexEnvi(GLenum texunit, GLenum target, GLenum pname, GLint param) {
text(glTexEnvi(target, pname, param));
}
void APIENTRY_GL4ES gl4es_glMultiTexEnviv(GLenum texunit, GLenum target, GLenum pname, const GLint *params) {
text(glTexEnviv(target, pname, params));
}
void APIENTRY_GL4ES gl4es_glMultiTexGend(GLenum texunit, GLenum coord, GLenum pname, GLdouble param) {
text(glTexGend(coord, pname, param));
}
void APIENTRY_GL4ES gl4es_glMultiTexGendv(GLenum texunit, GLenum coord, GLenum pname, const GLdouble *params) {
text(glTexGendv(coord, pname, params));
}
void APIENTRY_GL4ES gl4es_glMultiTexGenf(GLenum texunit, GLenum coord, GLenum pname, GLfloat param) {
text(glTexGenf(coord, pname, param));
}
void APIENTRY_GL4ES gl4es_glMultiTexGenfv(GLenum texunit, GLenum coord, GLenum pname, const GLfloat *params) {
text(glTexGenfv(coord, pname, params));
}
void APIENTRY_GL4ES gl4es_glMultiTexGeni(GLenum texunit, GLenum coord, GLenum pname, GLint param) {
text(glTexGeni(coord, pname, param));
}
void APIENTRY_GL4ES gl4es_glMultiTexGeniv(GLenum texunit, GLenum coord, GLenum pname, const GLint *params) {
text(glTexGeniv(coord, pname, params));
}
void APIENTRY_GL4ES gl4es_glGetMultiTexEnvfv(GLenum texunit, GLenum target, GLenum pname, GLfloat *params) {
text(glGetTexEnvfv(target, pname, params));
}
void APIENTRY_GL4ES gl4es_glGetMultiTexEnviv(GLenum texunit, GLenum target, GLenum pname, GLint *params) {
text(glGetTexEnviv(target, pname, params));
}
void APIENTRY_GL4ES gl4es_glGetMultiTexGendv(GLenum texunit, GLenum coord, GLenum pname, GLdouble *params) {
text(glGetTexGendv(coord, pname, params));
}
void APIENTRY_GL4ES gl4es_glGetMultiTexGenfv(GLenum texunit, GLenum coord, GLenum pname, GLfloat *params) {
text(glGetTexGenfv(coord, pname, params));
}
void APIENTRY_GL4ES gl4es_glGetMultiTexGeniv(GLenum texunit, GLenum coord, GLenum pname, GLint *params) {
text(glGetTexGeniv(coord, pname, params));
}
void APIENTRY_GL4ES gl4es_glMultiTexParameteri(GLenum texunit, GLenum target, GLenum pname, GLint param) {
text(glTexParameteri(target, pname, param));
}
void APIENTRY_GL4ES gl4es_glMultiTexParameteriv(GLenum texunit, GLenum target, GLenum pname, const GLint *param) {
text(glTexParameteriv(target, pname, param));
}
void APIENTRY_GL4ES gl4es_glMultiTexParameterf(GLenum texunit, GLenum target, GLenum pname, GLfloat param) {
text(glTexParameterf(target, pname, param));
}
void APIENTRY_GL4ES gl4es_glMultiTexParameterfv(GLenum texunit, GLenum target, GLenum pname, const GLfloat *param) {
text(glTexParameterfv(target, pname, param));
}
void APIENTRY_GL4ES gl4es_glMultiTexImage1D(GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels) {
text(glTexImage1D(target, level, internalformat, width, border, format, type, pixels));
}
void APIENTRY_GL4ES gl4es_glMultiTexImage2D(GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels) {
text(glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels));
}
void APIENTRY_GL4ES gl4es_glMultiTexSubImage1D(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels) {
text(glTexSubImage1D(target, level, xoffset, width, format, type, pixels));
}
void APIENTRY_GL4ES gl4es_glMultiTexSubImage2D(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels) {
text(glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels));
}
void APIENTRY_GL4ES gl4es_glCopyMultiTexImage1D(GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border) {
text(glCopyTexImage1D(target, level, internalformat, x, y, width, border));
}
void APIENTRY_GL4ES gl4es_glCopyMultiTexImage2D(GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) {
text(glCopyTexImage2D(target, level, internalformat, x, y, width, height, border));
}
void APIENTRY_GL4ES gl4es_glCopyMultiTexSubImage1D(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width) {
text(glCopyTexSubImage1D(target, level, xoffset, x, y, width));
}
void APIENTRY_GL4ES gl4es_glCopyMultiTexSubImage2D(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) {
text(glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height));
}
void APIENTRY_GL4ES gl4es_glGetMultiTexImage(GLenum texunit, GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels) {
text(glGetTexImage(target, level, format, type, pixels));
}
void APIENTRY_GL4ES gl4es_glGetMultiTexParameterfv(GLenum texunit, GLenum target, GLenum pname, GLfloat *params) {
text(glGetTexParameterfv(target, pname, params));
}
void APIENTRY_GL4ES gl4es_glGetMultiTexParameteriv(GLenum texunit, GLenum target, GLenum pname, GLint *params) {
text(glGetTexParameteriv(target, pname, params));
}
void APIENTRY_GL4ES gl4es_glGetMultiTexLevelParameterfv(GLenum texunit, GLenum target, GLint level, GLenum pname, GLfloat *params) {
text(glGetTexLevelParameterfv(target, level, pname, params));
}
void APIENTRY_GL4ES gl4es_glGetMultiTexLevelParameteriv(GLenum texunit, GLenum target, GLint level, GLenum pname, GLint *params) {
text(glGetTexLevelParameteriv(target, level, pname, params));
}
void APIENTRY_GL4ES gl4es_glMultiTexImage3D(GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels) {
text(glTexImage3D(target, level, internalformat, width, height, depth, border, format, type, pixels));
}
void APIENTRY_GL4ES gl4es_glMultiTexSubImage3D(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels) {
text(glTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels));
}
void APIENTRY_GL4ES gl4es_glCopyMultiTexSubImage3D(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) {
text(glCopyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height));
}
// Compressed texture
void APIENTRY_GL4ES gl4es_glCompressedMultiTexImage3D(GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data) {
text(glCompressedTexImage3D(target, level, internalformat, width, height, depth, border, imageSize, data));
}
void APIENTRY_GL4ES gl4es_glCompressedMultiTexImage2D(GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data) {
text(glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data));
}
void APIENTRY_GL4ES gl4es_glCompressedMultiTexImage1D(GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data) {
text(glCompressedTexImage1D(target, level, internalformat, width, border, imageSize, data));
}
void APIENTRY_GL4ES gl4es_glCompressedMultiTexSubImage3D(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data) {
text(glCompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data));
}
void APIENTRY_GL4ES gl4es_glCompressedMultiTexSubImage2D(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data) {
text(glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data));
}
void APIENTRY_GL4ES gl4es_glCompressedMultiTexSubImage1D(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data) {
text(glCompressedTexSubImage1D(target, level, xoffset, width, format, imageSize, data));
}
void APIENTRY_GL4ES gl4es_glGetCompressedMultiTexImage(GLenum texunit, GLenum target, GLint level, GLvoid *img) {
text(glGetCompressedTexImage(target, level, img));
}
void APIENTRY_GL4ES gl4es_glEnableClientStateIndexed(GLenum array, GLuint index) {
DBG(printf("glEnableClientStateIndexed(%s, %d)\n", PrintEnum(array), index);)
if (array == GL_TEXTURE_COORD_ARRAY) {
int old = glstate->texture.client;
if(old!=index) gl4es_glClientActiveTexture(GL_TEXTURE0+index);
gl4es_glEnableClientState(array);
if(old!=index) gl4es_glClientActiveTexture(GL_TEXTURE0+old);
errorGL();
} else {
errorShim(GL_INVALID_ENUM);
}
}
AliasDecl(void,gl4es_glEnableClientStatei,(GLenum array, GLuint index),gl4es_glEnableClientStateIndexed);
void APIENTRY_GL4ES gl4es_glDisableClientStateIndexed(GLenum array, GLuint index) {
DBG(printf("glDisableClientStateIndexed(%s, %d)\n", PrintEnum(array), index);)
if (array == GL_TEXTURE_COORD_ARRAY) {
int old = glstate->texture.client;
if(old!=index) gl4es_glClientActiveTexture(GL_TEXTURE0+index);
gl4es_glDisableClientState(array);
if(old!=index) gl4es_glClientActiveTexture(GL_TEXTURE0+old);
errorGL();
} else {
errorShim(GL_INVALID_ENUM);
}
}
AliasDecl(void,gl4es_glDisableClientStatei,(GLenum array, GLuint index),gl4es_glDisableClientStateIndexed);
void APIENTRY_GL4ES gl4es_glEnableVertexArray(GLuint vaobj, GLenum array) {
DBG(printf("glEnableVertexArray(%d, %s)\n", vaobj, PrintEnum(array));)
GLuint old = glstate->vao->array;
gl4es_glBindVertexArray(vaobj);
gl4es_glEnableClientState(array);
gl4es_glBindVertexArray(old);
}
void APIENTRY_GL4ES gl4es_glDisableVertexArray(GLuint vaobj, GLenum array) {
DBG(printf("glDisableVertexArray(%d, %s)\n", vaobj, PrintEnum(array));)
GLuint old = glstate->vao->array;
gl4es_glBindVertexArray(vaobj);
gl4es_glDisableClientState(array);
gl4es_glBindVertexArray(old);
}
void APIENTRY_GL4ES gl4es_glEnableVertexArrayAttrib(GLuint vaobj, GLuint index) {
DBG(printf("glEnableVertexArrayAttrib(%d, %d)\n", vaobj, index);)
GLuint old = glstate->vao->array;
gl4es_glBindVertexArray(vaobj);
gl4es_glEnableVertexAttribArray(index);
gl4es_glBindVertexArray(old);
}
void APIENTRY_GL4ES gl4es_glDisableVertexArrayAttrib(GLuint vaobj, GLuint index) {
DBG(printf("glDisableVertexArrayAttrib(%d, %d)\n", vaobj, index);)
GLuint old = glstate->vao->array;
gl4es_glBindVertexArray(vaobj);
gl4es_glDisableVertexAttribArray(index);
gl4es_glBindVertexArray(old);
}
#define GETXXX(XXX, xxx) \
void APIENTRY_GL4ES gl4es_glGet##XXX##Indexedv(GLenum target, GLuint index, GL##xxx *data) { \
switch(target) { \
case GL_PROGRAM_MATRIX_EXT: \
case GL_TRANSPOSE_PROGRAM_MATRIX_EXT: \
case GL_PROGRAM_MATRIX_STACK_DEPTH_EXT: \
{ \
int old = glstate->matrix_mode; \
gl4es_glMatrixMode(GL_MATRIX0_ARB+index); \
switch(target) { \
case GL_PROGRAM_MATRIX_EXT: \
gl4es_glGet##XXX##v(GL_CURRENT_MATRIX_ARB, data); \
break; \
case GL_TRANSPOSE_PROGRAM_MATRIX_EXT: \
gl4es_glGet##XXX##v(GL_TRANSPOSE_CURRENT_MATRIX_ARB, data); \
break; \
case GL_PROGRAM_MATRIX_STACK_DEPTH_EXT: \
gl4es_glGet##XXX##v(GL_CURRENT_MATRIX_STACK_DEPTH_ARB, data); \
break; \
} \
gl4es_glMatrixMode(old); \
} \
break; \
case GL_CURRENT_RASTER_TEXTURE_COORDS: \
case GL_CURRENT_TEXTURE_COORDS: \
case GL_TEXTURE_BINDING_1D: \
case GL_TEXTURE_BINDING_1D_ARRAY: \
case GL_TEXTURE_BINDING_2D: \
case GL_TEXTURE_BINDING_2D_ARRAY: \
case GL_TEXTURE_BINDING_3D: \
case GL_TEXTURE_BINDING_BUFFER_EXT: \
case GL_TEXTURE_BINDING_CUBE_MAP: \
case GL_TEXTURE_BINDING_RECTANGLE_ARB: \
case GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT: \
case GL_TEXTURE_BUFFER_FORMAT_EXT: \
case GL_TEXTURE_GEN_Q: \
case GL_TEXTURE_GEN_R: \
case GL_TEXTURE_GEN_S: \
case GL_TEXTURE_GEN_T: \
case GL_TEXTURE_MATRIX: \
case GL_TEXTURE_STACK_DEPTH: \
case GL_TRANSPOSE_TEXTURE_MATRIX: \
case GL_TEXTURE_1D: \
case GL_TEXTURE_2D: \
case GL_TEXTURE_3D: \
case GL_TEXTURE_CUBE_MAP: \
case GL_TEXTURE_RECTANGLE_ARB: \
{ \
int old = glstate->texture.active; \
if(old!=index+GL_TEXTURE0) gl4es_glActiveTexture(index+GL_TEXTURE0); \
gl4es_glGet##XXX##v(target, data); \
if(old!=index+GL_TEXTURE0) gl4es_glActiveTexture(old); \
} \
break; \
case GL_TEXTURE_COORD_ARRAY: \
case GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING: \
case GL_TEXTURE_COORD_ARRAY_COUNT: \
case GL_TEXTURE_COORD_ARRAY_SIZE: \
case GL_TEXTURE_COORD_ARRAY_STRIDE: \
case GL_TEXTURE_COORD_ARRAY_TYPE: \
{ \
int old = glstate->texture.client; \
if(old!=index) gl4es_glClientActiveTexture(index+GL_TEXTURE0); \
gl4es_glGet##XXX##v(target, data); \
if(old!=index) gl4es_glClientActiveTexture(old+GL_TEXTURE0); \
} \
break; \
default: \
gl4es_glGet##XXX##v(target, data); \
} \
}
GETXXX(Float, float);
GETXXX(Double, double);
GETXXX(Integer, int);
GETXXX(Boolean, boolean);
#undef GETXXX
void APIENTRY_GL4ES gl4es_glGetPointerIndexedv(GLenum pname, GLuint index, GLvoid **params) {
int old = glstate->texture.client;
if(old!=index) gl4es_glClientActiveTexture(index+GL_TEXTURE0);
gl4es_glGetPointerv(pname, params);
if(old!=index) gl4es_glClientActiveTexture(old+GL_TEXTURE0);
}
void APIENTRY_GL4ES gl4es_glEnableIndexed(GLenum cap, GLuint index) {
DBG(printf("glEnableIndexed(%s, %d)\n", PrintEnum(cap), index);)
int old = glstate->texture.active;
if(old!=index) gl4es_glActiveTexture(index+GL_TEXTURE0);
gl4es_glEnable(cap);
if(old!=index) gl4es_glActiveTexture(old);
}
void APIENTRY_GL4ES gl4es_glDisableIndexed(GLenum cap, GLuint index) {
DBG(printf("glDisableIndexed(%s, %d)\n", PrintEnum(cap), index);)
int old = glstate->texture.active;
if(old!=index) gl4es_glActiveTexture(index+GL_TEXTURE0);
gl4es_glDisable(cap);
if(old!=index) gl4es_glActiveTexture(old);
}
GLboolean APIENTRY_GL4ES gl4es_glIsEnabledIndexed(GLenum cap, GLuint index) {
DBG(printf("glIsEnabledIndexed(%s, %d)\n", PrintEnum(cap), index);)
int old;
GLboolean rv;
switch(cap) {
case GL_TEXTURE_1D:
case GL_TEXTURE_2D:
case GL_TEXTURE_3D:
case GL_TEXTURE_CUBE_MAP:
case GL_TEXTURE_RECTANGLE_ARB:
case GL_TEXTURE_GEN_S:
case GL_TEXTURE_GEN_T:
case GL_TEXTURE_GEN_R:
case GL_TEXTURE_GEN_Q:
old = glstate->texture.active;
if(old!=index) gl4es_glActiveTexture(index+GL_TEXTURE0);
rv = gl4es_glIsEnabled(cap);
if(old!=index) gl4es_glActiveTexture(old);
return rv;
case GL_TEXTURE_COORD_ARRAY:
old = glstate->texture.client;
if(old!=index) gl4es_glClientActiveTexture(index+GL_TEXTURE0);
rv = gl4es_glIsEnabled(cap);
if(old!=index) gl4es_glClientActiveTexture(old+GL_TEXTURE0);
return rv;
}
return gl4es_glIsEnabled(cap);
}
//EXT wrapper
AliasExport(void,glClientAttribDefault,EXT,(GLbitfield mask));
AliasExport(void,glPushClientAttribDefault,EXT,(GLbitfield mask));
AliasExport(void,glMatrixLoadf,EXT,(GLenum matrixMode, const GLfloat *m));
AliasExport(void,glMatrixLoadd,EXT,(GLenum matrixMode, const GLdouble *m));
AliasExport(void,glMatrixMultf,EXT,(GLenum matrixMode, const GLfloat *m));
AliasExport(void,glMatrixMultd,EXT,(GLenum matrixMode, const GLdouble *m));
AliasExport(void,glMatrixLoadIdentity,EXT,(GLenum matrixMode));
AliasExport(void,glMatrixRotatef,EXT,(GLenum matrixMode, GLfloat angle, GLfloat x, GLfloat y, GLfloat z));
AliasExport_D_1(void,glMatrixRotated,EXT,(GLenum matrixMode, GLdouble angle, GLdouble x, GLdouble y, GLdouble z));
AliasExport(void,glMatrixScalef,EXT,(GLenum matrixMode, GLfloat x, GLfloat y, GLfloat z));
AliasExport_D_1(void,glMatrixScaled,EXT,(GLenum matrixMode, GLdouble x, GLdouble y, GLdouble z));
AliasExport(void,glMatrixTranslatef,EXT,(GLenum matrixMode, GLfloat x, GLfloat y, GLfloat z));
AliasExport_D_1(void,glMatrixTranslated,EXT,(GLenum matrixMode, GLdouble x, GLdouble y, GLdouble z));
AliasExport_D_1(void,glMatrixOrtho,EXT,(GLenum matrixMode, GLdouble l, GLdouble r, GLdouble b, GLdouble t, GLdouble n, GLdouble f));
AliasExport_D_1(void,glMatrixFrustum,EXT,(GLenum matrixMode, GLdouble l, GLdouble r, GLdouble b, GLdouble t, GLdouble n, GLdouble f));
AliasExport(void,glMatrixPush,EXT,(GLenum matrixMode));
AliasExport(void,glMatrixPop,EXT,(GLenum matrixMode));
AliasExport(void,glTextureParameteri,EXT,(GLuint texture, GLenum target, GLenum pname, GLint param));
AliasExport(void,glTextureParameteriv,EXT,(GLuint texture, GLenum target, GLenum pname, const GLint *param));
AliasExport(void,glTextureParameterf,EXT,(GLuint texture, GLenum target, GLenum pname, GLfloat param));
AliasExport(void,glTextureParameterfv,EXT,(GLuint texture, GLenum target, GLenum pname, const GLfloat *param));
AliasExport(void,glTextureImage1D,EXT,(GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels));
AliasExport(void,glTextureImage2D,EXT,(GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels));
AliasExport(void,glTextureSubImage1D,EXT,(GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels));
AliasExport(void,glTextureSubImage2D,EXT,(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels));
AliasExport(void,glCopyTextureImage1D,EXT,(GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border));
AliasExport(void,glCopyTextureImage2D,EXT,(GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border));
AliasExport(void,glCopyTextureSubImage1D,EXT,(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width));
AliasExport(void,glCopyTextureSubImage2D,EXT,(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height));
AliasExport(void,glGetTextureImage,EXT,(GLuint texture, GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels));
AliasExport(void,glGetTextureParameterfv,EXT,(GLuint texture, GLenum target, GLenum pname, GLfloat *params));
AliasExport(void,glGetTextureParameteriv,EXT,(GLuint texture, GLenum target, GLenum pname, GLint *params));
AliasExport(void,glGetTextureLevelParameterfv,EXT,(GLuint texture, GLenum target, GLint level, GLenum pname, GLfloat *params));
AliasExport(void,glGetTextureLevelParameteriv,EXT,(GLuint texture, GLenum target, GLint level, GLenum pname, GLint *params));
AliasExport(void,glTextureImage3D,EXT,(GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels));
AliasExport(void,glTextureSubImage3D,EXT,(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels));
AliasExport(void,glCopyTextureSubImage3D,EXT,(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height));
AliasExport(void,glBindMultiTexture,EXT,(GLenum texunit, GLenum target, GLuint texture));
AliasExport(void,glMultiTexCoordPointer,EXT,(GLenum texunit, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer));
AliasExport(void,glMultiTexEnvf,EXT,(GLenum texunit, GLenum target, GLenum pname, GLfloat param));
AliasExport(void,glMultiTexEnvfv,EXT,(GLenum texunit, GLenum target, GLenum pname, const GLfloat *params));
AliasExport(void,glMultiTexEnvi,EXT,(GLenum texunit, GLenum target, GLenum pname, GLint param));
AliasExport(void,glMultiTexEnviv,EXT,(GLenum texunit, GLenum target, GLenum pname, const GLint *params));
AliasExport_M(void,glMultiTexGend,EXT,(GLenum texunit, GLenum coord, GLenum pname, GLdouble param),20);
AliasExport(void,glMultiTexGendv,EXT,(GLenum texunit, GLenum coord, GLenum pname, const GLdouble *params));
AliasExport(void,glMultiTexGenf,EXT,(GLenum texunit, GLenum coord, GLenum pname, GLfloat param));
AliasExport(void,glMultiTexGenfv,EXT,(GLenum texunit, GLenum coord, GLenum pname, const GLfloat *params));
AliasExport(void,glMultiTexGeni,EXT,(GLenum texunit, GLenum coord, GLenum pname, GLint param));
AliasExport(void,glMultiTexGeniv,EXT,(GLenum texunit, GLenum coord, GLenum pname, const GLint *params));
AliasExport(void,glGetMultiTexEnvfv,EXT,(GLenum texunit, GLenum target, GLenum pname, GLfloat *params));
AliasExport(void,glGetMultiTexEnviv,EXT,(GLenum texunit, GLenum target, GLenum pname, GLint *params));
AliasExport(void,glGetMultiTexGendv,EXT,(GLenum texunit, GLenum coord, GLenum pname, GLdouble *params));
AliasExport(void,glGetMultiTexGenfv,EXT,(GLenum texunit, GLenum coord, GLenum pname, GLfloat *params));
AliasExport(void,glGetMultiTexGeniv,EXT,(GLenum texunit, GLenum coord, GLenum pname, GLint *params));
AliasExport(void,glMultiTexParameteri,EXT,(GLenum texunit, GLenum target, GLenum pname, GLint param));
AliasExport(void,glMultiTexParameteriv,EXT,(GLenum texunit, GLenum target, GLenum pname, const GLint *param));
AliasExport(void,glMultiTexParameterf,EXT,(GLenum texunit, GLenum target, GLenum pname, GLfloat param));
AliasExport(void,glMultiTexParameterfv,EXT,(GLenum texunit, GLenum target, GLenum pname, const GLfloat *param));
AliasExport(void,glMultiTexImage1D,EXT,(GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels));
AliasExport(void,glMultiTexImage2D,EXT,(GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels));
AliasExport(void,glMultiTexSubImage1D,EXT,(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels));
AliasExport(void,glMultiTexSubImage2D,EXT,(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels));
AliasExport(void,glCopyMultiTexImage1D,EXT,(GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border));
AliasExport(void,glCopyMultiTexImage2D,EXT,(GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border));
AliasExport(void,glCopyMultiTexSubImage1D,EXT,(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width));
AliasExport(void,glCopyMultiTexSubImage2D,EXT,(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height));
AliasExport(void,glGetMultiTexImage,EXT,(GLenum texunit, GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels));
AliasExport(void,glGetMultiTexParameterfv,EXT,(GLenum texunit, GLenum target, GLenum pname, GLfloat *params));
AliasExport(void,glGetMultiTexParameteriv,EXT,(GLenum texunit, GLenum target, GLenum pname, GLint *params));
AliasExport(void,glGetMultiTexLevelParameterfv,EXT,(GLenum texunit, GLenum target, GLint level, GLenum pname, GLfloat *params));
AliasExport(void,glGetMultiTexLevelParameteriv,EXT,(GLenum texunit, GLenum target, GLint level, GLenum pname, GLint *params));
AliasExport(void,glMultiTexImage3D,EXT,(GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels));
AliasExport(void,glMultiTexSubImage3D,EXT,(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels));
AliasExport(void,glCopyMultiTexSubImage3D,EXT,(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height));
AliasExport(void,glCompressedTextureImage3D,EXT,(GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data));
AliasExport(void,glCompressedTextureImage2D,EXT,(GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data));
AliasExport(void,glCompressedTextureImage1D,EXT,(GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data));
AliasExport(void,glCompressedTextureSubImage3D,EXT,(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data));
AliasExport(void,glCompressedTextureSubImage2D,EXT,(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data));
AliasExport(void,glCompressedTextureSubImage1D,EXT,(GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data));
AliasExport(void,glGetCompressedTextureImage,EXT,(GLuint texture, GLenum target, GLint level, GLvoid *img));
AliasExport(void,glCompressedMultiTexImage3D,EXT,(GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data));
AliasExport(void,glCompressedMultiTexImage2D,EXT,(GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data));
AliasExport(void,glCompressedMultiTexImage1D,EXT,(GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data));
AliasExport(void,glCompressedMultiTexSubImage3D,EXT,(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data));
AliasExport(void,glCompressedMultiTexSubImage2D,EXT,(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data));
AliasExport(void,glCompressedMultiTexSubImage1D,EXT,(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data));
AliasExport(void,glGetCompressedMultiTexImage,EXT,(GLenum texunit, GLenum target, GLint level, GLvoid *img));
AliasExport(void,glMatrixLoadTransposef,EXT,(GLenum matrixMode, const GLfloat *m));
AliasExport(void,glMatrixLoadTransposed,EXT,(GLenum matrixMode, const GLdouble *m));
AliasExport(void,glMatrixMultTransposef,EXT,(GLenum matrixMode, const GLfloat *m));
AliasExport(void,glMatrixMultTransposed,EXT,(GLenum matrixMode, const GLdouble *m));
AliasExport(void,glEnableClientStateIndexed,EXT,(GLenum array, GLuint index));
AliasExport(void,glDisableClientStateIndexed,EXT,(GLenum array, GLuint index));
AliasExport_A(void,glEnableClientStatei,EXT,(GLenum array, GLuint index),glEnableClientStateIndexed);
AliasExport_A(void,glDisableClientStatei,EXT,(GLenum array, GLuint index),glEnableClientStateIndexed);
AliasExport(void,glEnableVertexArray,EXT,(GLuint vaobj, GLenum array));
AliasExport(void,glDisableVertexArray,EXT,(GLuint vaobj, GLenum array));
AliasExport(void,glEnableVertexArrayAttrib,EXT,(GLuint vaobj, GLuint index));
AliasExport(void,glDisableVertexArrayAttrib,EXT,(GLuint vaobj, GLuint index));
AliasExport(void,glGetPointerIndexedv,EXT,(GLenum pname, GLuint index, GLvoid **params));
AliasExport(void,glGetFloatIndexedv,EXT,(GLenum target, GLuint index, GLfloat *data));
AliasExport(void,glGetDoubleIndexedv,EXT,(GLenum target, GLuint index, GLdouble *data));
AliasExport(void,glGetIntegerIndexedv,EXT,(GLenum target, GLuint index, GLint *data));
AliasExport(void,glGetBooleanIndexedv,EXT,(GLenum target, GLuint index, GLboolean *data));
AliasExport(void,glEnableIndexed,EXT,(GLenum cap, GLuint index));
AliasExport(void,glDisableIndexed,EXT,(GLenum cap, GLuint index));
AliasExport(GLboolean,glIsEnabledIndexed,EXT,(GLenum cap, GLuint index));
#undef text
#undef texc
+126
View File
@@ -0,0 +1,126 @@
#ifndef _GL4ES_DIRECTSTATE_H_
#define _GL4ES_DIRECTSTATE_H_
#include "gles.h"
void APIENTRY_GL4ES gl4es_glClientAttribDefault(GLbitfield mask);
void APIENTRY_GL4ES gl4es_glPushClientAttribDefault(GLbitfield mask);
void APIENTRY_GL4ES gl4es_glMatrixLoadf(GLenum matrixMode, const GLfloat *m);
void APIENTRY_GL4ES gl4es_glMatrixLoadd(GLenum matrixMode, const GLdouble *m);
void APIENTRY_GL4ES gl4es_glMatrixMultf(GLenum matrixMode, const GLfloat *m);
void APIENTRY_GL4ES gl4es_glMatrixMultd(GLenum matrixMode, const GLdouble *m);
void APIENTRY_GL4ES gl4es_glMatrixLoadIdentity(GLenum matrixMode);
void APIENTRY_GL4ES gl4es_glMatrixRotatef(GLenum matrixMode, GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
void APIENTRY_GL4ES gl4es_glMatrixRotated(GLenum matrixMode, GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
void APIENTRY_GL4ES gl4es_glMatrixScalef(GLenum matrixMode, GLfloat x, GLfloat y, GLfloat z);
void APIENTRY_GL4ES gl4es_glMatrixScaled(GLenum matrixMode, GLdouble x, GLdouble y, GLdouble z);
void APIENTRY_GL4ES gl4es_glMatrixTranslatef(GLenum matrixMode, GLfloat x, GLfloat y, GLfloat z);
void APIENTRY_GL4ES gl4es_glMatrixTranslated(GLenum matrixMode, GLdouble x, GLdouble y, GLdouble z);
void APIENTRY_GL4ES gl4es_glMatrixOrtho(GLenum matrixMode, GLdouble l, GLdouble r, GLdouble b, GLdouble t, GLdouble n, GLdouble f);
void APIENTRY_GL4ES gl4es_glMatrixFrustum(GLenum matrixMode, GLdouble l, GLdouble r, GLdouble b, GLdouble t, GLdouble n, GLdouble f);
void APIENTRY_GL4ES gl4es_glMatrixPush(GLenum matrixMode);
void APIENTRY_GL4ES gl4es_glMatrixPop(GLenum matrixMode);
void APIENTRY_GL4ES gl4es_glTextureParameteri(GLuint texture, GLenum target, GLenum pname, GLint param);
void APIENTRY_GL4ES gl4es_glTextureParameteriv(GLuint texture, GLenum target, GLenum pname, const GLint *param);
void APIENTRY_GL4ES gl4es_glTextureParameterf(GLuint texture, GLenum target, GLenum pname, GLfloat param);
void APIENTRY_GL4ES gl4es_glTextureParameterfv(GLuint texture, GLenum target, GLenum pname, const GLfloat *param);
void APIENTRY_GL4ES gl4es_glTextureImage1D(GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
void APIENTRY_GL4ES gl4es_glTextureImage2D(GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
void APIENTRY_GL4ES gl4es_glTextureSubImage1D(GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
void APIENTRY_GL4ES gl4es_glTextureSubImage2D(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
void APIENTRY_GL4ES gl4es_glCopyTextureImage1D(GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
void APIENTRY_GL4ES gl4es_glCopyTextureImage2D(GLuint texture, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
void APIENTRY_GL4ES gl4es_glCopyTextureSubImage1D(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
void APIENTRY_GL4ES gl4es_glCopyTextureSubImage2D(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
void APIENTRY_GL4ES gl4es_glGetTextureImage(GLuint texture, GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels);
void APIENTRY_GL4ES gl4es_glGetTextureParameterfv(GLuint texture, GLenum target, GLenum pname, GLfloat *params);
void APIENTRY_GL4ES gl4es_glGetTextureParameteriv(GLuint texture, GLenum target, GLenum pname, GLint *params);
void APIENTRY_GL4ES gl4es_glGetTextureLevelParameterfv(GLuint texture, GLenum target, GLint level, GLenum pname, GLfloat *params);
void APIENTRY_GL4ES gl4es_glGetTextureLevelParameteriv(GLuint texture, GLenum target, GLint level, GLenum pname, GLint *params);
void APIENTRY_GL4ES gl4es_glTextureImage3D(GLuint texture, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
void APIENTRY_GL4ES gl4es_glTextureSubImage3D(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);
void APIENTRY_GL4ES gl4es_glCopyTextureSubImage3D(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
void APIENTRY_GL4ES gl4es_glBindMultiTexture(GLenum texunit, GLenum target, GLuint texture);
void APIENTRY_GL4ES gl4es_glMultiTexCoordPointer(GLenum texunit, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
void APIENTRY_GL4ES gl4es_glMultiTexEnvf(GLenum texunit, GLenum target, GLenum pname, GLfloat param);
void APIENTRY_GL4ES gl4es_glMultiTexEnvfv(GLenum texunit, GLenum target, GLenum pname, const GLfloat *params);
void APIENTRY_GL4ES gl4es_glMultiTexEnvi(GLenum texunit, GLenum target, GLenum pname, GLint param);
void APIENTRY_GL4ES gl4es_glMultiTexEnviv(GLenum texunit, GLenum target, GLenum pname, const GLint *params);
void APIENTRY_GL4ES gl4es_glMultiTexGend(GLenum texunit, GLenum coord, GLenum pname, GLdouble param);
void APIENTRY_GL4ES gl4es_glMultiTexGendv(GLenum texunit, GLenum coord, GLenum pname, const GLdouble *params);
void APIENTRY_GL4ES gl4es_glMultiTexGenf(GLenum texunit, GLenum coord, GLenum pname, GLfloat param);
void APIENTRY_GL4ES gl4es_glMultiTexGenfv(GLenum texunit, GLenum coord, GLenum pname, const GLfloat *params);
void APIENTRY_GL4ES gl4es_glMultiTexGeni(GLenum texunit, GLenum coord, GLenum pname, GLint param);
void APIENTRY_GL4ES gl4es_glMultiTexGeniv(GLenum texunit, GLenum coord, GLenum pname, const GLint *params);
void APIENTRY_GL4ES gl4es_glGetMultiTexEnvfv(GLenum texunit, GLenum target, GLenum pname, GLfloat *params);
void APIENTRY_GL4ES gl4es_glGetMultiTexEnviv(GLenum texunit, GLenum target, GLenum pname, GLint *params);
void APIENTRY_GL4ES gl4es_glGetMultiTexGendv(GLenum texunit, GLenum coord, GLenum pname, GLdouble *params);
void APIENTRY_GL4ES gl4es_glGetMultiTexGenfv(GLenum texunit, GLenum coord, GLenum pname, GLfloat *params);
void APIENTRY_GL4ES gl4es_glGetMultiTexGeniv(GLenum texunit, GLenum coord, GLenum pname, GLint *params);
void APIENTRY_GL4ES gl4es_glMultiTexParameteri(GLenum texunit, GLenum target, GLenum pname, GLint param);
void APIENTRY_GL4ES gl4es_glMultiTexParameteriv(GLenum texunit, GLenum target, GLenum pname, const GLint *param);
void APIENTRY_GL4ES gl4es_glMultiTexParameterf(GLenum texunit, GLenum target, GLenum pname, GLfloat param);
void APIENTRY_GL4ES gl4es_glMultiTexParameterfv(GLenum texunit, GLenum target, GLenum pname, const GLfloat *param);
void APIENTRY_GL4ES gl4es_glMultiTexImage1D(GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
void APIENTRY_GL4ES gl4es_glMultiTexImage2D(GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
void APIENTRY_GL4ES gl4es_glMultiTexSubImage1D(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
void APIENTRY_GL4ES gl4es_glMultiTexSubImage2D(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
void APIENTRY_GL4ES gl4es_glCopyMultiTexImage1D(GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLint border);
void APIENTRY_GL4ES gl4es_glCopyMultiTexImage2D(GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
void APIENTRY_GL4ES gl4es_glCopyMultiTexSubImage1D(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
void APIENTRY_GL4ES gl4es_glCopyMultiTexSubImage2D(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
void APIENTRY_GL4ES gl4es_glGetMultiTexImage(GLenum texunit, GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels);
void APIENTRY_GL4ES gl4es_glGetMultiTexParameterfv(GLenum texunit, GLenum target, GLenum pname, GLfloat *params);
void APIENTRY_GL4ES gl4es_glGetMultiTexParameteriv(GLenum texunit, GLenum target, GLenum pname, GLint *params);
void APIENTRY_GL4ES gl4es_glGetMultiTexLevelParameterfv(GLenum texunit, GLenum target, GLint level, GLenum pname, GLfloat *params);
void APIENTRY_GL4ES gl4es_glGetMultiTexLevelParameteriv(GLenum texunit, GLenum target, GLint level, GLenum pname, GLint *params);
void APIENTRY_GL4ES gl4es_glMultiTexImage3D(GLenum texunit, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
void APIENTRY_GL4ES gl4es_glMultiTexSubImage3D(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels);
void APIENTRY_GL4ES gl4es_glCopyMultiTexSubImage3D(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
void APIENTRY_GL4ES gl4es_glCompressedTextureImage3D(GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);
void APIENTRY_GL4ES gl4es_glCompressedTextureImage2D(GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
void APIENTRY_GL4ES gl4es_glCompressedTextureImage1D(GLuint texture, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data);
void APIENTRY_GL4ES gl4es_glCompressedTextureSubImage3D(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data);
void APIENTRY_GL4ES gl4es_glCompressedTextureSubImage2D(GLuint texture, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data);
void APIENTRY_GL4ES gl4es_glCompressedTextureSubImage1D(GLuint texture, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data);
void APIENTRY_GL4ES gl4es_glGetCompressedTextureImage(GLuint texture, GLenum target, GLint level, GLvoid *img);
void APIENTRY_GL4ES gl4es_glCompressedMultiTexImage3D(GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid *data);
void APIENTRY_GL4ES gl4es_glCompressedMultiTexImage2D(GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid *data);
void APIENTRY_GL4ES gl4es_glCompressedMultiTexImage1D(GLenum texunit, GLenum target, GLint level, GLenum internalformat, GLsizei width, GLint border, GLsizei imageSize, const GLvoid *data);
void APIENTRY_GL4ES gl4es_glCompressedMultiTexSubImage3D(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid *data);
void APIENTRY_GL4ES gl4es_glCompressedMultiTexSubImage2D(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid *data);
void APIENTRY_GL4ES gl4es_glCompressedMultiTexSubImage1D(GLenum texunit, GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLsizei imageSize, const GLvoid *data);
void APIENTRY_GL4ES gl4es_glGetCompressedMultiTexImage(GLenum texunit, GLenum target, GLint level, GLvoid *img);
void APIENTRY_GL4ES gl4es_glMatrixLoadTransposef(GLenum matrixMode, const GLfloat *m);
void APIENTRY_GL4ES gl4es_glMatrixLoadTransposed(GLenum matrixMode, const GLdouble *m);
void APIENTRY_GL4ES gl4es_glMatrixMultTransposef(GLenum matrixMode, const GLfloat *m);
void APIENTRY_GL4ES gl4es_glMatrixMultTransposed(GLenum matrixMode, const GLdouble *m);
void APIENTRY_GL4ES gl4es_glEnableClientStateIndexed(GLenum array, GLuint index);
void APIENTRY_GL4ES gl4es_glDisableClientStateIndexed(GLenum array, GLuint index);
void APIENTRY_GL4ES gl4es_glEnableClientStatei(GLenum array, GLuint index);
void APIENTRY_GL4ES gl4es_glDisableClientStatei(GLenum array, GLuint index);
void APIENTRY_GL4ES gl4es_glEnableVertexArray(GLuint vaobj, GLenum array);
void APIENTRY_GL4ES gl4es_glDisableVertexArray(GLuint vaobj, GLenum array);
void APIENTRY_GL4ES gl4es_glEnableVertexArrayAttrib(GLuint vaobj, GLuint index);
void APIENTRY_GL4ES gl4es_glDisableVertexArrayAttrib(GLuint vaobj, GLuint index);
void APIENTRY_GL4ES gl4es_glGetFloatIndexedv(GLenum target, GLuint index, GLfloat *data);
void APIENTRY_GL4ES gl4es_glGetDoubleIndexedv(GLenum target, GLuint index, GLdouble *data);
void APIENTRY_GL4ES gl4es_glGetIntegerIndexedv(GLenum target, GLuint index, GLint *data);
void APIENTRY_GL4ES gl4es_glGetBooleanIndexedv(GLenum target, GLuint index, GLboolean *data);
void APIENTRY_GL4ES gl4es_glGetPointerIndexedv(GLenum pname, GLuint index, GLvoid **params);
void APIENTRY_GL4ES gl4es_glEnableIndexed(GLenum cap, GLuint index);
void APIENTRY_GL4ES gl4es_glDisableIndexed(GLenum cap, GLuint index);
GLboolean APIENTRY_GL4ES gl4es_glIsEnabledIndexed(GLenum cap, GLuint index);
#endif // _GL4ES_DIRECTSTATE_H_
File diff suppressed because it is too large Load Diff
+426
View File
@@ -0,0 +1,426 @@
#include "gl4es.h"
#include "glstate.h"
#include "init.h"
#include "loader.h"
#include "debug.h"
//#define DEBUG
#ifdef DEBUG
#define DBG(a) a
#else
#define DBG(a)
#endif
static void gl_changetex(int n)
{
if(glstate->bound_changed < n+1)
glstate->bound_changed = n+1;
}
static void fpe_changeplane(int n, bool enable)
{
glstate->fpe = NULL;
if(enable)
glstate->fpe_state->plane |= 1<<n;
else
glstate->fpe_state->plane &= ~(1<<n);
}
static void fpe_changelight(int n, bool enable)
{
glstate->fpe = NULL;
if(enable)
glstate->fpe_state->light |= 1<<n;
else
glstate->fpe_state->light &= ~(1<<n);
}
static void fpe_changetex(int n)
{
if(glstate->fpe_bound_changed < n+1)
glstate->fpe_bound_changed = n+1;
}
#define generate_changetexgen(C) \
static void fpe_changetexgen_##C(int n, bool enable) \
{ \
glstate->fpe_state->texgen[n].texgen_##C = enable?1:0; \
}
generate_changetexgen(s)
generate_changetexgen(t)
generate_changetexgen(r)
generate_changetexgen(q)
#undef generate_changetexgen
void change_vao_texcoord(int tmu, bool enable)
{
glstate->vao->vertexattrib[ATT_MULTITEXCOORD0+tmu].enabled = enable;
if(enable) {
if(glstate->vao->maxtex<tmu+1) glstate->vao->maxtex=tmu+1;
} else {
if(glstate->vao->maxtex==tmu+1) {
glstate->vao->maxtex=tmu;
}
}
}
#ifndef GL_TEXTURE_STREAM_IMG
#define GL_TEXTURE_STREAM_IMG 0x8C0D
#endif
static void proxy_glEnable(GLenum cap, bool enable, void (APIENTRY_GLES *next)(GLenum)) {
#define proxy_GO(constant, name) \
case constant: if(glstate->enable.name != enable) {FLUSH_BEGINEND; glstate->enable.name = enable; next(cap);} break
#define proxy_GOFPE(constant, name, fct) \
case constant: if(glstate->enable.name != enable) {FLUSH_BEGINEND; glstate->enable.name = enable; if(glstate->fpe_state) { fct; } else next(cap);} break
#define GO(constant, name) \
case constant: if(glstate->list.pending && glstate->enable.name!=enable) gl4es_flush(); glstate->enable.name = enable; break;
#define GONF(constant, name) \
case constant: glstate->enable.name = enable; break;
#define GOFPE(constant, name, fct) \
case constant: if(glstate->list.pending && glstate->enable.name!=enable) gl4es_flush(); glstate->enable.name = enable; if(glstate->fpe_state) { fct; } break;
#define proxy_clientGO(constant, name) \
case constant: if (glstate->vao->name != enable) {glstate->vao->name = enable; next(cap);} break
#define clientGO(constant, name) \
case constant: glstate->vao->name = enable; break;
#define clientGO_proxyFPE(constant, name) \
case constant: glstate->vao->name = enable; if(glstate->fpe_state) { next(cap);} break;
// Alpha Hack
if (globals4es.alphahack && (cap==GL_ALPHA_TEST) && enable) {
if (!glstate->texture.bound[glstate->texture.active][ENABLED_TEX2D]->alpha)
enable = false;
}
noerrorShim();
#ifdef TEXSTREAM
if (cap==GL_TEXTURE_STREAM_IMG) {
FLUSH_BEGINEND;
if(enable)
glstate->enable.texture[glstate->texture.active] |= (1<<ENABLED_TEX2D);
else
glstate->enable.texture[glstate->texture.active] &= ~(1<<ENABLED_TEX2D);
gl_changetex(glstate->texture.active);
if(glstate->fpe_state)
fpe_changetex(glstate->texture.active);
else
next(cap);
return;
}
#endif
switch (cap) {
GO(GL_AUTO_NORMAL, auto_normal);
proxy_GOFPE(GL_ALPHA_TEST, alpha_test,glstate->fpe_state->alphatest=enable);
proxy_GOFPE(GL_FOG, fog, glstate->fpe_state->fog=enable);
case GL_BLEND: if(glstate->enable.blend != enable) {FLUSH_BEGINEND; glstate->enable.blend = enable; if(glstate->fpe_state && globals4es.shaderblend) { glstate->fpe_state->blend_enable = enable; } else next(cap);} break;
proxy_GO(GL_CULL_FACE, cull_face);
proxy_GO(GL_DEPTH_TEST, depth_test);
proxy_GO(GL_STENCIL_TEST, stencil_test);
// texgen
GOFPE(GL_TEXTURE_GEN_S, texgen_s[glstate->texture.active], fpe_changetexgen_s(glstate->texture.active, enable)); //TODO: FPE stuffs
GOFPE(GL_TEXTURE_GEN_T, texgen_t[glstate->texture.active], fpe_changetexgen_t(glstate->texture.active, enable));
GOFPE(GL_TEXTURE_GEN_R, texgen_r[glstate->texture.active], fpe_changetexgen_r(glstate->texture.active, enable));
GOFPE(GL_TEXTURE_GEN_Q, texgen_q[glstate->texture.active], fpe_changetexgen_q(glstate->texture.active, enable));
GO(GL_LINE_STIPPLE, line_stipple);
// clip plane
proxy_GOFPE(GL_CLIP_PLANE0, plane[0], fpe_changeplane(0, enable));
proxy_GOFPE(GL_CLIP_PLANE1, plane[1], fpe_changeplane(1, enable));
proxy_GOFPE(GL_CLIP_PLANE2, plane[2], fpe_changeplane(2, enable));
proxy_GOFPE(GL_CLIP_PLANE3, plane[3], fpe_changeplane(3, enable));
proxy_GOFPE(GL_CLIP_PLANE4, plane[4], fpe_changeplane(4, enable));
proxy_GOFPE(GL_CLIP_PLANE5, plane[5], fpe_changeplane(5, enable));
// lights
proxy_GOFPE(GL_LIGHT0, light[0], fpe_changelight(0, enable));
proxy_GOFPE(GL_LIGHT1, light[1], fpe_changelight(1, enable));
proxy_GOFPE(GL_LIGHT2, light[2], fpe_changelight(2, enable));
proxy_GOFPE(GL_LIGHT3, light[3], fpe_changelight(3, enable));
proxy_GOFPE(GL_LIGHT4, light[4], fpe_changelight(4, enable));
proxy_GOFPE(GL_LIGHT5, light[5], fpe_changelight(5, enable));
proxy_GOFPE(GL_LIGHT6, light[6], fpe_changelight(6, enable));
proxy_GOFPE(GL_LIGHT7, light[7], fpe_changelight(7, enable));
proxy_GOFPE(GL_LIGHTING, lighting, glstate->fpe_state->lighting=enable);
proxy_GOFPE(GL_NORMALIZE, normalize, glstate->fpe_state->normalize=enable);
proxy_GOFPE(GL_RESCALE_NORMAL, normal_rescale, glstate->fpe_state->rescaling=enable);
proxy_GOFPE(GL_COLOR_MATERIAL, color_material, glstate->fpe_state->color_material=enable);
// point sprite
proxy_GOFPE(GL_POINT_SPRITE, pointsprite, glstate->fpe_state->pointsprite=enable); // TODO: plugin fpe stuffs
proxy_GO(GL_PROGRAM_POINT_SIZE, point_size);
// Smooth and multisample (todo: do somthing with fpe?)
proxy_GOFPE(GL_MULTISAMPLE, multisample, );
proxy_GOFPE(GL_SAMPLE_COVERAGE, sample_coverage, );
proxy_GOFPE(GL_SAMPLE_ALPHA_TO_COVERAGE, sample_alpha_to_coverage, );
proxy_GOFPE(GL_SAMPLE_ALPHA_TO_ONE, sample_alpha_to_one, );
proxy_GOFPE(GL_POINT_SMOOTH, point_smooth, );
proxy_GOFPE(GL_LINE_SMOOTH, line_smooth, );
proxy_GO(GL_POLYGON_OFFSET_FILL, polyfill_offset);
// color logic op
proxy_GOFPE(GL_COLOR_LOGIC_OP, color_logic_op, );
// Secondary color
GOFPE(GL_COLOR_SUM, color_sum, glstate->fpe_state->colorsum = enable);
//cannot use clientGO_proxyFPE here, has the ClientArray are really enabled / disabled elsewhere in fact (inside glDraw or list_draw)
clientGO(GL_SECONDARY_COLOR_ARRAY, vertexattrib[ATT_SECONDARY].enabled);
clientGO(GL_FOG_COORD_ARRAY, vertexattrib[ATT_FOGCOORD].enabled);
// for glDrawArrays
clientGO(GL_VERTEX_ARRAY, vertexattrib[ATT_VERTEX].enabled);
clientGO(GL_NORMAL_ARRAY, vertexattrib[ATT_NORMAL].enabled);
clientGO(GL_COLOR_ARRAY, vertexattrib[ATT_COLOR].enabled);
case GL_TEXTURE_COORD_ARRAY: change_vao_texcoord(glstate->texture.client, enable); break;
// map eval
GONF(GL_MAP1_COLOR_4 , map1_color4);
GONF(GL_MAP1_INDEX , map1_index);
GONF(GL_MAP1_NORMAL , map1_normal);
GONF(GL_MAP1_TEXTURE_COORD_1 , map1_texture1);
GONF(GL_MAP1_TEXTURE_COORD_2 , map1_texture2);
GONF(GL_MAP1_TEXTURE_COORD_3 , map1_texture3);
GONF(GL_MAP1_TEXTURE_COORD_4 , map1_texture4);
GONF(GL_MAP1_VERTEX_3 , map1_vertex3);
GONF(GL_MAP1_VERTEX_4 , map1_vertex4);
GONF(GL_MAP2_COLOR_4 , map2_color4);
GONF(GL_MAP2_INDEX , map2_index);
GONF(GL_MAP2_NORMAL , map2_normal);
GONF(GL_MAP2_TEXTURE_COORD_1 , map2_texture1);
GONF(GL_MAP2_TEXTURE_COORD_2 , map2_texture2);
GONF(GL_MAP2_TEXTURE_COORD_3 , map2_texture3);
GONF(GL_MAP2_TEXTURE_COORD_4 , map2_texture4);
GONF(GL_MAP2_VERTEX_3 , map2_vertex3);
GONF(GL_MAP2_VERTEX_4 , map2_vertex4);
// ARB_vertex_program
proxy_GOFPE(GL_VERTEX_PROGRAM_ARB, vertex_arb, glstate->fpe_state->vertex_prg_enable=enable);
GONF(GL_VERTEX_PROGRAM_TWO_SIDE_ARB, vertex_two_side_arb);
// ARB_fragment_program
proxy_GOFPE(GL_FRAGMENT_PROGRAM_ARB, fragment_arb, glstate->fpe_state->fragment_prg_enable=enable);
// Texture 1D and 3D
case GL_TEXTURE_1D:
FLUSH_BEGINEND;
if(enable)
glstate->enable.texture[glstate->texture.active] |= (1<<ENABLED_TEX1D);
else
glstate->enable.texture[glstate->texture.active] &= ~(1<<ENABLED_TEX1D);
gl_changetex(glstate->texture.active);
if(glstate->fpe_state)
fpe_changetex(glstate->texture.active);
break;
case GL_TEXTURE_2D:
if(glstate->list.pending && ((glstate->enable.texture[glstate->texture.active]>>ENABLED_TEX2D)&1)!=enable) gl4es_flush();
if(enable == ((glstate->enable.texture[glstate->texture.active]>>ENABLED_TEX2D)&1))
return; // no change
if(enable)
glstate->enable.texture[glstate->texture.active] |= (1<<ENABLED_TEX2D);
else
glstate->enable.texture[glstate->texture.active] &= ~(1<<ENABLED_TEX2D);
gl_changetex(glstate->texture.active);
if(glstate->fpe_state)
fpe_changetex(glstate->texture.active);
else {
realize_active();
next(cap);
}
break;
case GL_TEXTURE_3D:
FLUSH_BEGINEND;
if(enable)
glstate->enable.texture[glstate->texture.active] |= (1<<ENABLED_TEX3D);
else
glstate->enable.texture[glstate->texture.active] &= ~(1<<ENABLED_TEX3D);
gl_changetex(glstate->texture.active);
if(glstate->fpe_state)
fpe_changetex(glstate->texture.active);
break;
case GL_TEXTURE_RECTANGLE_ARB:
FLUSH_BEGINEND;
if(enable)
glstate->enable.texture[glstate->texture.active] |= (1<<ENABLED_TEXTURE_RECTANGLE);
else
glstate->enable.texture[glstate->texture.active] &= ~(1<<ENABLED_TEXTURE_RECTANGLE);
gl_changetex(glstate->texture.active);
if(glstate->fpe_state)
fpe_changetex(glstate->texture.active);
break;
case GL_TEXTURE_CUBE_MAP:
FLUSH_BEGINEND;
if(enable)
glstate->enable.texture[glstate->texture.active] |= (1<<ENABLED_CUBE_MAP);
else
glstate->enable.texture[glstate->texture.active] &= ~(1<<ENABLED_CUBE_MAP);
gl_changetex(glstate->texture.active);
if(glstate->fpe_state)
fpe_changetex(glstate->texture.active);
else {
realize_active();
next(cap);
}
break;
default: errorGL(); FLUSH_BEGINEND; realize_active(); next(cap); break;
}
#undef proxy_GO
#undef GO
#undef proxy_clientGO
#undef clientGO
}
void APIENTRY_GL4ES gl4es_glEnable(GLenum cap) {
DBG(printf("glEnable(%s), glstate->list.pending=%d\n", PrintEnum(cap), glstate->list.pending);)
if(!glstate->list.pending) {
PUSH_IF_COMPILING(glEnable)
}
#ifdef TEXSTREAM00
if (globals4es.texstream && (cap==GL_TEXTURE_2D)) {
if (glstate->texture.bound[glstate->texture.active][ENABLED_TEX2D]->streamed)
cap = GL_TEXTURE_STREAM_IMG;
}
if (globals4es.texstream && (cap==GL_TEXTURE_RECTANGLE_ARB)) {
if (glstate->texture.bound[glstate->texture.active][ENABLED_TEXTURE_RECTANGLE]->streamed)
cap = GL_TEXTURE_STREAM_IMG;
}
#endif
LOAD_GLES(glEnable);
proxy_glEnable(cap, true, gles_glEnable);
}
AliasExport(void,glEnable,,(GLenum cap));
void APIENTRY_GL4ES gl4es_glDisable(GLenum cap) {
DBG(printf("glDisable(%s), glstate->list.pending=%d\n", PrintEnum(cap), glstate->list.pending);)
if(!glstate->list.pending) {
PUSH_IF_COMPILING(glDisable)
}
#ifdef TEXSTREAM00
if (globals4es.texstream && (cap==GL_TEXTURE_2D)) {
if (glstate->texture.bound[glstate->texture.active][ENABLED_TEX2D]->streamed)
cap = GL_TEXTURE_STREAM_IMG;
}
if (globals4es.texstream && (cap==GL_TEXTURE_RECTANGLE_ARB)) {
if (glstate->texture.bound[glstate->texture.active][ENABLED_TEXTURE_RECTANGLE]->streamed)
cap = GL_TEXTURE_STREAM_IMG;
}
#endif
LOAD_GLES(glDisable);
proxy_glEnable(cap, false, gles_glDisable);
}
AliasExport(void,glDisable,,(GLenum cap));
void APIENTRY_GL4ES gl4es_glEnableClientState(GLenum cap) {
DBG(printf("glEnableClientState(%s), list.begin=%dn", PrintEnum(cap), glstate->list.begin);)
ERROR_IN_BEGIN
// should flush for now... to be optimized later!
/*if (glstate->list.active && !glstate->list.compiling && !glstate->list.pending)
gl4es_flush();*/
proxy_glEnable(cap, true, fpe_glEnableClientState);
}
AliasExport(void,glEnableClientState,,(GLenum cap));
void APIENTRY_GL4ES gl4es_glDisableClientState(GLenum cap) {
DBG(printf("glDisableClientState(%s), list.begin=%d\n", PrintEnum(cap), glstate->list.begin);)
ERROR_IN_BEGIN
// should flush for now... to be optimized later!
/*if (glstate->list.active && !glstate->list.compiling && !glstate->list.pending)
gl4es_flush();*/
proxy_glEnable(cap, false, fpe_glDisableClientState);
}
AliasExport(void,glDisableClientState,,(GLenum cap));
#define isenabled(what, where) \
case what: return glstate->enable.where
#define clientisenabled(what, where) \
case what: return glstate->vao->where
GLboolean APIENTRY_GL4ES gl4es_glIsEnabled(GLenum cap) {
DBG(printf("glIsEnabed(%s), list.begin=%d, list.compiling=%d, list.pending=%d\n", PrintEnum(cap), glstate->list.begin, glstate->list.compiling, glstate->list.pending);)
if(glstate->list.begin) {errorShim(GL_INVALID_OPERATION); return GL_FALSE;}
if(glstate->list.compiling) {errorShim(GL_INVALID_OPERATION); return GL_FALSE;}
// should flush for now... but no need if it's just a pending list...
if (glstate->list.active && !glstate->list.pending)
gl4es_flush();
LOAD_GLES(glIsEnabled);
noerrorShim();
switch (cap) {
isenabled(GL_AUTO_NORMAL, auto_normal);
isenabled(GL_ALPHA_TEST, alpha_test);
isenabled(GL_FOG, fog);
isenabled(GL_BLEND, blend);
isenabled(GL_CULL_FACE, cull_face);
isenabled(GL_DEPTH_TEST, depth_test);
isenabled(GL_STENCIL_TEST, stencil_test);
isenabled(GL_LINE_STIPPLE, line_stipple);
isenabled(GL_TEXTURE_GEN_S, texgen_s[glstate->texture.active]);
isenabled(GL_TEXTURE_GEN_T, texgen_t[glstate->texture.active]);
isenabled(GL_TEXTURE_GEN_R, texgen_r[glstate->texture.active]);
isenabled(GL_TEXTURE_GEN_Q, texgen_q[glstate->texture.active]);
isenabled(GL_COLOR_MATERIAL, color_material);
isenabled(GL_COLOR_SUM, color_sum);
isenabled(GL_POINT_SPRITE, pointsprite);
isenabled(GL_PROGRAM_POINT_SIZE, point_size);
isenabled(GL_CLIP_PLANE0, plane[0]);
isenabled(GL_CLIP_PLANE1, plane[1]);
isenabled(GL_CLIP_PLANE2, plane[2]);
isenabled(GL_CLIP_PLANE3, plane[3]);
isenabled(GL_CLIP_PLANE4, plane[4]);
isenabled(GL_CLIP_PLANE5, plane[5]);
isenabled(GL_LIGHT0, light[0]);
isenabled(GL_LIGHT1, light[1]);
isenabled(GL_LIGHT2, light[2]);
isenabled(GL_LIGHT3, light[3]);
isenabled(GL_LIGHT4, light[4]);
isenabled(GL_LIGHT5, light[5]);
isenabled(GL_LIGHT6, light[6]);
isenabled(GL_LIGHT7, light[7]);
isenabled(GL_LIGHTING, lighting);
isenabled(GL_MULTISAMPLE, multisample);
isenabled(GL_SAMPLE_COVERAGE, sample_coverage);
isenabled(GL_SAMPLE_ALPHA_TO_COVERAGE, sample_alpha_to_coverage);
isenabled(GL_SAMPLE_ALPHA_TO_ONE, sample_alpha_to_one);
isenabled(GL_POINT_SMOOTH, point_smooth);
isenabled(GL_LINE_SMOOTH, line_smooth);
isenabled(GL_POLYGON_OFFSET_FILL, polyfill_offset);
isenabled(GL_COLOR_LOGIC_OP, color_logic_op);
clientisenabled(GL_SECONDARY_COLOR_ARRAY, vertexattrib[ATT_SECONDARY].enabled);
clientisenabled(GL_FOG_COORD_ARRAY, vertexattrib[ATT_FOGCOORD].enabled);
case GL_TEXTURE_1D: return glstate->enable.texture[glstate->texture.active]&(1<<ENABLED_TEX1D);
case GL_TEXTURE_2D: return glstate->enable.texture[glstate->texture.active]&(1<<ENABLED_TEX2D);
case GL_TEXTURE_3D: return glstate->enable.texture[glstate->texture.active]&(1<<ENABLED_TEX3D);
case GL_TEXTURE_CUBE_MAP: return glstate->enable.texture[glstate->texture.active]&(1<<ENABLED_CUBE_MAP);
clientisenabled(GL_VERTEX_ARRAY, vertexattrib[ATT_VERTEX].enabled);
clientisenabled(GL_NORMAL_ARRAY, vertexattrib[ATT_NORMAL].enabled);
clientisenabled(GL_COLOR_ARRAY, vertexattrib[ATT_COLOR].enabled);
clientisenabled(GL_TEXTURE_COORD_ARRAY, vertexattrib[ATT_MULTITEXCOORD0+glstate->texture.client].enabled);
isenabled(GL_NORMALIZE, normalize);
isenabled(GL_RESCALE_NORMAL, normal_rescale);
isenabled(GL_MAP1_COLOR_4, map1_color4);
isenabled(GL_MAP1_INDEX, map1_index);
isenabled(GL_MAP1_NORMAL, map1_normal);
isenabled(GL_MAP1_TEXTURE_COORD_1, map1_texture1);
isenabled(GL_MAP1_TEXTURE_COORD_2, map1_texture2);
isenabled(GL_MAP1_TEXTURE_COORD_3, map1_texture3);
isenabled(GL_MAP1_TEXTURE_COORD_4, map1_texture4);
isenabled(GL_MAP1_VERTEX_3, map1_vertex3);
isenabled(GL_MAP1_VERTEX_4, map1_vertex4);
isenabled(GL_MAP2_COLOR_4, map2_color4);
isenabled(GL_MAP2_INDEX, map2_index);
isenabled(GL_MAP2_NORMAL, map2_normal);
isenabled(GL_MAP2_TEXTURE_COORD_1, map2_texture1);
isenabled(GL_MAP2_TEXTURE_COORD_2, map2_texture2);
isenabled(GL_MAP2_TEXTURE_COORD_3, map2_texture3);
isenabled(GL_MAP2_TEXTURE_COORD_4, map2_texture4);
isenabled(GL_MAP2_VERTEX_3, map2_vertex3);
isenabled(GL_MAP2_VERTEX_4, map2_vertex4);
// ARB_vertex_program
isenabled(GL_VERTEX_PROGRAM_ARB, vertex_arb);
isenabled(GL_VERTEX_PROGRAM_TWO_SIDE_ARB, vertex_two_side_arb);
default:
errorGL();
return gles_glIsEnabled(cap);
}
}
#undef isenabled
#undef clientisenabled
AliasExport(GLboolean,glIsEnabled,,(GLenum cap));
+171
View File
@@ -0,0 +1,171 @@
#ifndef _GL4ES_ENUM_INFO_H
#define _GL4ES_ENUM_INFO_H
#include <stdbool.h>
#include "const.h"
#include "debug.h"
#include "logs.h"
static const GLsizei gl_sizeof(GLenum type) {
// types
switch (type) {
case GL_DOUBLE:
return 8;
case GL_FLOAT:
case GL_INT:
case GL_UNSIGNED_INT:
case GL_UNSIGNED_INT_10_10_10_2:
case GL_UNSIGNED_INT_2_10_10_10_REV:
case GL_UNSIGNED_INT_8_8_8_8:
case GL_UNSIGNED_INT_8_8_8_8_REV:
case GL_UNSIGNED_INT_24_8:
case GL_4_BYTES:
return 4;
case GL_3_BYTES:
return 3;
case GL_LUMINANCE_ALPHA:
case GL_SHORT:
case GL_HALF_FLOAT:
case GL_HALF_FLOAT_OES:
case GL_UNSIGNED_SHORT:
case GL_UNSIGNED_SHORT_1_5_5_5_REV:
case GL_UNSIGNED_SHORT_4_4_4_4:
case GL_UNSIGNED_SHORT_4_4_4_4_REV:
case GL_UNSIGNED_SHORT_5_5_5_1:
case GL_UNSIGNED_SHORT_5_6_5:
case GL_UNSIGNED_SHORT_5_6_5_REV:
case GL_2_BYTES:
return 2;
case GL_ALPHA:
case GL_LUMINANCE:
case GL_BYTE:
case GL_UNSIGNED_BYTE:
case GL_UNSIGNED_BYTE_2_3_3_REV:
case GL_UNSIGNED_BYTE_3_3_2:
case GL_DEPTH_COMPONENT:
case GL_COLOR_INDEX:
return 1;
}
// formats
LOGD("Unsupported pixel data type: %s\n", PrintEnum(type));
return 0;
}
static const GLuint gl_max_value(GLenum type) {
switch (type) {
// float/double only make sense on tex/color
// be careful about using this
case GL_DOUBLE:
case GL_FLOAT:
case GL_HALF_FLOAT:
case GL_HALF_FLOAT_OES:
return 1;
case GL_BYTE: return 127;
case GL_UNSIGNED_BYTE: return 255;
case GL_SHORT: return 32767;
case GL_UNSIGNED_SHORT: return 65535;
case GL_INT: return 2147483647;
case GL_UNSIGNED_INT: return 4294967295;
}
LOGD("unknown gl max value type: %s\n", PrintEnum(type));
return 0;
}
static const GLboolean is_type_packed(GLenum type) {
switch (type) {
case GL_4_BYTES:
case GL_3_BYTES:
case GL_2_BYTES:
case GL_UNSIGNED_BYTE_2_3_3_REV:
case GL_UNSIGNED_BYTE_3_3_2:
case GL_UNSIGNED_INT_10_10_10_2:
case GL_UNSIGNED_INT_2_10_10_10_REV:
case GL_UNSIGNED_INT_8_8_8_8:
case GL_UNSIGNED_INT_8_8_8_8_REV:
case GL_UNSIGNED_SHORT_1_5_5_5_REV:
case GL_UNSIGNED_SHORT_4_4_4_4:
case GL_UNSIGNED_SHORT_4_4_4_4_REV:
case GL_UNSIGNED_SHORT_5_5_5_1:
case GL_UNSIGNED_SHORT_5_6_5:
case GL_UNSIGNED_SHORT_5_6_5_REV:
case GL_DEPTH_STENCIL:
return true;
}
return false;
}
static const GLsizei pixel_sizeof(GLenum format, GLenum type) {
GLsizei width = 0;
switch (format) {
case GL_R:
case GL_RED:
case GL_ALPHA:
case GL_LUMINANCE:
case GL_DEPTH_COMPONENT:
case GL_DEPTH_STENCIL:
case GL_COLOR_INDEX:
width = 1;
break;
case GL_RG:
case GL_LUMINANCE_ALPHA:
width = 2;
break;
case GL_RGB:
case GL_BGR:
case GL_RGB8:
width = 3;
break;
case GL_RGBA:
case GL_BGRA:
case GL_RGBA8:
width = 4;
break;
default:
LOGD("unsupported pixel format %s\n", PrintEnum(format));
return 0;
}
if (is_type_packed(type))
width = 1;
return width * gl_sizeof(type);
}
static const GLboolean pixel_hasalpha(GLenum format) {
switch (format) {
case GL_ALPHA:
case GL_LUMINANCE_ALPHA:
case GL_RGBA:
case GL_BGRA:
case GL_RGBA8:
case GL_COLOR_INDEX:
return true;
case GL_RED:
case GL_LUMINANCE:
case GL_RG:
case GL_RGB:
case GL_BGR:
case GL_RGB8:
case GL_DEPTH_COMPONENT:
case GL_DEPTH_STENCIL:
return false;
default:
return true;
}
}
static inline const GLboolean valid_vertex_type(GLenum type) {
switch (type) {
case GL_UNSIGNED_BYTE:
case GL_BYTE:
case GL_FIXED:
case GL_FLOAT:
case GL_SHORT:
return true;
default:
return false;
}
}
#endif // _GL4ES_ENUM_INFO_H
+80
View File
@@ -0,0 +1,80 @@
#include "envvars.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
//----------------------------------------------------------------------------
const char* GetEnvVar(const char *name)
{
return getenv(name);
}
//----------------------------------------------------------------------------
int HasEnvVar(const char *name)
{
return GetEnvVar(name)!=NULL;
}
//----------------------------------------------------------------------------
int ReturnEnvVarInt(const char *name)
{
const char *s=GetEnvVar(name);
return s ? atoi(s) : 0;
}
//----------------------------------------------------------------------------
int ReturnEnvVarIntDef(const char *name,int def)
{
const char *s=GetEnvVar(name);
return s ? atoi(s) : def;
}
//----------------------------------------------------------------------------
int IsEnvVarTrue(const char *name)
{
const char *s=GetEnvVar(name);
return s && atoi(s)!=0;
}
//----------------------------------------------------------------------------
int IsEnvVarFalse(const char *name)
{
const char *s=GetEnvVar(name);
return s && *s=='0';
}
//----------------------------------------------------------------------------
int IsEnvVarInt(const char *name,int i)
{
const char *s=GetEnvVar(name);
return s && atoi(s)==i;
}
//----------------------------------------------------------------------------
int GetEnvVarInt(const char *name,int *i,int def)
{
const char *s=GetEnvVar(name);
*i=s ? atoi(s) : def;
return s!=NULL;
}
//----------------------------------------------------------------------------
int GetEnvVarBool(const char *name,int *b,int def)
{
const char *s=GetEnvVar(name);
*b=s ? atoi(s) : def;
if(*b) *b=1;
return s!=NULL;
}
//----------------------------------------------------------------------------
int GetEnvVarFloat(const char *name,float *f,float def)
{
const char *s=GetEnvVar(name);
*f=s ? atof(s) : def;
return s!=NULL;
}
//----------------------------------------------------------------------------
int GetEnvVarFmt(const char *name,const char *fmt,...)
{
int cnt=0;
const char *s=GetEnvVar(name);
if(s) {
va_list args;
va_start(args,fmt);
cnt=vsscanf(s,fmt,args);
va_end(args);
}
return cnt;
}
//----------------------------------------------------------------------------
+20
View File
@@ -0,0 +1,20 @@
#ifndef _GL4ES_ENVVARS_H_
#define _GL4ES_ENVVARS_H_
//----------------------------------------------------------------------------
const char* GetEnvVar(const char *name);
//----------------------------------------------------------------------------
int HasEnvVar(const char *name);
int ReturnEnvVarInt(const char *name);
int ReturnEnvVarIntDef(const char *name,int def);
//----------------------------------------------------------------------------
int IsEnvVarTrue(const char *name);
int IsEnvVarFalse(const char *name);
int IsEnvVarInt(const char *name,int i);
//----------------------------------------------------------------------------
int GetEnvVarInt(const char *name,int *i,int def);
int GetEnvVarBool(const char *name,int *b,int def);
int GetEnvVarFloat(const char *name,float *f,float def);
//----------------------------------------------------------------------------
int GetEnvVarFmt(const char *name,const char *fmt,...);
//----------------------------------------------------------------------------
#endif
+370
View File
@@ -0,0 +1,370 @@
// TODO: glIsEnabled(), glGetMap()
// TODO: GL_AUTO_NORMAL
#include "eval.h"
#include "math/eval.h"
#include "wrap/gl4es.h"
#include "array.h"
#include "logs.h"
#include "matvec.h"
static inline map_state_t **get_map_pointer(GLenum target) {
switch (target) {
case GL_MAP1_COLOR_4: return &glstate->map1.color4;
case GL_MAP1_INDEX: return &glstate->map1.index;
case GL_MAP1_TEXTURE_COORD_1: return &glstate->map1.texture1;
case GL_MAP1_TEXTURE_COORD_2: return &glstate->map1.texture2;
case GL_MAP1_TEXTURE_COORD_3: return &glstate->map1.texture3;
case GL_MAP1_TEXTURE_COORD_4: return &glstate->map1.texture4;
case GL_MAP1_VERTEX_3: return &glstate->map1.vertex3;
case GL_MAP1_VERTEX_4: return &glstate->map1.vertex4;
case GL_MAP2_COLOR_4: return &glstate->map2.color4;
case GL_MAP2_INDEX: return &glstate->map2.index;
case GL_MAP2_TEXTURE_COORD_1: return &glstate->map2.texture1;
case GL_MAP2_TEXTURE_COORD_2: return &glstate->map2.texture2;
case GL_MAP2_TEXTURE_COORD_3: return &glstate->map2.texture3;
case GL_MAP2_TEXTURE_COORD_4: return &glstate->map2.texture4;
case GL_MAP2_VERTEX_3: return &glstate->map2.vertex3;
case GL_MAP2_VERTEX_4: return &glstate->map2.vertex4;
default:
LOGE("unknown glMap target 0x%x\n", target);
}
return NULL;
}
#define set_map_coords(n) \
map->n._1 = n##1; \
map->n._2 = n##2; \
map->n.d = 1.0/(n##2 - n##1); \
map->n.order = n##order;
#define case_state(dims, magic, name) \
case magic: { \
map->width = get_map_width(magic); \
map_statef_t *m = (map_statef_t *)glstate->map##dims.name; \
if (m) { \
free((void *)m->points); \
free(m); \
} \
glstate->map##dims.name = (map_state_t *)map; \
break; \
}
#define map_switch(dims) \
switch (target) { \
case_state(dims, GL_MAP##dims##_COLOR_4, color4); \
case_state(dims, GL_MAP##dims##_INDEX, index); \
case_state(dims, GL_MAP##dims##_NORMAL, normal); \
case_state(dims, GL_MAP##dims##_TEXTURE_COORD_1, texture1); \
case_state(dims, GL_MAP##dims##_TEXTURE_COORD_2, texture2); \
case_state(dims, GL_MAP##dims##_TEXTURE_COORD_3, texture3); \
case_state(dims, GL_MAP##dims##_TEXTURE_COORD_4, texture4); \
case_state(dims, GL_MAP##dims##_VERTEX_3, vertex3); \
case_state(dims, GL_MAP##dims##_VERTEX_4, vertex4); \
}
void APIENTRY_GL4ES gl4es_glMap1d(GLenum target, GLdouble u1, GLdouble u2,
GLint ustride, GLint uorder, const GLdouble *points) {
noerrorShim();
map_statef_t *map = malloc(sizeof(map_statef_t));
map->type = GL_FLOAT; map->dims = 1;
set_map_coords(u);
map_switch(1);
map->points = copy_eval_double1(target, ustride, uorder, points);
}
void APIENTRY_GL4ES gl4es_glMap1f(GLenum target, GLfloat u1, GLfloat u2,
GLint ustride, GLint uorder, const GLfloat *points) {
noerrorShim();
map_statef_t *map = malloc(sizeof(map_statef_t));
map->type = GL_FLOAT; map->dims = 1;
set_map_coords(u);
map_switch(1);
map->points = copy_eval_float1(target, ustride, uorder, points);
}
void APIENTRY_GL4ES gl4es_glMap2d(GLenum target, GLdouble u1, GLdouble u2,
GLint ustride, GLint uorder, GLdouble v1, GLdouble v2,
GLint vstride, GLint vorder, const GLdouble *points) {
noerrorShim();
map_statef_t *map = malloc(sizeof(map_statef_t));
map->type = GL_FLOAT; map->dims = 2;
set_map_coords(u);
set_map_coords(v);
map_switch(2);
map->points = copy_eval_double2(target, ustride, uorder, vstride, vorder, points);
}
void APIENTRY_GL4ES gl4es_glMap2f(GLenum target, GLfloat u1, GLfloat u2,
GLint ustride, GLint uorder, GLfloat v1, GLfloat v2,
GLint vstride, GLint vorder, const GLfloat *points) {
noerrorShim();
map_statef_t *map = malloc(sizeof(map_statef_t));
map->type = GL_FLOAT; map->dims = 2;
set_map_coords(u);
set_map_coords(v);
map_switch(2);
map->points = copy_eval_float2(target, ustride, uorder, vstride, vorder, points);;
}
#undef set_map_coords
#undef case_state
#undef map_switch
#define p_map(d, name, func, code) \
if (glstate->map##d.name && glstate->enable.map##d##_##name) { \
map_state_t *_map = glstate->map##d.name; \
if (_map->type == GL_DOUBLE) { \
map_stated_t *map = (map_stated_t *)_map; \
LOGE("double: not implemented\n"); \
} else if (_map->type == GL_FLOAT) { \
map_statef_t *map = (map_statef_t *)_map; \
code \
gl4es_##func##v(out); \
} \
}
#define iter_maps(d, code) \
p_map(d, color4, glColor4f, code); \
p_map(d, index, glIndexf, code); \
if(!glstate->enable.auto_normal) \
p_map(d, normal, glNormal3f, code); \
p_map(d, texture4, glTexCoord4f, code) \
else \
p_map(d, texture3, glTexCoord3f, code) \
else \
p_map(d, texture2, glTexCoord2f, code) \
else \
p_map(d, texture1, glTexCoord1f, code); \
p_map(d, vertex4, glVertex4f, code) \
else \
p_map(d, vertex3, glVertex3f, code);
void APIENTRY_GL4ES gl4es_glEvalCoord1f(GLfloat u) {
noerrorShim();
GLfloat out[4]; \
iter_maps(1,
GLfloat uu = (u - map->u._1) * map->u.d;
_math_horner_bezier_curve((GLfloat*)map->points, out, uu, map->width, map->u.order);
)
}
void APIENTRY_GL4ES gl4es_glEvalCoord2f(GLfloat u, GLfloat v) {
noerrorShim();
GLfloat out[4]; \
iter_maps(2,
GLfloat uu = (u - map->u._1) * map->u.d;
GLfloat vv = (v - map->v._1) * map->v.d;
if(glstate->enable.auto_normal && (map == (map_statef_t *)glstate->map2.vertex3 || map == (map_statef_t *)glstate->map2.vertex4)) {
GLfloat norm[3];
GLfloat du[4];
GLfloat dv[4];
memset(out, 0, 3*sizeof(GLfloat)); out[3] = 1.0f;
_math_de_casteljau_surf((GLfloat*)map->points, out, du, dv, uu, vv,
map->width, map->u.order, map->v.order);
if(map->width == 4) {
du[0] = du[0]*out[3] - du[3]*out[0];
du[1] = du[1]*out[3] - du[3]*out[1];
du[2] = du[2]*out[3] - du[3]*out[2];
dv[0] = dv[0]*out[3] - dv[3]*out[0];
dv[1] = dv[1]*out[3] - dv[3]*out[1];
dv[2] = dv[2]*out[3] - dv[3]*out[2];
}
cross3(du, dv, norm);
vector_normalize(norm);
gl4es_glNormal3fv(norm);
} else
_math_horner_bezier_surf((GLfloat*)map->points, out, uu, vv,
map->width, map->u.order, map->v.order);
)
}
#undef p_map
#undef iter_maps
void APIENTRY_GL4ES gl4es_glMapGrid1f(GLint un, GLfloat u1, GLfloat u2) {
if(un<1) {
errorShim(GL_INVALID_VALUE);
return;
}
if(glstate->list.begin) {
errorShim(GL_INVALID_OPERATION);
return;
}
noerrorShim();
glstate->map_grid[0].n = un;
glstate->map_grid[0]._1 = u1;
glstate->map_grid[0]._2 = u2;
}
void APIENTRY_GL4ES gl4es_glMapGrid2f(GLint un, GLfloat u1, GLfloat u2,
GLint vn, GLfloat v1, GLfloat v2) {
if((un<1) || (vn<1)) {
errorShim(GL_INVALID_VALUE);
return;
}
if(glstate->list.begin) {
errorShim(GL_INVALID_OPERATION);
return;
}
noerrorShim();
glstate->map_grid[0].n = un;
glstate->map_grid[0]._1 = u1;
glstate->map_grid[0]._2 = u2;
glstate->map_grid[0].d = (glstate->map_grid[0]._2 - glstate->map_grid[0]._1)/glstate->map_grid[0].n;
glstate->map_grid[1].n = vn;
glstate->map_grid[1]._1 = v1;
glstate->map_grid[1]._2 = v2;
glstate->map_grid[1].d = (glstate->map_grid[1]._2 - glstate->map_grid[1]._1)/glstate->map_grid[1].n;
}
static inline GLenum eval_mesh_prep(GLenum mode) {
if ((!glstate->map2.vertex4) && (!glstate->map2.vertex3)) {
return 0;
}
switch (mode) {
case GL_POINT: return GL_POINTS;
case GL_LINE: return GL_LINE_STRIP;
case GL_FILL: return GL_TRIANGLE_STRIP;
case 0: return 1;
default:
LOGE("unknown glEvalMesh mode: %x\n", mode);
return 0;
}
}
void APIENTRY_GL4ES gl4es_glEvalMesh1(GLenum mode, GLint i1, GLint i2) {
GLenum renderMode = eval_mesh_prep(mode);
if (! renderMode) {
errorShim(GL_INVALID_ENUM);
return;
}
noerrorShim();
GLfloat u, du, u1;
du = glstate->map_grid[0].d;
u1 = glstate->map_grid[0]._1 + du*i1;
GLint i;
gl4es_glBegin(renderMode);
for (u = u1, i = i1; i <= i2; i++, u += du) {
gl4es_glEvalCoord1f(u);
}
gl4es_glEnd();
}
void APIENTRY_GL4ES gl4es_glEvalMesh2(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2) {
GLenum renderMode = eval_mesh_prep(mode);
if (! renderMode) {
errorShim(GL_INVALID_ENUM);
return;
}
noerrorShim();
GLfloat u, du, u1, v, dv, v1;
du = glstate->map_grid[0].d;
dv = glstate->map_grid[1].d;
u1 = glstate->map_grid[0]._1 + du*i1;
v1 = glstate->map_grid[1]._1 + dv*j1;
GLint i, j;
if(mode==GL_FILL) {
for (v = v1, j = j1; j <= j2-1; j++, v += dv) {
gl4es_glBegin(renderMode);
for (u = u1, i = i1; i <= i2; i++, u += du) {
gl4es_glEvalCoord2f(u, v);
gl4es_glEvalCoord2f(u, v + dv);
}
gl4es_glEnd();
}
} else {
for (v = v1, j = j1; j <= j2; j++, v += dv) {
gl4es_glBegin(renderMode);
for (u = u1, i = i1; i <= i2; i++, u += du) {
gl4es_glEvalCoord2f(u, v);
}
gl4es_glEnd();
}
if (mode == GL_LINE) {
gl4es_glBegin(renderMode);
for (u = u1, i = i1; i <= i2; i++, u += du) {
for (v = v1, j = j1; j <= j2; j++, v += dv) {
gl4es_glEvalCoord2f(u, v);
}
}
gl4es_glEnd();
}
}
}
void APIENTRY_GL4ES gl4es_glEvalPoint1(GLint i) {
gl4es_glEvalCoord1f(glstate->map_grid[0]._1 + glstate->map_grid[0].d*i);
}
void APIENTRY_GL4ES gl4es_glEvalPoint2(GLint i, GLint j) {
gl4es_glEvalCoord2f(glstate->map_grid[0]._1 + glstate->map_grid[0].d*i, glstate->map_grid[1]._1 + glstate->map_grid[1].d*j);
}
#define GL_GET_MAP(t, type) \
void APIENTRY_GL4ES gl4es_glGetMap##t##v(GLenum target, GLenum query, type *v) { \
noerrorShim(); \
map_statef_t *map = *(map_statef_t **)get_map_pointer(target); \
if (map) { \
switch (query) { \
case GL_COEFF: { \
const GLfloat *points = map->points; \
for (int i = 0; i < map->u.order; i++) { \
if (map->dims == 2) { \
for (int j = 0; j < map->v.order; j++) { \
*v++ = *points++; \
} \
} else { \
*v++ = *points++; \
} \
} \
return; \
} \
case GL_ORDER: \
*v++ = map->u.order; \
if (map->dims == 2) \
*v++ = map->v.order; \
return; \
case GL_DOMAIN: \
*v++ = map->u._1; \
*v++ = map->u._2; \
if (map->dims == 2) { \
*v++ = map->u._1; \
*v++ = map->u._2; \
} \
return; \
} \
} \
}
GL_GET_MAP(i, GLint)
GL_GET_MAP(f, GLfloat)
GL_GET_MAP(d, GLdouble)
#undef GL_GET_MAP
//Direct wrapper
AliasExport_M(void,glMap1d,,(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points),32);
AliasExport(void,glMap1f,,(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points));
AliasExport_M(void,glMap2d,,(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points),56);
AliasExport(void,glMap2f,,(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points));
AliasExport(void,glEvalCoord1f,,(GLfloat u));
AliasExport(void,glEvalCoord2f,,(GLfloat u, GLfloat v));
AliasExport(void,glEvalMesh1,,(GLenum mode, GLint i1, GLint i2));
AliasExport(void,glEvalMesh2,,(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2));
AliasExport(void,glEvalPoint1,,(GLint i));
AliasExport(void,glEvalPoint2,,(GLint i, GLint j));
AliasExport(void,glMapGrid1f,,(GLint un, GLfloat u1, GLfloat u2));
AliasExport(void,glMapGrid2f,,(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2));
AliasExport(void,glGetMapdv,,(GLenum target, GLenum query, GLdouble *v));
AliasExport(void,glGetMapfv,,(GLenum target, GLenum query, GLfloat *v));
AliasExport(void,glGetMapiv,,(GLenum target, GLenum query, GLint *v));
+87
View File
@@ -0,0 +1,87 @@
#ifndef _GL4ES_EVAL_H_
#define _GL4ES_EVAL_H_
#include "const.h"
#include "gles.h"
void APIENTRY_GL4ES gl4es_glMap1d(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points);
void APIENTRY_GL4ES gl4es_glMap1f(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points);
void APIENTRY_GL4ES gl4es_glMap2d(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points);
void APIENTRY_GL4ES gl4es_glMap2f(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points);
void APIENTRY_GL4ES gl4es_glEvalCoord1d(GLdouble u);
void APIENTRY_GL4ES gl4es_glEvalCoord1f(GLfloat u);
void APIENTRY_GL4ES gl4es_glEvalCoord2d(GLdouble u, GLdouble v);
void APIENTRY_GL4ES gl4es_glEvalCoord2f(GLfloat u, GLfloat v);
void APIENTRY_GL4ES gl4es_glEvalMesh1(GLenum mode, GLint i1, GLint i2);
void APIENTRY_GL4ES gl4es_glEvalMesh2(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2);
void APIENTRY_GL4ES gl4es_glEvalPoint1(GLint i);
void APIENTRY_GL4ES gl4es_glEvalPoint2(GLint i, GLint j);
void APIENTRY_GL4ES gl4es_glMapGrid1d(GLint un, GLdouble u1, GLdouble u2);
void APIENTRY_GL4ES gl4es_glMapGrid1f(GLint un, GLfloat u1, GLfloat u2);
void APIENTRY_GL4ES gl4es_glMapGrid2d(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2);
void APIENTRY_GL4ES gl4es_glMapGrid2f(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2);
void APIENTRY_GL4ES gl4es_glGetMapdv(GLenum target, GLenum query, GLdouble *v);
void APIENTRY_GL4ES gl4es_glGetMapfv(GLenum target, GLenum query, GLfloat *v);
void APIENTRY_GL4ES gl4es_glGetMapiv(GLenum target, GLenum query, GLint *v);
typedef struct {
GLenum type;
} map_state_t;
typedef struct {
GLdouble _1, _2, d;
GLint order;
} mapcoordd_t;
typedef struct {
GLfloat _1, _2, d;
GLint order;
} mapcoordf_t;
typedef struct {
GLenum type;
GLint dims, width;
mapcoordd_t u, v;
const GLdouble *points;
} map_stated_t;
typedef struct {
GLenum type;
GLint dims, width;
mapcoordf_t u, v;
const GLfloat *points;
} map_statef_t;
typedef struct {
GLfloat _1, _2;
GLfloat d;
GLint n;
} map_grid_t;
static const GLsizei get_map_width(GLenum target) {
switch (target) {
case GL_MAP1_COLOR_4: return 4;
case GL_MAP1_INDEX: return 3;
case GL_MAP1_NORMAL: return 3;
case GL_MAP1_TEXTURE_COORD_1: return 1;
case GL_MAP1_TEXTURE_COORD_2: return 2;
case GL_MAP1_TEXTURE_COORD_3: return 3;
case GL_MAP1_TEXTURE_COORD_4: return 4;
case GL_MAP1_VERTEX_3: return 3;
case GL_MAP1_VERTEX_4: return 4;
case GL_MAP2_COLOR_4: return 4;
case GL_MAP2_INDEX: return 3;
case GL_MAP2_NORMAL: return 3;
case GL_MAP2_TEXTURE_COORD_1: return 1;
case GL_MAP2_TEXTURE_COORD_2: return 2;
case GL_MAP2_TEXTURE_COORD_3: return 3;
case GL_MAP2_TEXTURE_COORD_4: return 4;
case GL_MAP2_VERTEX_3: return 3;
case GL_MAP2_VERTEX_4: return 4;
}
return 0;
}
#endif // _GL4ES_EVAL_H_
+45
View File
@@ -0,0 +1,45 @@
#include "face.h"
#include "loader.h"
#include "gl4es.h"
#include "glstate.h"
void APIENTRY_GL4ES gl4es_glCullFace(GLenum mode) {
if(!glstate->list.pending)
PUSH_IF_COMPILING(glCullFace);
if(mode!=GL_FRONT && mode!=GL_BACK && mode!=GL_FRONT_AND_BACK) {
errorShim(GL_INVALID_ENUM);
return;
}
if(glstate->face.cull == mode) {
noerrorShim();
return;
}
FLUSH_BEGINEND;
glstate->face.cull = mode;
LOAD_GLES(glCullFace);
gles_glCullFace(mode);
}
void APIENTRY_GL4ES gl4es_glFrontFace(GLenum mode) {
if(!glstate->list.pending)
PUSH_IF_COMPILING(glFrontFace);
if(mode!=GL_CW && mode!=GL_CCW) {
errorShim(GL_INVALID_ENUM);
return;
}
if(glstate->face.front == mode) {
noerrorShim();
return;
}
FLUSH_BEGINEND;
glstate->face.front = mode;
LOAD_GLES(glFrontFace);
gles_glFrontFace(mode);
}
AliasExport(void,glCullFace,,(GLenum mode));
AliasExport(void,glFrontFace,,(GLenum mode));
+9
View File
@@ -0,0 +1,9 @@
#ifndef _GL4ES_FACE_H_
#define _GL4ES_FACE_H_
#include "gles.h"
void APIENTRY_GL4ES gl4es_glCullFace(GLenum mode);
void APIENTRY_GL4ES gl4es_glFrontFace(GLenum mode);
#endif // _GL4ES_FACE_H_
+118
View File
@@ -0,0 +1,118 @@
#include "fog.h"
#include "../glx/hardext.h"
#include "fpe.h"
#include "gl4es.h"
#include "glstate.h"
#include "loader.h"
#include "matrix.h"
#include "matvec.h"
void APIENTRY_GL4ES gl4es_glFogfv(GLenum pname, const GLfloat* params) {
if (glstate->list.active)
if (glstate->list.compiling) {
NewStage(glstate->list.active, STAGE_FOG);
rlFogOp(glstate->list.active, pname, params);
return;
}
else gl4es_flush();
noerrorShim();
#define GO(A,name, size) if(memcmp(A glstate->fog.name, params, size)==0) return; else memcpy(A glstate->fog.name, params, size);
#define GOI(name) if(glstate->fog.name==params[0]) return; else glstate->fog.name=params[0];
switch (pname) {
case GL_FOG_MODE:
GOI(mode)
break;
case GL_FOG_DENSITY:
if(*params<0.f) {
errorShim(GL_INVALID_VALUE);
return;
}
GO(&, density, sizeof(GLfloat))
break;
case GL_FOG_START:
GO(&, start, sizeof(GLfloat))
break;
case GL_FOG_END:
GO(&, end, sizeof(GLfloat))
break;
case GL_FOG_INDEX:
GO(&, index, sizeof(GLfloat))
return; // unsupported for now
case GL_FOG_COLOR:
#if defined(__GNUC__) && (__GNUC__ > 7)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstringop-overflow"
#endif
// GCC 8.1 warn about reading 16 bytes from a 4 bytes value, but params is not (in that case) a 4 bytes value
GO(, color, 4*sizeof(GLfloat))
#if defined(__GNUC__) && (__GNUC__ > 7)
#pragma GCC diagnostic pop
#endif
break;
case GL_FOG_COORD_SRC:
GOI(coord_src)
if(hardext.esversion==1)
return; // unsupported on GLES1.1
break;
case GL_FOG_DISTANCE_MODE_NV:
GOI(distance)
if(hardext.esversion==1)
return; // unsupported on GLES1.1
break;
default:
errorShim(GL_INVALID_ENUM);
return;
}
#undef GO
#undef GOI
LOAD_GLES_FPE(glFogfv);
gles_glFogfv(pname, params);
errorGL();
}
void APIENTRY_GL4ES gl4es_glFogf(GLenum pname, GLfloat param) {
gl4es_glFogfv(pname, &param);
}
void APIENTRY_GL4ES gl4es_glFogCoordd(GLdouble coord) {
gl4es_glFogCoordf(coord);
}
void APIENTRY_GL4ES gl4es_glFogCoorddv(const GLdouble *coord) {
gl4es_glFogCoordf(*coord);
}
void APIENTRY_GL4ES gl4es_glFogCoordfv(const GLfloat *coord) {
gl4es_glFogCoordf(*coord);
}
void APIENTRY_GL4ES gl4es_glFogCoordf(GLfloat coord) {
if (glstate->list.active) {
if(glstate->list.pending)
gl4es_flush();
else
{
rlFogCoordf(glstate->list.active, coord);
glstate->list.active->lastFogCoord = coord;
}
noerrorShim();
} else {
noerrorShim();
}
// change the state last thing
glstate->fogcoord[0] = coord;
}
AliasExport(void,glFogfv,,(GLenum pname, const GLfloat* params));
AliasExport(void,glFogf,,(GLenum pname, GLfloat param));
AliasExport_D(void,glFogCoordd,,(GLdouble coord));
AliasExport(void,glFogCoorddv,,(const GLdouble *coord));
AliasExport(void,glFogCoordf,,(GLfloat coord));
AliasExport(void,glFogCoordfv,,(const GLfloat *coord));
AliasExport(void,glFogfv,EXT,(GLenum pname, const GLfloat* params));
AliasExport(void,glFogf,EXT,(GLenum pname, GLfloat param));
AliasExport_D(void,glFogCoordd,EXT,(GLdouble coord));
AliasExport(void,glFogCoorddv,EXT,(const GLdouble *coord));
AliasExport(void,glFogCoordf,EXT,(GLfloat coord));
AliasExport(void,glFogCoordfv,EXT,(const GLfloat *coord));
+23
View File
@@ -0,0 +1,23 @@
#ifndef _GL4ES_FOG_H_
#define _GL4ES_FOG_H_
#include "gles.h"
typedef struct {
GLenum mode;
GLfloat density;
GLenum distance;
GLfloat start;
GLfloat end;
GLfloat index;
GLfloat color[4];
GLenum coord_src;
} fog_t;
void APIENTRY_GL4ES gl4es_glFogfv(GLenum pname, const GLfloat* params);
void APIENTRY_GL4ES gl4es_glFogf(GLenum pname, GLfloat param);
void APIENTRY_GL4ES gl4es_glFogCoordf(GLfloat coord);
void APIENTRY_GL4ES gl4es_glFogCoordfv(const GLfloat *coord);
#endif // _GL4ES_FOG_H_
File diff suppressed because it is too large Load Diff
+284
View File
@@ -0,0 +1,284 @@
#ifndef _GL4ES_FPE_H_
#define _GL4ES_FPE_H_
/*
This is the FPE : Fixed Pipeline Emulator
It task is to create a shader that emulate the fixed pipeline.
So based on the current GL State, it will either take a shader from the cache or create a new one
For conveniance, the relevant GL states element are condenced in a bitfield packed fpe_state_t structure
*/
#include "gles.h"
#include "program.h"
#define FPE_FOG_EXP 0
#define FPE_FOG_EXP2 1
#define FPE_FOG_LINEAR 2
#define FPE_FOG_SRC_DEPTH 0
#define FPE_FOG_SRC_COORD 1
#define FPE_FOG_DIST_PLANE_ABS 0
#define FPE_FOG_DIST_PLANE 1
#define FPE_FOG_DIST_RADIAL 2
#define FPE_TEX_OFF 0
#define FPE_TEX_2D 1
#define FPE_TEX_RECT 2
#define FPE_TEX_3D 3
#define FPE_TEX_CUBE 4
#define FPE_TEX_STRM 5
#define FPE_ALWAYS 0
#define FPE_NEVER 1
#define FPE_LESS 2
#define FPE_EQUAL 3
#define FPE_LEQUAL 4
#define FPE_GREATER 5
#define FPE_NOTEQUAL 6
#define FPE_GEQUAL 7
#define FPE_CM_AMBIENTDIFFUSE 0
#define FPE_CM_EMISSION 1
#define FPE_CM_AMBIENT 2
#define FPE_CM_DIFFUSE 3
#define FPE_CM_SPECULAR 4
#define FPE_MODULATE 0
#define FPE_ADD 1
#define FPE_DECAL 2
#define FPE_BLEND 3
#define FPE_REPLACE 4
#define FPE_COMBINE 5
#define FPE_COMBINE4 6
#define FPE_CR_REPLACE 0
#define FPE_CR_MODULATE 1
#define FPE_CR_ADD 2
#define FPE_CR_ADD_SIGNED 3
#define FPE_CR_INTERPOLATE 4
#define FPE_CR_SUBTRACT 5
#define FPE_CR_DOT3_RGB 6
#define FPE_CR_DOT3_RGBA 7
#define FPE_CR_MOD_ADD 8
#define FPE_CR_MOD_ADD_SIGNED 9
#define FPE_CR_MOD_SUB 10
#define FPE_SRC_TEXTURE 0
#define FPE_SRC_TEXTURE0 1
#define FPE_SRC_TEXTURE1 2
#define FPE_SRC_TEXTURE2 3
#define FPE_SRC_TEXTURE3 4
#define FPE_SRC_TEXTURE4 5
#define FPE_SRC_TEXTURE5 6
#define FPE_SRC_TEXTURE6 7
#define FPE_SRC_TEXTURE7 8
#define FPE_SRC_TEXTURE8 9
#define FPE_SRC_TEXTURE9 10
#define FPE_SRC_TEXTURE10 11
#define FPE_SRC_TEXTURE11 12
#define FPE_SRC_TEXTURE12 13
#define FPE_SRC_TEXTURE13 14
#define FPE_SRC_TEXTURE14 15
#define FPE_SRC_TEXTURE15 16
#define FPE_SRC_CONSTANT 17
#define FPE_SRC_PRIMARY_COLOR 18
#define FPE_SRC_PREVIOUS 19
#define FPE_SRC_ZERO 20
#define FPE_SRC_ONE 21
#define FPE_SRC_SECONDARY_COLOR 22
#define FPE_OP_ALPHA 0
#define FPE_OP_MINUSALPHA 1
#define FPE_OP_SRCCOLOR 2
#define FPE_OP_MINUSCOLOR 3
#define FPE_TEX_RGBA 0
#define FPE_TEX_RGB 1
#define FPE_TEX_INTENSITY 2
#define FPE_TEX_LUM_ALPHA 3
#define FPE_TEX_LUM 4
#define FPE_TEX_ALPHA 5
#define FPE_TEX_DEPTH 6
#define FPE_TG_EYELINEAR 0
#define FPE_TG_OBJLINEAR 1
#define FPE_TG_SPHEREMAP 2
#define FPE_TG_NORMALMAP 3
#define FPE_TG_REFLECMAP 4
#define FPE_TG_NONE 5 // dummy, to help fpe
#define FPE_BLEND_ZERO 0
#define FPE_BLEND_ONE 1
#define FPE_BLEND_SRC_COLOR 2
#define FPE_BLEND_ONE_MINUS_SRC_COLOR 3
#define FPE_BLEND_DST_COLOR 4
#define FPE_BLEND_ONE_MINUS_DST_COLOR 5
#define FPE_BLEND_SRC_ALPHA 6
#define FPE_BLEND_ONE_MINUS_SRC_ALPHA 7
#define FPE_BLEND_DST_ALPHA 8
#define FPE_BLEND_ONE_MINUS_DST_ALPHA 9
#define FPE_BLEND_CONSTANT_COLOR 10
#define FPE_BLEND_ONE_MINUS_CONSTANT_COLOR 11
#define FPE_BLEND_CONSTANT_ALPHA 12
#define FPE_BLEND_ONE_MINUS_CONSTANT_ALPHA 13
#define FPE_BLEND_SRC_ALPHA_SATURATE 14
#define FPE_BLENDEQ_FUNC_ADD 0
#define FPE_BLENDEQ_FUNC_SUBTRACT 1
#define FPE_BLENDEQ_FUNC_REVERSE_SUBTRACT 2
#define FPE_BLENDEQ_MIN 3
#define FPE_BLENDEQ_MAX 4
typedef struct fpe_texgen_s {
unsigned int texgen_s:1; // texgen S enabled on 1 bit
unsigned int texgen_s_mode:3; // texgen S on 3 bits
unsigned int texgen_t:1; // texgen T enabled on 1 bit
unsigned int texgen_t_mode:3; // texgen T on 3 bits
unsigned int texgen_r:1; // texgen R enabled on 1 bit
unsigned int texgen_r_mode:3; // texgen R on 3 bits
unsigned int texgen_q:1; // texgen Q enabled on 1 bit
unsigned int texgen_q_mode:3; // texgen Q on 3 bits
} fpe_texgen_t;
typedef struct fpe_texture_s {
unsigned int texmat:1; // flags if texture matrix is not identity
unsigned int textype:3; // textures type stored on 3 bits
unsigned int texadjust:1; // flags if texture need adjustement
unsigned int texformat:3; // textures (simplified) internal format on 3 bits
} fpe_texture_t;
typedef struct fpe_texenv_s {
unsigned int texenv:4; // texenv flag
unsigned int texoprgb0:2; // texenv src op (OPERATION_n_RGB is 2 bits)
unsigned int texoprgb1:2; // texenv src op (OPERATION_n_RGB is 2 bits)
unsigned int texoprgb2:2; // texenv src op (OPERATION_n_RGB is 2 bits)
unsigned int texoprgb3:2; // texenv src op (OPERATION_n_RGB is 2 bits)
unsigned int texopalpha0:1; // texenv src op (OPERATION_n_ALPHA is 1 bits)
unsigned int texopalpha1:1; // texenv src op (OPERATION_n_ALPHA is 1 bits)
unsigned int texopalpha2:1; // texenv src op (OPERATION_n_ALPHA is 1 bits)
unsigned int texopalpha3:1; // texenv src op (OPERATION_n_ALPHA is 1 bits)
unsigned int texsrcrgb0:5; // texenv src rgb n
unsigned int texsrcrgb1:5; // texenv src rgb n
unsigned int texsrcrgb2:5; // texenv src rgb n
unsigned int texsrcrgb3:5; // texenv src rgb n
unsigned int texsrcalpha0:5; // texenv src alpha n
unsigned int texsrcalpha1:5; // texenv src alpha n
unsigned int texsrcalpha2:5; // texenv src alpha n
unsigned int texsrcalpha3:5; // texenv src alpha n
unsigned int texrgbscale:1; // flag if RGB_SCALE for texture is != 1.0
unsigned int texalphascale:1; // flag if ALPHA_SCALE for texture is != 1.0
unsigned int dummy:6; // align sturture to 64bits...
} fpe_texenv_t;
#pragma pack(1)
typedef struct fpe_state_s {
fpe_texture_t texture[MAX_TEX]; // 16 texture flags
fpe_texgen_t texgen[MAX_TEX]; // 16 texgen flags
fpe_texenv_t texenv[MAX_TEX]; // 16 texture env flags
uint8_t texcombine[MAX_TEX]; // 16 texture combined (RGB as lower 4 bits, A as higher 4 bits)
uint8_t light; // 8 lights packed
uint8_t light_cutoff180; // 8 lights cutoff!=180 flags
uint8_t light_direction; // 8 lights position[3].w==0 flags
unsigned int plane:6; // 6 planes packed
unsigned int fogmode:2; // fog mode
unsigned int fogdist:2; // fog distance mode
unsigned int fogsource:1; // fog source
unsigned int fog:1; // Fog enabled or not
unsigned int colorsum:1; // secondary color enabled
unsigned int lighting:1; // global lighting enabled
unsigned int normalize:1; // normalization
unsigned int rescaling:1; // rescale normal
unsigned int alphafunc:3; // alpha functions
unsigned int alphatest:1; // alpha test
unsigned int twosided:1; // lightmodel: two sided
unsigned int color_material:1; // color material enabled
unsigned int cm_front_mode:3; // front color material mode
unsigned int cm_back_mode:3; // back color material mode
unsigned int cm_front_nullexp:1; // front material shininess is 0
unsigned int cm_back_nullexp:1; // back material shininess is 0
unsigned int light_separate:1; // light separate specular color
unsigned int light_localviewer:1; // light local viewer
unsigned int point:1; // point rendering
unsigned int pointsprite:1; // point sprite rendering
unsigned int pointsprite_coord:1; // point sprite coord replace
unsigned int pointsprite_upper:1; // if coord is upper left and not lower left
unsigned int vertex_prg_enable:1; // if vertex program is enabled
unsigned int fragment_prg_enable:1; // if fragment program is enabled
unsigned int blend_enable:1;
unsigned int blendsrcrgb:4;
unsigned int blendsrcalpha:4;
unsigned int blenddstrgb:4;
unsigned int blenddstalpha:4;
unsigned int blendeqrgb:3;
unsigned int blendeqalpha:3;
uint16_t vertex_prg_id; // Id of vertex program currently binded (0 most of the time), 16bits is more than enough...
uint16_t fragment_prg_id; // Id of fragment program currently binded (0 most of the time)
} fpe_state_t;
#pragma pack()
typedef struct fpe_fpe_s {
GLuint frag, vert, prog; // shader info
fpe_state_t state; // state relevant to the current fpe program
program_t *glprogram;
} fpe_fpe_t;
typedef struct kh_fpecachelist_s kh_fpecachelist_t;
#define fpe_cache_t kh_fpecachelist_t
typedef struct scratch_s {
void* scratch[16];
int size;
} scratch_t;
void free_scratch(scratch_t* scratch);
fpe_fpe_t *fpe_GetCache(fpe_cache_t *cur, fpe_state_t *state, int fixed);
void fpe_disposeCache(fpe_cache_t* cache, int freeprog);
// fpe is gles export replacement, so should use same caling conversion
void APIENTRY_GLES fpe_glEnableClientState(GLenum cap);
void APIENTRY_GLES fpe_glDisableClientState(GLenum cap);
void APIENTRY_GLES fpe_glMultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
void APIENTRY_GLES fpe_glSecondaryColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
void APIENTRY_GLES fpe_glVertexPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
void APIENTRY_GLES fpe_glColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
void APIENTRY_GLES fpe_glNormalPointer(GLenum type, GLsizei stride, const GLvoid *pointer);
void APIENTRY_GLES fpe_glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
void APIENTRY_GLES fpe_glTexCoordPointerTMU(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer, int TMU);
void APIENTRY_GLES fpe_glFogCoordPointer(GLenum type, GLsizei stride, const GLvoid *pointer);
void APIENTRY_GLES fpe_glEnable(GLenum cap);
void APIENTRY_GLES fpe_glDisable(GLenum cap);
void APIENTRY_GLES fpe_glDrawArrays(GLenum mode, GLint first, GLsizei count);
void APIENTRY_GLES fpe_glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
void APIENTRY_GLES fpe_glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
void APIENTRY_GLES fpe_glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei primcount);
void APIENTRY_GLES fpe_glDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount);
void APIENTRY_GLES fpe_glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
void APIENTRY_GLES fpe_glNormal3f(GLfloat nx, GLfloat ny, GLfloat nz);
void APIENTRY_GLES fpe_glClientActiveTexture(GLenum texture);
void APIENTRY_GLES fpe_glFogfv(GLenum pname, const GLfloat* params);
void APIENTRY_GLES fpe_glAlphaFunc(GLenum func, GLclampf ref);
void APIENTRY_GLES fpe_glMatrixMode(GLenum mode);
void APIENTRY_GLES fpe_glLightModelf(GLenum pname, GLfloat param);
void APIENTRY_GLES fpe_glLightModelfv(GLenum pname, const GLfloat* params);
void APIENTRY_GLES fpe_glLightfv(GLenum light, GLenum pname, const GLfloat* params);
void APIENTRY_GLES fpe_glMaterialfv(GLenum face, GLenum pname, const GLfloat *params);
void APIENTRY_GLES fpe_glMaterialf(GLenum face, GLenum pname, const GLfloat param);
void APIENTRY_GLES fpe_glPointParameterfv(GLenum pname, const GLfloat * params);
void APIENTRY_GLES fpe_glPointSize(GLfloat size);
void builtin_Init(program_t *glprogram);
int builtin_CheckUniform(program_t *glprogram, char* name, GLint id, int size);
int builtin_CheckVertexAttrib(program_t *glprogram, char* name, GLint id);
void realize_glenv(int ispoint, int first, int count, GLenum type, const void* indices, scratch_t* scratch);
void realize_blitenv(int alpha);
#endif // _GL4ES_FPE_H_
+288
View File
@@ -0,0 +1,288 @@
#include <stdio.h>
#include <string.h>
#include "../glx/hardext.h"
#include "init.h"
#include "logs.h"
#include "debug.h"
#include "program.h"
#include "fpe_cache.h"
#include "fpe.h"
//#define DEBUG
#ifdef DEBUG
#pragma GCC optimize 0
#define DBG(a) a
#else
#define DBG(a)
#endif
static const char PSA_SIGN[] = "GL4ES PrecompiledShaderArchive";
#define CACHE_VERSION 112
static kh_inline khint_t _hash_fpe(fpe_state_t *p)
{
const char* s = (const char*)p;
khint_t h = (khint_t)*s;
for (int i=1 ; i<sizeof(fpe_state_t); ++i) h = (h << 5) - h + (khint_t)*(++s);
return h;
}
#define kh_fpe_hash_func(key) _hash_fpe(key)
#define kh_fpe_hash_equal(a, b) (memcmp(a, b, sizeof(fpe_state_t)) == 0)
#define KHASH_MAP_INIT_FPE(name, khval_t) \
KHASH_INIT(name, kh_fpe_t, khval_t, 1, kh_fpe_hash_func, kh_fpe_hash_equal)
KHASH_MAP_INIT_FPE(fpecachelist, fpe_fpe_t *);
// ********* Cache handling *********
fpe_cache_t* fpe_NewCache() {
khash_t(fpecachelist) *cache = kh_init(fpecachelist);
return cache;
}
void fpe_disposeCache(fpe_cache_t* cache, int freeprog) {
if(!cache) return;
fpe_fpe_t *m;
kh_foreach_value(cache, m,
if(freeprog) {
if(m->glprogram)
gl4es_glDeleteProgram(m->glprogram->id);
}
free(m);
)
kh_destroy(fpecachelist, cache);
}
fpe_fpe_t *fpe_GetCache(fpe_cache_t *cur, fpe_state_t *state, int fixed) {
khint_t k;
int r;
k = kh_get(fpecachelist, cur, state);
if(k != kh_end(cur)) {
return kh_value(cur, k);
} else {
fpe_fpe_t *n = (fpe_fpe_t*)calloc(1, sizeof(fpe_fpe_t));
memcpy(&n->state, state, sizeof(fpe_state_t));
k = kh_put(fpecachelist, cur, &n->state, &r);
kh_value(cur, k) = n;
return n;
}
}
typedef struct psa_s {
fpe_state_t state;
GLenum format;
int size;
void* prog;
} psa_t;
KHASH_MAP_INIT_FPE(psalist, psa_t *);
// Precompiled Shader Archive
typedef struct gl4es_psa_s {
int size;
int dirty;
kh_psalist_t* cache;
} gl4es_psa_t;
static gl4es_psa_t *psa = NULL;
static char *psa_name = NULL;
void fpe_readPSA()
{
if(!psa || !psa_name)
return;
FILE *f = fopen(psa_name, "rb");
if(!f)
return;
char tmp[sizeof(PSA_SIGN)];
if(fread(tmp, sizeof(PSA_SIGN), 1, f)!=1) {
fclose(f);
return; //to short
}
if(strcmp(tmp, PSA_SIGN)!=0) {
fclose(f);
return; // bad signature
}
int version = 0;
if(fread(&version, sizeof(version), 1, f)!=1) {
fclose(f);
return;
}
if(version!=CACHE_VERSION) {
fclose(f);
return; // unsupported version
}
int sz_fpe = 0;
if(fread(&sz_fpe, sizeof(sz_fpe), 1, f)!=1) {
fclose(f);
return;
}
if(sz_fpe!=sizeof(fpe_state_t)) {
fclose(f);
return; // maybe try to adapt instead?
}
int n = 0;
if(fread(&n, sizeof(n), 1, f)!=1) {
fclose(f);
return;
}
for (int i=0; i<n; ++i) {
psa_t *p = (psa_t*)calloc(1, sizeof(psa_t));
if(fread(&p->state, sizeof(p->state), 1, f)!=1) {
free(p);
fclose(f);
return;
}
if(fread(&p->format, sizeof(p->format), 1, f)!=1) {
free(p);
fclose(f);
return;
}
if(fread(&p->size, sizeof(p->size), 1, f)!=1) {
free(p);
fclose(f);
return;
}
p->prog = malloc(p->size);
if(fread(p->prog, p->size, 1, f)!=1) {
free(p->prog);
free(p);
fclose(f);
return;
}
int ret;
khint_t k = kh_put(psalist, psa->cache, &p->state, &ret);
kh_value(psa->cache, k) = p;
psa->size = kh_size(psa->cache);
}
fclose(f);
SHUT_LOGD("Loaded a PSA with %d Precompiled Programs\n", psa->size);
}
void fpe_writePSA()
{
if(!psa || !psa_name)
return;
if(!psa->dirty)
return; // no need
FILE *f = fopen(psa_name, "wb");
if(!f)
return;
if(fwrite(PSA_SIGN, sizeof(PSA_SIGN), 1, f)!=1) {
fclose(f);
return; //to short
}
int version = CACHE_VERSION;
if(fwrite(&version, sizeof(version), 1, f)!=1) {
fclose(f);
return;
}
int sz_fpe = sizeof(fpe_state_t);
if(fwrite(&sz_fpe, sizeof(sz_fpe), 1, f)!=1) {
fclose(f);
return;
}
if(fwrite(&psa->size, sizeof(psa->size), 1, f)!=1) {
fclose(f);
return;
}
psa_t *p;
kh_foreach_value(psa->cache, p,
if(fwrite(&p->state, sizeof(p->state), 1, f)!=1) {
fclose(f);
return;
}
if(fwrite(&p->format, sizeof(p->format), 1, f)!=1) {
fclose(f);
return;
}
if(fwrite(&p->size, sizeof(p->size), 1, f)!=1) {
fclose(f);
return;
}
if(fwrite(p->prog, p->size, 1, f)!=1) {
fclose(f);
return;
}
);
fclose(f);
SHUT_LOGD("Saved a PSA with %d Precompiled Programs\n", psa->size);
}
void fpe_InitPSA(const char* name)
{
if(psa)
return; // already inited
psa = (gl4es_psa_t*)calloc(1, sizeof(gl4es_psa_t));
psa->cache = kh_init(psalist);
psa_name = strdup(name);
}
void fpe_FreePSA()
{
if(!psa)
return; // nothing to init
psa_t *m;
kh_foreach_value(psa->cache, m,
free(m->prog);
free(m);
)
kh_destroy(psalist, psa->cache);
free(psa);
psa = NULL;
free(psa_name);
psa_name = NULL;
}
int fpe_GetProgramPSA(GLuint program, fpe_state_t* state)
{
if(!psa)
return 0;
// if state contains custom vertex of fragment shader, then ignore
if(state->vertex_prg_enable || state->fragment_prg_enable)
return 0;
khint_t k = kh_get(psalist, psa->cache, state);
if(k==kh_end(psa->cache))
return 0; // not here
psa_t *p = kh_value(psa->cache, k);
// try to load...
return gl4es_useProgramBinary(program, p->size, p->format, p->prog);
}
void fpe_AddProgramPSA(GLuint program, fpe_state_t* state)
{
if(!psa)
return;
// if state contains custom vertex of fragment shader, then ignore
if(state->vertex_prg_enable || state->fragment_prg_enable)
return;
psa->dirty = 1;
psa_t *p = (psa_t*)calloc(1, sizeof(psa_t));
memcpy(&p->state, state, sizeof(p->state));
int l = gl4es_getProgramBinary(program, &p->size, &p->format, &p->prog);
if(l==0) { // there was an error...
free(p->prog);
free(p);
return;
}
// add program
int ret;
khint_t k = kh_put(psalist, psa->cache, &p->state, &ret);
if(!ret) {
psa_t *p2 = kh_value(psa->cache, k);
free(p2->prog);
p2->prog = NULL;
free(p2);
}
kh_value(psa->cache, k) = p;
// all done
psa->size = kh_size(psa->cache);
}
+23
View File
@@ -0,0 +1,23 @@
#ifndef __FPE_CACHE_H__
#define __FPE_CACHE_H__
typedef struct fpe_state_s fpe_state_t;
typedef fpe_state_t *kh_fpe_t;
typedef struct fpe_fpe_s fpe_fpe_t;
typedef struct kh_fpecachelist_s kh_fpecachelist_t;
#ifndef fpe_cache_t
#define fpe_cache_t kh_fpecachelist_t
#endif
fpe_cache_t* fpe_NewCache();
void fpe_disposeCache(fpe_cache_t* cache, int freeprog);
fpe_fpe_t *fpe_GetCache(fpe_cache_t *cur, fpe_state_t *state, int fixed);
void fpe_InitPSA(const char* name);
void fpe_FreePSA();
void fpe_readPSA();
void fpe_writePSA();
int fpe_GetProgramPSA(GLuint program, fpe_state_t* state);
void fpe_AddProgramPSA(GLuint program, fpe_state_t* state);
#endif //__FPE_CACHE_H__
File diff suppressed because it is too large Load Diff
+14
View File
@@ -0,0 +1,14 @@
#ifndef _GL4ES_FPE_SHADER_H_
#define _GL4ES_FPE_SHADER_H_
#include "fpe.h"
extern const char* fpeshader_signature;
const char* const* fpe_VertexShader(shaderconv_need_t* need, fpe_state_t *state);
const char* const* fpe_FragmentShader(shaderconv_need_t* need, fpe_state_t *state);
const char* const* fpe_CustomVertexShader(const char* initial, fpe_state_t* state, int default_fragment);
const char* const* fpe_CustomFragmentShader(const char* initial, fpe_state_t* state);
#endif // _GL4ES_FPE_SHADER_H_
File diff suppressed because it is too large Load Diff
+60
View File
@@ -0,0 +1,60 @@
#ifndef _GL4ES_FRAMEBUFFERS_H_
#define _GL4ES_FRAMEBUFFERS_H_
#include "gles.h"
void APIENTRY_GL4ES gl4es_glGenerateMipmap(GLenum target);
void APIENTRY_GL4ES gl4es_glGenFramebuffers(GLsizei n, GLuint *ids);
void APIENTRY_GL4ES gl4es_glDeleteFramebuffers(GLsizei n, GLuint *framebuffers);
GLboolean APIENTRY_GL4ES gl4es_glIsFramebuffer(GLuint framebuffer);
GLenum APIENTRY_GL4ES gl4es_glCheckFramebufferStatus(GLenum target);
void APIENTRY_GL4ES gl4es_glBindFramebuffer(GLenum target, GLuint framebuffer);
void APIENTRY_GL4ES gl4es_glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
void APIENTRY_GL4ES gl4es_glGenRenderbuffers(GLsizei n, GLuint *renderbuffers);
void APIENTRY_GL4ES gl4es_glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
void APIENTRY_GL4ES gl4es_glDeleteRenderbuffers(GLsizei n, GLuint *renderbuffers);
void APIENTRY_GL4ES gl4es_glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
void APIENTRY_GL4ES gl4es_glBindRenderbuffer(GLenum target, GLuint renderbuffer);
GLboolean APIENTRY_GL4ES gl4es_glIsRenderbuffer(GLuint renderbuffer);
void APIENTRY_GL4ES gl4es_glGenerateMipmap(GLenum target);
void APIENTRY_GL4ES gl4es_glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint *params);
void APIENTRY_GL4ES gl4es_glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint * params);
void APIENTRY_GL4ES gl4es_glFramebufferTexture1D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); // naive Wrap
void APIENTRY_GL4ES gl4es_glFramebufferTexture3D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint layer); // naive Wrap
void APIENTRY_GL4ES gl4es_glRenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); //STUB
void APIENTRY_GL4ES gl4es_glFramebufferTextureLayer( GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); // naive Wrap
void APIENTRY_GL4ES gl4es_glBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
void APIENTRY_GL4ES gl4es_glDrawBuffers(GLsizei n, const GLenum *bufs);
void APIENTRY_GL4ES gl4es_glNamedFramebufferDrawBuffers(GLuint framebuffer, GLsizei n, const GLenum *bufs);
void APIENTRY_GL4ES gl4es_glClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint * value);
void APIENTRY_GL4ES gl4es_glClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint * value);
void APIENTRY_GL4ES gl4es_glClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat * value);
void APIENTRY_GL4ES gl4es_glClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
void APIENTRY_GL4ES gl4es_glClearNamedFramebufferiv(GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLint *value);
void APIENTRY_GL4ES gl4es_glClearNamedFramebufferuiv(GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLuint *value);
void APIENTRY_GL4ES gl4es_glClearNamedFramebufferfv(GLuint framebuffer, GLenum buffer, GLint drawbuffer, const GLfloat *value);
void APIENTRY_GL4ES gl4es_glClearNamedFramebufferfi(GLuint framebuffer, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
void APIENTRY_GL4ES gl4es_glColorMaskIndexed(GLuint framebuffer, GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
// In case of LIBGL_FB=2, let's create an FBO for everything, that is then blitted just before the SwapBuffer
void createMainFBO(int width, int height);
void blitMainFBO(int x, int y, int width, int height);
void deleteMainFBO(void* state);
void bindMainFBO();
void unbindMainFBO();
void readfboBegin();
void readfboEnd();
GLuint gl4es_getCurrentFBO();
void gl4es_setCurrentFBO();
void gl4es_saveCurrentFBO();
void gl4es_restoreCurrentFBO();
#endif // _GL4ES_FRAMEBUFFERS_H_
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+164
View File
@@ -0,0 +1,164 @@
#ifndef _GL4ES_GL4ES_H_
#define _GL4ES_GL4ES_H_
#include "khash.h"
#ifdef __ARM_NEON__
#include <arm_neon.h>
#endif // __ARM_NEON__
#include "wrap/gles.h"
#include "gles.h"
#include "glstate.h"
packed_call_t* APIENTRY_GL4ES glCopyPackedCall(const packed_call_t *packed);
#define checkError(code) \
{int error; while ((error = glGetError())) {} \
code \
if ((error = glGetError())) \
printf(#code " -> %i\n", error);}
#define printError(file, line) \
{int error; if ((error = glGetError())) \
printf(file ":%i -> %i\n", line, error);}
#define FLUSH_BEGINEND if(glstate->list.pending) gl4es_flush()
#define ERROR_IN_BEGIN if(glstate->list.begin) {errorShim(GL_INVALID_OPERATION); return;}
const GLubyte* APIENTRY_GL4ES gl4es_glGetString(GLenum name);
void APIENTRY_GL4ES gl4es_glGetIntegerv(GLenum pname, GLint *params);
void APIENTRY_GL4ES gl4es_glGetFloatv(GLenum pname, GLfloat *params);
void APIENTRY_GL4ES gl4es_glEnable(GLenum cap);
void APIENTRY_GL4ES gl4es_glDisable(GLenum cap);
void APIENTRY_GL4ES gl4es_glEnableClientState(GLenum cap);
void APIENTRY_GL4ES gl4es_glDisableClientState(GLenum cap);
GLboolean APIENTRY_GL4ES gl4es_glIsEnabled(GLenum cap);
void APIENTRY_GL4ES gl4es_glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
void APIENTRY_GL4ES gl4es_glDrawArrays(GLenum mode, GLint first, GLsizei count);
void APIENTRY_GL4ES gl4es_glInterleavedArrays(GLenum format, GLsizei stride, const GLvoid *pointer);
void APIENTRY_GL4ES gl4es_glBegin(GLenum mode);
void APIENTRY_GL4ES gl4es_glEnd(void);
void APIENTRY_GL4ES gl4es_glNormal3f(GLfloat nx, GLfloat ny, GLfloat nz);
void APIENTRY_GL4ES gl4es_glVertex4f(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
void APIENTRY_GL4ES gl4es_glColor4f(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
void APIENTRY_GL4ES gl4es_glSecondaryColor3f(GLfloat r, GLfloat g, GLfloat b);
void APIENTRY_GL4ES gl4es_glMaterialfv(GLenum face, GLenum pname, const GLfloat *params);
void APIENTRY_GL4ES gl4es_glMaterialf(GLenum face, GLenum pname, const GLfloat param);
void APIENTRY_GL4ES gl4es_glTexCoord4f(GLfloat s, GLfloat t, GLfloat r, GLfloat q);
void APIENTRY_GL4ES gl4es_glMultiTexCoord4f(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
void APIENTRY_GL4ES gl4es_glArrayElement(GLint i);
void APIENTRY_GL4ES gl4es_glLockArrays(GLint first, GLsizei count);
void APIENTRY_GL4ES gl4es_glUnlockArrays(void);
GLuint APIENTRY_GL4ES gl4es_glGenLists(GLsizei range);
void APIENTRY_GL4ES gl4es_glNewList(GLuint list, GLenum mode);
void APIENTRY_GL4ES gl4es_glEndList(void);
void APIENTRY_GL4ES gl4es_glCallList(GLuint list);
void APIENTRY_GL4ES gl4es_glCallLists(GLsizei n, GLenum type, const GLvoid *lists);
void APIENTRY_GL4ES gl4es_glDeleteLists(GLuint list, GLsizei range);
void APIENTRY_GL4ES gl4es_glListBase(GLuint base);
GLboolean APIENTRY_GL4ES gl4es_glIsList(GLuint list);
void APIENTRY_GL4ES gl4es_glPolygonMode(GLenum face, GLenum mode);
GLenum APIENTRY_GL4ES gl4es_glGetError(void);
void APIENTRY_GL4ES gl4es_glSecondaryColorPointer(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
void APIENTRY_GL4ES gl4es_glIndexPointer(GLenum type, GLsizei stride, const GLvoid * pointer);
void APIENTRY_GL4ES gl4es_glEdgeFlagPointer(GLsizei stride, const GLvoid * pointer);
void APIENTRY_GL4ES gl4es_glGetPointerv(GLenum pname, GLvoid* *params);
void APIENTRY_GL4ES gl4es_glFlush(void);
void APIENTRY_GL4ES gl4es_glFinish(void);
void APIENTRY_GL4ES gl4es_glFogfv(GLenum pname, const GLfloat* params);
void APIENTRY_GL4ES gl4es_glStencilMaskSeparate(GLenum face, GLuint mask);
void APIENTRY_GL4ES gl4es_glMultiDrawArrays(GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount);
void APIENTRY_GL4ES gl4es_glMultiDrawElements( GLenum mode, GLsizei *count, GLenum type, const void * const *indices, GLsizei primcount);
void APIENTRY_GL4ES gl4es_glMultiDrawElementsBaseVertex( GLenum mode, GLsizei *count, GLenum type, const void * const *indices, GLsizei primcount, const GLint * basevertex);
void APIENTRY_GL4ES gl4es_glDrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
void APIENTRY_GL4ES gl4es_glDrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex);
void APIENTRY_GL4ES gl4es_glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei primcount);
void APIENTRY_GL4ES gl4es_glDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
void APIENTRY_GL4ES gl4es_glDrawElementsInstancedBaseVertex(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount, GLint basevertex);
const GLubyte* APIENTRY_GL4ES gl4es_glGetStringi(GLenum name, GLuint index);
void APIENTRY_GL4ES gl4es_glClampColor(GLenum target, GLenum clamp);
void gl4es_flush(void);
int adjust_vertices(GLenum mode, int nb);
extern glstate_t *glstate;
void fpe_Init(glstate_t *glstate); // defined in fpe.c
void fpe_Dispose(glstate_t *glstate); // defined in fpe.c
// glGetError() return last error, but that error is not reset until read
// So if 2 operations generate an error,
// the 2nd error is lost if glGetError has not been called after 1st op
static inline void errorGL() { // next glGetError will be from GL
if(glstate->type_error && glstate->shim_error==GL_NO_ERROR)
glstate->type_error = 0;
else if(glstate->type_error==2)
glstate->type_error = 1; // will need to read glGetError...
}
static inline void errorShim(GLenum error) { // next glGetError will be "error" from gl4es
if(glstate->type_error && glstate->shim_error==GL_NO_ERROR)
glstate->type_error = 1;
if(glstate->shim_error == GL_NO_ERROR)
glstate->shim_error = error;
}
static inline void noerrorShim() {
if(glstate->type_error && glstate->shim_error==GL_NO_ERROR)
glstate->type_error = 1;
}
static inline void noerrorShimNoPurge() {
// doing nothing
}
void gl4es_scratch(int alloc);
void gl4es_scratch_vertex(int alloc);
void gl4es_scratch_indices(int alloc);
void gl4es_use_scratch_vertex(int use);
void gl4es_use_scratch_indices(int use);
void ToBuffer(int first, int count);
void UnBuffer();
GLboolean APIENTRY_GL4ES glIsList(GLuint list);
GLuint APIENTRY_GL4ES glGenLists(GLsizei range);
void APIENTRY_GL4ES glActiveTextureARB(GLenum texture);
void APIENTRY_GL4ES glArrayElement(GLint i);
void APIENTRY_GL4ES glBegin(GLenum mode);
void APIENTRY_GL4ES glCallList(GLuint list);
void APIENTRY_GL4ES glCallLists(GLsizei n, GLenum type, const GLvoid *lists);
void APIENTRY_GL4ES glClearDepth(GLdouble depth);
void APIENTRY_GL4ES glDeleteList(GLuint list);
void APIENTRY_GL4ES glDeleteLists(GLuint list, GLsizei range);
void APIENTRY_GL4ES glDrawArrays(GLenum mode, GLint first, GLsizei count);
void APIENTRY_GL4ES glEnd(void);
void APIENTRY_GL4ES glEndList(void);
void APIENTRY_GL4ES glFrustum(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble Near, GLdouble Far);
void APIENTRY_GL4ES glGetDoublev(GLenum pname, GLdouble *params);
void APIENTRY_GL4ES glIndexf(GLfloat i);
void APIENTRY_GL4ES glInterleavedArrays(GLenum format, GLsizei stride, const GLvoid *pointer);
void APIENTRY_GL4ES glListBase(GLuint base);
void APIENTRY_GL4ES glLockArraysEXT(GLint first, GLsizei count);
void APIENTRY_GL4ES glNewList(GLuint list, GLenum mode);
void APIENTRY_GL4ES glOrtho(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble Near, GLdouble Far);
void APIENTRY_GL4ES glSecondaryColor3f(GLfloat r, GLfloat g, GLfloat b);
void APIENTRY_GL4ES glTexCoord2f(GLfloat s, GLfloat t);
void APIENTRY_GL4ES glUnlockArraysEXT(void);
void APIENTRY_GL4ES glVertex2f(GLfloat x, GLfloat y);
void APIENTRY_GL4ES glVertex2i(GLint x, GLint y);
void APIENTRY_GL4ES glVertex3f(GLfloat x, GLfloat y, GLfloat z);
GLenum APIENTRY_GL4ES glGetError(void);
// custom functions
void APIENTRY_GL4ES glPushCall(void *call);
#endif // _GL4ES_GL4ES_H_
File diff suppressed because it is too large Load Diff
+47
View File
@@ -0,0 +1,47 @@
#ifndef _GL_LOOKUP_H_
#define _GL_LOOKUP_H_
#include "attributes.h"
#ifdef DEBUG
#define MAP(func_name, func) \
if (strcmp(name, func_name) == 0) {printf("%p (%s)\n", (void*)func, #func) ;return (void *)func;}
#else
#define MAP(func_name, func) \
if (strcmp(name, func_name) == 0) return (void *)func;
#endif
#define EX(func_name) MAP(#func_name, func_name)
#define ARB(func_name) MAP(#func_name "ARB", func_name)
#define EXT(func_name) MAP(#func_name "EXT", func_name)
#define _EX(func_name) MAP(#func_name, gl4es_ ## func_name)
#define _ARB(func_name) MAP(#func_name "ARB", gl4es_ ## func_name)
#define _EXT(func_name) MAP(#func_name "EXT", gl4es_ ## func_name)
#ifndef STUB_FCT
#error STUB_FCT is not defined
#endif
#ifdef DEBUG
#define STUB(func_name) \
if (strcmp(name, #func_name) == 0) { \
printf("=> STUB\n"); \
if(!globals4es.silentstub) LOGD("GL4ES stub: %s\n", #func_name); \
return (void *)STUB_FCT; \
}
#else
#define STUB(func_name) \
if (strcmp(name, #func_name) == 0) { \
if(!globals4es.silentstub) LOGD("GL4ES stub: %s\n", #func_name); \
return (void *)STUB_FCT; \
}
#endif
NonAliasExportDecl(void*,gl4es_GetProcAddress,(const char *name));
#endif //_GL_LOOKUP_H_
+88
View File
@@ -0,0 +1,88 @@
#ifndef _GL4ES_GLCASE_H_
#define _GL4ES_GLCASE_H_
#define GL_TYPE_CASE(name, var, magic, vtype, code)\
case magic: { \
vtype *name = (vtype *)var; \
code \
break; \
}
#define GL_TYPE_CASE_ALT(name, var, name2, var2, magic, vtype, code) \
case magic: { \
vtype *name = (vtype *)var; \
vtype *name2= (vtype *)var2; \
code \
break; \
}
#define GL_TYPE_CASE2(name, var, magic, vtype, code2, code) \
case magic: { \
code2 { \
vtype *name = (vtype *)var; \
code \
} \
break; \
}
#define GL_TYPE_CASE_MAX(name, var, magic, vtype, code, max) \
case magic: { \
vtype *name = (vtype *)var; \
vtype maxv = max; \
code \
break; \
}
#define GL_TYPE_SWITCH(name, var, type, code, extra) \
switch (type) { \
GL_TYPE_CASE(name, var, GL_DOUBLE, GLdouble, code) \
GL_TYPE_CASE(name, var, GL_FLOAT, GLfloat, code) \
GL_TYPE_CASE(name, var, GL_INT, GLint, code) \
GL_TYPE_CASE(name, var, GL_SHORT, GLshort, code) \
GL_TYPE_CASE(name, var, GL_BYTE, GLbyte, code) \
GL_TYPE_CASE(name, var, GL_UNSIGNED_BYTE, GLubyte, code) \
GL_TYPE_CASE(name, var, GL_UNSIGNED_INT, GLuint, code) \
GL_TYPE_CASE(name, var, GL_UNSIGNED_SHORT, GLushort, code) \
extra \
}
#define GL_TYPE_SWITCH_ALT(name, var, name2, var2, type, code, extra) \
switch (type) { \
GL_TYPE_CASE_ALT(name, var, name2, var2, GL_DOUBLE, GLdouble, code) \
GL_TYPE_CASE_ALT(name, var, name2, var2, GL_FLOAT, GLfloat, code) \
GL_TYPE_CASE_ALT(name, var, name2, var2, GL_INT, GLint, code) \
GL_TYPE_CASE_ALT(name, var, name2, var2, GL_SHORT, GLshort, code) \
GL_TYPE_CASE_ALT(name, var, name2, var2, GL_BYTE, GLbyte, code) \
GL_TYPE_CASE_ALT(name, var, name2, var2, GL_UNSIGNED_BYTE, GLubyte, code) \
GL_TYPE_CASE_ALT(name, var, name2, var2, GL_UNSIGNED_INT, GLuint, code) \
GL_TYPE_CASE_ALT(name, var, name2, var2, GL_UNSIGNED_SHORT, GLushort, code) \
extra \
}
#define GL_TYPE_SWITCH2(name, var, type, code2, code, extra) \
switch (type) { \
GL_TYPE_CASE2(name, var, GL_DOUBLE, GLdouble, code2, code) \
GL_TYPE_CASE2(name, var, GL_FLOAT, GLfloat, code2, code) \
GL_TYPE_CASE2(name, var, GL_INT, GLint, code2, code) \
GL_TYPE_CASE2(name, var, GL_SHORT, GLshort, code2, code) \
GL_TYPE_CASE2(name, var, GL_BYTE, GLbyte, code2, code) \
GL_TYPE_CASE2(name, var, GL_UNSIGNED_BYTE, GLubyte, code2, code) \
GL_TYPE_CASE2(name, var, GL_UNSIGNED_INT, GLuint, code2, code) \
GL_TYPE_CASE2(name, var, GL_UNSIGNED_SHORT, GLushort, code2, code) \
extra \
}
#define GL_TYPE_SWITCH_MAX(name, var, type, code, extra) \
switch (type) { \
GL_TYPE_CASE_MAX(name, var, GL_DOUBLE, GLdouble, code, 1.0) \
GL_TYPE_CASE_MAX(name, var, GL_FLOAT, GLfloat, code, 1.0f) \
GL_TYPE_CASE_MAX(name, var, GL_INT, GLint, code, 2147483647l) \
GL_TYPE_CASE_MAX(name, var, GL_SHORT, GLshort, code, 32767) \
GL_TYPE_CASE_MAX(name, var, GL_BYTE, GLbyte, code, 127) \
GL_TYPE_CASE_MAX(name, var, GL_UNSIGNED_BYTE, GLubyte, code, 255) \
GL_TYPE_CASE_MAX(name, var, GL_UNSIGNED_INT, GLuint, code, 4294967295l) \
GL_TYPE_CASE_MAX(name, var, GL_UNSIGNED_SHORT, GLushort, code, 65535) \
extra \
}
#endif // _GL4ES_GLCASE_H_
File diff suppressed because it is too large Load Diff
+241
View File
@@ -0,0 +1,241 @@
_EX(glActiveTexture);
_EX(glAlphaFunc);
_EX(glAlphaFuncx);
_EX(glAttachShader);
_EX(glBindAttribLocation);
_EX(glBindBuffer);
_EX(glBindFramebuffer);
_EX(glBindRenderbuffer);
_EX(glBindTexture);
_EX(glBlendColor);
_EX(glBlendEquation);
_EX(glBlendEquationSeparate);
_EX(glBlendFunc);
_EX(glBlendFuncSeparate);
_EX(glBufferData);
_EX(glBufferSubData);
_EX(glCheckFramebufferStatus);
_EX(glClear);
_EX(glClearColor);
_EX(glClearColorx);
_EX(glClearDepthf);
_EX(glClearDepthx);
_EX(glClearStencil);
_EX(glClientActiveTexture);
_EX(glClipPlanef);
_EX(glClipPlanex);
_EX(glColor4f);
_EX(glColor4ub);
_EX(glColor4x);
_EX(glColorMask);
_EX(glColorPointer);
_EX(glCompileShader);
_EX(glCompressedTexImage2D);
_EX(glCompressedTexSubImage2D);
_EX(glCopyTexImage2D);
_EX(glCopyTexSubImage2D);
_EX(glCreateProgram);
_EX(glCreateShader);
_EX(glCullFace);
_EX(glDeleteBuffers);
_EX(glDeleteFramebuffers);
_EX(glDeleteProgram);
_EX(glDeleteRenderbuffers);
_EX(glDeleteShader);
_EX(glDeleteTextures);
_EX(glDepthFunc);
_EX(glDepthMask);
_EX(glDepthRangef);
_EX(glDepthRangex);
_EX(glDetachShader);
_EX(glDisable);
_EX(glDisableClientState);
_EX(glDisableVertexAttribArray);
_EX(glDrawArrays);
_EX(glDrawElements);
_EX(glDrawTexf);
_EX(glDrawTexi);
_EX(glEnable);
_EX(glEnableClientState);
_EX(glEnableVertexAttribArray);
_EX(glFinish);
_EX(glFlush);
_EX(glFogCoordPointer);
_EX(glFogCoordf);
_EX(glFogCoordfv);
_EX(glFogf);
_EX(glFogfv);
_EX(glFogx);
_EX(glFogxv);
_EX(glFramebufferRenderbuffer);
_EX(glFramebufferTexture2D);
_EX(glFrontFace);
_EX(glFrustumf);
_EX(glFrustumx);
_EX(glGenBuffers);
_EX(glGenFramebuffers);
_EX(glGenRenderbuffers);
_EX(glGenTextures);
_EX(glGenerateMipmap);
_EX(glGetActiveAttrib);
_EX(glGetActiveUniform);
_EX(glGetAttachedShaders);
_EX(glGetAttribLocation);
_EX(glGetBooleanv);
_EX(glGetBufferParameteriv);
_EX(glGetClipPlanef);
_EX(glGetClipPlanex);
_EX(glGetError);
_EX(glGetFixedv);
_EX(glGetFloatv);
_EX(glGetFramebufferAttachmentParameteriv);
_EX(glGetIntegerv);
_EX(glGetLightfv);
_EX(glGetLightxv);
_EX(glGetMaterialfv);
_EX(glGetMaterialxv);
_EX(glGetPointerv);
_EX(glGetProgramBinary);
_EX(glGetProgramInfoLog);
_EX(glGetProgramiv);
_EX(glGetRenderbufferParameteriv);
_EX(glGetShaderInfoLog);
_EX(glGetShaderPrecisionFormat);
_EX(glGetShaderSource);
_EX(glGetShaderiv);
_EX(glGetString);
_EX(glGetTexEnvfv);
_EX(glGetTexEnviv);
_EX(glGetTexEnvxv);
_EX(glGetTexParameterfv);
_EX(glGetTexParameteriv);
_EX(glGetTexParameterxv);
_EX(glGetUniformLocation);
_EX(glGetUniformfv);
_EX(glGetUniformiv);
_EX(glGetVertexAttribPointerv);
_EX(glGetVertexAttribfv);
_EX(glGetVertexAttribiv);
_EX(glHint);
_EX(glIsBuffer);
_EX(glIsEnabled);
_EX(glIsFramebuffer);
_EX(glIsProgram);
_EX(glIsRenderbuffer);
_EX(glIsShader);
_EX(glIsTexture);
_EX(glLightModelf);
_EX(glLightModelfv);
_EX(glLightModelx);
_EX(glLightModelxv);
_EX(glLightf);
_EX(glLightfv);
_EX(glLightx);
_EX(glLightxv);
_EX(glLineWidth);
_EX(glLineWidthx);
_EX(glLinkProgram);
_EX(glLoadIdentity);
_EX(glLoadMatrixf);
_EX(glLoadMatrixx);
_EX(glLogicOp);
_EX(glMaterialf);
_EX(glMaterialfv);
_EX(glMaterialx);
_EX(glMaterialxv);
_EX(glMatrixMode);
_EX(glMultMatrixf);
_EX(glMultMatrixx);
_EX(glMultiDrawArrays);
_EX(glMultiDrawElements);
_EX(glMultiTexCoord4f);
_EX(glMultiTexCoord4x);
_EX(glNormal3f);
_EX(glNormal3x);
_EX(glNormalPointer);
_EX(glOrthof);
_EX(glOrthox);
_EX(glPixelStorei);
_EX(glPointParameterf);
_EX(glPointParameterfv);
_EX(glPointParameterx);
_EX(glPointParameterxv);
_EX(glPointSize);
_EX(glPointSizePointerOES);
_EX(glPointSizex);
_EX(glPolygonOffset);
_EX(glPolygonOffsetx);
_EX(glPopMatrix);
_EX(glProgramBinary);
_EX(glPushMatrix);
_EX(glReadPixels);
_EX(glReleaseShaderCompiler);
_EX(glRenderbufferStorage);
_EX(glRotatef);
_EX(glRotatex);
_EX(glSampleCoverage);
_EX(glSampleCoveragex);
_EX(glScalef);
_EX(glScalex);
_EX(glScissor);
_EX(glShadeModel);
_EX(glShaderBinary);
_EX(glShaderSource);
_EX(glStencilFunc);
_EX(glStencilFuncSeparate);
_EX(glStencilMask);
_EX(glStencilMaskSeparate);
_EX(glStencilOp);
_EX(glStencilOpSeparate);
_EX(glTexCoordPointer);
_EX(glTexEnvf);
_EX(glTexEnvfv);
_EX(glTexEnvi);
_EX(glTexEnviv);
_EX(glTexEnvx);
_EX(glTexEnvxv);
_EX(glTexGenfv);
_EX(glTexGeni);
_EX(glTexImage2D);
_EX(glTexParameterf);
_EX(glTexParameterfv);
_EX(glTexParameteri);
_EX(glTexParameteriv);
_EX(glTexParameterx);
_EX(glTexParameterxv);
_EX(glTexSubImage2D);
_EX(glTranslatef);
_EX(glTranslatex);
_EX(glUniform1f);
_EX(glUniform1fv);
_EX(glUniform1i);
_EX(glUniform1iv);
_EX(glUniform2f);
_EX(glUniform2fv);
_EX(glUniform2i);
_EX(glUniform2iv);
_EX(glUniform3f);
_EX(glUniform3fv);
_EX(glUniform3i);
_EX(glUniform3iv);
_EX(glUniform4f);
_EX(glUniform4fv);
_EX(glUniform4i);
_EX(glUniform4iv);
_EX(glUniformMatrix2fv);
_EX(glUniformMatrix3fv);
_EX(glUniformMatrix4fv);
_EX(glUseProgram);
_EX(glValidateProgram);
_EX(glVertexAttrib1f);
_EX(glVertexAttrib1fv);
_EX(glVertexAttrib2f);
_EX(glVertexAttrib2fv);
_EX(glVertexAttrib3f);
_EX(glVertexAttrib3fv);
_EX(glVertexAttrib4f);
_EX(glVertexAttrib4fv);
_EX(glVertexAttribPointer);
_EX(glVertexAttribIPointer);
_EX(glVertexPointer);
_EX(glViewport);
+632
View File
@@ -0,0 +1,632 @@
#include "glstate.h"
#include "../glx/hardext.h"
#include "fpe.h"
#include "framebuffers.h"
#include "gl4es.h"
#include "glstate.h"
#include "init.h"
#include "loader.h"
#include "oldprogram.h"
glstate_t *glstate = NULL;
glstate_t default_glstate = {0};
#define DEFAULT_STATE (void*)(~(uintptr_t)0)
void init_matrix(glstate_t* glstate);
static void free_renderbuffer(glrenderbuffer_t *rend)
{
LOAD_GLES2_OR_OES(glDeleteRenderbuffers);
if(!rend || !gles_glDeleteRenderbuffers)
return;
if(rend->secondarybuffer)
gles_glDeleteRenderbuffers(1, &rend->secondarybuffer);
if(rend->renderbuffer)
gles_glDeleteRenderbuffers(1, &rend->renderbuffer);
// the texture will be free by the free of the texture list, as it's referenced there...
free(rend);
}
static void free_framebuffer(glframebuffer_t *fb)
{
LOAD_GLES2_OR_OES(glDeleteFramebuffers);
if(!fb || !gles_glDeleteFramebuffers)
return;
if(fb->id)
gles_glDeleteFramebuffers(1, &fb->id);
// the texture will be free by the free of the texture list, as it's referenced there...
free(fb);
}
static void free_texture(gltexture_t *tex)
{
LOAD_GLES(glDeleteTextures);
if(!tex || !gles_glDeleteTextures)
return;
if(tex->glname)
gles_glDeleteTextures(1, &tex->glname);
if(tex->data)
free(tex->data);
// renderbuffer linked to this texture will be freed by the free_renderbuffer function.
free(tex);
}
void CopyGLEShard(void* dst, const void* src)
{
if(!dst || !src)
return;
memcpy(((glstate_t*)dst)->gleshard, ((const glstate_t*)src)->gleshard, sizeof(gleshard_t));
}
void* NewGLState(void* shared_glstate, int es2only) {
glstate_t *glstate = (shared_glstate!=DEFAULT_STATE)?((glstate_t*)calloc(1, sizeof(glstate_t))):&default_glstate;
#if defined(AMIGAOS4) || defined(__EMSCRIPTEN__)
int def = 0;
if(shared_glstate==DEFAULT_STATE)
def = 1;
#endif
if(shared_glstate==DEFAULT_STATE)
shared_glstate=NULL;
if(shared_glstate) {
glstate_t* copy_state = (glstate_t*)shared_glstate;
if(!copy_state->shared_cnt) {
copy_state->shared_cnt = (int*)malloc(sizeof(int));
(*copy_state->shared_cnt) = 2;
} else
(*copy_state->shared_cnt)++;
glstate->shared_cnt = copy_state->shared_cnt;
glstate->headlists = copy_state->headlists;
glstate->actual_tex2d = copy_state->actual_tex2d;
glstate->texture.list = copy_state->texture.list;
glstate->glsl = copy_state->glsl;
//glstate->gleshard = copy_state->gleshard; // Not shared (at least not the VA)
glstate->buffers = copy_state->buffers;
glstate->fpe_cache = copy_state->fpe_cache;
glstate->fbo.renderbufferlist = copy_state->fbo.renderbufferlist;
glstate->fbo.default_rb = copy_state->fbo.default_rb;
glstate->fbo.framebufferlist = copy_state->fbo.framebufferlist;
glstate->fbo.fbo_0 = copy_state->fbo.fbo_0;
glstate->fbo.old = copy_state->fbo.old;
glstate->samplers.samplerlist = copy_state->samplers.samplerlist;
glstate->queries.querylist = copy_state->queries.querylist;
glstate->defaultvbo = copy_state->defaultvbo;
}
// set all VAValue to default
GLfloat vadefault[] = {0.0f, 0.0f, 0.0f, 1.0f};
for (int i=0; i<MAX_VATTRIB; ++i)
memcpy(glstate->vavalue[i], vadefault, sizeof(vadefault));
// set shortcut
glstate->vertex = glstate->vavalue[ATT_VERTEX];
glstate->color = glstate->vavalue[ATT_COLOR];
glstate->secondary = glstate->vavalue[ATT_SECONDARY];
glstate->normal = glstate->vavalue[ATT_NORMAL];
glstate->fogcoord = glstate->vavalue[ATT_FOGCOORD];
for (int i=0; i<MAX_TEX; ++i)
glstate->texcoord[i] = glstate->vavalue[ATT_MULTITEXCOORD0+i];
// set specifics default
GLfloat white[] = {1.0f, 1.0f, 1.0f, 1.0f};
memcpy(glstate->color, white, sizeof(GLfloat)*4);
glstate->shim_error = GL_NO_ERROR;
glstate->normal[2] = 1.0f; // default normal is 0/0/1
glstate->matrix_mode = GL_MODELVIEW;
// add default VBO
if(!shared_glstate) // TODO: check if default VBO is shared?
{
khint_t k;
int ret;
khash_t(buff) *list = glstate->buffers = kh_init(buff);
k = kh_put(buff, list, 0, &ret);
glbuffer_t *buff = kh_value(list, k) = calloc(1, sizeof(glbuffer_t));
/*buff->buffer = 0;
buff->type = 0;
buff->data = NULL;*/
buff->usage = GL_STATIC_DRAW;
//buff->size = 0;
buff->access = GL_READ_WRITE;
//buff->mapped = 0;
glstate->defaultvbo = buff;
}
// add default VAO
{
khint_t k;
int ret;
khash_t(glvao) *list = glstate->vaos = kh_init(glvao);
k = kh_put(glvao, list, 0, &ret);
glvao_t *glvao = kh_value(list, k) = malloc(sizeof(glvao_t));
// new vao is binded to default vbo
VaoInit(glvao);
// just put is number
glvao->array = 0;
glstate->defaultvao = glvao;
}
// initialize gllists
if(!shared_glstate)
{
khint_t k;
int ret;
khash_t(gllisthead) *list = glstate->headlists = kh_init(gllisthead);
k = kh_put(gllisthead, list, 1, &ret);
kh_del(gllisthead, list, k);
}
// actual_tex2d
if(!shared_glstate)
{
glstate->actual_tex2d = (GLuint*)calloc(MAX_TEX, sizeof(GLuint));
}
// glsl
glstate->gleshard = (gleshard_t*)calloc(1, sizeof(gleshard_t)); // Not shared!
if(!shared_glstate)
{
glstate->glsl = (glsl_t*)malloc(sizeof(glsl_t));
memset(glstate->glsl, 0, sizeof(glsl_t));
InitOldProgramMap(glstate);
}
// Bind defaults...
glstate->vao = glstate->defaultvao;
//raster & viewport
glstate->raster.raster_zoomx=1.0f;
glstate->raster.raster_zoomy=1.0f;
glstate->raster.map_i2i_size=1;
glstate->raster.map_i2r_size=1;
glstate->raster.map_i2g_size=1;
glstate->raster.map_i2b_size=1;
glstate->raster.map_i2a_size=1;
/*
glstate->raster.map_s2s_size=1;
glstate->raster.map_r2r_size=1;
glstate->raster.map_g2g_size=1;
glstate->raster.map_b2b_size=1;
glstate->raster.map_a2a_size=1;
*/
// pack & unpack alignment
glstate->texture.pack_align = 4;
glstate->texture.unpack_align = 4;
// eval
glstate->map_grid[0]._2 = 1.0f;
glstate->map_grid[0].n = 1;
glstate->map_grid[0].d = 1.0f;
glstate->map_grid[1]._2 = 1.0f;
glstate->map_grid[1].n = 1;
glstate->map_grid[1].d = 1.0f;
// line stipple
glstate->linestipple.factor = 1;
glstate->linestipple.pattern = 0xFFFF;
glstate->linestipple.data = (GLubyte *)malloc(sizeof(GLubyte) * 16);
memset(glstate->linestipple.data, 0xff, sizeof(GLubyte) * 16);
glstate->linestipple.texture = 0;
// fpe
if(hardext.esversion>1) {
glstate->fpe_state = (fpe_state_t*)calloc(1, sizeof(fpe_state_t));
glstate->glsl->es2 = es2only;
fpe_Init(glstate);
}
// init the matrix tracking
init_matrix(glstate);
// init the textures
{
gltexture_t* tex;
if(!shared_glstate) {
int ret;
khint_t k;
khash_t(tex) *list = glstate->texture.list;
list = glstate->texture.list = kh_init(tex);
// segfaults if we don't do a single put
k = kh_put(tex, list, 1, &ret);
kh_del(tex, list, k);
}
// now add default "0" texture => no, because tex 0 is not shared....
/*k = kh_put(tex, list, 0, &ret);
glstate->texture.zero = tex = kh_value(list, k) = malloc(sizeof(gltexture_t));*/
glstate->texture.zero = tex = calloc(1, sizeof(gltexture_t));
tex->adjustxy[0] = tex->adjustxy[1] = 1.f;
tex->mipmap_auto = (globals4es.automipmap==1);
tex->mipmap_need = (globals4es.automipmap==1)?1:0;
tex->streamingID = -1;
tex->base_level = -1;
tex->max_level = -1;
tex->alpha = true;
init_sampler(&tex->sampler);
tex->fpe_format = FPE_TEX_RGBA;
tex->format = GL_RGBA;
tex->type = GL_UNSIGNED_BYTE;
tex->inter_format = GL_RGBA;
tex->inter_type = GL_UNSIGNED_BYTE;
// now bind that texture on all unit
for (int itarget=0; itarget<ENABLED_TEXTURE_LAST; ++itarget)
for (int i=0; i<MAX_TEX; ++i)
glstate->texture.bound[i][itarget] = tex;
}
// init the light tracking
glstate->light.ambient[0]=glstate->light.ambient[1]=glstate->light.ambient[2]=0.2f;
glstate->light.ambient[3]=1.0f;
glstate->light.lights[0].diffuse[0]=
glstate->light.lights[0].diffuse[1]=
glstate->light.lights[0].diffuse[2]=
glstate->light.lights[0].diffuse[3]=1.0f;
memcpy(glstate->light.lights[0].specular, glstate->light.lights[0].diffuse, 4*sizeof(GLfloat));
for (int i=0; i<hardext.maxlights; i++) {
glstate->light.lights[i].ambient[3] = 1.0f;
glstate->light.lights[i].position[2] = 1.0f;
glstate->light.lights[i].spotDirection[2] = -1.0f;
glstate->light.lights[i].spotCutoff = 180;
glstate->light.lights[i].constantAttenuation = 1;
}
// Materials
glstate->material.front.ambient[0] =
glstate->material.front.ambient[1] =
glstate->material.front.ambient[2] = 0.2f;
glstate->material.front.ambient[3] = 1.0f;
glstate->material.front.diffuse[0] =
glstate->material.front.diffuse[1] =
glstate->material.front.diffuse[2] = 0.8f;
glstate->material.front.diffuse[3] = 1.0f;
glstate->material.front.specular[3] = 1.0f;
glstate->material.front.emission[3] = 1.0f;
glstate->material.front.colormat = GL_AMBIENT_AND_DIFFUSE;
memcpy(&glstate->material.back, &glstate->material.front, sizeof(material_t));
// Fog
glstate->fog.mode = GL_EXP;
glstate->fog.density = 1.0f;
glstate->fog.end = 1.0f;
glstate->fog.coord_src = GL_FRAGMENT_DEPTH;
glstate->fog.distance = GL_EYE_PLANE_ABSOLUTE_NV;
// Alpha Func
glstate->alphafunc = GL_ALWAYS;
glstate->alpharef = 0.0f;
// Blend
glstate->blendsfactorrgb = GL_ONE;
glstate->blenddfactorrgb = GL_ZERO;
glstate->blendsfactoralpha = GL_ONE;
glstate->blenddfactoralpha = GL_ZERO;
// Depth
glstate->depth.func = GL_LESS;
glstate->depth.mask = GL_TRUE;
glstate->depth.Far = 1.0f;
glstate->depth.clear= 1.0f;
// Face
glstate->face.cull = GL_BACK;
glstate->face.front = GL_CCW;
// Point Sprite
glstate->pointsprite.size = 1.0f;
glstate->pointsprite.sizeMax = 32.0f; // spec indicate 1., but it seems it's set to hardware limit, so puting 32...
glstate->pointsprite.fadeThresholdSize = 1.0f;
glstate->pointsprite.distance[0] = 1.0f;
glstate->pointsprite.coordOrigin = GL_UPPER_LEFT;
// Stencil
glstate->stencil.func[0] = glstate->stencil.func[1] = GL_ALWAYS;
//glstate->stencil.f_ref[0] = glstate->stencil.f_ref[1] = 0;
glstate->stencil.f_mask[0] = glstate->stencil.f_mask[1] = ~(GLuint)0;
glstate->stencil.mask[0] = glstate->stencil.mask[1] = ~(GLuint)0;
glstate->stencil.sfail[0] = glstate->stencil.sfail[1] = GL_KEEP;
glstate->stencil.dpfail[0] = glstate->stencil.dpfail[1] = GL_KEEP;
glstate->stencil.dppass[0] = glstate->stencil.dppass[1] = GL_KEEP;
// Color Mask
for(int i=0; i<4; i++)
glstate->colormask[i] = 1;
// Raster
for(int i=0; i<4; i++)
glstate->raster.raster_scale[i] = 1.0f;
// ShadeModel
glstate->shademodel = GL_SMOOTH;
// TexEnv
for (int i=0; i<hardext.maxtex; i++) {
glstate->texenv[i].env.mode = GL_MODULATE;
glstate->texenv[i].env.rgb_scale = 1.0f;
glstate->texenv[i].env.alpha_scale = 1.0f;
glstate->texenv[i].env.src0_rgb = glstate->texenv[i].env.src0_alpha = GL_TEXTURE;
glstate->texenv[i].env.src1_rgb = glstate->texenv[i].env.src1_alpha = GL_PREVIOUS;
glstate->texenv[i].env.src2_rgb = glstate->texenv[i].env.src2_alpha = GL_CONSTANT;
glstate->texenv[i].env.op0_rgb = glstate->texenv[i].env.op1_rgb = GL_SRC_COLOR;
glstate->texenv[i].env.op2_rgb = glstate->texenv[i].env.op0_alpha =
glstate->texenv[i].env.op1_alpha = glstate->texenv[i].env.op2_alpha = GL_SRC_ALPHA;
}
// TexGen
for (int i=0; i<hardext.maxtex; i++) {
glstate->texgen[i].S = GL_EYE_LINEAR;
glstate->texgen[i].T = GL_EYE_LINEAR;
glstate->texgen[i].R = GL_EYE_LINEAR;
glstate->texgen[i].Q = GL_EYE_LINEAR;
glstate->texgen[i].S_E[0] = 1.0;
glstate->texgen[i].S_O[0] = 1.0;
glstate->texgen[i].T_E[1] = 1.0;
glstate->texgen[i].T_O[1] = 1.0;
}
// fpe
if(hardext.esversion>1) {
glstate->fpe_state = (fpe_state_t*)calloc(1, sizeof(fpe_state_t));
glstate->glsl->es2 = es2only;
if(!shared_glstate)
fpe_Init(glstate);
// some default are not 0...
for (int i=0; i<MAX_TEX; i++) {
//TexEnv Combine that are not 0
glstate->fpe_state->texenv[i].texsrcrgb0 = FPE_SRC_TEXTURE;
glstate->fpe_state->texenv[i].texsrcalpha0 = FPE_SRC_TEXTURE;
glstate->fpe_state->texenv[i].texsrcrgb1 = FPE_SRC_PREVIOUS;
glstate->fpe_state->texenv[i].texsrcalpha1 = FPE_SRC_PREVIOUS;
glstate->fpe_state->texenv[i].texsrcrgb2 = FPE_SRC_CONSTANT;
glstate->fpe_state->texenv[i].texsrcalpha2 = FPE_SRC_CONSTANT;
glstate->fpe_state->texenv[i].texoprgb0 = FPE_OP_SRCCOLOR;
glstate->fpe_state->texenv[i].texoprgb1 = FPE_OP_SRCCOLOR;
}
if(globals4es.shaderblend) {
glstate->fpe_state->blendsrcrgb = FPE_BLEND_ONE;
glstate->fpe_state->blendsrcalpha = FPE_BLEND_ONE;
}
}
// GLSL stuff
if(!shared_glstate)
{
khint_t k;
int ret;
khash_t(shaderlist) *shaders = glstate->glsl->shaders = kh_init(shaderlist);
k = kh_put(shaderlist, shaders, 1, &ret);
kh_del(shaderlist, shaders, k);
khash_t(programlist) *programs = glstate->glsl->programs = kh_init(programlist);
k = kh_put(programlist, programs, 1, &ret);
kh_del(programlist, programs, k);
}
// Grab ViewPort & Scissor
#if defined(AMIGAOS4) || defined(__EMSCRIPTEN__)
if(!def) {// if it's default_glstate, then there is probably no glcontext...
#endif
LOAD_GLES(glGetIntegerv);
gles_glGetIntegerv(GL_VIEWPORT, (GLint*)&glstate->raster.viewport);
gles_glGetIntegerv(GL_SCISSOR_BOX, (GLint*)&glstate->raster.scissor);
#if defined(AMIGAOS4) || defined(__EMSCRIPTEN__)
}
#endif
// FBO
glstate->fbowidth = glstate->fbo.mainfbo_width = glstate->raster.viewport.width;
glstate->fboheight = glstate->fbo.mainfbo_height = glstate->raster.viewport.height;
glstate->fbo.mainfbo_nwidth = (hardext.npot)?glstate->fbo.mainfbo_width:npot(glstate->fbo.mainfbo_width);
glstate->fbo.mainfbo_nheight = (hardext.npot)?glstate->fbo.mainfbo_height:npot(glstate->fbo.mainfbo_height);
// add default Renderbuffer
if(!shared_glstate)
{
khint_t k;
int ret;
khash_t(renderbufferlist_t) *list = glstate->fbo.renderbufferlist = kh_init(renderbufferlist_t);
k = kh_put(renderbufferlist_t, list, 0, &ret);
glrenderbuffer_t *rend = kh_value(list, k) = calloc(1, sizeof(glrenderbuffer_t));
glstate->fbo.default_rb = rend;
}
// add default Framebuffer
if(!shared_glstate)
{
khint_t k;
int ret;
khash_t(framebufferlist_t) *list = glstate->fbo.framebufferlist = kh_init(framebufferlist_t);
k = kh_put(framebufferlist_t, list, 0, &ret);
glframebuffer_t *fb = kh_value(list, k) = calloc(1, sizeof(glframebuffer_t));
fb->width = glstate->fbo.mainfbo_width;
fb->height = glstate->fbo.mainfbo_height;
glstate->fbo.fbo_0 = fb;
if(globals4es.recyclefbo) {
glstate->fbo.old = (oldfbos_t*)calloc(1, sizeof(oldfbos_t));
}
}
glstate->fbo.current_fb = glstate->fbo.fbo_0;
glstate->fbo.current_rb = glstate->fbo.default_rb;
glstate->fbo.fbo_read = glstate->fbo.fbo_0;
glstate->fbo.fbo_draw = glstate->fbo.fbo_0;
// Samplers & queries
if(!shared_glstate)
{
glstate->samplers.samplerlist = kh_init(samplerlist_t);
glstate->queries.querylist = kh_init(queries);
}
glstate->queries.start = get_clock();
// Get the per/context hardware values
glstate->readf = GL_RGBA;
glstate->readt = GL_UNSIGNED_BYTE;
#if defined(AMIGAOS4) || defined(__EMSCRIPTEN__)
if(!def) // if it's default_glstate, then there is probably no glcontext...
{
LOAD_GLES(glGetIntegerv);
#endif
gles_glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES, (GLint *) &glstate->readf);
gles_glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE_OES, (GLint *) &glstate->readt);
#if defined(AMIGAOS4) || defined(__EMSCRIPTEN__)
}
#endif
//printf("LIBGL: Implementation Read is %s/%s\n", PrintEnum(glstate->readf), PrintEnum(glstate->readt));
// All done
return (void*)glstate;
}
void DeleteGLState(void* oldstate) {
glstate_t* state = (glstate_t*)oldstate;
if(!state) return;
if(state==&default_glstate) return;
if(oldstate==DEFAULT_STATE)
state = &default_glstate;
if(state->shared_cnt) {
if(!--(*state->shared_cnt)) {
free(state->shared_cnt);
state->shared_cnt = 0;
}
}
if(globals4es.noclean)
return;
if(glstate == state)
glstate = (oldstate==DEFAULT_STATE)?NULL:&default_glstate;
if(!state->shared_cnt)
free(state->actual_tex2d);
#define free_hashmap(T, N, K, F) \
if(state->N) \
{ \
T *m; \
kh_foreach_value(state->N, m, \
F(m); \
) \
kh_destroy(K, state->N); \
}
free_hashmap(glvao_t, vaos, glvao, free);
if(!state->shared_cnt) {
free_hashmap(glbuffer_t, buffers, buff, free);
free_hashmap(gltexture_t, texture.list, tex, free_texture);
free_hashmap(renderlist_t, headlists, gllisthead, free_renderlist);
free_hashmap(glrenderbuffer_t, fbo.renderbufferlist, renderbufferlist_t, free_renderbuffer);
free_hashmap(glframebuffer_t, fbo.framebufferlist, framebufferlist_t, free_framebuffer);
free_hashmap(glsampler_t, samplers.samplerlist, samplerlist_t, free);
free_hashmap(glquery_t, queries.querylist, queries, free);
}
#undef free_hashmap
// free texture zero as it's not in the list anymore
free(state->texture.zero);
// free eval maps
#define freemap(dims, name) \
{ map_statef_t *m = (map_statef_t *)state->map##dims.name; \
if (m) { \
free((void *)m->points); \
free(m); \
} }
freemap(1, vertex3); freemap(1, vertex4); freemap(1, index); freemap(1, color4); freemap(1, normal);
freemap(1, texture1); freemap(1, texture2); freemap(1, texture3); freemap(1, texture4);
freemap(2, vertex3); freemap(2, vertex4); freemap(2, index); freemap(2, color4); freemap(2, normal);
freemap(2, texture1); freemap(2, texture2); freemap(2, texture3); freemap(2, texture4);
#undef freemap
// free active list
if(!state->shared_cnt && state->list.active) free_renderlist(state->list.active);
// free matrix stack
#define free_matrix(A) \
if (state->A) { \
free(state->A->stack); \
free(state->A); \
}
free_matrix(projection_matrix);
free_matrix(modelview_matrix);
for (int i=0; i<MAX_TEX; i++)
free_matrix(texture_matrix[i]);
free(state->texture_matrix);
for (int i=0; i<MAX_ARB_MATRIX; i++)
free_matrix(arb_matrix[i]);
#undef free_matrix
// states stack
if(state->stack)
free(state->stack);
if(state->clientStack)
free(state->clientStack);
// linestipple
if(state->linestipple.data)
free(state->linestipple.data);
// raster / bitmap
if(state->raster.data)
free(state->raster.data);
if(state->raster.bitmap)
free(state->raster.bitmap);
// TODO: delete the "immediate" stuff and bitmap texture?
// scratch buffer
if(state->scratch)
free(state->scratch);
// merger buffers
if(state->merger_master)
free(state->merger_master);
if(state->merger_secondary)
free(state->merger_secondary);
for(int a=0; a<MAX_TEX-2; ++a)
if(state->merger_tex[a])
free(state->merger_tex[a]);
// mainfbo
if(!state->shared_cnt) {
if(state->fbo.mainfbo_fbo)
deleteMainFBO(state);
}
// oldfbos
if(!state->shared_cnt && state->fbo.old) {
LOAD_GLES2_OR_OES(glDeleteFramebuffers);
gles_glDeleteFramebuffers(state->fbo.old->nbr, state->fbo.old->fbos);
free(state->fbo.old->fbos);
free(state->fbo.old);
}
// free blit GLES2 stuff
if(state->blit) {
//TODO: check if should delete GL object too
free(state->blit);
}
if(!state->shared_cnt) {
FreeOldProgramMap(state);
free(state->glsl);
if(state->fpe_cache) {
fpe_Dispose(state);
}
}
free(state->gleshard); // Not shared!
// get extensions
if(state->extensions)
free(state->extensions);
if(state->extensions_list) {
for(int i=0; i<state->num_extensions; ++i)
free(state->extensions_list[i]);
free(state->extensions_list);
}
// helper texture adjust
for(int i=0; i<MAX_TEX; ++i) {
if(state->helper_tex[i])
free(state->helper_tex[i]);
if(state->texgened[i])
free(state->texgened[i]);
}
//TODO: free sharderlist and programlist...
// probably missing some things to free here!
// all done
if(oldstate!=DEFAULT_STATE)
free(state);
return;
}
void ActivateGLState(void* new_glstate) {
glstate_t *newstate = (new_glstate)?(glstate_t*)new_glstate:&default_glstate;
if(glstate == newstate) return; // same state, nothing to do
// check if viewport is correct
#if defined(AMIGAOS4) || defined(__EMSCRIPTEN__)
if(glstate || newstate!=&default_glstate) // avoid getting gles info with no context
#endif
if(new_glstate && (newstate->raster.viewport.width==0 || newstate->raster.viewport.height==0)) {
LOAD_GLES(glGetIntegerv);
gles_glGetIntegerv(GL_VIEWPORT, (GLint*)&newstate->raster.viewport);
gles_glGetIntegerv(GL_SCISSOR_BOX, (GLint*)&newstate->raster.scissor);
}
glstate = newstate;
}
void gl_init() {
#ifdef GL4ES_COMPILE_FOR_USE_IN_SHARED_LIB
glstate=NULL;
memset(&default_glstate,0,sizeof(glstate_t));
#endif
(void)NewGLState(DEFAULT_STATE, 0); // automaticaly fill default_glstate
ActivateGLState(&default_glstate);
}
void gl_close() {
DeleteGLState(DEFAULT_STATE);
}
+137
View File
@@ -0,0 +1,137 @@
#ifndef _GL4ES_GLSTATE_H_
#define _GL4ES_GLSTATE_H_
#include "fog.h"
#include "fpe.h"
#include "light.h"
#include "pointsprite.h"
#include "queries.h"
#include "stack.h"
#include "stencil.h"
typedef struct glstate_s {
int dummy[16]; // dummy zone, test for memory overwriting...
displaylist_state_t list;
enable_state_t enable;
map_grid_t map_grid[2];
map_states_t map1, map2;
khash_t(gllisthead) *headlists; // shared
texgen_state_t texgen[MAX_TEX];
texenv_state_t texenv[MAX_TEX];
texture_state_t texture;
GLboolean colormask[4];
int render_mode;
int polygon_mode;
int clamp_read_color;
namestack_t namestack;
GLfloat mvp_matrix[16];
int mvp_matrix_dirty;
GLfloat inv_mv_matrix[16];
int inv_mv_matrix_dirty;
GLfloat normal_matrix[9];
int normal_matrix_dirty;
matrixstack_t *modelview_matrix;
matrixstack_t *projection_matrix;
matrixstack_t **texture_matrix;
matrixstack_t **arb_matrix;
int matrix_mode;
selectbuf_t selectbuf;
khash_t(glvao) *vaos;
khash_t(buff) *buffers; //shared
glvao_t *vao;
glbuffer_t *defaultvbo;
glvao_t *defaultvao;
GLfloat vavalue[MAX_VATTRIB][4]; // the "static" value of a VA
GLfloat *vertex; // shortcut to actual vavalue...
GLfloat *color;
GLfloat *secondary;
GLfloat *texcoord[MAX_TEX];
GLfloat *normal;
GLfloat *fogcoord; // last shortcut
int type_error;
GLenum shim_error;
GLint vp[4];
glstack_t *stack;
glclientstack_t *clientStack;
raster_state_t raster;
GLuint *actual_tex2d; // store the texture actually bounded TEX2D unit, because it's shared... (TODO: all binding and not only TEX2D)
int bound_changed; // 0 if not changed or max TMU if changed...
int fpe_bound_changed; // same but for fpe
#ifdef TEXSTREAM
int bound_stream[MAX_TEX]; // should be shared too
#endif
int emulatedPixmap;
int emulatedWin;
int *shared_cnt;
light_state_t light;
fog_t fog;
material_state_t material;
stencil_t stencil;
float planes[MAX_CLIP_PLANES][4];
pointsprite_t pointsprite;
linestipple_t linestipple;
GLenum shademodel;
GLenum alphafunc;
GLfloat alpharef;
GLenum logicop;
glsl_t *glsl; //shared
fpe_state_t *fpe_state;
fpe_fpe_t *fpe;
fpestatus_t fpe_client;
fpe_cache_t *fpe_cache;
gleshard_t *gleshard; //shared
glesblit_t *blit;
fbo_t fbo;
int fbowidth, fboheight; // initial size (usefull only on LIBGL_FB=1 or 2)
depth_state_t depth;
face_state_t face;
GLint instanceID;
GLint proxy_width;
GLint proxy_height;
GLint proxy_intformat;
// scratch array
int scratch_alloc;
void* scratch;
// glBegin/glEnd merger
int merger_cap;
GLfloat* merger_master;
GLfloat* merger_secondary;
GLfloat* merger_tex[MAX_TEX-2];
int merger_indice_cap;
GLushort* merger_indices;
int merger_used;
// scratch VBO
GLuint scratch_vertex;
GLsizei scratch_vertex_size;
GLuint scratch_indices;
GLsizei scratch_indices_size;
// Implementation read
GLenum readf; // implementation Read Format
GLenum readt; // implementation Read Type
// Get extension
GLubyte* extensions;
int num_extensions;
GLubyte** extensions_list;
// Texture adjust helper
void* helper_tex[MAX_TEX];
int helper_texlen[MAX_TEX];
GLfloat* texgened[MAX_TEX];
int texgenedsz[MAX_TEX];
// Sampler
samplers_t samplers;
// Queries
queries_t queries;
// Binded buffer (if used)
bind_buffers_t bind_buffer;
// Blend status
float blend_color[4];
GLenum blendsfactorrgb;
GLenum blenddfactorrgb;
GLenum blendsfactoralpha;
GLenum blenddfactoralpha;
GLenum blendeqrgb;
GLenum blendeqalpha;
} glstate_t;
#endif // _GL4ES_GLSTATE_H_
+135
View File
@@ -0,0 +1,135 @@
#include "hint.h"
#include <gl4eshint.h>
#include "init.h"
#include "loader.h"
#include "gl4es.h"
#include "glstate.h"
#ifdef PANDORA
void pandora_set_gamma();
#endif
void APIENTRY_GL4ES gl4es_glHint(GLenum pname, GLenum mode) {
FLUSH_BEGINEND;
LOAD_GLES(glHint);
noerrorShim();
switch(pname) {
// some Hint are not supported in GLES2, so just ignoring them
case GL_FOG_HINT:
if(hardext.esversion>1)
return;
gles_glHint(pname, mode);
break;
case GL_PERSPECTIVE_CORRECTION_HINT:
if(hardext.esversion>1)
return;
gles_glHint(pname, mode);
break;
case GL_LINE_SMOOTH_HINT:
if(hardext.esversion>1)
return;
gles_glHint(pname, mode);
break;
case GL_POINT_SMOOTH_HINT:
if(hardext.esversion>1)
return;
gles_glHint(pname, mode);
break;
case GL_TEXTURE_COMPRESSION_HINT: // ignore this one
// TODO: track setted value
return;
// specifics GL4ES Hints
case GL_SHRINK_HINT_GL4ES:
if (mode<=11)
globals4es.texshrink = mode;
else
errorShim(GL_INVALID_ENUM);
break;
case GL_ALPHAHACK_HINT_GL4ES:
if (mode<=1)
globals4es.alphahack = mode;
else
errorShim(GL_INVALID_ENUM);
break;
case GL_RECYCLEFBO_HINT_GL4ES:
if (mode<=1)
globals4es.recyclefbo = mode;
else
errorShim(GL_INVALID_ENUM);
break;
case GL_MIPMAP_HINT_GL4ES:
if (mode<=4)
globals4es.automipmap = mode;
else
errorShim(GL_INVALID_ENUM);
break;
case GL_TEXDUMP_HINT_GL4ES:
if (mode<=1)
globals4es.texdump = mode;
else
errorShim(GL_INVALID_ENUM);
break;
case GL_COPY_HINT_GL4ES:
if (mode>1) //removed
errorShim(GL_INVALID_ENUM);
break;
case GL_NOLUMAPHA_HINT_GL4ES:
if (mode<=1)
globals4es.nolumalpha = mode;
else
errorShim(GL_INVALID_ENUM);
break;
case GL_BLENDHACK_HINT_GL4ES:
if (mode<=1)
globals4es.blendhack = mode;
else
errorShim(GL_INVALID_ENUM);
break;
case GL_BATCH_HINT_GL4ES:
globals4es.minbatch = 0;
globals4es.maxbatch = mode*100;
break;
case GL_NOERROR_HINT_GL4ES:
if (mode<=1)
globals4es.noerror = mode;
else
errorShim(GL_INVALID_ENUM);
break;
case GL_NODOWNSAMPLING_HINT_GL4ES:
if (mode<=1)
globals4es.nodownsampling = mode;
else
errorShim(GL_INVALID_ENUM);
break;
case GL_NOVAOCACHE_HINT_GL4ES:
if (mode<=1)
globals4es.novaocache = mode;
else
errorShim(GL_INVALID_ENUM);
break;
case GL_BEGINEND_HINT_GL4ES:
if(mode<=2)
globals4es.beginend = mode;
else
errorShim(GL_INVALID_ENUM);
case GL_AVOID16BITS_HINT_GL4ES:
if (mode<=1)
globals4es.avoid16bits = mode;
else
errorShim(GL_INVALID_ENUM);
break;
case GL_GAMMA_HINT_GL4ES:
globals4es.gamma = ((float)mode)/10.f;
#ifdef PANDORA
pandora_set_gamma();
#endif
break;
default:
errorGL();
gles_glHint(pname, mode);
}
}
AliasExport(void,glHint,,(GLenum pname, GLenum mode));
+8
View File
@@ -0,0 +1,8 @@
#ifndef _GL4ES_HINT_H_
#define _GL4ES_HINT_H_
#include "gles.h"
void APIENTRY_GL4ES gl4es_glHint(GLenum pname, GLenum mode);
#endif // _GL4ES_HINT_H_
+756
View File
@@ -0,0 +1,756 @@
#include <stdio.h>
#ifndef _WIN32
#include <unistd.h>
#else
#include <stdio.h>
#include <direct.h>
#define getcwd(a,b) _getcwd(a,b)
#define snprintf _snprintf
#endif
#include "../../version.h"
#include "../glx/glx_gbm.h"
#include "../glx/streaming.h"
#include "build_info.h"
#include "debug.h"
#include "loader.h"
#include "logs.h"
#include "fpe_cache.h"
#include "init.h"
#include "envvars.h"
#if defined(__EMSCRIPTEN__) || defined(__APPLE__)
#define NO_INIT_CONSTRUCTOR
#endif
void gl_init();
void gl_close();
#ifdef GL4ES_COMPILE_FOR_USE_IN_SHARED_LIB
#ifdef AMIGAOS4
void agl_reset_internals();
#endif
void fpe_shader_reset_internals();
#endif
globals4es_t globals4es = {0};
#if defined(PANDORA) || defined(CHIP) || defined(GOA_CLONE)
static void fast_math() {
// enable Cortex A8 RunFast
int v = 0;
__asm__ __volatile__ (
"vmrs %0, fpscr\n"
"orr %0, #((1<<25)|(1<<24))\n" // default NaN, flush-to-zero
"vmsr fpscr, %0\n"
//"vmrs %0, fpscr\n"
: "=&r"(v));
}
#endif
#ifndef DEFAULT_ES
#if defined(PANDORA) || defined(ANDROID)
#define DEFAULT_ES 1
#else
#define DEFAULT_ES 2
#endif
#endif
void load_libs();
void glx_init();
static int inited = 0;
EXPORT
void set_getmainfbsize(void (APIENTRY_GL4ES *new_getMainFBSize)(int* w, int* h)) {
gl4es_getMainFBSize = (void*)new_getMainFBSize;
}
EXPORT
void set_getprocaddress(void *(APIENTRY_GL4ES *new_proc_address)(const char *)) {
gles_getProcAddress = new_proc_address;
}
#ifdef NO_INIT_CONSTRUCTOR
EXPORT
#else
#if defined(_WIN32) || defined(__CYGWIN__)
#define BUILD_WINDOWS_DLL
// dll can't initialize emulator in startup code :(
static unsigned char dll_inited;
EXPORT
#endif
#if !defined(_MSC_VER) || defined(__clang__)
__attribute__((constructor(101)))
#endif
#endif
void initialize_gl4es() {
#ifdef BUILD_WINDOWS_DLL
if(!dll_inited) {
LOGE("Windows ES emulator's can't be initialized from DllMain (directX limitation)\n");
return;
}
#endif
// only init 1 time
if(inited++) return;
// default init of globals
memset(&globals4es, 0, sizeof(globals4es));
globals4es.mergelist = 1;
globals4es.queries = 1;
globals4es.beginend = 1;
#ifdef PYRA
GetEnvVarInt("LIBGL_DEEPBIND", &globals4es.deepbind, 0);
#else
GetEnvVarInt("LIBGL_DEEPBIND", &globals4es.deepbind, 1);
#endif
// overrides by env. variables
#ifdef GL4ES_COMPILE_FOR_USE_IN_SHARED_LIB
GetEnvVarInt("LIBGL_NOBANNER",&globals4es.nobanner,1);
#else
globals4es.nobanner = IsEnvVarTrue("LIBGL_NOBANNER");
#endif
SHUT_LOGD("Initialising gl4es\n");
if(!globals4es.nobanner) print_build_infos();
#define env(name, global, message) \
if(IsEnvVarTrue(#name)) {\
SHUT_LOGD(message "\n"); \
global = true; \
}
env(LIBGL_XREFRESH, globals4es.xrefresh, "xrefresh will be called on cleanup");
env(LIBGL_STACKTRACE, globals4es.stacktrace, "stacktrace will be printed on crash");
switch(ReturnEnvVarInt("LIBGL_FB")) {
case 1:
SHUT_LOGD("framebuffer output enabled\n");
globals4es.usefb = 1;
break;
case 2:
SHUT_LOGD("using framebuffer + fbo\n");
globals4es.usefb = 1;
globals4es.usefbo = 1;
break;
#ifndef NOX11
case 3:
SHUT_LOGD("using pbuffer\n");
globals4es.usefb = 0;
globals4es.usepbuffer = 1;
break;
#endif
case 4:
#ifdef NO_GBM
SHUT_LOGD("GBM support not built, cannot use it\n");
#else
SHUT_LOGD("using GBM\n");
globals4es.usefb = 0;
globals4es.usegbm = 1;
#endif
break;
default:
break;
}
env(LIBGL_BLITFB0, globals4es.blitfb0, "Blit to FB 0 force a SwapBuffer");
env(LIBGL_FPS, globals4es.showfps, "fps counter enabled");
#if defined(USE_FBIO) || defined(PYRA)
env(LIBGL_VSYNC, globals4es.vsync, "vsync enabled");
#endif
#ifdef PANDORA
if(GetEnvVarFloat("LIBGL_GAMMA",&globals4es.gamma,0.0f)) {
SHUT_LOGD("Set gamma to %.2f\n", globals4es.gamma);
}
#endif
env(LIBGL_NOBGRA, globals4es.nobgra, "Ignore BGRA texture capability");
env(LIBGL_NOTEXRECT, globals4es.notexrect, "Don't export Text Rectangle extension");
if(globals4es.usefbo) {
env(LIBGL_FBONOALPHA, globals4es.fbo_noalpha, "Main FBO has no alpha channel");
}
globals4es.es=ReturnEnvVarInt("LIBGL_ES");
switch(globals4es.es) {
case 1:
case 2:
break;
default:
// automatic ES backend selection
globals4es.es = DEFAULT_ES;
break;
}
globals4es.gl=ReturnEnvVarInt("LIBGL_GL");
switch(globals4es.gl) {
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
case 20:
case 21:
case 30:
case 31:
case 32:
case 33:
case 40:
case 41:
case 42:
case 43:
case 44:
case 45:
break;
default:
// automatic GL version selection
globals4es.gl = (globals4es.es==1)?15:21; // forcing GL 1.5 for es1.1 and GL 2.1 for es2.0
break;
}
SHUT_LOGD("Using GLES %s backend\n", (globals4es.es==1)?"1.1":"2.0");
env(LIBGL_NODEPTHTEX, globals4es.nodepthtex, "Disable usage of Depth Textures");
const char* env_drmcard = GetEnvVar("LIBGL_DRMCARD");
if(env_drmcard) {
#ifdef NO_GBM
SHUT_LOGD("Warning, GBM not compiled in, cannot use LIBGL_DRMCARD\n");
#else
strncpy(globals4es.drmcard, env_drmcard, 50);
} else {
strcpy(globals4es.drmcard, "/dev/dri/card0");
#endif
}
#if !defined(__EMSCRIPTEN__) && !defined(__APPLE__)
load_libs();
#endif
#if (defined(NOEGL) && !defined(ANDROID) && !defined(__APPLE__)) || defined(__EMSCRIPTEN__)
int gl4es_notest = !gles_getProcAddress;
#else
int gl4es_notest = IsEnvVarTrue("LIBGL_NOTEST");
#endif
env(LIBGL_NOHIGHP, globals4es.nohighp, "Do not use HIGHP in fragment shader even if detected");
globals4es.floattex=ReturnEnvVarIntDef("LIBGL_FLOAT", 1);
switch(globals4es.floattex) {
case 0:
SHUT_LOGD("Float and Half-Float texture support disabled\n");
break;
case 2:
SHUT_LOGD("Float and Half-float texture support forced\n");
break;
default:
globals4es.floattex = 1;
break;
}
GetHardwareExtensions(gl4es_notest);
#if !defined(NO_LOADER) && !defined(NO_GBM)
if(globals4es.usegbm)
LoadGBMFunctions();
if(globals4es.usegbm && !(gbm && drm)) {
SHUT_LOGD("cannot use GBM, disabling\n");
globals4es.usegbm = 0; // should do some smarter fallback?
}
#else
globals4es.usegbm = 0;
#endif
#if !defined(NOX11)
glx_init();
#endif
gl_init();
#ifdef GL4ES_COMPILE_FOR_USE_IN_SHARED_LIB
fpe_shader_reset_internals();
#ifdef AMIGAOS4
agl_reset_internals();
#endif
#endif
env(LIBGL_RECYCLEFBO, globals4es.recyclefbo, "Recycling of FBO enabled");
// Texture hacks
globals4es.automipmap=ReturnEnvVarInt("LIBGL_MIPMAP");
switch(globals4es.automipmap) {
case 1:
SHUT_LOGD("AutoMipMap forced\n");
break;
case 2:
SHUT_LOGD("guess AutoMipMap\n");
break;
case 3:
SHUT_LOGD("ignore MipMap\n");
break;
case 4:
SHUT_LOGD("ignore AutoMipMap on non-squared textures\n");
break;
case 5:
SHUT_LOGD("Calculate sub-mipmap in case some are missing\n");
break;
default:
globals4es.automipmap = 0;
break;
}
if(IsEnvVarTrue("LIBGL_TEXCOPY")) {
globals4es.texcopydata = 1;
SHUT_LOGD("Texture copy enabled\n");
}
globals4es.texshrink=ReturnEnvVarInt("LIBGL_SHRINK");
switch(globals4es.texshrink) {
case 10:
SHUT_LOGD("Texture shrink, mode 10 selected (advertise 8192 max texture size, but >2048 are quadshrinked and > 512 are shrinked), but not for empty textures\n");
break;
case 11:
SHUT_LOGD("Texture shrink, mode 11 selected (advertise a max texture size *2, but every texture with one dimension > max texture size will get shrinked to max texture size), but not for empty textures\n");
break;
case 1:
SHUT_LOGD("Texture shrink, mode 1 selected (everything / 2)\n");
break;
case 2:
SHUT_LOGD("Texture shrink, mode 2 selected (only > 512 /2 )\n");
break;
case 3:
SHUT_LOGD("Texture shrink, mode 3 selected (only > 256 /2 )\n");
break;
case 4:
SHUT_LOGD("Texture shrink, mode 4 selected (only > 256 /2, >=1024 /4 )\n");
break;
case 5:
SHUT_LOGD("Texture shrink, mode 5 selected (every > 256 is downscaled to 256 ), but not for empty textures\n");
break;
case 6:
SHUT_LOGD("Texture shrink, mode 6 selected (only > 128 /2, >=512 is downscaled to 256 ), but not for empty textures\n");
break;
case 7:
SHUT_LOGD("Texture shrink, mode 7 selected (only > 512 /2 ), but not for empty textures\n");
break;
case 8:
SHUT_LOGD("Texture shrink, mode 8 selected (advertise 8192 max texture size, but >2048 are shrinked to 2048)\n");
break;
case 9:
SHUT_LOGD("Texture shrink, mode 9 selected (advertise 8192 max texture size, but >4096 are quadshrinked and > 512 are shrinked), but not for empty textures\n");
break;
default:
globals4es.texshrink=0;
break;
}
env(LIBGL_TEXDUMP, globals4es.texdump, "Texture dump enabled");
env(LIBGL_ALPHAHACK, globals4es.alphahack, "Alpha Hack enabled");
#ifdef TEXSTREAM
switch(ReturnEnvVarInt("LIBGL_STREAM")) {
case 1:
globals4es.texstream = InitStreamingCache();
SHUT_LOGD("Streaming texture %s\n",(globals4es.texstream)?"enabled":"not available");
//FreeStreamed(AddStreamed(1024, 512, 0));
break;
case 2:
globals4es.texstream = InitStreamingCache()?2:0;
SHUT_LOGD("Streaming texture %s\n",(globals4es.texstream)?"forced":"not available");
//FreeStreamed(AddStreamed(1024, 512, 0));
break;
default:
break;
}
#endif
env(LIBGL_NOLUMALPHA, globals4es.nolumalpha, "GL_LUMINANCE_ALPHA hardware support disabled");
env(LIBGL_BLENDHACK, globals4es.blendhack, "Change Blend GL_SRC_ALPHA, GL_ONE to GL_ONE, GL_ONE");
env(LIBGL_BLENDCOLOR, globals4es.blendcolor, "Export a (faked) glBlendColor");
env(LIBGL_NOERROR, globals4es.noerror, "glGetError() always return GL_NOERROR");
globals4es.silentstub = 1;
if(IsEnvVarInt("LIBGL_SILENTSTUB",0)) {
globals4es.silentstub = 0;
SHUT_LOGD("Stub/non present functions are printed");
}
env(LIBGL_VABGRA, globals4es.vabgra, "Export GL_ARB_vertex_array_bgra extension");
const char *env_version = GetEnvVar("LIBGL_VERSION");
if (env_version) {
SHUT_LOGD("Override version string with \"%s\" (should be in the form of \"1.x\")\n", env_version);
}
if(env_version) {
snprintf(globals4es.version, 49, "%s gl4es wrapper %d.%d.%d", env_version, MAJOR, MINOR, REVISION);
SHUT_LOGD("Targeting OpenGL %s\n", env_version);
} else {
snprintf(globals4es.version, 49, "%d.%d gl4es wrapper %d.%d.%d", globals4es.gl/10, globals4es.gl%10, MAJOR, MINOR, REVISION);
SHUT_LOGD("Targeting OpenGL %d.%d\n", globals4es.gl/10, globals4es.gl%10);
}
if(hardext.srgb && IsEnvVarTrue("LIBGL_SRGB")) {
globals4es.glx_surface_srgb = 2;
SHUT_LOGD("enabling sRGB support\n");
}
if(IsEnvVarTrue("LIBGL_FASTMATH")) {
#if defined(PANDORA) || defined(CHIP) || defined(GOA_CLONE)
SHUT_LOGD("Enable FastMath for cortex-a8\n");
fast_math();
#else
SHUT_LOGD("No FastMath on this platform\n");
#endif
}
switch(hardext.npot) {
case 0: globals4es.npot = 0; break;
case 1:
case 2: globals4es.npot = 1; break;
case 3: globals4es.npot = 2; break;
}
switch(ReturnEnvVarInt("LIBGL_NPOT")) {
case 1:
if(globals4es.npot<1) {
globals4es.npot = 1;
SHUT_LOGD("Expose limited NPOT extension\n");
}
break;
case 2:
if(globals4es.npot<3) {
globals4es.npot = 2;
SHUT_LOGD("Expose GL_ARB_texture_non_power_of_two extension\n");
}
break;
}
if(IsEnvVarFalse("LIBGL_GLQUERIES")) {
globals4es.queries = 0;
SHUT_LOGD("Don't expose fake glQueries functions\n");
}
if(IsEnvVarTrue("LIBGL_NODOWNSAMPLING")) {
globals4es.nodownsampling = 1;
SHUT_LOGD("No downsampling of DXTc textures\n");
}
env(LIBGL_NOTEXMAT, globals4es.texmat, "Don't handle Texture Matrice internally");
env(LIBGL_NOVAOCACHE, globals4es.novaocache, "Don't use VAO cache");
if(IsEnvVarTrue("LIBGL_NOINTOVLHACK")) {
globals4es.nointovlhack = 1;
SHUT_LOGD("No hack in shader converter to define overloaded function with int\n");
}
if(IsEnvVarTrue("LIBGL_NOSHADERLOD")) {
globals4es.noshaderlod = 1;
SHUT_LOGD("No GL_EXT_shader_texture_lod used even if present\n");
hardext.shaderlod=0;
}
int env_begin_end;
if(GetEnvVarInt("LIBGL_BEGINEND",&env_begin_end,0)) {
switch(env_begin_end) {
case 0:
globals4es.beginend = 0;
globals4es.mergelist = 0;
SHUT_LOGD("Don't try to merge subsequent glBegin/glEnd blocks\n");
break;
case 1:
case 2:
globals4es.beginend = 1;
SHUT_LOGD("Try to merge subsequent glBegin/glEnd blocks, even if there is a glColor / glNormal in between\n");
break;
}
}
if(GetEnvVarBool("LIBGL_AVOID16BITS", &globals4es.avoid16bits, (hardext.vendor&VEND_IMGTEC)?0:1)) {
if(globals4es.avoid16bits) {
SHUT_LOGD("Avoid 16bits textures\n");
} else {
SHUT_LOGD("Don't avoid 16bits textures\n");
}
}
if(GetEnvVarInt("LIBGL_AVOID24BITS",&globals4es.avoid24bits,0)) {
switch(globals4es.avoid24bits) {
case 0:
SHUT_LOGD("Don't try to avoid 24bits textures\n");
break;
case 1:
globals4es.avoid24bits = 2;
SHUT_LOGD("Avoid 24bits textures\n");
break;
default:
globals4es.avoid24bits = 0;
break;
}
}
env(LIBGL_FORCE16BITS, globals4es.force16bits, "Force 16bits textures");
env(LIBGL_POTFRAMEBUFFER, globals4es.potframebuffer, "Force framebuffers to be on POT size");
int env_forcenpot=ReturnEnvVarIntDef("LIBGL_FORCENPOT",0);
if(env_forcenpot==0 && (hardext.esversion==2 && (hardext.npot==1 || hardext.npot==2))) {
SHUT_LOGD("Not forcing NPOT support\n");
} else if(env_forcenpot!=0 || (hardext.esversion==2 && (hardext.npot==1 || hardext.npot==2))) {
if(hardext.npot==3) {
SHUT_LOGD("NPOT texture handled in hardware\n");
} else if(hardext.npot==1) {
globals4es.forcenpot = 1;
SHUT_LOGD("Forcing NPOT support by disabling MIPMAP support for NPOT textures\n");
} else {
SHUT_LOGD("WARNING, No Limited or Full NPOT support in hardware, Forcing NPOT has no effect!\n");
}
}
#if defined(GL4ES_COMPILE_FOR_USE_IN_SHARED_LIB) && defined(AMIGAOS4) // temporary workaround for not-working envs
globals4es.maxbatch = 40;
#else
globals4es.maxbatch = 0;
#endif
globals4es.minbatch = 0;
int tmp = 0, tmp2 = 0;
switch(GetEnvVarFmt("LIBGL_BATCH","%d-%d",&tmp,&tmp2)) {
case 2:
globals4es.maxbatch = tmp2;
globals4es.minbatch = tmp;
if(globals4es.minbatch>globals4es.maxbatch) {
globals4es.maxbatch = tmp;
globals4es.minbatch = tmp2;
}
break;
case 1:
globals4es.maxbatch = 10*10*tmp;
globals4es.minbatch = 0;
break;
}
if(globals4es.maxbatch==0) {
SHUT_LOGD("Not trying to batch small subsequent glDrawXXXX\n");
} else {
SHUT_LOGD("Trying to batch subsequent glDrawXXXX of size between %d and %d vertices\n", globals4es.minbatch, globals4es.maxbatch);
}
if(hardext.esversion==1) globals4es.usevbo=0; // VBO on ES1.1 backend will be too messy, so disabling
else {
globals4es.usevbo = ReturnEnvVarIntDef("LIBGL_USEVBO",1);
switch(globals4es.usevbo) {
case 0:
SHUT_LOGD("Use of VBO disabled\n");
break;
case 1:
SHUT_LOGD("Trying to use VBO\n");
break;
case 2:
SHUT_LOGD("Trying to use VBO (also with glLockArrays)\n");
break;
case 3:
SHUT_LOGD("Trying to use VBO (special glLockArrays case for idtech3 engine)\n");
break;
default:
globals4es.usevbo=1;
break;
}
}
globals4es.fbomakecurrent = 0;
if((hardext.vendor & VEND_ARM) || (globals4es.usefb))
globals4es.fbomakecurrent = 1;
switch(ReturnEnvVarIntDef("LIBGL_FBOMAKECURRENT",-1)) {
case 0:
if(globals4es.fbomakecurrent) {
globals4es.fbomakecurrent = 0;
SHUT_LOGD("glXMakeCurrent FBO workaround disabled\n");
}
break;
case 1:
globals4es.fbomakecurrent = 1;
break;
}
if(globals4es.fbomakecurrent) {
SHUT_LOGD("glXMakeCurrent FBO workaround enabled\n");
}
globals4es.fbounbind = 0;
if((hardext.vendor & VEND_ARM) || (hardext.vendor & VEND_IMGTEC))
globals4es.fbounbind = 1;
switch(ReturnEnvVarIntDef("LIBGL_FBOUNBIND",-1)) {
case 0:
if(globals4es.fbounbind) {
globals4es.fbounbind = 0;
SHUT_LOGD("FBO workaround for using binded texture disabled\n");
}
break;
case 1:
globals4es.fbounbind = 1;
break;
}
if(globals4es.fbounbind) {
SHUT_LOGD("FBO workaround for using binded texture enabled\n");
}
globals4es.fboforcetex = 1;
GetEnvVarInt("LIBGL_FBOFORCETEX", &globals4es.fboforcetex, globals4es.fboforcetex);
if(globals4es.fboforcetex)
SHUT_LOGD("Force texture for Attachment color0 on FBO\n");
globals4es.blitfullscreen = 1;
GetEnvVarInt("LIBGL_BLITFULLSCREEN", &globals4es.blitfullscreen, globals4es.blitfullscreen);
if(globals4es.blitfullscreen)
SHUT_LOGD("Hack to trigger a SwapBuffers when a Full Framebuffer Blit on default FBO is done\n");
env(LIBGL_COMMENTS, globals4es.comments, "Keep comments in converted Shaders");
env(LIBGL_NOARBPROGRAM, globals4es.noarbprogram, "Not exposing ARB Program extensions");
if(hardext.npot==3)
globals4es.defaultwrap=0;
else
globals4es.defaultwrap=1;
if(GetEnvVarInt("LIBGL_DEFAULTWRAP",&globals4es.defaultwrap,(hardext.npot==3) ? 0 : 1)) {
switch(globals4es.defaultwrap) {
case 0:
SHUT_LOGD("Default wrap mode is GL_REPEAT\n");
break;
case 1:
SHUT_LOGD("Default wrap mode is GL_CLAMP_TO_EDGE\n");
break;
case 2:
default:
globals4es.defaultwrap=2;
SHUT_LOGD("Default wrap mode is GL_CLAMP_TO_EDGE, enforced\n");
break;
}
}
GetEnvVarBool("LIBGL_NOTEXARRAY",&globals4es.notexarray,0);
if(globals4es.notexarray) {
SHUT_LOGD("No Texture Array in Shaders\n");
}
env(LIBGL_LOGSHADERERROR, globals4es.logshader, "Log errors compiling shaders to the console");
env(LIBGL_SHADERNOGLES, globals4es.shadernogles, "Remove GLES part in shader");
env(LIBGL_NOES2COMPAT, globals4es.noes2, "Don't expose GLX_EXT_create_context_es2_profile extension");
env(LIBGL_NORMALIZE, globals4es.normalize, "Force normals to be normalized on FPE shaders");
globals4es.dbgshaderconv=ReturnEnvVarIntDef("LIBGL_DBGSHADERCONV",0);
if(globals4es.dbgshaderconv) {
if(globals4es.dbgshaderconv==1)
globals4es.dbgshaderconv=15;
if(!(globals4es.dbgshaderconv&3)) // neither vertex or fragment
globals4es.dbgshaderconv|=3; // select both
if(!(globals4es.dbgshaderconv&12)) // neither before or after
globals4es.dbgshaderconv|=12; // select both
SHUT_LOGD_NOPREFIX("Log all shaders, before and after conversion, to the console: ");
if(globals4es.dbgshaderconv&4)
SHUT_LOGD_NOPREFIX("Before ");
if(globals4es.dbgshaderconv&8)
SHUT_LOGD_NOPREFIX("After ");
if(globals4es.dbgshaderconv&1)
SHUT_LOGD_NOPREFIX("Vertex ");
if(globals4es.dbgshaderconv&2)
SHUT_LOGD_NOPREFIX("Fragment ");
SHUT_LOGD_NOPREFIX("\n");
}
env(LIBGL_NOCLEAN, globals4es.noclean, "Don't clean Context when destroyed");
globals4es.glxrecycle = 1;
#ifndef NOEGL
if((globals4es.usepbuffer) || (globals4es.usefb))
globals4es.glxrecycle = 0;
int env_glxrecycle=ReturnEnvVarIntDef("LIBGL_GLXRECYCLE",-1);
if(globals4es.glxrecycle && env_glxrecycle==0 && !((globals4es.usepbuffer) || (globals4es.usefb))) {
globals4es.glxrecycle = 0;
SHUT_LOGD("glX Will NOT try to recycle EGL Surface\n");
}
if(env_glxrecycle==1)
globals4es.glxrecycle = 1;
if(globals4es.glxrecycle) {
SHUT_LOGD("glX Will try to recycle EGL Surface\n");
}
env(LIBGL_GLXNATIVE, globals4es.glxnative, "Don't filter GLXConfig with GLX_X_NATIVE_TYPE");
#endif
char cwd[4096];
if (getcwd(cwd, sizeof(cwd))!= NULL)
SHUT_LOGD("Current folder is:%s\n", cwd);
if(hardext.shader_fbfetch) {
env(LIBGL_SHADERBLEND, globals4es.shaderblend, "Blend will be handled in shaders");
}
if(hardext.prgbin_n>0 && !globals4es.notexarray) {
env(LIBGL_NOPSA, globals4es.nopsa, "Don't use PrecompiledShaderArchive");
if(globals4es.nopsa==0) {
cwd[0]='\0';
// TODO: What to do on ANDROID and EMSCRIPTEN?
const char* custom_psa = GetEnvVar("LIBGL_PSA_FOLDER");
#ifdef __linux__
const char* home = GetEnvVar("HOME");
if(custom_psa)
strcpy(cwd, custom_psa);
else if(home)
strcpy(cwd, home);
if(strlen(cwd))
if(cwd[strlen(cwd)]!='/')
strcat(cwd, "/");
#elif defined AMIGAOS4
if(custom_psa)
strcpy(cwd, custom_psa);
else
strcpy(cwd, "PROGDIR:");
#endif
if(strlen(cwd)) {
strcat(cwd, ".gl4es.psa");
fpe_InitPSA(cwd);
fpe_readPSA();
}
}
} else
SHUT_LOGD("Not using PSA (prgbin_n=%d, notexarray=%d)\n", hardext.prgbin_n, globals4es.notexarray);
env(LIBGL_SKIPTEXCOPIES, globals4es.skiptexcopies, "Texture Copies will be skipped");
if(GetEnvVarFloat("LIBGL_FB_TEX_SCALE",&globals4es.fbtexscale,0.0f)) {
SHUT_LOGD("Framebuffer Textures will be scaled by %.2f\n", globals4es.fbtexscale);
}
}
#ifndef NOX11
void FreeFBVisual();
#endif
#ifdef NO_INIT_CONSTRUCTOR
EXPORT
#else
#ifdef BUILD_WINDOWS_DLL
EXPORT // symmetric for init -- trivialize application code
#endif
#if !defined(_MSC_VER) || defined(__clang__)
__attribute__((destructor))
#endif
#endif
void close_gl4es() {
#ifdef GL4ES_COMPILE_FOR_USE_IN_SHARED_LIB
SHUT_LOGD("Shutdown requested\n");
if(--inited) return;
#endif
SHUT_LOGD("Shutting down\n");
#ifndef NOX11
FreeFBVisual();
#endif
gl_close();
fpe_writePSA();
fpe_FreePSA();
#if defined(GL4ES_COMPILE_FOR_USE_IN_SHARED_LIB) && defined(AMIGAOS4)
os4CloseLib();
#endif
}
#ifdef BUILD_WINDOWS_DLL
#if !defined(_MSC_VER) || defined(__clang__)
__attribute__((constructor(103)))
#endif
void dll_init_done()
{ dll_inited = 1; }
#endif
#if defined(_MSC_VER) && !defined(NO_INIT_CONSTRUCTOR) && !defined(__clang__)
#pragma const_seg(".CRT$XCU")
void (*const gl4es_ctors[])() = { initialize_gl4es, dll_init_done };
#pragma const_seg(".CRT$XTX")
void (*const gl4es_dtor)() = close_gl4es;
#pragma const_seg()
#endif
+89
View File
@@ -0,0 +1,89 @@
#ifndef _GL4ES_INIT_H_
#define _GL4ES_INIT_H_
#if defined(PANDORA)
#define USE_FBIO 1
#endif
typedef struct _globals4es {
int nobanner;
int mergelist;
int xrefresh;
int stacktrace;
int usefb;
int usegbm;
int usefbo;
int recyclefbo;
int usepbuffer;
int showfps;
int vsync;
int automipmap;
int texcopydata;
int tested_env;
int texshrink;
int texdump;
int alphahack;
int texstream;
int nolumalpha;
int blendhack;
int blendcolor;
int noerror;
int npot;
int defaultwrap;
int notexrect;
int queries;
int silentstub;
int glx_surface_srgb;
int nodownsampling;
int vabgra;
int nobgra;
int potframebuffer;
float gamma;
int texmat;
int novaocache;
int beginend;
int avoid16bits;
int avoid24bits;
int force16bits;
int nohighp;
int minbatch;
int maxbatch;
int es;
int gl;
int usevbo;
int comments;
int forcenpot;
int fbomakecurrent; // hack to bind/unbind FBO when doing glXMakeCurrent
int fbounbind; // hack to bind/unbind fbo if a bind texture is used for drawing
int fboforcetex; // force texture attachment for Color0
int blitfullscreen; // a "fullscreen" blit to FB0 means SwapBuffers
int notexarray;
int nodepthtex;
int logshader;
int shadernogles;
int floattex;
int glxrecycle;
int noclean;
int dbgshaderconv;
int nopsa;
int noes2;
int nointovlhack;
int noshaderlod;
int fbo_noalpha;
int noarbprogram; // to disable ARB Program
int glxnative;
int normalize; // force normal normalization (workaround a bug)
int blitfb0;
int skiptexcopies;
int shaderblend;
int deepbind;
float fbtexscale;
#ifndef NO_GBM
char drmcard[50];
#endif
char version[50];
} globals4es_t;
extern globals4es_t globals4es;
#endif // _GL4ES_INIT_H_
+441
View File
@@ -0,0 +1,441 @@
#include "light.h"
#include "../glx/hardext.h"
#include "fpe.h"
#include "loader.h"
#include "matrix.h"
#include "matvec.h"
void APIENTRY_GL4ES gl4es_glLightModelf(GLenum pname, GLfloat param) {
//printf("%sglLightModelf(%04X, %.2f)\n", (state.list.compiling)?"list":"", pname, param);
ERROR_IN_BEGIN
if(glstate->list.active)
if ((glstate->list.compiling)) {
GLfloat dummy[4];
dummy[0]=param;
gl4es_glLightModelfv(pname, dummy);
return;
} else gl4es_flush();
switch (pname) {
case GL_LIGHT_MODEL_TWO_SIDE:
errorGL();
glstate->light.two_side = param;
if(glstate->fpe_state)
glstate->fpe_state->twosided = param;
break;
case GL_LIGHT_MODEL_COLOR_CONTROL:
if(param!=GL_SINGLE_COLOR && param!=GL_SEPARATE_SPECULAR_COLOR ) {
errorShim(GL_INVALID_VALUE);
return;
} else {
GLboolean value = (param==GL_SEPARATE_SPECULAR_COLOR);
if(glstate->light.separate_specular == value) {
noerrorShim();
return;
}
glstate->light.separate_specular=value;
if(glstate->fpe_state)
glstate->fpe_state->light_separate=value;
}
return; // NOT Supported in GLES 1.1 anyway
case GL_LIGHT_MODEL_LOCAL_VIEWER:
{
GLboolean value = (param!=0.0);
if(glstate->light.local_viewer == value) {
noerrorShim();
return;
}
glstate->light.local_viewer=value;
if(glstate->fpe_state)
glstate->fpe_state->light_localviewer=value;
}
return; // NOT Supported in GLES 1.1 anyway
case GL_LIGHT_MODEL_AMBIENT:
default:
errorShim(GL_INVALID_ENUM);
return;
}
LOAD_GLES_FPE(glLightModelf);
gles_glLightModelf(pname, param);
}
void APIENTRY_GL4ES gl4es_glLightModelfv(GLenum pname, const GLfloat* params) {
//printf("%sglLightModelfv(%04X, [%.2f, %.2f, %.2f, %.2f])\n", (state.list.compiling)?"list":"", pname, params[0], params[1], params[2], params[3]);
ERROR_IN_BEGIN
if(glstate->list.active)
if ((glstate->list.compiling)) {
NewStage(glstate->list.active, STAGE_LIGHTMODEL);
/* if (glstate->list.active->lightmodel)
glstate->list.active = extend_renderlist(glstate->list.active);*/
glstate->list.active->lightmodelparam = pname;
glstate->list.active->lightmodel = (GLfloat*)malloc(4*sizeof(GLfloat));
int sz = 4;
if(pname==GL_LIGHT_MODEL_TWO_SIDE || pname==GL_LIGHT_MODEL_COLOR_CONTROL || pname==GL_LIGHT_MODEL_LOCAL_VIEWER)
sz=1;
memcpy(glstate->list.active->lightmodel, params, sz*sizeof(GLfloat));
noerrorShim();
return;
} else gl4es_flush();
switch (pname) {
case GL_LIGHT_MODEL_AMBIENT:
if(memcmp(glstate->light.ambient, params, 4*sizeof(GLfloat))==0) {
noerrorShim();
return;
}
errorGL();
memcpy(glstate->light.ambient, params, 4*sizeof(GLfloat));
break;
case GL_LIGHT_MODEL_TWO_SIDE:
if(glstate->light.two_side == params[0]) {
noerrorShim();
return;
}
errorGL();
glstate->light.two_side = params[0];
if(glstate->fpe_state)
glstate->fpe_state->twosided = params[0];
break;
case GL_LIGHT_MODEL_COLOR_CONTROL:
if(params[0]!=GL_SINGLE_COLOR && params[0]!=GL_SEPARATE_SPECULAR_COLOR ) {
errorShim(GL_INVALID_VALUE);
return;
} else {
GLboolean value = (params[0]==GL_SEPARATE_SPECULAR_COLOR);
if(glstate->light.separate_specular == value) {
noerrorShim();
return;
}
glstate->light.separate_specular=value;
if(glstate->fpe_state)
glstate->fpe_state->light_separate=value;
}
return; // NOT Supported in GLES 1.1 anyway
case GL_LIGHT_MODEL_LOCAL_VIEWER:
{
GLboolean value = (params[0]!=0.0);
if(glstate->light.local_viewer == value) {
noerrorShim();
return;
}
glstate->light.local_viewer=value;
if(glstate->fpe_state)
glstate->fpe_state->light_localviewer=value;
}
return; // NOT Supported in GLES 1.1 anyway
default:
errorShim(GL_INVALID_ENUM);
return;
}
LOAD_GLES_FPE(glLightModelfv);
gles_glLightModelfv(pname, params);
}
void APIENTRY_GL4ES gl4es_glLightfv(GLenum light, GLenum pname, const GLfloat* params) {
//printf("%sglLightfv(%s, %s, %p=[%.2f, %.2f, %.2f, %.2f])\n", (glstate->list.compiling)?"list":"", PrintEnum(light), PrintEnum(pname), params, (params)?params[0]:0.0f, (params)?params[1]:0.0f, (params)?params[2]:0.0f, (params)?params[3]:0.0f);
const int nl = light-GL_LIGHT0;
if(nl<0 || nl>=hardext.maxlights) {
errorShim(GL_INVALID_ENUM);
return;
}
ERROR_IN_BEGIN
if(glstate->list.active)
if (glstate->list.compiling) {
NewStage(glstate->list.active, STAGE_LIGHT);
rlLightfv(glstate->list.active, light, pname, params);
noerrorShim();
return;
} else gl4es_flush();
GLfloat tmp[4];
noerrorShim();
switch(pname) {
case GL_AMBIENT:
if(memcmp(glstate->light.lights[nl].ambient, params, 4*sizeof(GLfloat))==0)
return;
memcpy(glstate->light.lights[nl].ambient, params, 4*sizeof(GLfloat));
break;
case GL_DIFFUSE:
if(memcmp(glstate->light.lights[nl].diffuse, params, 4*sizeof(GLfloat))==0)
return;
memcpy(glstate->light.lights[nl].diffuse, params, 4*sizeof(GLfloat));
break;
case GL_SPECULAR:
if(memcmp(glstate->light.lights[nl].specular, params, 4*sizeof(GLfloat))==0)
return;
memcpy(glstate->light.lights[nl].specular, params, 4*sizeof(GLfloat));
break;
case GL_POSITION:
vector_matrix(params, getMVMat(), tmp);
if(memcmp(glstate->light.lights[nl].position, tmp, 4*sizeof(GLfloat))==0)
return;
memcpy(glstate->light.lights[nl].position, tmp, 4*sizeof(GLfloat));
if(glstate->fpe_state) {
int dir = (tmp[3]!=0.f);
if (dir) {
glstate->fpe_state->light_direction |= (1<<nl);
} else {
glstate->fpe_state->light_direction &= ~(1<<nl);
}
}
break;
case GL_SPOT_DIRECTION:
vector3_matrix4(params,getMVMat(), tmp);
if(memcmp(glstate->light.lights[nl].spotDirection, tmp, 3*sizeof(GLfloat))==0)
return;
memcpy(glstate->light.lights[nl].spotDirection, tmp, 3*sizeof(GLfloat));
break;
case GL_SPOT_EXPONENT:
if(params[0]<0 || params[0]>128) {
errorShim(GL_INVALID_VALUE);
return;
}
if(glstate->light.lights[nl].spotExponent == params[0])
return;
glstate->light.lights[nl].spotExponent = params[0];
break;
case GL_SPOT_CUTOFF:
if(params[0]<0.f || (params[0]>90.0f && params[0]!=180.f)) {
errorShim(GL_INVALID_VALUE);
return;
}
if(glstate->light.lights[nl].spotCutoff == params[0])
return;
glstate->light.lights[nl].spotCutoff = params[0];
if(glstate->fpe_state) {
int dir = (params[0]!=180.f);
if (dir) {
glstate->fpe_state->light_cutoff180 |= (1<<nl);
} else {
glstate->fpe_state->light_cutoff180 &= ~(1<<nl);
}
}
break;
case GL_CONSTANT_ATTENUATION:
if(params[0]<0) {
errorShim(GL_INVALID_VALUE);
return;
}
if(glstate->light.lights[nl].constantAttenuation == params[0])
return;
glstate->light.lights[nl].constantAttenuation = params[0];
break;
case GL_LINEAR_ATTENUATION:
if(params[0]<0) {
errorShim(GL_INVALID_VALUE);
return;
}
if(glstate->light.lights[nl].linearAttenuation == params[0])
return;
glstate->light.lights[nl].linearAttenuation = params[0];
break;
case GL_QUADRATIC_ATTENUATION:
if(params[0]<0) {
errorShim(GL_INVALID_VALUE);
return;
}
if(glstate->light.lights[nl].quadraticAttenuation == params[0])
return;
glstate->light.lights[nl].quadraticAttenuation = params[0];
break;
}
LOAD_GLES_FPE(glLightfv);
gles_glLightfv(light, pname, params);
errorGL();
}
void APIENTRY_GL4ES gl4es_glLightf(GLenum light, GLenum pname, GLfloat param) {
GLfloat dummy[4];
dummy[0]=param;
gl4es_glLightfv(light, pname, dummy);
}
void APIENTRY_GL4ES gl4es_glMaterialfv(GLenum face, GLenum pname, const GLfloat *params) {
if(glstate->list.active)
if(glstate->list.begin) {
// if a glMaterialfv is called inside a glBegin/glEnd block
// then use rlMaterial to store in current list the material wanted
// as if the material was asked before the glBegin()
// It's not real behavour, but it's better then nothing
rlMaterialfv(glstate->list.active, face, pname, params);
noerrorShim();
return;
} else {
if (glstate->list.compiling) {
NewStage(glstate->list.active, STAGE_MATERIAL);
rlMaterialfv(glstate->list.active, face, pname, params);
noerrorShim();
return;
} else gl4es_flush();
}
if(face!=GL_FRONT_AND_BACK && face!=GL_FRONT && face!=GL_BACK) {
errorShim(GL_INVALID_ENUM);
return;
}
switch(pname) {
case GL_AMBIENT:
if(face==GL_FRONT_AND_BACK || face==GL_FRONT)
memcpy(glstate->material.front.ambient, params, 4*sizeof(GLfloat));
if(face==GL_FRONT_AND_BACK || face==GL_BACK)
memcpy(glstate->material.back.ambient, params, 4*sizeof(GLfloat));
break;
case GL_DIFFUSE:
if(face==GL_FRONT_AND_BACK || face==GL_FRONT)
memcpy(glstate->material.front.diffuse, params, 4*sizeof(GLfloat));
if(face==GL_FRONT_AND_BACK || face==GL_BACK)
memcpy(glstate->material.back.diffuse, params, 4*sizeof(GLfloat));
break;
case GL_SPECULAR:
if(face==GL_FRONT_AND_BACK || face==GL_FRONT)
memcpy(glstate->material.front.specular, params, 4*sizeof(GLfloat));
if(face==GL_FRONT_AND_BACK || face==GL_BACK)
memcpy(glstate->material.back.specular, params, 4*sizeof(GLfloat));
break;
case GL_EMISSION:
if(face==GL_FRONT_AND_BACK || face==GL_FRONT)
memcpy(glstate->material.front.emission, params, 4*sizeof(GLfloat));
if(face==GL_FRONT_AND_BACK || face==GL_BACK)
memcpy(glstate->material.back.emission, params, 4*sizeof(GLfloat));
break;
case GL_AMBIENT_AND_DIFFUSE:
if(face==GL_FRONT_AND_BACK || face==GL_FRONT) {
memcpy(glstate->material.front.ambient, params, 4*sizeof(GLfloat));
memcpy(glstate->material.front.diffuse, params, 4*sizeof(GLfloat));
}
if(face==GL_FRONT_AND_BACK || face==GL_BACK) {
memcpy(glstate->material.back.ambient, params, 4*sizeof(GLfloat));
memcpy(glstate->material.back.diffuse, params, 4*sizeof(GLfloat));
}
break;
case GL_SHININESS:
if(*params<0.0f || *params>128.0f) {
errorShim(GL_INVALID_VALUE);
return;
}
if(face==GL_FRONT_AND_BACK || face==GL_FRONT) {
glstate->material.front.shininess = *params;
if(glstate->fpe_state)
glstate->fpe_state->cm_front_nullexp=(*params<=0.0)?0:1;
}
if(face==GL_FRONT_AND_BACK || face==GL_BACK) {
glstate->material.back.shininess = *params;
if(glstate->fpe_state)
glstate->fpe_state->cm_back_nullexp=(*params<=0.0)?0:1;
}
break;
case GL_COLOR_INDEXES:
if(face==GL_FRONT_AND_BACK || face==GL_FRONT) {
glstate->material.front.indexes[0] = params[0];
glstate->material.front.indexes[1] = params[1];
glstate->material.front.indexes[2] = params[2];
}
if(face==GL_FRONT_AND_BACK || face==GL_BACK) {
glstate->material.back.indexes[0] = params[0];
glstate->material.back.indexes[1] = params[1];
glstate->material.back.indexes[2] = params[2];
}
break;
}
if(face==GL_BACK && hardext.esversion==1) { // lets ignore GL_BACK in GLES 1.1
noerrorShim();
return;
}
LOAD_GLES_FPE(glMaterialfv);
gles_glMaterialfv(GL_FRONT_AND_BACK, pname, params);
errorGL();
}
void APIENTRY_GL4ES gl4es_glMaterialf(GLenum face, GLenum pname, GLfloat param) {
ERROR_IN_BEGIN
if(glstate->list.active)
if (glstate->list.compiling) {
GLfloat params[4];
memset(params, 0, 4*sizeof(GLfloat));
params[0] = param;
NewStage(glstate->list.active, STAGE_MATERIAL);
rlMaterialfv(glstate->list.active, face, pname, params);
noerrorShim();
return;
}
if(face!=GL_FRONT_AND_BACK && face!=GL_FRONT && face!=GL_BACK) {
errorShim(GL_INVALID_ENUM);
return;
}
if(pname!=GL_SHININESS) {
errorShim(GL_INVALID_ENUM);
return;
}
if(param<0.0f || param>128.0f) {
errorShim(GL_INVALID_VALUE);
return;
}
if(face==GL_FRONT_AND_BACK || face==GL_FRONT) {
if(glstate->material.front.shininess == param)
return;
glstate->material.front.shininess = param;
}
if(face==GL_FRONT_AND_BACK || face==GL_BACK) {
if(glstate->material.back.shininess == param)
return;
glstate->material.back.shininess = param;
}
if(face==GL_BACK && hardext.esversion==1) { // lets ignore GL_BACK in GLES 1.1
noerrorShim();
return;
}
FLUSH_BEGINEND;
LOAD_GLES_FPE(glMaterialf);
gles_glMaterialf(GL_FRONT_AND_BACK, pname, param);
errorGL();
}
void APIENTRY_GL4ES gl4es_glColorMaterial(GLenum face, GLenum mode) {
ERROR_IN_BEGIN
if(glstate->list.active)
if (glstate->list.compiling) {
NewStage(glstate->list.active, STAGE_COLOR_MATERIAL);
glstate->list.active->colormat_face = face;
glstate->list.active->colormat_mode = mode;
noerrorShim();
return;
} else gl4es_flush();
if(face!=GL_FRONT_AND_BACK && face!=GL_FRONT && face!=GL_BACK) {
errorShim(GL_INVALID_ENUM);
return;
}
if(mode!=GL_EMISSION && mode!=GL_AMBIENT && mode!=GL_DIFFUSE && mode!=GL_SPECULAR && mode!=GL_AMBIENT_AND_DIFFUSE) {
errorShim(GL_INVALID_ENUM);
return;
}
if(face==GL_FRONT_AND_BACK || face==GL_FRONT)
glstate->material.front.colormat = mode;
if(face==GL_FRONT_AND_BACK || face==GL_BACK)
glstate->material.back.colormat = mode;
if(glstate->fpe_state) {
int value = FPE_CM_AMBIENTDIFFUSE;
switch(mode) {
case GL_EMISSION: value = FPE_CM_EMISSION; break;
case GL_AMBIENT: value=FPE_CM_AMBIENT; break;
case GL_DIFFUSE: value=FPE_CM_DIFFUSE; break;
case GL_SPECULAR: value=FPE_CM_SPECULAR; break;
}
if(face==GL_FRONT_AND_BACK || face==GL_FRONT) {
glstate->fpe_state->cm_front_mode = value;
}
if(face==GL_FRONT_AND_BACK || face==GL_BACK) {
glstate->fpe_state->cm_back_mode = value;
}
}
noerrorShim();
}
AliasExport(void,glLightModelf,,(GLenum pname, GLfloat param));
AliasExport(void,glLightModelfv,,(GLenum pname, const GLfloat* params));
AliasExport(void,glLightfv,,(GLenum light, GLenum pname, const GLfloat* params));
AliasExport(void,glLightf,,(GLenum light, GLenum pname, GLfloat param));
AliasExport(void,glMaterialfv,,(GLenum face, GLenum pname, const GLfloat *params));
AliasExport(void,glMaterialf,,(GLenum face, GLenum pname, GLfloat param));
AliasExport(void,glColorMaterial,,(GLenum face, GLenum mode));
+53
View File
@@ -0,0 +1,53 @@
#ifndef _GL4ES_LIGHT_H_
#define _GL4ES_LIGHT_H_
#include "gles.h"
#include "../config.h"
typedef struct {
GLfloat ambient[4];
GLfloat diffuse[4];
GLfloat specular[4];
GLfloat constantAttenuation, linearAttenuation, quadraticAttenuation;
GLfloat position[4];
GLfloat spotDirection[3]; // It's only 3 in fact, because it's a direction
GLfloat spotExponent;
GLfloat spotCutoff;
} light_t;
typedef struct {
light_t lights[MAX_LIGHT];
GLfloat ambient[4];
GLboolean two_side;
GLboolean separate_specular;
GLboolean local_viewer;
} light_state_t;
typedef struct {
GLfloat ambient[4];
GLfloat diffuse[4];
GLfloat specular[4];
GLfloat emission[4];
GLfloat shininess;
int indexes[3];
GLenum colormat;
} material_t;
typedef struct {
material_t front;
material_t back;
} material_state_t;
void APIENTRY_GL4ES gl4es_glLightModelf(GLenum pname, GLfloat param);
void APIENTRY_GL4ES gl4es_glLightModelfv(GLenum pname, const GLfloat* params);
void APIENTRY_GL4ES gl4es_glLightfv(GLenum light, GLenum pname, const GLfloat* params);
void APIENTRY_GL4ES gl4es_glLightf(GLenum light, GLenum pname, GLfloat params);
void APIENTRY_GL4ES gl4es_glGetLightfv(GLenum light, GLenum pname, GLfloat * params);
void APIENTRY_GL4ES gl4es_glGetLightiv(GLenum light, GLenum pname, GLint * params);
void APIENTRY_GL4ES gl4es_glMaterialfv(GLenum face, GLenum pname, const GLfloat *params) ;
void APIENTRY_GL4ES gl4es_glMaterialf(GLenum face, GLenum pname, GLfloat param);
void APIENTRY_GL4ES gl4es_glColorMaterial(GLenum face, GLenum mode);
#endif // _GL4ES_LIGHT_H_
+166
View File
@@ -0,0 +1,166 @@
#include "line.h"
#include <stdio.h>
#include "debug.h"
#include "gl4es.h"
#include "glstate.h"
#include "list.h"
#include "matrix.h"
#include "matvec.h"
//#define DEBUG
#ifdef DEBUG
#define DBG(a) a
#else
#define DBG(a)
#endif
void APIENTRY_GL4ES gl4es_glLineStipple(GLuint factor, GLushort pattern) {
DBG(printf("glLineStipple(%d, 0x%04X)\n", factor, pattern);)
if(glstate->list.active) {
if (glstate->list.compiling) {
NewStage(glstate->list.active, STAGE_LINESTIPPLE);
glstate->list.active->linestipple_op = 1;
glstate->list.active->linestipple_factor = factor;
glstate->list.active->linestipple_pattern = pattern;
return;
} else gl4es_flush();
}
if(factor<1) factor = 1;
if(factor>256) factor = 256;
if(pattern!=glstate->linestipple.pattern || factor!=glstate->linestipple.factor || !glstate->linestipple.texture) {
glstate->linestipple.factor = factor;
glstate->linestipple.pattern = pattern;
for (int i = 0; i < 16; i++) {
glstate->linestipple.data[i] = ((pattern >> i) & 1) ? 255 : 0;
}
// "Push" current Texture0 binding
GLuint old_act = glstate->texture.active;
if(old_act)
gl4es_glActiveTexture(GL_TEXTURE0);
GLuint old_tex = glstate->texture.bound[0][ENABLED_TEX2D]->texture;
// create / update stipple texture
if (! glstate->linestipple.texture) {
gl4es_glGenTextures(1, &glstate->linestipple.texture);
gl4es_glBindTexture(GL_TEXTURE_2D, glstate->linestipple.texture);
gl4es_glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
gl4es_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
gl4es_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
gl4es_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
gl4es_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
gl4es_glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA,
16, 1, 0, GL_ALPHA, GL_UNSIGNED_BYTE, glstate->linestipple.data);
} else {
gl4es_glBindTexture(GL_TEXTURE_2D, glstate->linestipple.texture);
gl4es_glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 16, 1,
GL_ALPHA, GL_UNSIGNED_BYTE, glstate->linestipple.data);
}
// "Pop" texture 0 binding
gl4es_glBindTexture(GL_TEXTURE_2D, old_tex);
if(old_act)
gl4es_glActiveTexture(GL_TEXTURE0+old_act);
// all done
noerrorShim();
}
}
AliasExport(void,glLineStipple,,(GLuint factor, GLushort pattern));
void bind_stipple_tex() {
gl4es_glBindTexture(GL_TEXTURE_2D, glstate->linestipple.texture);
}
GLfloat *gen_stipple_tex_coords(GLfloat *vert, GLushort *sindices, modeinit_t *modes, int stride, int length, GLfloat* noalloctex) {
DBG(printf("Generate stripple tex (stride=%d, noalloctex=%p) length=%d:", stride, noalloctex, length);)
// generate our texture coords
GLfloat *tex = noalloctex?noalloctex:(GLfloat *)malloc(modes[length-1].ilen * 4 * sizeof(GLfloat));
GLfloat *texPos = tex;
GLfloat *vertPos = vert;
GLfloat x1, x2, y1, y2;
GLfloat oldlen, len;
const GLfloat* mvp = getMVPMat();
GLfloat v[4];
GLfloat w = (GLfloat)glstate->raster.viewport.width;
GLfloat h = (GLfloat)glstate->raster.viewport.height;
if(stride==0) stride = 4; else stride/=sizeof(GLfloat);
int texstride = noalloctex?stride:4;
// projected coordinates here, and transform to screen pixel using viewport
// because projected coordinates are from -1. to +1., w and h are to be divided by 2...
w*=0.5f; h*=0.5f;
int i=0;
for (int k=0; k<length; k++) {
GLenum mode = modes[k].mode_init;
DBG(printf("[%s->%d] ", PrintEnum(mode), modes[k].ilen);)
oldlen = len = 0.f;
if(modes[k].ilen<2)
continue;
if(mode==GL_LINES || length>1) // always line when multiple lines were merged
for (; i < modes[k].ilen; i+=2) {
if(sindices)
vertPos = vert+stride*sindices[i];
vector_matrix(vertPos, mvp, v);
if(sindices)
vertPos = vert+stride*sindices[i+1];
else
vertPos+=stride;
// need to take "w" componant into acount...
if(v[3]==0.0f) {
x1=v[0]*w; y1=v[1]*h;
} else {
x1=(v[0]/v[3])*w; y1=(v[1]/v[3])*h;
}
vector_matrix(vertPos, mvp, v);
vertPos+=stride;
if(v[3]==0.0f) {
x2=v[0]*w; y2=v[1]*h;
} else {
x2=(v[0]/v[3])*w; y2=(v[1]/v[3])*h;
}
oldlen = len;
len += sqrtf((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1)) / (glstate->linestipple.factor * 16.f);
DBG(printf("%f->%f (%f,%f -> %f,%f)\t", oldlen, len, x1, y1, x2, y2);)
if(sindices)
texPos = tex+texstride*sindices[i+0]; // it get writen 2*, but that should be ok, it's the same value
memset(texPos, 0, 4*sizeof(GLfloat));
texPos[0] = oldlen; texPos[3] = 1.0f;
if(sindices)
texPos = tex+texstride*sindices[i+1];
else
texPos+=texstride;
memset(texPos, 0, 4*sizeof(GLfloat));
texPos[0] = len; texPos[3] = 1.0f;
texPos+=texstride;
}
else { // GL_LINE_STRIP and GL_LINE_LOOPS works the same here
// (well, last segment, the "loop" one, will look strange, but I will not add a vertex for that)
if(sindices)
vertPos = vert+stride*sindices[i];
vector_matrix(vertPos, mvp, v);
x2=(v[0]/v[3])*w; y2=(v[1]/v[3])*h;
vertPos+=stride;
DBG(printf("%f\t", len);)
memset(texPos, 0, 4*sizeof(GLfloat));
texPos[0] = len; texPos[3] = 1.0f;
texPos+=texstride;
++i;
for (; i < modes[k].ilen; i++) {
x1 = x2; y1 = y2;
if(sindices)
vertPos = vert+stride*sindices[i];
vector_matrix(vertPos, mvp, v);
vertPos+=stride;
x2=(v[0]/v[3])*w; y2=(v[1]/v[3])*h;
len += sqrtf((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1)) / (glstate->linestipple.factor * 16.f);
DBG(printf("->%f\t", len);)
if(sindices)
texPos = tex+texstride*sindices[i];
memset(texPos, 0, 4*sizeof(GLfloat));
texPos[0] = len; texPos[3] = 1.0f;
texPos+=texstride;
}
}
}
DBG(printf("\n");)
return tex;
}
+11
View File
@@ -0,0 +1,11 @@
#ifndef _GL4ES_LINE_H
#define _GL4ES_LINE_H
#include "gles.h"
#include "list.h"
void APIENTRY_GL4ES gl4es_glLineStipple(GLuint factor, GLushort pattern);
GLfloat *gen_stipple_tex_coords(GLfloat *vert, GLushort *sindices, modeinit_t *modes, int stride, int length, GLfloat* noalloctex);
void bind_stipple_tex();
#endif // _GL4ES_LINE_H
+971
View File
@@ -0,0 +1,971 @@
#include "list.h"
#include "../glx/hardext.h"
#include "const.h"
#include "gl4es.h"
#include "glstate.h"
#include "init.h"
#include "loader.h"
#include "buffers.h"
// KH Map implementation
KHASH_MAP_IMPL_INT(material, rendermaterial_t *);
KHASH_MAP_IMPL_INT(light, renderlight_t *);
KHASH_MAP_IMPL_INT(texgen, rendertexgen_t *);
KHASH_MAP_IMPL_INT(texenv, rendertexenv_t *);
KHASH_MAP_IMPL_INT(gllisthead, renderlist_t*);
renderlist_t *alloc_renderlist() {
renderlist_t *list = (renderlist_t *)malloc(sizeof(renderlist_t));
memset(list, 0, sizeof(renderlist_t));
list->cap = DEFAULT_RENDER_LIST_CAPACITY;
list->matrix_val[0] = list->matrix_val[5] = list->matrix_val[10] =
list->matrix_val[15] = 1.0f;
list->lightmodelparam = GL_LIGHT_MODEL_AMBIENT;
list->target_texture = GL_TEXTURE_2D;
list->tmu = glstate->texture.active;
memcpy(list->lastNormal, glstate->normal, 3*sizeof(GLfloat));
memcpy(list->lastSecondaryColors, glstate->secondary, 3*sizeof(GLfloat));
memcpy(list->lastColors, glstate->color, 4*sizeof(GLfloat));
memcpy(&list->lastFogCoord, glstate->fogcoord, 1*sizeof(GLfloat));
list->instanceCount = 1;
list->open = true;
return list;
}
bool ispurerender_renderlist(renderlist_t *list) {
// return true if renderlist contains only rendering command, no state changes
if (list->calls.len)
return false;
if (list->matrix_op)
return false;
if (list->raster_op)
return false;
if (list->raster)
return false;
if (list->bitmaps)
return false;
if (list->pushattribute)
return false;
if (list->popattribute)
return false;
if (list->material || list->colormat_face || list->light || list->lightmodel || list->texgen || list->texenv)
return false;
if (list->fog_op)
return false;
if (list->instanceCount!=1)
return false;
if (list->pointparam_op)
return false;
if (list->mode_init == 0)
return false;
if (list->ind_lines || list->final_colors)
return false;
if (list->set_texture || list->set_tmu)
return false;
return true;
}
bool isempty_renderlist(renderlist_t *list) {
return (list->stage == STAGE_NONE);
}
int rendermode_dimensions(GLenum mode) {
// return 1 for points, 2 for any lines, 3 for any triangles, 4 for any Quad and 5 for polygon
switch (mode) {
case GL_POINTS:
return 1;
case GL_LINES:
case GL_LINE_LOOP:
case GL_LINE_STRIP:
return 2;
case GL_TRIANGLES:
case GL_TRIANGLE_FAN:
case GL_TRIANGLE_STRIP:
return 3;
case GL_QUADS:
case GL_QUAD_STRIP:
return 3; // It's 4, but we use only triangles...
case GL_POLYGON:
return 3; // It's 5, but we use only triangles too.
}
return 0;
}
bool islistscompatible_renderlist(renderlist_t *a, renderlist_t *b) {
if (!globals4es.mergelist || !a)
return false;
// check if 2 "pure rendering" list are compatible for merge
if (a->mode_init != b->mode_init) {
int a_mode = a->mode_dimension;
int b_mode = b->mode_dimension;
if ((a_mode == 0) || (b_mode == 0))
return false; // undetermined is not good
if (a_mode == 4) a_mode = 3; // quads are handled as triangles
if (b_mode == 4) b_mode = 3;
if (a_mode != b_mode)
return false;
}
if(a->use_vbo_array==2 || b->use_vbo_array==2)
return false;
if(a->use_vbo_indices==2 || b->use_vbo_indices==2)
return false;
if(!a->open || !b->open)
return false;
if(a->use_glstate)
return false; //TODO: Handle this case
/* if ((a->indices==NULL) != (b->indices==NULL))
return false;*/
if (a->polygon_mode != b->polygon_mode)
return false;
if ((a->vert==NULL) != (b->vert==NULL))
return false;
if ((a->normal==NULL) != (b->normal==NULL))
return false;
if ((a->color==NULL) != (b->color==NULL))
return false;
if ((a->secondary==NULL) != (b->secondary==NULL))
return false;
if ((a->fogcoord==NULL) != (b->fogcoord==NULL))
return false;
// check the textures
if(a->maxtex!=b->maxtex)
return false;
for (int i=0; i<a->maxtex; i++)
if ((a->tex[i]==NULL) != (b->tex[i]==NULL))
return false;
if ((a->set_texture==b->set_texture) && ((a->texture != b->texture) || (a->target_texture != b->target_texture)))
return false;
if (!a->set_texture && b->set_texture)
return false;
// post color is only important if b as no color pointer...
if(a->post_color && b->color==NULL)
return false;
// same for post_normal
if(a->post_normal && b->normal==NULL)
return false;
// check instanceCount (maybe it would be better to just check if both are == 1)
if(a->instanceCount != b->instanceCount)
return false;
// Check the size of a list, if it"s too big, don't merge...
if ((a->len+b->len)>60000)
return false;
if ((a->ilen+b->ilen)>60000)
return false;
return true;
}
void renderlist_createindices(int ilen, GLushort *indices, int count) {
for (int i = 0; i<ilen; i++) {
indices[i] = i+count;
}
}
#define vind(a) (((ind)?ind[(a)]:(a))+count)
void renderlist_lineloop_lines(GLushort *ind, int len, GLushort *indices, int count) {
int ilen = len*2; // new size is 2* + return
if(len>1) {
int k=0;
indices[k++] = vind(0);
indices[k++] = vind(1);
for (int i = 2; i<len; i++) {
indices[k++] = vind(i-1);
indices[k++] = vind(i);
}
// go back to initial point
indices[k++] = indices[(len-1)*2-1];
indices[k++] = indices[0];
}
}
void renderlist_linestrip_lines(GLushort *ind, int len, GLushort *indices, int count) {
int ilen = len*2-2; // new size is 2*
if (ilen<1) ilen=0;
if(len>1) {
int k=0;
indices[k++] = vind(0);
indices[k++] = vind(1);
for (int i = 2; i<len; i++) {
indices[k++] = vind(i-1);
indices[k++] = vind(i);
}
}
}
void renderlist_trianglestrip_triangles(GLushort *ind, int len, GLushort *indices, int count) {
int ilen = (len-2)*3;
if (ilen<0) ilen=0;
for (int i = 2; i<len; i++) {
indices[(i-2)*3+(i%2)] = vind(i-2);
indices[(i-2)*3+1-(i%2)] = vind(i-1);
indices[(i-2)*3+2] = vind(i);
}
}
void renderlist_trianglefan_triangles(GLushort *ind, int len, GLushort *indices, int count) {
int ilen = (len-2)*3;
if (ilen<0) ilen=0;
for (int i = 2; i<len; i++) {
indices[(i-2)*3+0] = vind(0);
indices[(i-2)*3+1] = vind(i-1);
indices[(i-2)*3+2] = vind(i);
}
}
void renderlist_quads_triangles(GLushort *ind, int len, GLushort *indices, int count) {
// len must be a multiple of 4 !
len &= ~3; // discard extra vertex...
int ilen = len*3/2;
for (int i=0, j=0; i+3<len; i+=4, j+=6) {
indices[j+0] = vind(i+0);
indices[j+1] = vind(i+1);
indices[j+2] = vind(i+2);
indices[j+3] = vind(i+0);
indices[j+4] = vind(i+2);
indices[j+5] = vind(i+3);
}
}
#undef vind
#define vind(a) ((ind)?ind[(a)]:(a))
void renderlist_quads2triangles(renderlist_t *a) {
GLushort *ind = a->indices;
int len = (ind)? a->ilen:a->len;
// len must be a multiple of 4 !
len &= ~3; // discard extra vertex...
int ilen = len*3/2;
if(a->use_glstate) {
if(ind) {//need to copy first...
ind = (GLushort*)malloc(len*sizeof(GLushort));
memcpy(ind, glstate->merger_indices, len*sizeof(GLushort));
a->shared_indices = NULL; // should not be needed
}
resize_merger_indices(ilen);
a->indices = glstate->merger_indices;
} else
a->indices = (GLushort*)malloc(ilen*sizeof(GLushort));
for (int i=0, j=0; i+3<len; i+=4, j+=6) {
a->indices[j+0] = vind(i+0);
a->indices[j+1] = vind(i+1);
a->indices[j+2] = vind(i+2);
a->indices[j+3] = vind(i+0);
a->indices[j+4] = vind(i+2);
a->indices[j+5] = vind(i+3);
}
a->ilen = ilen;
if (ind) {
if (!a->shared_indices || ((*a->shared_indices)--)==0) {
free(ind);
free(a->shared_indices);
}
a->shared_indices = NULL; // unshared list
}
a->mode = GL_TRIANGLES;
}
#undef vind
int indices_getindicesize(GLenum mode, int len) {
int ilen_a;
switch (mode) {
case GL_LINE_LOOP:
ilen_a = len*2;
if (ilen_a<0) ilen_a=1; // special borked case...
break;
case GL_LINE_STRIP:
ilen_a = (len*2)-2;
if (ilen_a<0) ilen_a=1; // special borked case...
break;
case GL_QUAD_STRIP:
case GL_TRIANGLE_STRIP:
case GL_TRIANGLE_FAN:
case GL_POLYGON:
ilen_a = (len-2)*3;
if (ilen_a<0) ilen_a=1; // special borked case...
break;
case GL_QUADS:
ilen_a = ((len&~3)*3)/2;
break;
default:
ilen_a = len;
break;
}
return ilen_a;
}
int renderlist_getindicesize(renderlist_t *a) {
int ilen_a = indices_getindicesize(a->mode, ((a->indices)? a->ilen:a->len));
return ilen_a;
}
int mode_needindices(GLenum m) {
switch(m) {
case GL_LINE_LOOP:
case GL_LINE_STRIP:
case GL_TRIANGLE_FAN:
case GL_TRIANGLE_STRIP:
case GL_QUAD_STRIP:
case GL_POLYGON:
//case GL_QUADS: // not needed, but will appens anyway
return 1;
default:
return 0;
}
}
void list_add_modeinit(renderlist_t* list, GLenum mode) {
if (list->mode_init_len+1 >= list->mode_init_cap) {
list->mode_init_cap+=128;
list->mode_inits = (modeinit_t*)realloc(list->mode_inits, list->mode_init_cap*sizeof(modeinit_t));
}
list->mode_inits[list->mode_init_len].mode_init = mode;
list->mode_inits[list->mode_init_len++].ilen = list->indices?list->ilen:(list->cur_istart?list->cur_istart:list->len);
}
void unshared_renderlist(renderlist_t *a, int cap) {
if(a->shared_arrays && ((*a->shared_arrays)--)>0) {
a->cap = cap;
GLfloat *tmp;
tmp = a->vert;
if (tmp) {
a->vert = alloc_sublist(4, cap);
memcpy(a->vert, tmp, 4*a->len*sizeof(GLfloat));
}
tmp = a->normal;
if (tmp) {
a->normal = alloc_sublist(3, cap);
memcpy(a->normal, tmp, 3*a->len*sizeof(GLfloat));
}
tmp = a->color;
if (tmp) {
a->color = alloc_sublist(4, cap);
memcpy(a->color, tmp, 4*a->len*sizeof(GLfloat));
}
tmp = a->secondary;
if (tmp) {
a->secondary = alloc_sublist(4, cap);
memcpy(a->secondary, tmp, 4*a->len*sizeof(GLfloat));
}
tmp = a->fogcoord;
if (tmp) {
a->fogcoord = alloc_sublist(1, cap);
memcpy(a->fogcoord, tmp, 1*a->len*sizeof(GLfloat));
}
for (int i=0; i<a->maxtex; i++) {
tmp = a->tex[i];
if (tmp) {
a->tex[i] = alloc_sublist(4, cap);
memcpy(a->tex[i], tmp, 4*a->len*sizeof(GLfloat));
}
}
}
if(a->shared_arrays && (*a->shared_arrays)==0) {
free(a->shared_arrays);
a->shared_arrays=NULL;
}
}
void unsharedindices_renderlist(renderlist_t* a, int cap)
{
if (a->shared_indices && ((*a->shared_indices)--)>0) {
if (a->indices) {
GLushort* tmpi = a->indices;
a->indice_cap = cap;
if (a->indice_cap > 48) a->indice_cap = ((a->indice_cap+512)>>9)<<9;
a->indices = (GLushort*)malloc(a->indice_cap*sizeof(GLushort));
memcpy(a->indices, tmpi, a->ilen*sizeof(GLushort));
}
}
if(a->shared_indices && (*a->shared_indices)==0) {
free(a->shared_indices);
a->shared_indices=0;
}
}
void redim_renderlist(renderlist_t *a, int cap) {
if (a->cap < cap) {
a->cap = cap;
realloc_sublist(a->vert, 4, cap);
realloc_sublist(a->normal, 3, cap);
realloc_sublist(a->color, 4, cap);
realloc_sublist(a->secondary, 4, cap);
realloc_sublist(a->fogcoord, 1, cap);
for (int i=0; i<a->maxtex; i++)
realloc_sublist(a->tex[i], 4, cap);
}
}
void prepareadd_renderlist(renderlist_t* a, int size_to_add)
{
// alloc or realloc a->indices first...
int capindices = renderlist_getindicesize(a)+size_to_add;
if (capindices > 48) capindices = ((capindices+512)>>9)<<9;
#define alloc_a_indices \
newind=(GLushort*)malloc(capindices*sizeof(GLushort))
#define copy_a_indices \
if (a->indices) free(a->indices); \
a->indices = newind; \
a->indice_cap = capindices
// check if "a" needs to be converted
int ilen_a = renderlist_getindicesize(a);
GLushort *newind=NULL;
switch (a->mode) {
case GL_LINE_LOOP:
alloc_a_indices;
renderlist_lineloop_lines(a->indices, a->indices?a->ilen:a->len, newind, 0);
a->mode = GL_LINES;
copy_a_indices;
break;
case GL_LINE_STRIP:
alloc_a_indices;
renderlist_linestrip_lines(a->indices, a->indices?a->ilen:a->len, newind, 0);
a->mode = GL_LINES;
copy_a_indices;
break;
case GL_QUAD_STRIP:
case GL_TRIANGLE_STRIP:
alloc_a_indices;
renderlist_trianglestrip_triangles(a->indices, a->indices?a->ilen:a->len, newind, 0);
a->mode = GL_TRIANGLES;
copy_a_indices;
break;
case GL_TRIANGLE_FAN:
case GL_POLYGON:
alloc_a_indices;
renderlist_trianglefan_triangles(a->indices, a->indices?a->ilen:a->len, newind, 0);
a->mode = GL_TRIANGLES;
copy_a_indices;
break;
case GL_QUADS:
alloc_a_indices;
renderlist_quads_triangles(a->indices, a->indices?a->ilen:a->len, newind, 0);
a->mode = GL_TRIANGLES;
copy_a_indices;
break;
default:
if (!a->indices) {
// no a->indices, must alloc and fill one
alloc_a_indices;
renderlist_createindices(a->len, newind, 0);
copy_a_indices;
} else {
// a->indices already exist, just check if need to adjust its size
if (a->indice_cap < capindices) {
a->indices = (GLushort*)realloc(a->indices, capindices*sizeof(GLushort));
a->indice_cap = capindices;
}
}
break;
}
#undef copy_a_indices
#undef alloc_a_indices
a->ilen = ilen_a;
}
void doadd_renderlist(renderlist_t* a, GLenum mode, GLushort* indices, int count, int size_to_add)
{
// then append b
switch (mode) {
case GL_LINE_LOOP:
renderlist_lineloop_lines(indices, count, a->indices + a->ilen, a->len);
break;
case GL_LINE_STRIP:
renderlist_linestrip_lines(indices, count, a->indices + a->ilen, a->len);
break;
case GL_QUAD_STRIP:
case GL_TRIANGLE_STRIP:
renderlist_trianglestrip_triangles(indices, count, a->indices + a->ilen, a->len);
break;
case GL_POLYGON:
case GL_TRIANGLE_FAN:
renderlist_trianglefan_triangles(indices, count, a->indices + a->ilen, a->len);
break;
case GL_QUADS:
renderlist_quads_triangles(indices, count, a->indices + a->ilen, a->len);
break;
default:
// no transform here, just take (or create) the indice list as-is
if (!indices) {
// append a newly created indice list
renderlist_createindices(count, a->indices + a->ilen, a->len);
} else {
// append existing one
GLushort* newind = a->indices+a->ilen;
for(int i=0; i<count; i++)
newind[i] = indices[i]+a->len;
}
break;
}
a->ilen += size_to_add;
}
void append_renderlist(renderlist_t *a, renderlist_t *b) {
// append all draw elements of b in a
// check the final indice size of a and b
int ilen_a = a->ilen;
int ilen_b = b->ilen;
// lets append all the arrays
unsigned long cap = a->cap;
if (a->len + b->len >= cap) cap += b->cap + DEFAULT_RENDER_LIST_CAPACITY;
// Unshare if shared (shared array are not used for now)
unshared_renderlist(a, cap);
redim_renderlist(a, cap);
unsharedindices_renderlist(a, ((ilen_a)?ilen_a:a->len) + ((ilen_b)?ilen_b:b->len));
// append arrays
if (a->vert) memcpy(a->vert+a->len*4, b->vert, b->len*4*sizeof(GLfloat));
if (a->normal) memcpy(a->normal+a->len*3, b->normal, b->len*3*sizeof(GLfloat));
if (a->color) memcpy(a->color+a->len*4, b->color, b->len*4*sizeof(GLfloat));
if (a->secondary) memcpy(a->secondary+a->len*4, b->secondary, b->len*4*sizeof(GLfloat));
if (a->fogcoord) memcpy(a->fogcoord+a->len*1, b->fogcoord, b->len*1*sizeof(GLfloat));
for (int i=0; i<a->maxtex; i++)
if (a->tex[i]) memcpy(a->tex[i]+a->len*4, b->tex[i], b->len*4*sizeof(GLfloat));
// indices
if(!a->mode_inits) list_add_modeinit(a, a->mode_init);
if (ilen_a || ilen_b || mode_needindices(a->mode) || mode_needindices(b->mode)
|| (a->mode!=b->mode && (a->mode==GL_QUADS || b->mode==GL_QUADS)) )
{
// alloc or realloc a->indices first...
ilen_b = renderlist_getindicesize(b);
prepareadd_renderlist(a, ilen_b);
// then append b
doadd_renderlist(a, b->mode, b->indices, b->indices?b->ilen:b->len, ilen_b);
}
// lenghts
a->len += b->len;
if(a->mode_inits) list_add_modeinit(a, b->mode);
// copy the lastColors if needed
if(b->lastColorsSet) {
a->lastColorsSet = 1;
memcpy(a->lastColors, b->lastColors, 4*sizeof(GLfloat));
}
if(b->post_color) {
a->post_color = 1;
memcpy(a->post_colors, b->post_colors, 4*sizeof(GLfloat));
}
if(b->post_normal) {
a->post_normal = 1;
memcpy(a->post_normals, b->post_normals, 3*sizeof(GLfloat));
}
//all done
a->stage = STAGE_DRAW; // just in case
return;
}
void adjust_renderlist(renderlist_t *list);
renderlist_t *extend_renderlist(renderlist_t *list) {
if ((list->prev!=NULL) && ispurerender_renderlist(list) && islistscompatible_renderlist(list->prev, list)) {
// append list!
append_renderlist(list->prev, list);
renderlist_t *new = alloc_renderlist();
new->prev = list->prev;
list->prev->next = new;
// just in case
memcpy(new->lastNormal, list->lastNormal, 3*sizeof(GLfloat));
memcpy(new->lastSecondaryColors, list->lastSecondaryColors, 3*sizeof(GLfloat));
memcpy(new->lastColors, list->lastColors, 4*sizeof(GLfloat));
new->lastColorsSet = list->lastColorsSet;
// detach
list->prev = NULL;
// free list now
free_renderlist(list);
return new;
} else {
renderlist_t *new = alloc_renderlist();
list->next = new;
new->prev = list;
new->tmu = list->tmu;
// copy local state
memcpy(new->lastNormal, list->lastNormal, 3*sizeof(GLfloat));
memcpy(new->lastSecondaryColors, list->lastSecondaryColors, 3*sizeof(GLfloat));
memcpy(new->lastColors, (list->post_color)?list->post_colors:list->lastColors, 4*sizeof(GLfloat));
new->lastColorsSet = (list->post_color || list->lastColorsSet)?1:0;
return new;
}
}
renderlist_t* append_calllist(renderlist_t *list, renderlist_t *a)
{
// go to end of list
while(list->next) list = list->next;
while(a) {
if(ispurerender_renderlist(a) && islistscompatible_renderlist(list, a)) {
// append list!
append_renderlist(list, a);
} else {
// create a new appended list
renderlist_t *new = alloc_renderlist();
// prepared shared stuff...
if(a->len && !a->shared_arrays) {
a->shared_arrays = (int*)malloc(sizeof(int));
*a->shared_arrays = 0;
}
if(a->ilen && !a->shared_indices) {
a->shared_indices = (int*)malloc(sizeof(int));
*a->shared_indices = 0;
}
if(a->calls.len && !a->shared_calls) {
a->shared_calls = (int*)malloc(sizeof(int));
*a->shared_calls = 0;
}
// batch copy first
memcpy(new, a, sizeof(renderlist_t));
list->next = new;
new->prev = list;
// ok, now on new list
list = new;
// copy the many list arrays
if (list->calls.len > 0) {
++(*list->shared_calls);
/*
list->calls.calls = (packed_call_t**)malloc(sizeof(packed_call_t*)*a->calls.cap);
for (int i = 0; i < list->calls.len; i++) {
list->calls.calls[i] = glCopyPackedCall(a->calls.calls[i]);
}*/
}
if(list->len) {
++(*list->shared_arrays);
}
if(list->ilen) {
++(*list->shared_indices);
}
#define PROCESS(W, T, C) if(list->W) { \
list->W = kh_init(W); \
T *m, *m2; \
khint_t k; \
int ret; \
kh_foreach_value(a->W, m, \
k = kh_put(W, list->W, C, &ret); \
m2= kh_value(list->W, k) = malloc(sizeof(T)); \
memcpy(m2, m, sizeof(T)); \
); \
}
PROCESS(material, rendermaterial_t, m->pname);
PROCESS(light, renderlight_t, m->pname | ((m->which-GL_LIGHT0)<<16));
PROCESS(texgen, rendertexgen_t, m->pname | ((m->coord-GL_S)<<16));
PROCESS(texenv, rendertexenv_t, m->pname | ((m->target)<<16));
#undef PROCESS
if (list->lightmodel) {
list->lightmodel = (GLfloat*)malloc(4*sizeof(GLfloat));
memcpy(list->lightmodel, a->lightmodel, 4*sizeof(GLfloat));
}
if (list->raster) {
(*list->raster->shared)++;
}
if (list->bitmaps) {
(*list->bitmaps->shared)++;
}
}
a = a->next;
}
return list;
}
void free_renderlist(renderlist_t *list) {
// test if list is NULL
if (list == NULL)
return;
// we want the first list in the chain
while (list->prev)
list = list->prev;
renderlist_t *next;
do {
if(list->mode_inits)
free(list->mode_inits);
if ((list->calls.len > 0) && (!list->shared_calls || ((*list->shared_calls)--)==0)) {
if(list->shared_calls) free(list->shared_calls);
for (int i = 0; i < list->calls.len; i++) {
free(list->calls.calls[i]);
}
free(list->calls.calls);
}
int a;
if(!list->use_glstate) {
if (!list->shared_arrays || ((*list->shared_arrays)--)==0) {
if (list->shared_arrays) free(list->shared_arrays);
if (list->vert) free(list->vert);
if (list->normal) free(list->normal);
if (list->color) free(list->color);
if (list->secondary) free(list->secondary);
if (list->fogcoord) free(list->fogcoord);
for (a=0; a<list->maxtex; a++)
if (list->tex[a]) free(list->tex[a]);
}
if (!list->shared_indices || ((*list->shared_indices)--)==0) {
if (list->shared_indices) free(list->shared_indices);
if (list->indices)
free(list->indices);
}
} else
glstate->merger_used = 0;
if (list->material) {
rendermaterial_t *m;
kh_foreach_value(list->material, m,
free(m);
)
kh_destroy(material, list->material);
}
if (list->light) {
renderlight_t *m;
kh_foreach_value(list->light, m,
free(m);
)
kh_destroy(light, list->light);
}
if (list->texgen) {
rendertexgen_t *m;
kh_foreach_value(list->texgen, m,
free(m);
)
kh_destroy(texgen, list->texgen);
}
if (list->texenv) {
rendertexenv_t *m;
kh_foreach_value(list->texenv, m,
free(m);
)
kh_destroy(texenv, list->texenv);
}
if (list->lightmodel)
free(list->lightmodel);
if (list->raster && !((*list->raster->shared)--)) {
if (list->raster->texture)
gl4es_glDeleteTextures(1, &list->raster->texture);
free(list->raster->shared);
free(list->raster);
}
if(list->bitmaps && !((*list->bitmaps->shared)--)) {
for(int i=0; i<list->bitmaps->count; i++)
if(list->bitmaps->list[i].bitmap)
free(list->bitmaps->list[i].bitmap);
free(list->bitmaps->list);
free(list->bitmaps->shared);
free(list->bitmaps);
}
if(list->ind_lines)
free(list->ind_lines);
if(list->final_colors)
free(list->final_colors);
if(list->vbo_array)
deleteSingleBuffer(list->vbo_array);
if(list->vbo_indices)
deleteSingleBuffer(list->vbo_indices);
next = list->next;
free(list);
} while ((list = next));
}
void resize_renderlist(renderlist_t *list) {
if (list->use_glstate) {
if (list->len >= glstate->merger_cap) {
glstate->merger_cap += DEFAULT_RENDER_LIST_CAPACITY*8;
realloc_merger_sublist(glstate->merger_master, 4*5, glstate->merger_cap);
realloc_sublist(glstate->merger_secondary, 4, glstate->merger_cap);
for (int a=2; a<list->maxtex; a++)
realloc_sublist(glstate->merger_tex[a-2], 4, glstate->merger_cap);
if(list->vert) list->vert = glstate->merger_master;
if(list->normal) list->normal = glstate->merger_master+4+4+2*4;
if(list->color) list->color = glstate->merger_master+4;
if(list->tex[0]) list->tex[0] = glstate->merger_master+4+4;
if(list->tex[1]) list->tex[1] = glstate->merger_master+4+4+4;
if(list->fogcoord) list->fogcoord = glstate->merger_master+4+4+2*4+3;
if(list->secondary) list->secondary = glstate->merger_secondary;
for (int a=2; a<list->maxtex; a++)
if(list->tex[a]) list->tex[a] = glstate->merger_tex[a-2];
}
} else {
if (list->len >= list->cap) {
list->cap += DEFAULT_RENDER_LIST_CAPACITY*8;
realloc_sublist(list->vert, 4, list->cap);
realloc_sublist(list->normal, 3, list->cap);
realloc_sublist(list->color, 4, list->cap);
realloc_sublist(list->secondary, 4, list->cap);
realloc_sublist(list->fogcoord, 1, list->cap);
for (int a=0; a<list->maxtex; a++)
realloc_sublist(list->tex[a], 4, list->cap);
}
}
}
void resize_merger_indices(int cap) {
if(cap<glstate->merger_indice_cap)
return;
glstate->merger_indice_cap = ((glstate->merger_indice_cap+cap+512)>>9)<<9;
glstate->merger_indices = (GLushort*)realloc(glstate->merger_indices, glstate->merger_indice_cap*sizeof(GLushort));
}
void resize_indices_renderlist(renderlist_t *list, int n) {
if (!list->indices || list->shared_indices)
return;
if (list->use_glstate) {
resize_merger_indices(list->ilen+n);
list->indices = glstate->merger_indices;
} else {
if(list->ilen+n<list->indice_cap)
return;
list->indice_cap = ((list->indice_cap+n+511)>>9)<<9;
list->indices = (GLushort*)realloc(list->indices, list->indice_cap*sizeof(GLushort));
}
}
void adjust_renderlist(renderlist_t *list) {
if (! list->open)
return;
list->stage = STAGE_LAST;
list->open = false;
if(hardext.esversion==1) // no more adjustment needed for ES2
for (int a=0; a<list->maxtex; a++) {
const GLint itarget = get_target(glstate->enable.texture[a]);
gltexture_t *bound = (itarget>=0)?glstate->texture.bound[a][itarget]:NULL;
// in case of Texture bounding inside a list
if (list->set_texture && (list->tmu == a))
bound = gl4es_getTexture(list->target_texture, list->texture);
// GL_ARB_texture_rectangle
if ((list->tex[a]) && (itarget == ENABLED_TEXTURE_RECTANGLE) && (bound)) {
tex_coord_rect_arb(list->tex[a], list->tex_stride[a]>>2, list->len, bound->width, bound->height);
}
}
}
renderlist_t* end_renderlist(renderlist_t *list) {
if (!list || ! list->open)
return list;
adjust_renderlist(list);
switch (list->mode) {
case GL_QUADS:
if (((list->indices) && (list->ilen==4)) || ((list->indices==NULL) && (list->len==4))) {
list->mode = GL_TRIANGLE_FAN;
} else {
renderlist_quads2triangles(list);
}
break;
case GL_POLYGON:
list->mode = GL_TRIANGLE_FAN;
break;
case GL_QUAD_STRIP:
list->mode = GL_TRIANGLE_STRIP;
break;
}
if(list->prev && isempty_renderlist(list)) {
renderlist_t *p = list;
list = list->prev;
list->next = NULL;
p->prev = NULL;
free_renderlist(p);
}
return list;
}
renderlist_t* recycle_renderlist(renderlist_t *list, GLenum mode) {
if(isempty_renderlist(list) || (ispurerender_renderlist(list) && list->len==0)) {
list->mode_init = mode;
list->mode = mode;
list->stage=STAGE_DRAW;
if (list->post_color) {
list->post_color = 0;
rlColor4f(list, list->post_colors[0], list->post_colors[1], list->post_colors[2], list->post_colors[3]);
}
if (list->post_normal) {
list->post_normal = 0;
rlNormal3f(list, list->post_normals[0], list->post_normals[1], list->post_normals[2]);
}
return list; // recycling...
}
// check if pending color...
if (list->post_color) {
list->post_color = 0;
rlColor4f(list, list->post_colors[0], list->post_colors[1], list->post_colors[2], list->post_colors[3]);
}
if (list->post_normal) {
list->post_normal = 0;
rlNormal3f(list, list->post_normals[0], list->post_normals[1], list->post_normals[2]);
}
// check if list needs to be converted to triangles / lines...
GLushort *indices = NULL;
#define pre_expand \
if(list->use_glstate) {\
resize_merger_indices(renderlist_getindicesize(list)); indices = glstate->merger_indices;\
} else {\
list->indice_cap = renderlist_getindicesize(list);\
indices = (GLushort*)malloc(sizeof(GLushort)*list->indice_cap);\
}
#define post_expand \
list->ilen = renderlist_getindicesize(list);\
list->indices = indices
list->merger_mode = mode;
switch(list->mode) {
case GL_LINES:
if(mode!=GL_LINES && !list->indices) {
pre_expand;
renderlist_createindices(list->len, indices, 0);
post_expand;
}
break;
case GL_LINE_LOOP:
pre_expand;
renderlist_lineloop_lines(list->indices, list->indices?list->ilen:list->len, indices, 0);
post_expand;
list->mode=GL_LINES;
break;
case GL_LINE_STRIP:
pre_expand;
renderlist_linestrip_lines(list->indices, list->indices?list->ilen:list->len, indices, 0);
post_expand;
list->mode=GL_LINES;
break;
case GL_TRIANGLES:
if(mode!=GL_TRIANGLES && !list->indices) {
pre_expand;
renderlist_createindices(list->len, indices, 0);
post_expand;
}
break;
case GL_POLYGON:
case GL_TRIANGLE_FAN:
pre_expand;
renderlist_trianglefan_triangles(list->indices, list->indices?list->ilen:list->len, indices, 0);
post_expand;
list->mode=GL_TRIANGLES;
break;
case GL_QUAD_STRIP:
case GL_TRIANGLE_STRIP:
pre_expand;
renderlist_trianglestrip_triangles(list->indices, list->indices?list->ilen:list->len, indices, 0);
post_expand;
list->mode=GL_TRIANGLES;
break;
case GL_QUADS:
pre_expand;
renderlist_quads_triangles(list->indices, list->indices?list->ilen:list->len, indices, 0);
post_expand;
list->mode=GL_TRIANGLES;
break;
}
#undef pre_expand
#undef post_expand
list->cur_istart = list->len;
// All done
list->stage=STAGE_DRAW;
return list;
}
+323
View File
@@ -0,0 +1,323 @@
#ifndef _GL4ES_LIST_H_
#define _GL4ES_LIST_H_
#include <stdbool.h>
#include "khash.h"
#include "../config.h"
#include "wrap/gles.h"
#include "attributes.h"
#include "gles.h"
typedef enum {
STAGE_NONE = 0,
STAGE_PUSH,
STAGE_POP,
STAGE_GLCALL,
STAGE_RENDER,
STAGE_FOG,
STAGE_POINTPARAM,
STAGE_MATRIX,
STAGE_ACTIVETEX,
STAGE_BINDTEX,
STAGE_RASTER,
STAGE_BITMAP,
STAGE_MATERIAL,
STAGE_COLOR_MATERIAL,
STAGE_LIGHT,
STAGE_LIGHTMODEL,
STAGE_LINESTIPPLE,
STAGE_TEXENV,
STAGE_TEXGEN,
STAGE_POLYGON,
STAGE_DRAW,
STAGE_POSTDRAW,
STAGE_LAST
} liststage_t;
static int StageExclusive[] = {
0, // STAGE_NONE
1, // STAGE_PUSH
1, // STAGE_POP
0, // STAGE_GLCALL
1, // STAGE_RENDER
1, // STAGE_FOG
1, // STAGE_POINTPARAM
1, // STAGE_MATRIX
1, // STAGE_ACTIVETEX
1, // STAGE_BINDTEX
1, // STAGE_RASTER
0, // STAGE_BITMAP
0, // STAGE_MATERIAL
1, // STAGE_COLOR_MATERIAL
0, // STAGE_LIGHT
1, // STAGE_LIGTMODEL
1, // STAGE_LINESTIPPLE
0, // STAGE_TEXENV
0, // STAGE_TEXGEN
1, // STAGE_POLYGON
1, // STAGE_DRAW
1, // STAGE_POSTDRAW (used for "pending", i.e. post glEnd(), in case a similar glBegin occurs)
0 // STAGE_LAST
};
typedef struct {
int face;
int pname;
GLfloat color[4];
int count;
} rendermaterial_t;
typedef struct {
int which;
int pname;
GLfloat color[4];
int count;
} renderlight_t;
typedef struct {
int coord;
int pname;
GLfloat color[4];
int count;
} rendertexgen_t;
typedef struct {
int target;
int pname;
GLfloat params[4];
int count;
} rendertexenv_t;
typedef struct {
GLfloat xmove;
GLfloat ymove;
GLsizei width;
GLsizei height;
GLsizei nwidth;
GLsizei nheight;
GLfloat xorig;
GLfloat yorig;
GLfloat zoomx;
GLfloat zoomy;
GLboolean bitmap;
GLuint texture;
int *shared;
} rasterlist_t;
KHASH_MAP_DECLARE_INT(material, rendermaterial_t *);
KHASH_MAP_DECLARE_INT(light, renderlight_t *);
KHASH_MAP_DECLARE_INT(texgen, rendertexgen_t *);
KHASH_MAP_DECLARE_INT(texenv, rendertexenv_t *);
typedef struct _call_list_t {
unsigned long len;
unsigned long cap;
packed_call_t **calls;
} call_list_t;
typedef struct {
GLsizei width;
GLsizei height;
GLfloat xorig;
GLfloat yorig;
GLfloat xmove;
GLfloat ymove;
GLubyte *bitmap;
} bitmap_list_t;
typedef struct {
int count;
int cap;
bitmap_list_t *list;
int *shared;
} bitmaps_t;
typedef struct {
GLenum mode_init;
int ilen;
} modeinit_t;
typedef struct _renderlist_t {
unsigned long len;
unsigned long ilen;
unsigned long cap;
GLenum mode;
GLenum mode_init; // initial requested mode
GLuint name;
modeinit_t* mode_inits; // array of requested/len, for the merger
int mode_init_cap;
int mode_init_len;
int mode_dimension;
GLfloat lastNormal[3];
GLfloat lastColors[4];
GLfloat lastSecondaryColors[4];
GLfloat lastFogCoord;
int use_glstate;
int lastColorsSet;
int* shared_calls;
call_list_t calls;
int *shared_arrays;
GLfloat *vert;
GLfloat *normal;
GLfloat *color;
GLfloat *secondary;
GLfloat *fogcoord;
GLfloat *tex[MAX_TEX];
int vert_stride;
int normal_stride;
int color_stride;
int secondary_stride;
int fogcoord_stride;
int tex_stride[MAX_TEX];
GLuint vbo_array;
GLuint vbo_indices;
int use_vbo_array; // 0=Not evaluated, 1=No, 2=Yes
int use_vbo_indices; // same
GLfloat *vbo_vert;
GLfloat *vbo_normal;
GLfloat *vbo_color;
GLfloat *vbo_secondary;
GLfloat *vbo_fogcoord;
GLfloat *vbo_tex[MAX_TEX];
int *shared_indices;
GLushort *indices;
unsigned int indice_cap;
int maxtex;
GLenum merger_mode;
int cur_istart; // used by glBegin/glEnd merger.
rasterlist_t *raster;
bitmaps_t *bitmaps;
liststage_t stage;
GLbitfield pushattribute;
GLboolean popattribute;
int render_op;
GLuint render_arg;
int raster_op;
GLfloat raster_xyz[3];
int matrix_op;
GLfloat matrix_val[16];
int fog_op;
GLfloat fog_val[4];
int pointparam_op;
GLfloat pointparam_val[4];
int linestipple_op;
GLuint linestipple_factor, linestipple_pattern;
int post_color;
GLfloat post_colors[4];
int post_normal;
GLfloat post_normals[3];
GLushort *ind_lines;
int ind_line;
GLfloat *final_colors;
int instanceCount;
khash_t(material) *material;
GLenum colormat_face;
GLenum colormat_mode;
khash_t(light) *light;
khash_t(texgen) *texgen;
khash_t(texenv) *texenv;
GLfloat *lightmodel;
GLenum lightmodelparam;
GLenum polygon_mode;
GLboolean set_tmu; // TRUE is glActiveTexture called
int tmu; // the current TMU...
GLuint texture;
GLenum target_texture;
GLboolean set_texture;
struct _renderlist_t *prev;
struct _renderlist_t *next;
GLboolean open;
} renderlist_t;
KHASH_MAP_DECLARE_INT(gllisthead, renderlist_t*);
#define DEFAULT_CALL_LIST_CAPACITY 20
#define DEFAULT_RENDER_LIST_CAPACITY 64
int rendermode_dimensions(GLenum mode);
renderlist_t* recycle_renderlist(renderlist_t* list, GLenum mode);
renderlist_t* NewDrawStage(renderlist_t* l, GLenum m);
#define NewStage(l, s) if (l->stage+StageExclusive[l->stage] > s) {l = extend_renderlist(l);} l->stage = s
renderlist_t* GetFirst(renderlist_t* list);
#define alloc_sublist(n, cap) \
(GLfloat *)malloc(n * sizeof(GLfloat) * cap)
#define realloc_sublist(ref, n, cap) \
if (ref) \
ref = (GLfloat *)realloc(ref, n * sizeof(GLfloat) * cap)
#define realloc_merger_sublist(ref, n, cap) \
ref = (GLfloat *)realloc(ref, n * sizeof(GLfloat) * cap)
renderlist_t *alloc_renderlist();
renderlist_t *extend_renderlist(renderlist_t *list);
void free_renderlist(renderlist_t *list);
void draw_renderlist(renderlist_t *list);
renderlist_t* end_renderlist(renderlist_t *list);
bool isempty_renderlist(renderlist_t *list);
void resize_renderlist(renderlist_t *list);
renderlist_t *alloc_renderlist();
int mode_needindices(GLenum m);
void resize_indices_renderlist(renderlist_t *list, int n);
void resize_merger_indices(int cap);
int indices_getindicesize(GLenum mode, int len);
void list_add_modeinit(renderlist_t* list, GLenum mode);
void unshared_renderlist(renderlist_t *a, int cap);
void unsharedindices_renderlist(renderlist_t* a, int cap);
void redim_renderlist(renderlist_t *a, int cap);
void prepareadd_renderlist(renderlist_t* a, int size_to_add);
void doadd_renderlist(renderlist_t* a, GLenum mode, GLushort* indices, int count, int size_to_add);
void renderlist_createindices(int ilen, GLushort *indices, int count);
void renderlist_lineloop_lines(GLushort *ind, int len, GLushort *indices, int count);
void renderlist_linestrip_lines(GLushort *ind, int len, GLushort *indices, int count);
void renderlist_trianglestrip_triangles(GLushort *ind, int len, GLushort *indices, int count);
void renderlist_trianglefan_triangles(GLushort *ind, int len, GLushort *indices, int count);
void renderlist_quads_triangles(GLushort *ind, int len, GLushort *indices, int count);
void rlActiveTexture(renderlist_t *list, GLenum texture );
void rlBindTexture(renderlist_t *list, GLenum target, GLuint texture);
void rlColor4f(renderlist_t *list, GLfloat r, GLfloat g, GLfloat b, GLfloat a) FASTMATH;
void rlColor4fv(renderlist_t *list, GLfloat* v) FASTMATH;
void rlMaterialfv(renderlist_t *list, GLenum face, GLenum pname, const GLfloat * params);
void rlLightfv(renderlist_t *list, GLenum which, GLenum pname, const GLfloat * params);
void rlTexGenfv(renderlist_t *list, GLenum coord, GLenum pname, const GLfloat * params);
void rlTexEnvfv(renderlist_t *list, GLenum target, GLenum pname, const GLfloat * params);
void rlTexEnviv(renderlist_t *list, GLenum target, GLenum pname, const GLint * params);
void rlNormal3f(renderlist_t *list, GLfloat x, GLfloat y, GLfloat z) FASTMATH;
void rlNormal3fv(renderlist_t *list, GLfloat* v) FASTMATH;
void rlPushCall(renderlist_t *list, packed_call_t *data);
void rlMultiTexCoord4f(renderlist_t *list, GLenum texture, GLfloat s, GLfloat t, GLfloat r, GLfloat q) FASTMATH;
void rlMultiTexCoord2fv(renderlist_t *list, GLenum texture, GLfloat* v) FASTMATH;
void rlMultiTexCoord4fv(renderlist_t *list, GLenum texture, GLfloat* v) FASTMATH;
void rlVertex4f(renderlist_t *list, GLfloat x, GLfloat y, GLfloat z, GLfloat w) FASTMATH;
void rlVertex3fv(renderlist_t *list, GLfloat* v) FASTMATH;
void rlVertex4fv(renderlist_t *list, GLfloat* v) FASTMATH;
void rlSecondary3f(renderlist_t *list, GLfloat r, GLfloat g, GLfloat b) FASTMATH;
void rlRasterOp(renderlist_t *list, int op, GLfloat x, GLfloat y, GLfloat z) FASTMATH;
void rlFogOp(renderlist_t *list, int op, const GLfloat* v);
void rlPointParamOp(renderlist_t *list, int op, const GLfloat* v);
void rlFogCoordf(renderlist_t *list, GLfloat coord);
void rlEnd(renderlist_t *list);
#endif // _GL4ES_LIST_H_
+864
View File
@@ -0,0 +1,864 @@
#include "list.h"
#include "../glx/hardext.h"
#include "wrap/gl4es.h"
#include "fpe.h"
#include "init.h"
#include "line.h"
#include "loader.h"
#include "matrix.h"
#include "texgen.h"
#include "render.h"
#include "fpe.h"
/* return 1 if failed, 2 if succeed */
typedef struct array2vbo_s {
uintptr_t real_base;
uint32_t real_size;
uint32_t stride;
uintptr_t vbo_base;
uintptr_t vbo_basebase;
} array2vbo_t;
int list2VBO(renderlist_t* list)
{
LOAD_GLES2(glGenBuffers);
LOAD_GLES2(glBufferData);
LOAD_GLES2(glBufferSubData);
array2vbo_t work[ATT_MAX] = {0};
// list -> work
int imax = 0;
int len = list->len;
if(list->vert) {
work[imax].real_base = (uintptr_t)list->vert;
work[imax].stride = list->vert_stride;
if(!work[imax].stride) work[imax].stride = 4*4; // 4*GL_FLOAT
work[imax].real_size = work[imax].stride*len;
imax++;
}
if(list->color) {
work[imax].real_base = (uintptr_t)list->color;
work[imax].stride = list->color_stride;
if(!work[imax].stride) work[imax].stride = 4*4; // 4*GL_FLOAT
work[imax].real_size = work[imax].stride*len;
imax++;
}
if(list->secondary) {
work[imax].real_base = (uintptr_t)list->secondary;
work[imax].stride = list->secondary_stride;
if(!work[imax].stride) work[imax].stride = 4*4; // 4*GL_FLOAT
work[imax].real_size = work[imax].stride*len;
imax++;
}
if(list->fogcoord) {
work[imax].real_base = (uintptr_t)list->fogcoord;
work[imax].stride = list->fogcoord_stride;
if(!work[imax].stride) work[imax].stride = 1*4; // 1*GL_FLOAT
work[imax].real_size = work[imax].stride*len;
imax++;
}
if(list->normal) {
work[imax].real_base = (uintptr_t)list->normal;
work[imax].stride = list->normal_stride;
if(!work[imax].stride) work[imax].stride = 3*4; // 3*GL_FLOAT
work[imax].real_size = work[imax].stride*len;
imax++;
}
for (int a=0; a<list->maxtex; ++a) {
if(list->tex[a]) {
work[imax].real_base = (uintptr_t)list->tex[a];
work[imax].stride = list->tex_stride[a];
if(!work[imax].stride) work[imax].stride = 4*4; // 4*GL_FLOAT
work[imax].real_size = work[imax].stride*len;
imax++;
}
}
// sort the real address...
int sorted[ATT_MAX];
for (int i=0; i<imax; ++i)
sorted[i] = i;
// bubble sort, array is small enough, and probably almost sorted
for (int i=0; i<imax-1; ++i)
for (int j=i+1; j<imax; ++j)
if(work[sorted[i]].real_base > work[sorted[j]].real_base) {
int tmp = sorted[i];
sorted[i] = sorted[j];
sorted[j] = tmp;
}
// get a base vbo offset
uintptr_t vbo_base = 0;
for (int i=0; i<imax; ++i) {
uintptr_t base = vbo_base;
uintptr_t basebase = vbo_base;
array2vbo_t *r = work+sorted[i];
if(i) for(int j=i-1; j<i; ++j) {
array2vbo_t *t = work+sorted[j];
if(r->real_base<t->real_base+t->real_size) {
base = r->vbo_base + (r->real_base - t->real_base);
basebase = r->vbo_basebase;
break;
}
}
r->vbo_base = base;
r->vbo_basebase = basebase;
if(base == basebase)
vbo_base += r->real_size;
}
if(!vbo_base) // no data?!
return 1;
// Create the VBO and fill the data
gles_glGenBuffers(1, &list->vbo_array);
bindBuffer(GL_ARRAY_BUFFER, list->vbo_array);
gles_glBufferData(GL_ARRAY_BUFFER, vbo_base, NULL, GL_STATIC_DRAW);
for(int i=0; i<imax; ++i) {
array2vbo_t *r = work+sorted[i];
if(r->vbo_base==r->vbo_basebase)
gles_glBufferSubData(GL_ARRAY_BUFFER, r->vbo_basebase, r->real_size, (void*)r->real_base);
}
// work -> list
imax = 0;
if(list->vert) {
list->vbo_vert = (GLfloat*)work[imax].vbo_base;
imax++;
}
if(list->color) {
list->vbo_color = (GLfloat*)work[imax].vbo_base;
imax++;
}
if(list->secondary) {
list->vbo_secondary = (GLfloat*)work[imax].vbo_base;
imax++;
}
if(list->fogcoord) {
list->vbo_fogcoord = (GLfloat*)work[imax].vbo_base;
imax++;
}
if(list->normal) {
list->vbo_normal = (GLfloat*)work[imax].vbo_base;
imax++;
}
for (int a=0; a<list->maxtex; ++a) {
if(list->tex[a]) {
list->vbo_tex[a] = (GLfloat*)work[imax].vbo_base;
imax++;
}
}
return 2;
}
typedef struct save_vbo_s {
GLuint real_buffer;
const GLvoid* real_pointer;
glbuffer_t* buffer;
} save_vbo_t;
void listActiveVBO(renderlist_t* list, save_vbo_t* saved) {
if(list->vert) {
saved[ATT_VERTEX].real_buffer = glstate->vao->vertexattrib[ATT_VERTEX].real_buffer;
saved[ATT_VERTEX].real_pointer = glstate->vao->vertexattrib[ATT_VERTEX].real_pointer;
saved[ATT_VERTEX].buffer = glstate->vao->vertexattrib[ATT_VERTEX].buffer;
glstate->vao->vertexattrib[ATT_VERTEX].real_buffer = list->vbo_array;
glstate->vao->vertexattrib[ATT_VERTEX].real_pointer = list->vbo_vert;
glstate->vao->vertexattrib[ATT_VERTEX].buffer = NULL;
}
if(list->color) {
saved[ATT_COLOR].real_buffer = glstate->vao->vertexattrib[ATT_COLOR].real_buffer;
saved[ATT_COLOR].real_pointer = glstate->vao->vertexattrib[ATT_COLOR].real_pointer;
saved[ATT_COLOR].buffer = glstate->vao->vertexattrib[ATT_COLOR].buffer;
glstate->vao->vertexattrib[ATT_COLOR].real_buffer = list->vbo_array;
glstate->vao->vertexattrib[ATT_COLOR].real_pointer = list->vbo_color;
glstate->vao->vertexattrib[ATT_COLOR].buffer = NULL;
}
if(list->secondary) {
saved[ATT_SECONDARY].real_buffer = glstate->vao->vertexattrib[ATT_SECONDARY].real_buffer;
saved[ATT_SECONDARY].real_pointer = glstate->vao->vertexattrib[ATT_SECONDARY].real_pointer;
saved[ATT_SECONDARY].buffer = glstate->vao->vertexattrib[ATT_SECONDARY].buffer;
glstate->vao->vertexattrib[ATT_SECONDARY].real_buffer = list->vbo_array;
glstate->vao->vertexattrib[ATT_SECONDARY].real_pointer = list->vbo_secondary;
glstate->vao->vertexattrib[ATT_SECONDARY].buffer = NULL;
}
if(list->fogcoord) {
saved[ATT_FOGCOORD].real_buffer = glstate->vao->vertexattrib[ATT_FOGCOORD].real_buffer;
saved[ATT_FOGCOORD].real_pointer = glstate->vao->vertexattrib[ATT_FOGCOORD].real_pointer;
saved[ATT_FOGCOORD].buffer = glstate->vao->vertexattrib[ATT_FOGCOORD].buffer;
glstate->vao->vertexattrib[ATT_FOGCOORD].real_buffer = list->vbo_array;
glstate->vao->vertexattrib[ATT_FOGCOORD].real_pointer = list->vbo_fogcoord;
glstate->vao->vertexattrib[ATT_FOGCOORD].buffer = NULL;
}
if(list->normal) {
saved[ATT_NORMAL].real_buffer = glstate->vao->vertexattrib[ATT_NORMAL].real_buffer;
saved[ATT_NORMAL].real_pointer = glstate->vao->vertexattrib[ATT_NORMAL].real_pointer;
saved[ATT_NORMAL].buffer = glstate->vao->vertexattrib[ATT_NORMAL].buffer;
glstate->vao->vertexattrib[ATT_NORMAL].real_buffer = list->vbo_array;
glstate->vao->vertexattrib[ATT_NORMAL].real_pointer = list->vbo_normal;
glstate->vao->vertexattrib[ATT_NORMAL].buffer = NULL;
}
for (int a=0; a<list->maxtex; ++a) {
if(list->tex[a]) {
saved[ATT_MULTITEXCOORD0+a].real_buffer = glstate->vao->vertexattrib[ATT_MULTITEXCOORD0+a].real_buffer;
saved[ATT_MULTITEXCOORD0+a].real_pointer = glstate->vao->vertexattrib[ATT_MULTITEXCOORD0+a].real_pointer;
saved[ATT_MULTITEXCOORD0+a].buffer = glstate->vao->vertexattrib[ATT_MULTITEXCOORD0+a].buffer;
glstate->vao->vertexattrib[ATT_MULTITEXCOORD0+a].real_buffer = list->vbo_array;
glstate->vao->vertexattrib[ATT_MULTITEXCOORD0+a].real_pointer = list->vbo_tex[a];
glstate->vao->vertexattrib[ATT_MULTITEXCOORD0+a].buffer = NULL;
}
}
}
void listInactiveVBO(renderlist_t* list, save_vbo_t* saved) {
if(list->vert) {
glstate->vao->vertexattrib[ATT_VERTEX].real_buffer = saved[ATT_VERTEX].real_buffer;
glstate->vao->vertexattrib[ATT_VERTEX].real_pointer = saved[ATT_VERTEX].real_pointer;
glstate->vao->vertexattrib[ATT_VERTEX].buffer = saved[ATT_VERTEX].buffer;
}
if(list->color) {
glstate->vao->vertexattrib[ATT_COLOR].real_buffer = saved[ATT_COLOR].real_buffer;
glstate->vao->vertexattrib[ATT_COLOR].real_pointer = saved[ATT_COLOR].real_pointer;
glstate->vao->vertexattrib[ATT_COLOR].buffer = saved[ATT_COLOR].buffer;
}
if(list->secondary) {
glstate->vao->vertexattrib[ATT_SECONDARY].real_buffer = saved[ATT_SECONDARY].real_buffer;
glstate->vao->vertexattrib[ATT_SECONDARY].real_pointer = saved[ATT_SECONDARY].real_pointer;
glstate->vao->vertexattrib[ATT_SECONDARY].buffer = saved[ATT_SECONDARY].buffer;
}
if(list->fogcoord) {
glstate->vao->vertexattrib[ATT_FOGCOORD].real_buffer = saved[ATT_FOGCOORD].real_buffer;
glstate->vao->vertexattrib[ATT_FOGCOORD].real_pointer = saved[ATT_FOGCOORD].real_pointer;
glstate->vao->vertexattrib[ATT_FOGCOORD].buffer = saved[ATT_FOGCOORD].buffer;
}
if(list->normal) {
glstate->vao->vertexattrib[ATT_NORMAL].real_buffer = saved[ATT_NORMAL].real_buffer;
glstate->vao->vertexattrib[ATT_NORMAL].real_pointer = saved[ATT_NORMAL].real_pointer;
glstate->vao->vertexattrib[ATT_NORMAL].buffer = saved[ATT_NORMAL].buffer;
}
for (int a=0; a<list->maxtex; ++a) {
if(list->tex[a]) {
glstate->vao->vertexattrib[ATT_MULTITEXCOORD0+a].real_buffer = saved[ATT_MULTITEXCOORD0+a].real_buffer;
glstate->vao->vertexattrib[ATT_MULTITEXCOORD0+a].real_pointer = saved[ATT_MULTITEXCOORD0+a].real_pointer;
glstate->vao->vertexattrib[ATT_MULTITEXCOORD0+a].buffer = saved[ATT_MULTITEXCOORD0+a].buffer;
}
}
}
int fill_lineIndices(modeinit_t *modes, int length, GLenum mode, GLushort* indices, GLushort *ind_line)
{
#define ind(a) indices?indices[a]:(a)
int k=0;
int i=0;
for (int m=0; m<length; m++) {
GLenum mode_init = modes[k].mode_init;
int len = modes[k].ilen;
switch (mode) {
case GL_TRIANGLE_STRIP:
// first 3 points a triangle, then a 2 lines per new point
if (len>2) {
ind_line[k++] = ind(i+0); ind_line[k++] = ind(i+1);
i+=2;
for (; i<len; i++) {
ind_line[k++] = ind(i-2); ind_line[k++] = ind(i);
ind_line[k++] = ind(i-1); ind_line[k++] = ind(i);
}
}
break;
case GL_TRIANGLE_FAN:
if(mode_init==GL_QUAD_STRIP) {
// first 4 points is a quad, then 2 points per new quad
if (len>3) {
ind_line[k++] = ind(i+0); ind_line[k++] = ind(i+1);
i+=2;
for (; i<len-1; i+=2) {
ind_line[k++] = ind(i-1); ind_line[k++] = ind(i);
ind_line[k++] = ind(i-2); ind_line[k++] = ind(i+1);
ind_line[k++] = ind(i+0); ind_line[k++] = ind(i+1);
}
}
} else if(mode_init==GL_POLYGON) {
if (len) {
int z = i;
ind_line[k++] = ind(i+0); ind_line[k++] = ind(i+1);
++i;
for (; i<len; i++) {
ind_line[k++] = ind(i-1); ind_line[k++] = ind(i);
}
ind_line[k++] = ind(len-1); ind_line[k++] = ind(z);
}
} else {
// first 3 points a triangle, then a 2 lines per new point too
if (len>2) {
int z = i;
ind_line[k++] = ind(i+0); ind_line[k++] = ind(i+1);
i+=2;
for (; i<len; i++) {
ind_line[k++] = ind(z); ind_line[k++] = ind(i);
ind_line[k++] = ind(i-1); ind_line[k++] = ind(i);
}
}
}
break;
case GL_TRIANGLES:
switch (mode_init) {
case GL_TRIANGLE_STRIP:
case GL_TRIANGLE_FAN:
case GL_TRIANGLES:
if(len>2) {
// 1 triangle -> 3 lines => 6 half-lines !
for (; i<len-2; i+=3) {
ind_line[k++] = ind(i+0); ind_line[k++] = ind(i+1);
ind_line[k++] = ind(i+1); ind_line[k++] = ind(i+2);
ind_line[k++] = ind(i+2); ind_line[k++] = ind(i+0);
}
}
break;
case GL_QUADS:
if (len>3) {
// 4 lines per quads, but dest may already be a triangles list...
if (len==4) {
// just 1 Quad
for (; i<4; i++) {
ind_line[k++] = ind(i+0); ind_line[k++] = ind((i+1)%4);
}
} else {
// list of triangles, 2 per quads...
for (; i<len-5; i+=6) {
ind_line[k++] = ind(i+0); ind_line[k++] = ind(i+1);
ind_line[k++] = ind(i+1); ind_line[k++] = ind(i+2);
ind_line[k++] = ind(i+2); ind_line[k++] = ind(i+5);
ind_line[k++] = ind(i+5); ind_line[k++] = ind(i+0);
}
}
}
break;
case GL_QUAD_STRIP:
// first 4 points is a quad, then 2 points per new quad
if (len>3) {
ind_line[k++] = ind(i+0); ind_line[k++] = ind(i+1);
i+=2;
for (; i<len-1; i+=2) {
ind_line[k++] = ind(i-1); ind_line[k++] = ind(i);
ind_line[k++] = ind(i-2); ind_line[k++] = ind(i+1);
ind_line[k++] = ind(i+0); ind_line[k++] = ind(i+1);
}
}
break;
case GL_POLYGON:
// if polygons have been merged, then info is lost...
if (len) {
int z = i;
ind_line[k++] = ind(i+0); ind_line[k++] = ind(i+1);
++i;
for (; i<len; i++) {
ind_line[k++] = ind(i-1); ind_line[k++] = ind(i);
}
ind_line[k++] = ind(len-1); ind_line[k++] = ind(z);
}
break;
}
break;
}
}
#undef ind
return k;
}
void draw_renderlist(renderlist_t *list) {
if (!list) return;
// go to 1st...
while (list->prev) list = list->prev;
// ok, go on now, draw everything
//printf("draw_renderlist %p, size=%i, mode=%s(%s), ilen=%d, next=%p, color=%p, secondarycolor=%p fogcoord=%p\n", list, list->len, PrintEnum(list->mode), PrintEnum(list->mode_init), list->ilen, list->next, list->color, list->secondary, list->fogcoord);
LOAD_GLES_FPE(glDrawArrays);
LOAD_GLES_FPE(glDrawElements);
LOAD_GLES_FPE(glVertexPointer);
LOAD_GLES_FPE(glNormalPointer);
LOAD_GLES_FPE(glColorPointer);
LOAD_GLES_FPE(glTexCoordPointer);
LOAD_GLES_FPE(glEnable);
LOAD_GLES_FPE(glDisable);
gl4es_glPushClientAttrib(GL_CLIENT_VERTEX_ARRAY_BIT);
int old_tex;
GLushort *indices;
int use_texgen[MAX_TEX] = {0};
old_tex = glstate->texture.client;
GLuint cur_tex = old_tex;
GLint needclean[MAX_TEX] = {0};
bool stipple;
int stipple_tmu;
GLenum stipple_env;
GLenum stipple_afunc;
GLfloat stipple_aref;
int stipple_tex2d;
int stipple_alpha;
int stipple_old;
int stipple_texgen[4];
do {
// close if needed!
if (list->open)
list = end_renderlist(list);
// push/pop attributes
if (list->pushattribute)
gl4es_glPushAttrib(list->pushattribute);
if (list->popattribute)
gl4es_glPopAttrib();
call_list_t *cl = &list->calls;
if (cl->len > 0) {
for (int i = 0; i < cl->len; i++) {
glPackedCall(cl->calls[i]);
}
}
if(list->render_op) {
switch(list->render_op) {
case 1: gl4es_glInitNames(); break;
case 2: gl4es_glPopName(); break;
case 3: gl4es_glPushName(list->render_arg); break;
case 4: gl4es_glLoadName(list->render_arg); break;
}
}
if (list->fog_op) {
gl4es_glFogfv(GL_FOG_COLOR, list->fog_val);
}
if (list->pointparam_op) {
switch (list->pointparam_op) {
case 1: // GL_POINT_DISTANCE_ATTENUATION
gl4es_glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION , list->pointparam_val);
break;
}
}
if (list->matrix_op) {
switch (list->matrix_op) {
case 1: // load
gl4es_glLoadMatrixf(list->matrix_val);
break;
case 2: // mult
gl4es_glMultMatrixf(list->matrix_val);
break;
}
}
if (list->set_tmu) {
gl4es_glActiveTexture(GL_TEXTURE0+list->tmu);
}
if (list->set_texture) {
gl4es_glBindTexture(list->target_texture, list->texture);
}
// raster
if (list->raster_op) {
if (list->raster_op==1) {
gl4es_glRasterPos3f(list->raster_xyz[0], list->raster_xyz[1], list->raster_xyz[2]);
} else if (list->raster_op==2) {
gl4es_glWindowPos3f(list->raster_xyz[0], list->raster_xyz[1], list->raster_xyz[2]);
} else if (list->raster_op==3) {
gl4es_glPixelZoom(list->raster_xyz[0], list->raster_xyz[1]);
} else if ((list->raster_op&0x10000) == 0x10000) {
gl4es_glPixelTransferf(list->raster_op&0xFFFF, list->raster_xyz[0]);
}
}
if (list->raster) {
rasterlist_t * r = list->raster;
//glBitmap(r->width, r->height, r->xorig, r->yorig, r->xmove, r->ymove, r->raster);
render_raster_list(list->raster);
}
// bitmaps
if (list->bitmaps) {
for (int i=0; i<list->bitmaps->count; i++) {
bitmap_list_t *l = &list->bitmaps->list[i];
gl4es_glBitmap(l->width, l->height, l->xorig, l->yorig, l->xmove, l->ymove, l->bitmap);
}
}
if (list->material) {
khash_t(material) *map = list->material;
rendermaterial_t *m;
kh_foreach_value(map, m,
switch (m->pname) {
case GL_SHININESS:
gl4es_glMaterialf(m->face, m->pname, m->color[0]);
break;
default:
gl4es_glMaterialfv(m->face, m->pname, m->color);
}
)
}
if (list->colormat_face)
gl4es_glColorMaterial(list->colormat_face, list->colormat_mode);
if (list->light) {
khash_t(light) *lig = list->light;
renderlight_t *m;
kh_foreach_value(lig, m,
switch (m->pname) {
default:
gl4es_glLightfv(m->which, m->pname, m->color);
}
)
}
if (list->lightmodel) {
gl4es_glLightModelfv(list->lightmodelparam, list->lightmodel);
}
if (list->linestipple_op) {
gl4es_glLineStipple(list->linestipple_factor, list->linestipple_pattern);
}
if (list->texenv) {
khash_t(texenv) *tgn = list->texenv;
rendertexenv_t *m;
kh_foreach_value(tgn, m,
gl4es_glTexEnvfv(m->target, m->pname, m->params);
)
}
if (list->texgen) {
khash_t(texgen) *tgn = list->texgen;
rendertexgen_t *m;
kh_foreach_value(tgn, m,
gl4es_glTexGenfv(m->coord, m->pname, m->color);
)
}
if (list->polygon_mode) {
gl4es_glPolygonMode(GL_FRONT_AND_BACK, list->polygon_mode);
}
if (! list->len)
continue;
int use_vbo_array = list->use_vbo_array;
if(!use_vbo_array && (hardext.esversion==1 || globals4es.usevbo==0 || !list->name)) {
use_vbo_array = 1;
}
int use_vbo_indices = list->use_vbo_indices;
if(!use_vbo_indices && (hardext.esversion==1 || globals4es.usevbo==0 || !list->name)) {
use_vbo_indices = 1;
}
if (list->vert) {
fpe_glEnableClientState(GL_VERTEX_ARRAY);
gles_glVertexPointer(4, GL_FLOAT, list->vert_stride, list->vert);
} else {
fpe_glDisableClientState(GL_VERTEX_ARRAY);
}
if (list->normal) {
fpe_glEnableClientState(GL_NORMAL_ARRAY);
gles_glNormalPointer(GL_FLOAT, list->normal_stride, list->normal);
} else {
fpe_glDisableClientState(GL_NORMAL_ARRAY);
}
indices = list->indices;
if(glstate->raster.bm_drawing)
bitmap_flush();
if (list->color) {
fpe_glEnableClientState(GL_COLOR_ARRAY);
if (glstate->enable.color_sum && (list->secondary) && hardext.esversion==1 && !list->use_glstate) {
if(!list->final_colors) {
list->final_colors=(GLfloat*)malloc(list->len * 4 * sizeof(GLfloat));
if (indices) {
for (int i=0; i<list->ilen; i++)
for (int j=0; j<4; j++) {
const int k=indices[i]*4+j;
list->final_colors[k]=list->color[k] + list->secondary[k];
}
} else {
for (int i=0; i<list->len*4; i++)
list->final_colors[i]=list->color[i] + list->secondary[i];
}
}
gles_glColorPointer(4, GL_FLOAT, 0, list->final_colors);
} else {
//printf("colors=%f, %f, %f, %f / %f, %f, %f, %f\n", list->color[0],list->color[1],list->color[2],list->color[3], list->color[4],list->color[5],list->color[6],list->color[7]);
gles_glColorPointer(4, GL_FLOAT, list->color_stride, list->color);
}
} else {
fpe_glDisableClientState(GL_COLOR_ARRAY);
}
if(hardext.esversion > 1) {
// secondary color only on ES2+
if (glstate->enable.color_sum && (list->secondary)) {
fpe_glEnableClientState(GL_SECONDARY_COLOR_ARRAY);
fpe_glSecondaryColorPointer(4, GL_FLOAT, list->secondary_stride, list->secondary);
} else {
fpe_glDisableClientState(GL_SECONDARY_COLOR_ARRAY);
}
// fog coord only on ES2+
if ((glstate->fog.coord_src==GL_FOG_COORD) && (list->fogcoord)) {
fpe_glEnableClientState(GL_FOG_COORD_ARRAY);
fpe_glFogCoordPointer(GL_FLOAT, list->fogcoord_stride, list->fogcoord);
} else {
fpe_glDisableClientState(GL_FOG_COORD_ARRAY);
}
}
#define TEXTURE(A) if (cur_tex!=A) {gl4es_glClientActiveTexture(A+GL_TEXTURE0); cur_tex=A;}
stipple = false;
if ((list->mode == GL_LINES || list->mode == GL_LINE_STRIP || list->mode == GL_LINE_LOOP)
&& glstate->enable.line_stipple) {
stipple = true;
if(get_target(glstate->enable.texture[0])!=-1)
stipple_tmu = 1;
else
stipple_tmu = 0;
}
if (stipple) {
if(!use_vbo_array) use_vbo_array = 1;
stipple_old = glstate->gleshard->active;
if(glstate->gleshard->active!=stipple_tmu) {
LOAD_GLES(glActiveTexture);
gl4es_glActiveTexture(GL_TEXTURE0+stipple_tmu);
}
TEXTURE(stipple_tmu);
GLenum matmode;
gl4es_glGetIntegerv(GL_MATRIX_MODE, (GLint *) &matmode);
gl4es_glMatrixMode(GL_TEXTURE);
gl4es_glPushMatrix();
gl4es_glLoadIdentity();
gl4es_glMatrixMode(matmode);
stipple_env = glstate->texenv[stipple_tmu].env.mode;
gl4es_glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
stipple_tex2d = gl4es_glIsEnabled(GL_TEXTURE_2D);
stipple_alpha = gl4es_glIsEnabled(GL_ALPHA_TEST);
gl4es_glEnable(GL_TEXTURE_2D);
gl4es_glEnable(GL_ALPHA_TEST);
for (int k=0; k<4; k++) {
stipple_texgen[k] = gl4es_glIsEnabled(GL_TEXTURE_GEN_S+k);
if(stipple_texgen[k])
gl4es_glDisable(GL_TEXTURE_GEN_S+k);
}
stipple_afunc = glstate->alphafunc;
stipple_aref = glstate->alpharef;
gl4es_glAlphaFunc(GL_GREATER, 0.0f);
bind_stipple_tex();
modeinit_t tmp; tmp.mode_init = list->mode_init; tmp.ilen=list->ilen?list->ilen:list->len;
list->tex[stipple_tmu] = gen_stipple_tex_coords(list->vert, list->indices, list->mode_inits?list->mode_inits:&tmp, list->vert_stride, list->mode_inits?list->mode_init_len:1, (list->use_glstate)?(list->vert+8+stipple_tmu*4):NULL);
}
#define RS(A, len) if(glstate->texgenedsz[A]<len) {free(glstate->texgened[A]); glstate->texgened[A]=malloc(4*sizeof(GLfloat)*len); glstate->texgenedsz[A]=len; } use_texgen[A]=1
// cannot use list->maxtex because some TMU can be using TexGen or point sprites...
if(hardext.esversion==1) {
for (int a=0; a<hardext.maxtex; a++) {
if(glstate->enable.texture[a] || (stipple && a==stipple_tmu)) {
const GLint itarget = (stipple && a==stipple_tmu)?ENABLED_TEX2D:get_target(glstate->enable.texture[a]);
needclean[a]=0;
use_texgen[a]=0;
if ((glstate->enable.texgen_s[a] || glstate->enable.texgen_t[a] || glstate->enable.texgen_r[a] || glstate->enable.texgen_q[a])) {
TEXTURE(a);
RS(a, list->len);
gen_tex_coords(list->vert, list->normal, &glstate->texgened[a], list->len, &needclean[a], a, (list->ilen<list->len)?indices:NULL, (list->ilen<list->len)?list->ilen:0);
} else if ((list->tex[a]==NULL) && !(list->mode==GL_POINT && glstate->texture.pscoordreplace[a])) {
RS(a, list->len);
gen_tex_coords(list->vert, list->normal, &glstate->texgened[a], list->len, &needclean[a], a, (list->ilen<list->len)?indices:NULL, (list->ilen<list->len)?list->ilen:0);
}
// adjust the tex_coord now if needed, even on texgened ones
gltexture_t *bound = glstate->texture.bound[a][itarget];
if((list->tex[a] || (use_texgen[a] && !needclean[a])) && ((!(globals4es.texmat || glstate->texture_matrix[a]->identity)) || (bound->adjust))) {
if(!use_texgen[a]) {
RS(a, list->len);
if(list->tex_stride[a]) {
GLfloat *src = list->tex[a];
GLfloat *dst = glstate->texgened[a];
int stride = list->tex_stride[a]>>2; // stride need to be a multiple of 4 (i.e. sizeof(GLfloat))
for (int ii=0; ii<list->len; ii++) {
memcpy(dst, src, 4*sizeof(GLfloat));
src+=stride;
dst+=4;
}
} else
memcpy(glstate->texgened[a], list->tex[a], 4*sizeof(GLfloat)*list->len);
}
if (!(globals4es.texmat || glstate->texture_matrix[a]->identity))
tex_coord_matrix(glstate->texgened[a], list->len, getTexMat(a));
if (bound->adjust) {
tex_coord_npot(glstate->texgened[a], list->len, bound->width, bound->height, bound->nwidth, bound->nheight);
}
}
}
if ((list->tex[a] || (use_texgen[a] && !needclean[a]))/* && glstate->enable.texture[a]*/) {
TEXTURE(a);
fpe_glEnableClientState(GL_TEXTURE_COORD_ARRAY);
gles_glTexCoordPointer(4, GL_FLOAT, (use_texgen[a])?0:list->tex_stride[a], (use_texgen[a])?glstate->texgened[a]:list->tex[a]);
} else {
if (glstate->gleshard->vertexattrib[ATT_MULTITEXCOORD0+a].enabled || (hardext.esversion!=1)) { // optim for ES1.1 to avoid useless texture switch
TEXTURE(a);
fpe_glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
//else if (!glstate->enable.texgen_s[a] && glstate->enable.texture[a]) printf("LIBGL: texture[%i] without TexCoord, mode=0x%04X (init=0x%04X), listlen=%i\n", a, list->mode, list->mode_init, list->len);
}
if (!IS_TEX2D(glstate->enable.texture[a]) && (IS_ANYTEX(glstate->enable.texture[a]))) {
TEXTURE(a);
gl4es_glActiveTexture(GL_TEXTURE0+a);
realize_active();
gles_glEnable(GL_TEXTURE_2D);
}
}
} else {
// texture loop for ES2+ version
for (int a=0; a<hardext.maxtex; a++) {
if(list->tex[a]) {
TEXTURE(a);
fpe_glEnableClientState(GL_TEXTURE_COORD_ARRAY);
gles_glTexCoordPointer(4, GL_FLOAT, list->tex_stride[a], list->tex[a]);
} else {
TEXTURE(a);
fpe_glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
}
}
if (glstate->texture.client != old_tex) TEXTURE(old_tex);
#undef RS
#undef TEXTURE
realize_textures(1);
if(use_vbo_array==0) {
if((glstate->render_mode == GL_SELECT) || (glstate->polygon_mode == GL_LINE) || (glstate->polygon_mode == GL_POINT))
use_vbo_array = 1;
else
// evaluated, seems good to go !
use_vbo_array = list2VBO(list);
}
save_vbo_t saved[NB_VA];
if(use_vbo_array==2)
listActiveVBO(list, saved);
if(list->use_vbo_array != use_vbo_array)
list->use_vbo_array = use_vbo_array;
GLenum mode;
mode = list->mode;
if ((glstate->polygon_mode == GL_LINE) && (mode>=GL_TRIANGLES))
mode = GL_LINES;
if ((glstate->polygon_mode == GL_POINT) && (mode>=GL_TRIANGLES))
mode = GL_POINTS;
if (indices) {
if (glstate->render_mode == GL_SELECT) {
vertexattrib_t vtx = {0};
vtx.pointer = list->vert;
vtx.type = GL_FLOAT;
vtx.normalized = GL_FALSE;
vtx.size = 4;
vtx.stride = 0;
select_glDrawElements(&vtx, list->mode, list->ilen, GL_UNSIGNED_SHORT, indices);
use_vbo_indices = 1;
} else {
GLuint old_index = wantBufferIndex(0);
if (glstate->polygon_mode == GL_LINE && list->mode_init>=GL_TRIANGLES) {
int ilen = list->ilen;
if(!list->ind_lines) {
GLushort *ind_line = list->ind_lines = (GLushort*)malloc(sizeof(GLushort)*ilen*4+2);
modeinit_t tmp; tmp.mode_init = list->mode_init; tmp.ilen=list->ilen;
int k = fill_lineIndices(list->mode_inits?list->mode_inits:&tmp, list->mode_inits?list->mode_init_len:1, list->mode, indices, list->ind_lines);
list->ind_line = k;
}
bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
gles_glDrawElements(mode, list->ind_line, GL_UNSIGNED_SHORT, list->ind_lines);
use_vbo_indices = 1;
} else {
int vbo_indices = 0;
if(!use_vbo_indices) {
// create VBO for indices
LOAD_GLES2(glGenBuffers);
LOAD_GLES2(glBufferData);
gles_glGenBuffers(1, &list->vbo_indices);
bindBuffer(GL_ELEMENT_ARRAY_BUFFER, list->vbo_indices);
gles_glBufferData(GL_ELEMENT_ARRAY_BUFFER, list->ilen*sizeof(GLushort), indices, GL_STATIC_DRAW);
use_vbo_indices = 2;
vbo_indices = 1;
} else if(use_vbo_indices==2) {
bindBuffer(GL_ELEMENT_ARRAY_BUFFER, list->vbo_indices);
vbo_indices = 1;
} else
realize_bufferIndex();
if(list->instanceCount==1)
gles_glDrawElements(mode, list->ilen, GL_UNSIGNED_SHORT, vbo_indices?NULL:indices);
else {
for (glstate->instanceID=0; glstate->instanceID<list->instanceCount; ++glstate->instanceID)
gles_glDrawElements(mode, list->ilen, GL_UNSIGNED_SHORT, vbo_indices?NULL:indices);
glstate->instanceID = 0;
}
}
wantBufferIndex(old_index);
}
} else {
if (glstate->render_mode == GL_SELECT) {
vertexattrib_t vtx = {0};
vtx.pointer = list->vert;
vtx.type = GL_FLOAT;
vtx.size = 4;
vtx.normalized = GL_FALSE;
vtx.stride = 0;
select_glDrawArrays(&vtx, list->mode, 0, list->len);
} else {
int len = list->len;
if ((glstate->polygon_mode == GL_LINE) && (list->mode_init>=GL_TRIANGLES)) {
if(!list->ind_lines) {
GLushort *ind_line = list->ind_lines = (GLushort*)malloc(sizeof(GLushort)*len*4+2);
modeinit_t tmp; tmp.mode_init = list->mode_init; tmp.ilen=len;
int k = fill_lineIndices(list->mode_inits?list->mode_inits:&tmp, list->mode_inits?list->mode_init_len:1, list->mode, NULL, list->ind_lines);
list->ind_line = k;
}
bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
gles_glDrawElements(mode, list->ind_line, GL_UNSIGNED_SHORT, list->ind_lines);
} else {
if(list->instanceCount==1)
gles_glDrawArrays(mode, 0, len);
else {
for (glstate->instanceID=0; glstate->instanceID<list->instanceCount; ++glstate->instanceID)
gles_glDrawArrays(mode, 0, len);
glstate->instanceID = 0;
}
}
}
}
if(list->use_vbo_indices != use_vbo_indices)
list->use_vbo_indices = use_vbo_indices;
if(use_vbo_array==2)
listInactiveVBO(list, saved);
#define TEXTURE(A) if (cur_tex!=A) {gl4es_glClientActiveTexture(A+GL_TEXTURE0); cur_tex=A;}
if(hardext.esversion==1)
for (int a=0; a<hardext.maxtex; a++) {
if (needclean[a]) {
TEXTURE(a);
gen_tex_clean(needclean[a], a);
}
if (!IS_TEX2D(glstate->enable.texture[a]) && (IS_ANYTEX(glstate->enable.texture[a]))) {
TEXTURE(a);
gles_glDisable(GL_TEXTURE_2D);
}
}
if (glstate->texture.client!=old_tex)
TEXTURE(old_tex);
#undef TEXTURE
if (stipple) {
if(!list->use_glstate) //TODO: avoid that malloc/free...
free(list->tex[stipple_tmu]);
list->tex[stipple_tmu]=NULL;
LOAD_GLES(glActiveTexture);
if(glstate->gleshard->active!=stipple_tmu)
gl4es_glActiveTexture(GL_TEXTURE0+stipple_tmu);
GLenum matmode;
gl4es_glGetIntegerv(GL_MATRIX_MODE, (GLint *) &matmode);
gl4es_glMatrixMode(GL_TEXTURE);
gl4es_glPopMatrix();
gl4es_glMatrixMode(matmode);
gl4es_glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, stipple_env);
gl4es_glAlphaFunc(stipple_afunc, stipple_aref);
if(stipple_tex2d)
gl4es_glEnable(GL_TEXTURE_2D);
else
gl4es_glDisable(GL_TEXTURE_2D);
if(stipple_alpha)
gl4es_glEnable(GL_ALPHA_TEST);
else
gl4es_glDisable(GL_ALPHA_TEST);
for (int k=0; k<4; k++) {
if(stipple_texgen[k])
gl4es_glEnable(GL_TEXTURE_GEN_S+k);
}
if(glstate->gleshard->active!=stipple_old)
gl4es_glActiveTexture(GL_TEXTURE0+stipple_old);
}
if(list->post_color) gl4es_glColor4fv(list->post_colors);
if(list->post_normal) gl4es_glNormal3fv(list->post_normals);
} while ((list = list->next));
gl4es_glPopClientAttrib();
}
+526
View File
@@ -0,0 +1,526 @@
#include "list.h"
#include "../glx/hardext.h"
#include "gl4es.h"
#include "glstate.h"
#include "init.h"
#include "matrix.h"
static inline void rlVertexCommon(renderlist_t *list, int idx, int l) {
if(list->use_glstate) {
resize_renderlist(list);
if (!list->vert) list->vert = glstate->merger_master;
if (list->normal) memcpy(list->normal + idx, list->lastNormal, sizeof(GLfloat) * 3);
if (list->fogcoord) memcpy(list->fogcoord + idx, glstate->fogcoord, sizeof(GLfloat) * 1);
} else {
if (!list->vert) list->vert = alloc_sublist(4, list->cap);
else resize_renderlist(list);
if (list->normal) memcpy(list->normal + (l * 3), list->lastNormal, sizeof(GLfloat) * 3);
if (list->fogcoord) memcpy(list->fogcoord + (l * 1), glstate->fogcoord, sizeof(GLfloat) * 1);
}
// common part
if (list->color) memcpy(list->color + idx, list->lastColors, sizeof(GLfloat) * 4);
if (list->secondary) memcpy(list->secondary + (l * 4), glstate->secondary, sizeof(GLfloat) * 4);
if (list->tex[0]) memcpy(list->tex[0] + idx, glstate->texcoord[0], sizeof(GLfloat) * 4);
if (list->tex[1]) memcpy(list->tex[1] + idx, glstate->texcoord[1], sizeof(GLfloat) * 4);
for (int a=2; a<list->maxtex; a++)
if (list->tex[a]) memcpy(list->tex[a] + (l * 4), glstate->texcoord[a], sizeof(GLfloat) * 4);
}
void FASTMATH rlVertex4f(renderlist_t *list, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
const int idx = (list->use_glstate)?(list->len * 5*4):(list->len * 4);
rlVertexCommon(list, idx, list->len);
++list->len;
GLfloat * const vert = list->vert + idx;
vert[0] = x; vert[1] = y; vert[2] = z; vert[3] = w;
}
void FASTMATH rlVertex3fv(renderlist_t *list, GLfloat* v) {
const int idx = (list->use_glstate)?(list->len * 5*4):(list->len * 4);
rlVertexCommon(list, idx, list->len);
GLfloat * const vert = list->vert + idx;
++list->len;
memcpy(vert, v, 3*sizeof(GLfloat));
vert[3] = 1.f;
}
void FASTMATH rlVertex4fv(renderlist_t *list, GLfloat* v) {
const int idx = (list->use_glstate)?(list->len * 5*4):(list->len * 4);
rlVertexCommon(list, idx, list->len);
GLfloat * const vert = list->vert + idx;
++list->len;
memcpy(vert, v, 4*sizeof(GLfloat));
}
void rlEnd(renderlist_t *list) {
// adjust number of vertex, to remove extra vertex
int adj = list->len - list->cur_istart;
adj -= adjust_vertices(list->merger_mode?list->merger_mode:list->mode_init, adj);
//printf("rlEnd(%d), indices=%p, mode_init_len=%d, len/cur_istart(adj)/ilen=%d/%d(%d)/%d, mode/mode_init=%s/%s, merger_mode=%s\n", list, list->indices, list->mode_init_len, list->len, list->cur_istart, adj, list->ilen, PrintEnum(list->mode), PrintEnum(list->mode_init), list->merger_mode?PrintEnum(list->merger_mode):"none");
list->len -= adj;
if(!list->mode_inits && list->cur_istart) list_add_modeinit(list, list->mode_init);
if(list->indices && list->merger_mode && list->len-list->cur_istart) {
// also feed the indices...
int istart = list->cur_istart;
int ivert = 0;
int len = list->len-istart;
resize_indices_renderlist(list, indices_getindicesize(list->merger_mode, len));
switch (list->merger_mode) {
case GL_LINE_STRIP:
if(len>1) {
list->indices[list->ilen++]=istart+(ivert);
list->indices[list->ilen++]=istart+(++ivert);
for (int i=2; i<len; i++) {
list->indices[list->ilen++]=istart+(ivert);
list->indices[list->ilen++]=istart+(++ivert);
}
}
break;
case GL_LINE_LOOP:
if(len>1) {
list->indices[list->ilen++]=istart+(ivert++);
list->indices[list->ilen++]=istart+(ivert++);
for (int i=istart+2; i<list->len; i++) {
list->indices[list->ilen++]=istart+(ivert-1);
list->indices[list->ilen++]=istart+(ivert++);
}
list->indices[list->ilen++]=istart+(ivert-1);
list->indices[list->ilen++]=istart;
}
break;
case GL_POLYGON:
case GL_TRIANGLE_FAN:
if(len>2) {
list->indices[list->ilen++]=istart+(ivert++);
list->indices[list->ilen++]=istart+(ivert++);
list->indices[list->ilen++]=istart+(ivert++);
}
for (int i=istart+3; i<list->len; i++) {
// add a new triangle for each new point
list->indices[list->ilen++]=istart;
list->indices[list->ilen++]=istart+(ivert-1);
list->indices[list->ilen++]=istart+(ivert++);
}
break;
case GL_QUAD_STRIP:
case GL_TRIANGLE_STRIP:
if(len>2) {
list->indices[list->ilen++]=istart+(ivert++);
list->indices[list->ilen++]=istart+(ivert++);
list->indices[list->ilen++]=istart+(ivert++);
}
for (int i=istart+3; i<list->len; i++) {
// add a new triangle for each new point
list->indices[list->ilen++]=istart+(ivert-((ivert%2)?1:2));
list->indices[list->ilen++]=istart+(ivert-((ivert%2)?2:1));
list->indices[list->ilen++]=istart+(ivert++);
}
break;
case GL_QUADS:
if(len>3)
for (int i=istart; i+3<list->len; i+=4) {
list->indices[list->ilen++]=i+0;
list->indices[list->ilen++]=i+1;
list->indices[list->ilen++]=i+2;
list->indices[list->ilen++]=i+0;
list->indices[list->ilen++]=i+2;
list->indices[list->ilen++]=i+3;
}
break;
default:
for (int i=istart; i<list->len; i++)
list->indices[list->ilen++]=i;
break;
}
}
list->cur_istart = 0;
if(list->mode_inits) list_add_modeinit(list, list->merger_mode?list->merger_mode:list->mode_init);
if(list->color)
memcpy(glstate->color, list->lastColors, 4*sizeof(GLfloat));
if(list->normal)
memcpy(glstate->normal, list->lastNormal, 3*sizeof(GLfloat));
}
static inline void rlNormalCommon(renderlist_t *list) {
if (list->normal == NULL) {
const int stride = (list->use_glstate)?(5*4):3;
if(list->use_glstate) {
list->normal = glstate->merger_master+4+4+2*4;
} else {
list->normal = alloc_sublist(3, list->cap);
}
// catch up
for (int i = 0; i < list->len; i++) {
GLfloat *normal = (list->normal + (i * stride));
memcpy(normal, list->lastNormal, sizeof(GLfloat) * 3);
}
}
}
void FASTMATH rlNormal3f(renderlist_t *list, GLfloat x, GLfloat y, GLfloat z) {
rlNormalCommon(list);
GLfloat *normal = list->lastNormal;
normal[0] = x; normal[1] = y; normal[2] = z;
}
void FASTMATH rlNormal3fv(renderlist_t *list, GLfloat*v) {
rlNormalCommon(list);
memcpy(list->lastNormal, v, 3*sizeof(GLfloat));
}
static inline void rlColorCommon(renderlist_t *list) {
if (list->color == NULL) {
list->lastColorsSet = 1;
const int stride = (list->use_glstate)?(5*4):4;
if(list->use_glstate) {
list->color = glstate->merger_master+4;
} else {
list->color = alloc_sublist(4, list->cap);
}
// catch up
for (int i = 0; i < list->len; i++) {
GLfloat *color = (list->color + (i * stride));
memcpy(color,list->lastColors, sizeof(GLfloat) * 4);
}
}
}
void FASTMATH rlColor4f(renderlist_t *list, GLfloat r, GLfloat g, GLfloat b, GLfloat a) {
rlColorCommon(list);
GLfloat *color = list->lastColors;
color[0] = r; color[1] = g; color[2] = b; color[3] = a;
}
void FASTMATH rlColor4fv(renderlist_t *list, GLfloat* v) {
rlColorCommon(list);
memcpy(list->lastColors, v, 4*sizeof(GLfloat));
}
void FASTMATH rlSecondary3f(renderlist_t *list, GLfloat r, GLfloat g, GLfloat b) {
if (list->secondary == NULL) {
if(list->use_glstate) {
if(!glstate->merger_secondary)
glstate->merger_secondary = (GLfloat*)malloc(sizeof(GLfloat)*4*glstate->merger_cap);
list->secondary = glstate->merger_secondary;
} else {
list->secondary = alloc_sublist(4, list->cap);
}
// catch up
GLfloat *secondary = list->secondary;
for (int i = 0; i < list->len; i++) {
memcpy(secondary, list->lastSecondaryColors, sizeof(GLfloat) * 4);
secondary += 4;
}
}
GLfloat *color = glstate->secondary;
color[0] = r; color[1] = g; color[2] = b; color[3] = 0.0f;
}
void rlMaterialfv(renderlist_t *list, GLenum face, GLenum pname, const GLfloat * params) {
rendermaterial_t *m;
khash_t(material) *map;
khint_t k;
int ret;
if (! list->material) {
list->material = map = kh_init(material);
// segfaults if we don't do a single put
kh_put(material, map, 1, &ret);
kh_del(material, map, 1);
} else {
map = list->material;
}
int iface = (face==GL_FRONT)?0:((face==GL_BACK)?1:2);
int key = pname | (iface<<16);
k = kh_get(material, map, key);
if (k == kh_end(map)) {
k = kh_put(material, map, key, &ret);
m = kh_value(map, k) = malloc(sizeof(rendermaterial_t));
} else {
m = kh_value(map, k);
}
m->face = face;
m->pname = pname;
int sz=4;
if(pname==GL_SHININESS || pname==GL_COLOR_INDEXES) sz=1;
memcpy(m->color, params, sz*sizeof(GLfloat));
}
void rlLightfv(renderlist_t *list, GLenum which, GLenum pname, const GLfloat * params) {
renderlight_t *m;
khash_t(light) *map;
khint_t k;
int ret;
if (! list->light) {
list->light = map = kh_init(light);
// segfaults if we don't do a single put
kh_put(light, map, 1, &ret);
kh_del(light, map, 1);
} else {
map = list->light;
}
int key = pname | ((which-GL_LIGHT0)<<16);
k = kh_get(light, map, key);
if (k == kh_end(map)) {
k = kh_put(light, map, key, &ret);
m = kh_value(map, k) = malloc(sizeof(renderlight_t));
} else {
m = kh_value(map, k);
}
m->which = which;
m->pname = pname;
int sz=4;
if(pname==GL_SPOT_DIRECTION) sz=3;
if(pname==GL_SPOT_EXPONENT || pname==GL_SPOT_CUTOFF
|| pname==GL_CONSTANT_ATTENUATION || pname==GL_LINEAR_ATTENUATION
|| pname==GL_QUADRATIC_ATTENUATION) sz=1;
memcpy(m->color, params, sz*sizeof(GLfloat));
}
void rlTexGenfv(renderlist_t *list, GLenum coord, GLenum pname, const GLfloat * params) {
rendertexgen_t *m;
khash_t(texgen) *map;
khint_t k;
int ret;
if (! list->texgen) {
list->texgen = map = kh_init(texgen);
// segfaults if we don't do a single put
kh_put(texgen, map, 1, &ret);
kh_del(texgen, map, 1);
} else {
map = list->texgen;
}
int key = pname | ((coord-GL_S)<<16);
k = kh_get(texgen, map, key);
if (k == kh_end(map)) {
k = kh_put(texgen, map, key, &ret);
m = kh_value(map, k) = malloc(sizeof(rendertexgen_t));
} else {
m = kh_value(map, k);
}
m->coord = coord;
m->pname = pname;
memcpy(m->color, params, 4*sizeof(GLfloat));
}
void rlMultiTexCoordCommon(renderlist_t* list, int tmu) {
if (list->tex[tmu] == NULL) {
if (list->maxtex<tmu+1) list->maxtex = tmu+1;
const int stride = (list->use_glstate && tmu<2)?(5*4):4;
if(list->use_glstate) {
if(tmu<2)
list->tex[tmu] = glstate->merger_master+4+4+tmu*4;
else {
if(!glstate->merger_tex[tmu-2])
glstate->merger_tex[tmu-2] = (GLfloat*)malloc(sizeof(GLfloat)*4*glstate->merger_cap);
list->tex[tmu] = glstate->merger_tex[tmu-2];
}
} else {
list->tex[tmu] = alloc_sublist(4, list->cap);
}
// catch up
GLfloat *tex = list->tex[tmu];
for (int i = 0; i < list->len; i++) {
memcpy(tex, glstate->texcoord[tmu], sizeof(GLfloat) * 4);
tex += stride;
}
}
}
void FASTMATH rlMultiTexCoord4f(renderlist_t *list, GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) {
const int tmu = target - GL_TEXTURE0;
rlMultiTexCoordCommon(list, tmu);
GLfloat *tex = glstate->texcoord[tmu];
tex[0] = s; tex[1] = t;
tex[2] = r; tex[3] = q;
}
void FASTMATH rlMultiTexCoord2fv(renderlist_t *list, GLenum target, GLfloat* v) {
const int tmu = target - GL_TEXTURE0;
rlMultiTexCoordCommon(list, tmu);
GLfloat *tex = glstate->texcoord[tmu];
memcpy(tex, v, 2*sizeof(GLfloat));
tex[2] = 0.f; tex[3] = 1.f;
}
void FASTMATH rlMultiTexCoord4fv(renderlist_t *list, GLenum target, GLfloat* v) {
const int tmu = target - GL_TEXTURE0;
rlMultiTexCoordCommon(list, tmu);
GLfloat *tex = glstate->texcoord[tmu];
memcpy(tex, v, 4*sizeof(GLfloat));
}
void FASTMATH rlFogCoordf(renderlist_t *list, GLfloat coord) {
if (list->fogcoord == NULL) {
const int stride = (list->use_glstate)?(5*4):1;
if(list->use_glstate) {
list->fogcoord = glstate->merger_master+4+4+2*4+3;
} else {
list->fogcoord = alloc_sublist(1, list->cap);
}
// catch up
GLfloat *fog = list->fogcoord;
for (int i = 0; i < list->len; i++) {
memcpy(fog, glstate->fogcoord, sizeof(GLfloat) * 1);
fog+=stride;
}
}
glstate->fogcoord[0] = coord;
}
void rlActiveTexture(renderlist_t *list, GLenum texture ) {
list->set_tmu = true;
list->tmu = texture - GL_TEXTURE0;
if(list->maxtex < list->tmu+1) list->maxtex = list->tmu+1;
}
void rlBindTexture(renderlist_t *list, GLenum target, GLuint texture) {
list->texture = texture;
list->target_texture = target;
list->set_texture = true;
}
void rlRasterOp(renderlist_t *list, int op, GLfloat x, GLfloat y, GLfloat z) {
list->raster_op = op;
list->raster_xyz[0] = x;
list->raster_xyz[1] = y;
list->raster_xyz[2] = z;
}
void rlFogOp(renderlist_t *list, int op, const GLfloat* v) {
int n = 1;
if (op==GL_FOG_COLOR) n = 4;
list->fog_op = op;
list->fog_val[0] = v[0];
if (n>1) list->fog_val[1] = v[1];
if (n>2) list->fog_val[2] = v[2];
if (n>3) list->fog_val[3] = v[3];
}
void rlPointParamOp(renderlist_t *list, int op, const GLfloat* v) {
list->pointparam_op = op;
list->pointparam_val[0] = v[0];
list->pointparam_val[1] = v[1];
list->pointparam_val[2] = v[2];
list->pointparam_val[3] = v[3];
}
void rlPushCall(renderlist_t *list, packed_call_t *data) {
call_list_t *cl = &list->calls;
if (!cl->calls) {
cl->cap = DEFAULT_CALL_LIST_CAPACITY;
cl->calls = malloc(DEFAULT_CALL_LIST_CAPACITY * sizeof(void*));
} else if (list->calls.len == list->calls.cap) {
cl->cap += DEFAULT_CALL_LIST_CAPACITY;
cl->calls = realloc(cl->calls, cl->cap * sizeof(void*));
}
cl->calls[cl->len++] = data;
}
renderlist_t* GetFirst(renderlist_t* list) {
while(list->prev)
list = list->prev;
return list;
}
void rlTexEnvfv(renderlist_t *list, GLenum target, GLenum pname, const GLfloat * params) {
int n = 1;
switch(target) {
case GL_POINT_SPRITE: n = 1; break;
default:
switch(pname) {
case GL_TEXTURE_ENV_MODE: n=1; break;
case GL_TEXTURE_ENV_COLOR: n=4; break;
case GL_TEXTURE_LOD_BIAS: n=1; break;
}
}
rendertexenv_t *m;
khash_t(texenv) *map;
khint_t k;
int ret;
if (! list->texenv) {
list->texenv = map = kh_init(texenv);
// segfaults if we don't do a single put
kh_put(texenv, map, 1, &ret);
kh_del(texenv, map, 1);
} else {
map = list->texenv;
}
int key = pname | ((target)<<16);
k = kh_get(texenv, map, key);
if (k == kh_end(map)) {
k = kh_put(texenv, map, key, &ret);
m = kh_value(map, k) = malloc(sizeof(rendertexenv_t));
} else {
m = kh_value(map, k);
}
m->target = target;
m->pname = pname;
memcpy(m->params, params, n*sizeof(GLfloat));
}
void rlTexEnviv(renderlist_t *list, GLenum target, GLenum pname, const GLint * params) {
GLfloat fparams[4];
int n = 1;
switch(target) {
case GL_POINT_SPRITE: n = 1; break;
default:
switch(pname) {
case GL_TEXTURE_ENV_MODE: n=1; break;
case GL_TEXTURE_ENV_COLOR: n=4; break;
case GL_TEXTURE_LOD_BIAS: n=1; break;
}
}
for (int i=0; i<n; i++) fparams[i] = params[i];
rlTexEnvfv(list, target, pname, fparams);
}
#undef alloc_sublist
#undef realloc_sublist
renderlist_t* NewDrawStage(renderlist_t* l, GLenum m) {
if(globals4es.mergelist && !glstate->polygon_mode
&& ((isempty_renderlist(l) && l->prev && l->prev->open && l->prev->mode==m && l->prev->mode_init==m)
|| (l->stage==STAGE_POSTDRAW && l->open))
&& ((l->mode_dimension==rendermode_dimensions(m) && l->mode_dimension>0)))
{
return recycle_renderlist(l, m);
} else {
// if we are just in glBegin/glEnd merger, then purge the list...
if(!glstate->list.compiling && glstate->list.pending) {
glstate->list.active = NULL;
l = end_renderlist(l);
draw_renderlist(l);
free_renderlist(l);
l = alloc_renderlist();
NewStage(l, STAGE_DRAW);
} else {
NewStage(l, STAGE_DRAW);
}
l->mode=m;
l->mode_init=m;
l->mode_dimension = rendermode_dimensions(m);
if(!glstate->merger_used && !glstate->list.compiling
&& !(glstate->render_mode==GL_SELECT || glstate->polygon_mode==GL_LINE || glstate->polygon_mode == GL_POINT))
{
l->vert_stride=sizeof(GLfloat)*4*5;
l->color_stride=sizeof(GLfloat)*4*5;
l->tex_stride[0]=sizeof(GLfloat)*4*5;
l->tex_stride[1]=sizeof(GLfloat)*4*5;
l->normal_stride=sizeof(GLfloat)*4*5;
l->fogcoord_stride=sizeof(GLfloat)*4*5;
l->use_glstate=1;
glstate->merger_used=1;
}
return l;
}
}
+212
View File
@@ -0,0 +1,212 @@
#include "loader.h"
void (APIENTRY_GL4ES *gl4es_getMainFBSize)(GLint* width, GLint* height);
#if defined NO_LOADER
void *gles = (void*)(~(uintptr_t)0);
void *egl = (void*)(~(uintptr_t)0);
void *open_lib(const char **names, const char *override) {
return (void*)(~(uintptr_t)0);
}
void load_libs() {
}
#elif defined AMIGAOS4
#include "../agl/amigaos.h"
void *gles;
void load_libs() {
os4OpenLib(&gles);
}
void *open_lib(const char **names, const char *override) {
return (void*)(~(uintptr_t)0);
}
#else
#ifndef _WIN32
// PATH_MAX
#ifdef __linux__
#include <linux/limits.h>
#else
#include <limits.h>
#endif
#else
__declspec(dllimport)
struct HINSTANCE__* __stdcall LoadLibraryW(const wchar_t*);
#endif
#include "logs.h"
#include "init.h"
#include "envvars.h"
void *gles = NULL, *egl = NULL, *bcm_host = NULL, *vcos = NULL, *gbm = NULL, *drm = NULL;
#ifndef _WIN32
#ifndef NO_GBM
static const char *drm_lib[] = {
"libdrm",
NULL
};
static const char *gbm_lib[] = {
"libgbm",
NULL
};
#endif
static const char *path_prefix[] = {
"",
"/opt/vc/lib/",
"/usr/local/lib/",
"/usr/lib/",
NULL,
};
static const char *lib_ext[] = {
#ifndef NO_GBM
"so.19",
#endif
"so",
"so.1",
"so.2",
"dylib",
"dll",
NULL,
};
static const char *gles2_lib[] = {
#if defined(BCMHOST)
"libbrcmGLESv2",
#endif
"libGLESv2_CM",
"libGLESv2",
NULL
};
static const char *gles_lib[] = {
#if defined(BCMHOST)
"libbrcmGLESv1_CM",
#endif
#if !defined(PYRA)
"libGLESv1_CM",
#endif
"libGLES_CM",
NULL
};
static const char *egl_lib[] = {
#if defined(BCMHOST)
"libbrcmEGL",
#endif
"libEGL",
NULL
};
void *open_lib(const char **names, const char *override) {
void *lib = NULL;
char path_name[PATH_MAX + 1];
int flags = RTLD_LOCAL | RTLD_NOW;
#if defined(RTLD_DEEPBIND)
static int totest = 1;
static int sanitizer = 0;
if(totest) {
totest = 0;
char *p = getenv("LD_PRELOAD");
if(p && strstr(p, "libasan.so"))
sanitizer = 1;
}
// note: breaks address sanitizer
if(!sanitizer && globals4es.deepbind)
flags |= RTLD_DEEPBIND;
#endif
if (override) {
if ((lib = dlopen(override, flags))) {
strncpy(path_name, override, PATH_MAX);
if(!globals4es.nobanner) LOGD("LIBGL:loaded: %s\n", path_name);
return lib;
} else {
LOGE("LIBGL_GLES override failed: %s\n", dlerror());
}
}
for (int p = 0; path_prefix[p]; p++) {
for (int i = 0; names[i]; i++) {
for (int e = 0; lib_ext[e]; e++) {
snprintf(path_name, PATH_MAX, "%s%s.%s", path_prefix[p], names[i], lib_ext[e]);
if ((lib = dlopen(path_name, flags))) {
if(!globals4es.nobanner) LOGD("loaded: %s\n", path_name);
return lib;
}
}
}
}
return lib;
}
#else // _WIN32
void* open_lib(const wchar_t* envvar, const wchar_t* dll)
{
const wchar_t* name = _wgetenv(envvar);
return LoadLibraryW(name?name:dll);
}
#endif
void load_libs() {
static int first = 1;
if (! first) return;
first = 0;
#ifndef _WIN32
const char *gles_override = GetEnvVar("LIBGL_GLES");
#if defined(BCMHOST) && !defined(ANDROID)
// optimistically try to load the raspberry pi libs
if (! gles_override) {
const char *bcm_host_name[] = {"libbcm_host", NULL};
const char *vcos_name[] = {"libvcos", NULL};
bcm_host = open_lib(bcm_host_name, NULL);
vcos = open_lib(vcos_name, NULL);
}
#endif
gles = open_lib((globals4es.es==1)?gles_lib:gles2_lib, gles_override);
#else
gles = open_lib(L"LIBGL_GLES", L"libGLESv2.dll");
#endif
WARN_NULL(gles);
#ifdef NOEGL
egl = gles;
#elif !defined(_WIN32)
const char *egl_override = GetEnvVar("LIBGL_EGL");
egl = open_lib(egl_lib, egl_override);
#else
egl = open_lib(L"LIBGL_EGL", L"libEGL.dll");
#endif
WARN_NULL(egl);
#ifndef NO_GBM
const char *gbm_override = GetEnvVar("LIBGL_GBM");
gbm = open_lib(gbm_lib, gbm_override);
const char *drm_override = GetEnvVar("LIBGL_DRM");
drm = open_lib(drm_lib, drm_override);
#endif
}
#endif
// user-defined getProcAddress
void* (APIENTRY_GL4ES *gles_getProcAddress)(const char *name);
void* APIENTRY_GL4ES proc_address(void *lib, const char *name) {
if (gles_getProcAddress)
return gles_getProcAddress(name);
#ifdef AMIGAOS4
return os4GetProcAddress(name);
#elif defined __EMSCRIPTEN__
void *emscripten_GetProcAddress(const char *name);
return emscripten_GetProcAddress(name);
#elif defined __APPLE__
// apple code seems to use RTLD_NEXT which is usually ((void*)-1)
// remove if it not needed
return dlsym((void*)(~(uintptr_t)0), name);
#elif !defined NO_LOADER
return dlsym(lib, name);
#else
return NULL;
#endif
}
+251
View File
@@ -0,0 +1,251 @@
#ifndef _GL4ES_LOADER_H_
#define _GL4ES_LOADER_H_
#include <stdbool.h>
#include "gl4es.h"
#include "gles.h"
#include "logs.h"
#ifndef NOEGL
//Typedef for egl to be able to call LOAD_EGL...
#include <EGL/egl.h>
#include <EGL/eglext.h>
typedef EGLBoolean (*eglBindAPI_PTR)(EGLenum api);
typedef EGLBoolean (*eglBindTexImage_PTR)(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
typedef EGLBoolean (*eglChooseConfig_PTR)(EGLDisplay dpy, const EGLint * attrib_list, EGLConfig * configs, EGLint config_size, EGLint * num_config);
typedef EGLBoolean (*eglCopyBuffers_PTR)(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target);
typedef EGLContext (*eglCreateContext_PTR)(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint * attrib_list);
typedef EGLSurface (*eglCreatePbufferFromClientBuffer_PTR)(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint * attrib_list);
typedef EGLSurface (*eglCreatePbufferSurface_PTR)(EGLDisplay dpy, EGLConfig config, const EGLint * attrib_list);
typedef EGLSurface (*eglCreatePixmapSurface_PTR)(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint * attrib_list);
typedef EGLSurface (*eglCreatePlatformWindowSurface_PTR)(EGLDisplay display, EGLConfig config, void * native_window, const EGLint * attrib_list);
typedef EGLSurface (*eglCreateWindowSurface_PTR)(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint * attrib_list);
typedef EGLBoolean (*eglDestroyContext_PTR)(EGLDisplay dpy, EGLContext ctx);
typedef EGLBoolean (*eglDestroySurface_PTR)(EGLDisplay dpy, EGLSurface surface);
typedef EGLBoolean (*eglGetConfigAttrib_PTR)(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint * value);
typedef EGLBoolean (*eglGetConfigs_PTR)(EGLDisplay dpy, EGLConfig * configs, EGLint config_size, EGLint * num_config);
typedef EGLContext (*eglGetCurrentContext_PTR)();
typedef EGLDisplay (*eglGetCurrentDisplay_PTR)();
typedef EGLSurface (*eglGetCurrentSurface_PTR)(EGLint readdraw);
typedef EGLDisplay (*eglGetDisplay_PTR)(EGLNativeDisplayType display_id);
typedef EGLDisplay (*eglGetPlatformDisplay_PTR)(EGLenum platform, void * native_display, const EGLint * attrib_list);
typedef EGLint (*eglGetError_PTR)();
typedef __eglMustCastToProperFunctionPointerType (*eglGetProcAddress_PTR)(const char * procname);
typedef EGLBoolean (*eglInitialize_PTR)(EGLDisplay dpy, EGLint * major, EGLint * minor);
typedef EGLBoolean (*eglMakeCurrent_PTR)(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
typedef EGLenum (*eglQueryAPI_PTR)();
typedef EGLBoolean (*eglQueryContext_PTR)(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint * value);
typedef const char * (*eglQueryString_PTR)(EGLDisplay dpy, EGLint name);
typedef EGLBoolean (*eglQuerySurface_PTR)(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint * value);
typedef EGLBoolean (*eglReleaseTexImage_PTR)(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
typedef EGLBoolean (*eglReleaseThread_PTR)();
typedef EGLBoolean (*eglSurfaceAttrib_PTR)(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value);
typedef EGLBoolean (*eglSwapBuffers_PTR)(EGLDisplay dpy, EGLSurface surface);
typedef EGLBoolean (*eglSwapBuffersWithDamageEXT_PTR)(EGLDisplay dpy, EGLSurface surface, EGLint * rects, EGLint n_rects);
typedef EGLBoolean (*eglSwapInterval_PTR)(EGLDisplay dpy, EGLint interval);
typedef EGLBoolean (*eglTerminate_PTR)(EGLDisplay dpy);
typedef EGLBoolean (*eglUnlockSurfaceKHR_PTR)(EGLDisplay display, EGLSurface surface);
typedef EGLBoolean (*eglWaitClient_PTR)();
typedef EGLBoolean (*eglWaitGL_PTR)();
typedef EGLBoolean (*eglWaitNative_PTR)(EGLint engine);
typedef EGLSyncKHR (*eglCreateSyncKHR_PTR)(EGLDisplay dpy, EGLenum type, const EGLint * attrib_list);
typedef EGLint (*eglClientWaitSyncKHR_PTR)(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout);
typedef NativePixmapType (*egl_create_pixmap_ID_mapping_PTR)(void *pixmap);
typedef NativePixmapType (*egl_destroy_pixmap_ID_mapping_PTR)(int id);
#ifdef TEXSTREAM
typedef EGLSurface (*eglCreatePixmapSurfaceHI_PTR)(EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI * pixmap);
typedef EGLBoolean (*eglDestroyImageKHR_PTR)(EGLDisplay dpy, EGLImageKHR image);
typedef EGLBoolean (*eglDestroyStreamKHR_PTR)(EGLDisplay dpy, EGLStreamKHR stream);
typedef EGLImageKHR (*eglCreateImageKHR_PTR)(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint * attrib_list);
typedef EGLStreamKHR (*eglCreateStreamFromFileDescriptorKHR_PTR)(EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor);
typedef EGLStreamKHR (*eglCreateStreamKHR_PTR)(EGLDisplay dpy, const EGLint * attrib_list);
typedef EGLBoolean (*eglDestroySyncKHR_PTR)(EGLDisplay dpy, EGLSyncKHR sync);
typedef EGLBoolean (*eglSignalSyncKHR_PTR)(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode);
typedef EGLBoolean (*eglGetSyncAttribKHR_PTR)(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint * value);
typedef EGLBoolean (*eglStreamAttribKHR_PTR)(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint value);
typedef EGLBoolean (*eglStreamConsumerAcquireKHR_PTR)(EGLDisplay dpy, EGLStreamKHR stream);
typedef EGLBoolean (*eglStreamConsumerGLTextureExternalKHR_PTR)(EGLDisplay dpy, EGLStreamKHR stream);
typedef EGLBoolean (*eglStreamConsumerReleaseKHR_PTR)(EGLDisplay dpy, EGLStreamKHR stream);
typedef EGLBoolean (*eglLockSurfaceKHR_PTR)(EGLDisplay display, EGLSurface surface, const EGLint * attrib_list);
typedef EGLNativeFileDescriptorKHR (*eglGetStreamFileDescriptorKHR_PTR)(EGLDisplay dpy, EGLStreamKHR stream);
typedef EGLBoolean (*eglQueryStreamKHR_PTR)(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint * value);
typedef EGLBoolean (*eglQueryStreamTimeKHR_PTR)(EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLTimeKHR * value);
typedef EGLint (*eglWaitSyncKHR_PTR)(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags);
typedef EGLSurface (*eglCreateStreamProducerSurfaceKHR_PTR)(EGLDisplay dpy, EGLConfig config, EGLStreamKHR stream, const EGLint * attrib_list);
#endif // TEXSTREAM
#endif // NOEGL
#ifdef AMIGAOS4
#include "../agl/amigaos.h"
#elif !defined(_WIN32)
#include <dlfcn.h>
#else
#ifndef _WINBASE_
typedef struct HISTANCE__* HISTANCE;
typedef intptr_t (__stdcall* FPROC)();
__declspec(dllimport)
FPROC __stdcall GetProcAddress(HISTANCE, const char*);
#endif
#ifdef _MSC_VER
__forceinline
#elif defined(__GNUC__)
__attribute__((always_inline)) __inline
#endif
static void* dlsym(void* __restrict handle, const char* __restrict symbol)
{ return (void*)GetProcAddress(handle, symbol); }
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../glx/hardext.h"
extern void* (APIENTRY_GL4ES *gles_getProcAddress)(const char *name);
extern void (APIENTRY_GL4ES *gl4es_getMainFBSize)(GLint* width, GLint* height);
NonAliasExportDecl(void*,proc_address,(void *lib, const char *name));
// will become references to dlopen'd gles and egl
extern void *gles, *bcm_host, *vcos, *gbm, *drm;
EXPORT extern void *egl;
#if defined __APPLE__ || defined __EMSCRIPTEN__
#define NO_LOADER
#endif
#define WARN_NULL(name) if (name == NULL) LOGD("warning, %s line %d function %s: " #name " is NULL\n", __FILE__, __LINE__, __func__);
#define MSVC_SPC(MACRO, ARGS) MACRO ARGS
#define PUSH_IF_COMPILING_EXT(nam, ...) \
if (glstate->list.active) { \
if (!glstate->list.pending) { \
NewStage(glstate->list.active, STAGE_GLCALL); \
MSVC_SPC(push_##nam, (__VA_ARGS__)); \
noerrorShim(); \
return (nam##_RETURN)0; \
} \
else gl4es_flush(); \
}
#define PUSH_IF_COMPILING(name) PUSH_IF_COMPILING_EXT(name, name##_ARG_NAMES)
#define DEFINE_RAW(lib, name) static name##_PTR lib##_##name = NULL
#define LOAD_RAW(lib, name, ...) \
{ \
static bool first = true; \
if (first) { \
first = false; \
if (lib != NULL) { \
lib##_##name = (name##_PTR)__VA_ARGS__; \
} \
WARN_NULL(lib##_##name); \
} \
}
#define LOAD_RAW_3(lib, name, fnc1, fnc2, ...) \
{ \
static bool first = true; \
if (first) { \
first = false; \
if (lib != NULL) { \
lib##_##name = (name##_PTR)fnc1; \
if(! lib##_##name) \
lib##_##name = (name##_PTR)fnc2; \
if(! lib##_##name) { \
__VA_ARGS__ \
} \
} \
} \
}
#define LOAD_RAW_SILENT(lib, name, ...) \
{ \
static bool first = true; \
if (first) { \
first = false; \
if (lib != NULL) { \
lib##_##name = (name##_PTR)__VA_ARGS__; \
} \
} \
}
#define LOAD_RAW_ALT(lib, alt, name, ...) \
{ \
static bool first = true; \
if (first) { \
first = false; \
if (lib != NULL) { \
lib##_##name = (name##_PTR)__VA_ARGS__; \
} \
if(lib##_##name == NULL) \
lib##_##name = alt##_##name; \
} \
}
#define LOAD_LIB(lib, name) DEFINE_RAW(lib, name); LOAD_RAW(lib, name, proc_address(lib, #name))
#define LOAD_LIB_SILENT(lib, name) DEFINE_RAW(lib, name); LOAD_RAW_SILENT(lib, name, proc_address(lib, #name))
#define LOAD_LIB_ALT(lib, alt, name) DEFINE_RAW(lib, name); LOAD_RAW_ALT(lib, alt, name, proc_address(lib, #name))
#define LOAD_GLES(name) LOAD_LIB(gles, name)
#define LOAD_GLES2(name) LOAD_LIB_SILENT(gles, name)
#define LOAD_GLES_OR_FPE(name) LOAD_LIB_ALT(gles, fpe, name)
#define LOAD_GLES_FPE(name) \
DEFINE_RAW(gles, name); \
if(hardext.esversion==1) { \
LOAD_RAW(gles, name, proc_address(gles, #name)); \
} else { \
gles_##name = fpe_##name; \
}
#define LOAD_EGL(name) LOAD_LIB(egl, name)
#define LOAD_GBM(name) LOAD_LIB(gbm, name)
#if defined(AMIGAOS4) || defined(NOEGL) || defined(__EMSCRIPTEN__)
#define LOAD_GLES_OES(name) \
DEFINE_RAW(gles, name); \
{ \
LOAD_RAW(gles, name, proc_address(gles, #name"OES")); \
}
#define LOAD_GLES_EXT(name) \
DEFINE_RAW(gles, name); \
{ \
LOAD_RAW(gles, name, proc_address(gles, #name"EXT")); \
}
#define LOAD_GLES2_OR_OES(name) \
DEFINE_RAW(gles, name); \
{ \
LOAD_RAW_SILENT(gles, name, proc_address(gles, #name)); \
}
#else // defined(AMIGAOS4) || defined(NOEGL)
#define LOAD_EGL_EXT(name) \
DEFINE_RAW(egl, name); \
LOAD_RAW_3(egl, name, proc_address(egl, #name), proc_address(egl, #name "EXT"), LOAD_EGL(eglGetProcAddress); LOAD_RAW(egl, name, egl_eglGetProcAddress(#name "EXT")); )
#define LOAD_GLES_OES(name) \
DEFINE_RAW(gles, name); \
{ \
LOAD_EGL(eglGetProcAddress); \
LOAD_RAW(gles, name, egl_eglGetProcAddress(#name"OES")); \
}
#define LOAD_GLES_EXT(name) \
DEFINE_RAW(gles, name); \
{ \
LOAD_EGL(eglGetProcAddress); \
LOAD_RAW(gles, name, egl_eglGetProcAddress(#name"EXT")); \
}
#define LOAD_GLES2_OR_OES(name) \
DEFINE_RAW(gles, name); \
{ \
LOAD_EGL(eglGetProcAddress); \
LOAD_RAW_SILENT(gles, name, ((hardext.esversion==1)?((void*)egl_eglGetProcAddress(#name"OES")):((void*)dlsym(gles, #name)))); \
}
#endif // defined(AMIGAOS4) || defined(NOEGL)
#endif // _GL4ES_LOADER_H_
+51
View File
@@ -0,0 +1,51 @@
#include "logs.h"
#include "init.h"
#include <stdarg.h>
#if defined(ANDROID) && defined(USE_ANDROID_LOG)
#include <android/log.h>
#endif
//----------------------------------------------------------------------------
static const char * const log_prefix="LIBGL: ";
//----------------------------------------------------------------------------
void LogPrintf_NoPrefix(const char *fmt,...)
{
va_list args;
va_start(args,fmt);
#if defined(ANDROID) && defined(USE_ANDROID_LOG)
__android_log_vprint(ANDROID_LOG_INFO, "LIBGL", fmt, args);
#else
vprintf(fmt,args);
#endif
va_end(args);
}
//----------------------------------------------------------------------------
void LogFPrintf(FILE *fp,const char *fmt,...)
{
#ifndef ANDROID
fprintf(fp,log_prefix);
#endif
va_list args;
va_start(args,fmt);
#if defined(ANDROID) && defined(USE_ANDROID_LOG)
// also on logcat
__android_log_vprint(ANDROID_LOG_INFO, "LIBGL", fmt, args);
#endif
vfprintf(fp,fmt,args);
va_end(args);
}
//----------------------------------------------------------------------------
void LogPrintf(const char *fmt,...)
{
#ifndef ANDROID
printf(log_prefix);
#endif
va_list args;
va_start(args,fmt);
#if defined(ANDROID) && defined(USE_ANDROID_LOG)
__android_log_vprint(ANDROID_LOG_INFO, "LIBGL", fmt, args);
#else
vprintf(fmt,args);
#endif
va_end(args);
}
//----------------------------------------------------------------------------
+25
View File
@@ -0,0 +1,25 @@
#ifndef _GL4ES_LOGS_H_
#define _GL4ES_LOGS_H_
//----------------------------------------------------------------------------
#include <stdio.h>
#include "init.h"
#include "attributes.h"
//----------------------------------------------------------------------------
void LogPrintf_NoPrefix(const char *fmt,...);
void LogFPrintf(FILE *fp,const char *fmt,...);
EXPORT void LogPrintf(const char *fmt,...);
//----------------------------------------------------------------------------
#ifdef GL4ES_SILENCE_MESSAGES
#define SHUT_LOGD(...)
#define SHUT_LOGD_NOPREFIX(...)
#define SHUT_LOGE(...)
#else
#define SHUT_LOGD(...) if(!globals4es.nobanner) LogPrintf(__VA_ARGS__)
#define SHUT_LOGD_NOPREFIX(...) if(!globals4es.nobanner) LogPrintf_NoPrefix(__VA_ARGS__)
#define SHUT_LOGE(...) if(!globals4es.nobanner) LogFPrintf(stderr,__VA_ARGS__)
#endif
//----------------------------------------------------------------------------
#define LOGD(...) LogPrintf(__VA_ARGS__)
#define LOGE(...) LogFPrintf(stderr,__VA_ARGS__)
//----------------------------------------------------------------------------
#endif // _GL4ES_LOGS_H_
+103
View File
@@ -0,0 +1,103 @@
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef _M_EVAL_H
#define _M_EVAL_H
#include "../gl4es.h"
void _math_init_eval( void );
/*
* Horner scheme for Bezier curves
*
* Bezier curves can be computed via a Horner scheme.
* Horner is numerically less stable than the de Casteljau
* algorithm, but it is faster. For curves of degree n
* the complexity of Horner is O(n) and de Casteljau is O(n^2).
* Since stability is not important for displaying curve
* points I decided to use the Horner scheme.
*
* A cubic Bezier curve with control points b0, b1, b2, b3 can be
* written as
*
* (([3] [3] ) [3] ) [3]
* c(t) = (([0]*s*b0 + [1]*t*b1)*s + [2]*t^2*b2)*s + [3]*t^2*b3
*
* [n]
* where s=1-t and the binomial coefficients [i]. These can
* be computed iteratively using the identity:
*
* [n] [n ] [n]
* [i] = (n-i+1)/i * [i-1] and [0] = 1
*/
void
_math_horner_bezier_curve(const GLfloat *cp, GLfloat *out, GLfloat t,
GLuint dim, GLuint order);
/*
* Tensor product Bezier surfaces
*
* Again the Horner scheme is used to compute a point on a
* TP Bezier surface. First a control polygon for a curve
* on the surface in one parameter direction is computed,
* then the point on the curve for the other parameter
* direction is evaluated.
*
* To store the curve control polygon additional storage
* for max(uorder,vorder) points is needed in the
* control net cn.
*/
void
_math_horner_bezier_surf(GLfloat *cn, GLfloat *out, GLfloat u, GLfloat v,
GLuint dim, GLuint uorder, GLuint vorder);
/*
* The direct de Casteljau algorithm is used when a point on the
* surface and the tangent directions spanning the tangent plane
* should be computed (this is needed to compute normals to the
* surface). In this case the de Casteljau algorithm approach is
* nicer because a point and the partial derivatives can be computed
* at the same time. To get the correct tangent length du and dv
* must be multiplied with the (u2-u1)/uorder-1 and (v2-v1)/vorder-1.
* Since only the directions are needed, this scaling step is omitted.
*
* De Casteljau needs additional storage for uorder*vorder
* values in the control net cn.
*/
void
_math_de_casteljau_surf(GLfloat *cn, GLfloat *out, GLfloat *du, GLfloat *dv,
GLfloat u, GLfloat v, GLuint dim,
GLuint uorder, GLuint vorder);
#endif
+452
View File
@@ -0,0 +1,452 @@
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* eval.c was written by
* Bernd Barsuhn (bdbarsuh@cip.informatik.uni-erlangen.de) and
* Volker Weiss (vrweiss@cip.informatik.uni-erlangen.de).
*
* My original implementation of evaluators was simplistic and didn't
* compute surface normal vectors properly. Bernd and Volker applied
* used more sophisticated methods to get better results.
*
* Thanks guys!
*/
#include "eval.h"
static GLboolean init_done = false;
static GLfloat inv_tab[MAX_EVAL_ORDER];
/*
* Horner scheme for Bezier curves
*
* Bezier curves can be computed via a Horner scheme.
* Horner is numerically less stable than the de Casteljau
* algorithm, but it is faster. For curves of degree n
* the complexity of Horner is O(n) and de Casteljau is O(n^2).
* Since stability is not important for displaying curve
* points I decided to use the Horner scheme.
*
* A cubic Bezier curve with control points b0, b1, b2, b3 can be
* written as
*
* (([3] [3] ) [3] ) [3]
* c(t) = (([0]*s*b0 + [1]*t*b1)*s + [2]*t^2*b2)*s + [3]*t^2*b3
*
* [n]
* where s=1-t and the binomial coefficients [i]. These can
* be computed iteratively using the identity:
*
* [n] [n ] [n]
* [i] = (n-i+1)/i * [i-1] and [0] = 1
*/
void
_math_horner_bezier_curve(const GLfloat * cp, GLfloat * out, GLfloat t,
GLuint dim, GLuint order) {
if (! init_done)
_math_init_eval();
GLfloat s, powert, bincoeff;
GLuint i, k;
if (order >= 2) {
bincoeff = (GLfloat) (order - 1);
s = 1.0F - t;
for (k = 0; k < dim; k++)
out[k] = s * cp[k] + bincoeff * t * cp[dim + k];
for (i = 2, cp += 2 * dim, powert = t * t; i < order;
i++, powert *= t, cp += dim) {
bincoeff *= (GLfloat) (order - i);
bincoeff *= inv_tab[i];
for (k = 0; k < dim; k++)
out[k] = s * out[k] + bincoeff * powert * cp[k];
}
} else { /* order=1 -> constant curve */
for (k = 0; k < dim; k++)
out[k] = cp[k];
}
}
/*
* Tensor product Bezier surfaces
*
* Again the Horner scheme is used to compute a point on a
* TP Bezier surface. First a control polygon for a curve
* on the surface in one parameter direction is computed,
* then the point on the curve for the other parameter
* direction is evaluated.
*
* To store the curve control polygon additional storage
* for max(uorder,vorder) points is needed in the
* control net cn.
*/
void
_math_horner_bezier_surf(GLfloat * cn, GLfloat * out, GLfloat u, GLfloat v,
GLuint dim, GLuint uorder, GLuint vorder) {
if (! init_done)
_math_init_eval();
GLfloat *cp = cn + uorder * vorder * dim;
GLuint i, uinc = vorder * dim;
if (vorder > uorder) {
if (uorder >= 2) {
GLfloat s, poweru, bincoeff;
GLuint j, k;
/* Compute the control polygon for the surface-curve in u-direction */
for (j = 0; j < vorder; j++) {
GLfloat *ucp = &cn[j * dim];
/* Each control point is the point for parameter u on a */
/* curve defined by the control polygons in u-direction */
bincoeff = (GLfloat) (uorder - 1);
s = 1.0F - u;
for (k = 0; k < dim; k++)
cp[j * dim + k] = s * ucp[k] + bincoeff * u * ucp[uinc + k];
for (i = 2, ucp += 2 * uinc, poweru = u * u; i < uorder;
i++, poweru *= u, ucp += uinc) {
bincoeff *= (GLfloat) (uorder - i);
bincoeff *= inv_tab[i];
for (k = 0; k < dim; k++)
cp[j * dim + k] =
s * cp[j * dim + k] + bincoeff * poweru * ucp[k];
}
}
/* Evaluate curve point in v */
_math_horner_bezier_curve(cp, out, v, dim, vorder);
} else /* uorder=1 -> cn defines a curve in v */
_math_horner_bezier_curve(cn, out, v, dim, vorder);
} else { /* vorder <= uorder */
if (vorder > 1) {
GLuint i;
/* Compute the control polygon for the surface-curve in u-direction */
for (i = 0; i < uorder; i++, cn += uinc) {
/* For constant i all cn[i][j] (j=0..vorder) are located */
/* on consecutive memory locations, so we can use */
/* horner_bezier_curve to compute the control points */
_math_horner_bezier_curve(cn, &cp[i * dim], v, dim, vorder);
}
/* Evaluate curve point in u */
_math_horner_bezier_curve(cp, out, u, dim, uorder);
} else /* vorder=1 -> cn defines a curve in u */
_math_horner_bezier_curve(cn, out, u, dim, uorder);
}
}
/*
* The direct de Casteljau algorithm is used when a point on the
* surface and the tangent directions spanning the tangent plane
* should be computed (this is needed to compute normals to the
* surface). In this case the de Casteljau algorithm approach is
* nicer because a point and the partial derivatives can be computed
* at the same time. To get the correct tangent length du and dv
* must be multiplied with the (u2-u1)/uorder-1 and (v2-v1)/vorder-1.
* Since only the directions are needed, this scaling step is omitted.
*
* De Casteljau needs additional storage for uorder*vorder
* values in the control net cn.
*/
void
_math_de_casteljau_surf(GLfloat * cn, GLfloat * out, GLfloat * du,
GLfloat * dv, GLfloat u, GLfloat v, GLuint dim,
GLuint uorder, GLuint vorder) {
GLfloat *dcn = cn + uorder * vorder * dim;
GLfloat us = 1.0F - u, vs = 1.0F - v;
GLuint h, i, j, k;
GLuint minorder = uorder < vorder ? uorder : vorder;
GLuint uinc = vorder * dim;
GLuint dcuinc = vorder;
/* Each component is evaluated separately to save buffer space */
/* This does not drasticaly decrease the performance of the */
/* algorithm. If additional storage for (uorder-1)*(vorder-1) */
/* points would be available, the components could be accessed */
/* in the innermost loop which could lead to less cache misses. */
#define CN(I,J,K) cn[(I)*uinc+(J)*dim+(K)]
#define DCN(I, J) dcn[(I)*dcuinc+(J)]
if (minorder < 3) {
if (uorder == vorder) {
for (k = 0; k < dim; k++) {
/* Derivative direction in u */
du[k] = vs * (CN(1, 0, k) - CN(0, 0, k)) +
v * (CN(1, 1, k) - CN(0, 1, k));
/* Derivative direction in v */
dv[k] = us * (CN(0, 1, k) - CN(0, 0, k)) +
u * (CN(1, 1, k) - CN(1, 0, k));
/* bilinear de Casteljau step */
out[k] = us * (vs * CN(0, 0, k) + v * CN(0, 1, k)) +
u * (vs * CN(1, 0, k) + v * CN(1, 1, k));
}
} else if (minorder == uorder) {
for (k = 0; k < dim; k++) {
/* bilinear de Casteljau step */
DCN(1, 0) = CN(1, 0, k) - CN(0, 0, k);
DCN(0, 0) = us * CN(0, 0, k) + u * CN(1, 0, k);
for (j = 0; j < vorder - 1; j++) {
/* for the derivative in u */
DCN(1, j + 1) = CN(1, j + 1, k) - CN(0, j + 1, k);
DCN(1, j) = vs * DCN(1, j) + v * DCN(1, j + 1);
/* for the `point' */
DCN(0, j + 1) = us * CN(0, j + 1, k) + u * CN(1, j + 1, k);
DCN(0, j) = vs * DCN(0, j) + v * DCN(0, j + 1);
}
/* remaining linear de Casteljau steps until the second last step */
for (h = minorder; h < vorder - 1; h++)
for (j = 0; j < vorder - h; j++) {
/* for the derivative in u */
DCN(1, j) = vs * DCN(1, j) + v * DCN(1, j + 1);
/* for the `point' */
DCN(0, j) = vs * DCN(0, j) + v * DCN(0, j + 1);
}
/* derivative direction in v */
dv[k] = DCN(0, 1) - DCN(0, 0);
/* derivative direction in u */
du[k] = vs * DCN(1, 0) + v * DCN(1, 1);
/* last linear de Casteljau step */
out[k] = vs * DCN(0, 0) + v * DCN(0, 1);
}
} else { /* minorder == vorder */
for (k = 0; k < dim; k++) {
/* bilinear de Casteljau step */
DCN(0, 1) = CN(0, 1, k) - CN(0, 0, k);
DCN(0, 0) = vs * CN(0, 0, k) + v * CN(0, 1, k);
for (i = 0; i < uorder - 1; i++) {
/* for the derivative in v */
DCN(i + 1, 1) = CN(i + 1, 1, k) - CN(i + 1, 0, k);
DCN(i, 1) = us * DCN(i, 1) + u * DCN(i + 1, 1);
/* for the `point' */
DCN(i + 1, 0) = vs * CN(i + 1, 0, k) + v * CN(i + 1, 1, k);
DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0);
}
/* remaining linear de Casteljau steps until the second last step */
for (h = minorder; h < uorder - 1; h++)
for (i = 0; i < uorder - h; i++) {
/* for the derivative in v */
DCN(i, 1) = us * DCN(i, 1) + u * DCN(i + 1, 1);
/* for the `point' */
DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0);
}
/* derivative direction in u */
du[k] = DCN(1, 0) - DCN(0, 0);
/* derivative direction in v */
dv[k] = us * DCN(0, 1) + u * DCN(1, 1);
/* last linear de Casteljau step */
out[k] = us * DCN(0, 0) + u * DCN(1, 0);
}
}
} else if (uorder == vorder) {
for (k = 0; k < dim; k++) {
/* first bilinear de Casteljau step */
for (i = 0; i < uorder - 1; i++) {
DCN(i, 0) = us * CN(i, 0, k) + u * CN(i + 1, 0, k);
for (j = 0; j < vorder - 1; j++) {
DCN(i, j + 1) = us * CN(i, j + 1, k) + u * CN(i + 1, j + 1, k);
DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1);
}
}
/* remaining bilinear de Casteljau steps until the second last step */
for (h = 2; h < minorder - 1; h++) {
for (i = 0; i < uorder - h; i++) {
DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0);
for (j = 0; j < vorder - h; j++) {
DCN(i, j + 1) = us * DCN(i, j + 1) + u * DCN(i + 1, j + 1);
DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1);
}
}
}
/* derivative direction in u */
du[k] = vs * (DCN(1, 0) - DCN(0, 0)) + v * (DCN(1, 1) - DCN(0, 1));
/* derivative direction in v */
dv[k] = us * (DCN(0, 1) - DCN(0, 0)) + u * (DCN(1, 1) - DCN(1, 0));
/* last bilinear de Casteljau step */
out[k] = us * (vs * DCN(0, 0) + v * DCN(0, 1)) +
u * (vs * DCN(1, 0) + v * DCN(1, 1));
}
} else if (minorder == uorder) {
for (k = 0; k < dim; k++) {
/* first bilinear de Casteljau step */
for (i = 0; i < uorder - 1; i++) {
DCN(i, 0) = us * CN(i, 0, k) + u * CN(i + 1, 0, k);
for (j = 0; j < vorder - 1; j++) {
DCN(i, j + 1) = us * CN(i, j + 1, k) + u * CN(i + 1, j + 1, k);
DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1);
}
}
/* remaining bilinear de Casteljau steps until the second last step */
for (h = 2; h < minorder - 1; h++) {
for (i = 0; i < uorder - h; i++) {
DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0);
for (j = 0; j < vorder - h; j++) {
DCN(i, j + 1) = us * DCN(i, j + 1) + u * DCN(i + 1, j + 1);
DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1);
}
}
}
/* last bilinear de Casteljau step */
DCN(2, 0) = DCN(1, 0) - DCN(0, 0);
DCN(0, 0) = us * DCN(0, 0) + u * DCN(1, 0);
for (j = 0; j < vorder - 1; j++) {
/* for the derivative in u */
DCN(2, j + 1) = DCN(1, j + 1) - DCN(0, j + 1);
DCN(2, j) = vs * DCN(2, j) + v * DCN(2, j + 1);
/* for the `point' */
DCN(0, j + 1) = us * DCN(0, j + 1) + u * DCN(1, j + 1);
DCN(0, j) = vs * DCN(0, j) + v * DCN(0, j + 1);
}
/* remaining linear de Casteljau steps until the second last step */
for (h = minorder; h < vorder - 1; h++) {
for (j = 0; j < vorder - h; j++) {
/* for the derivative in u */
DCN(2, j) = vs * DCN(2, j) + v * DCN(2, j + 1);
/* for the `point' */
DCN(0, j) = vs * DCN(0, j) + v * DCN(0, j + 1);
}
}
/* derivative direction in v */
dv[k] = DCN(0, 1) - DCN(0, 0);
/* derivative direction in u */
du[k] = vs * DCN(2, 0) + v * DCN(2, 1);
/* last linear de Casteljau step */
out[k] = vs * DCN(0, 0) + v * DCN(0, 1);
}
} else { /* minorder == vorder */
for (k = 0; k < dim; k++) {
/* first bilinear de Casteljau step */
for (i = 0; i < uorder - 1; i++) {
DCN(i, 0) = us * CN(i, 0, k) + u * CN(i + 1, 0, k);
for (j = 0; j < vorder - 1; j++) {
DCN(i, j + 1) = us * CN(i, j + 1, k) + u * CN(i + 1, j + 1, k);
DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1);
}
}
/* remaining bilinear de Casteljau steps until the second last step */
for (h = 2; h < minorder - 1; h++) {
for (i = 0; i < uorder - h; i++) {
DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0);
for (j = 0; j < vorder - h; j++) {
DCN(i, j + 1) = us * DCN(i, j + 1) + u * DCN(i + 1, j + 1);
DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1);
}
}
}
/* last bilinear de Casteljau step */
DCN(0, 2) = DCN(0, 1) - DCN(0, 0);
DCN(0, 0) = vs * DCN(0, 0) + v * DCN(0, 1);
for (i = 0; i < uorder - 1; i++) {
/* for the derivative in v */
DCN(i + 1, 2) = DCN(i + 1, 1) - DCN(i + 1, 0);
DCN(i, 2) = us * DCN(i, 2) + u * DCN(i + 1, 2);
/* for the `point' */
DCN(i + 1, 0) = vs * DCN(i + 1, 0) + v * DCN(i + 1, 1);
DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0);
}
/* remaining linear de Casteljau steps until the second last step */
for (h = minorder; h < uorder - 1; h++) {
for (i = 0; i < uorder - h; i++) {
/* for the derivative in v */
DCN(i, 2) = us * DCN(i, 2) + u * DCN(i + 1, 2);
/* for the `point' */
DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0);
}
}
/* derivative direction in u */
du[k] = DCN(1, 0) - DCN(0, 0);
/* derivative direction in v */
dv[k] = us * DCN(0, 2) + u * DCN(1, 2);
/* last linear de Casteljau step */
out[k] = us * DCN(0, 0) + u * DCN(1, 0);
}
}
#undef DCN
#undef CN
}
/*
* Do one-time initialization for evaluators.
*/
void _math_init_eval() {
GLuint i;
/* KW: precompute 1/x for useful x.
*/
for (i = 1; i < MAX_EVAL_ORDER; i++)
inv_tab[i] = 1.0F / i;
init_done = true;
}
+389
View File
@@ -0,0 +1,389 @@
#include "matrix.h"
#include "../glx/hardext.h"
#include "debug.h"
#include "fpe.h"
#include "gl4es.h"
#include "glstate.h"
#include "init.h"
#include "loader.h"
//#define DEBUG
#ifdef DEBUG
#define DBG(a) a
#else
#define DBG(a)
#endif
void alloc_matrix(matrixstack_t **matrixstack, int depth) {
*matrixstack = (matrixstack_t*)malloc(sizeof(matrixstack_t));
(*matrixstack)->top = 0;
(*matrixstack)->identity = 0;
(*matrixstack)->stack = (GLfloat*)malloc(sizeof(GLfloat)*depth*16);
}
#define TOP(A) (glstate->A->stack+(glstate->A->top*16))
static GLfloat* update_current_mat() {
switch(glstate->matrix_mode) {
case GL_MODELVIEW:
return TOP(modelview_matrix);
case GL_PROJECTION:
return TOP(projection_matrix);
case GL_TEXTURE:
return TOP(texture_matrix[glstate->texture.active]);
default:
if(glstate->matrix_mode>=GL_MATRIX0_ARB && glstate->matrix_mode<GL_MATRIX0_ARB+MAX_ARB_MATRIX)
return TOP(arb_matrix[glstate->matrix_mode-GL_MATRIX0_ARB]);
return NULL;
}
}
static int update_current_identity(int I) {
switch(glstate->matrix_mode) {
case GL_MODELVIEW:
return glstate->modelview_matrix->identity = (I)?1:is_identity(TOP(modelview_matrix));
case GL_PROJECTION:
return glstate->projection_matrix->identity = (I)?1:is_identity(TOP(projection_matrix));
case GL_TEXTURE:
return glstate->texture_matrix[glstate->texture.active]->identity = (I)?1:is_identity(TOP(texture_matrix[glstate->texture.active]));
default:
if(glstate->matrix_mode>=GL_MATRIX0_ARB && glstate->matrix_mode<GL_MATRIX0_ARB+MAX_ARB_MATRIX)
return glstate->arb_matrix[glstate->matrix_mode-GL_MATRIX0_ARB]->identity = (I)?1:is_identity(TOP(arb_matrix[glstate->matrix_mode-GL_MATRIX0_ARB]));
return 0;
}
}
static int send_to_hardware() {
if(hardext.esversion>1)
return 0;
switch(glstate->matrix_mode) {
case GL_PROJECTION:
return 1;
case GL_MODELVIEW:
return 1;
case GL_TEXTURE:
return (globals4es.texmat)?1:0;
/*default:
if(glstate->matrix_mode>=GL_MATRIX0_ARB && glstate->matrix_mode<GL_MATRIX0_ARB+MAX_ARB_MATRIX)
return 0;*/
}
return 0;
}
void init_matrix(glstate_t* glstate) {
DBG(printf("init_matrix(%p)\n", glstate);)
alloc_matrix(&glstate->projection_matrix, MAX_STACK_PROJECTION);
set_identity(TOP(projection_matrix));
glstate->projection_matrix->identity = 1;
alloc_matrix(&glstate->modelview_matrix, MAX_STACK_MODELVIEW);
set_identity(TOP(modelview_matrix));
glstate->modelview_matrix->identity = 1;
glstate->texture_matrix = (matrixstack_t**)malloc(sizeof(matrixstack_t*)*MAX_TEX);
glstate->arb_matrix = (matrixstack_t**)malloc(sizeof(matrixstack_t*)*MAX_ARB_MATRIX);
set_identity(glstate->mvp_matrix);
glstate->mvp_matrix_dirty = 0;
set_identity(glstate->inv_mv_matrix);
glstate->inv_mv_matrix_dirty = 0;
// no identity function for 3x3 matrix
memset(glstate->normal_matrix, 0, 9*sizeof(GLfloat));
glstate->normal_matrix[0] = glstate->normal_matrix[4] = glstate->normal_matrix[8] = 1.0f;
glstate->normal_matrix_dirty = 1;
for (int i=0; i<MAX_TEX; i++) {
alloc_matrix(&glstate->texture_matrix[i], MAX_STACK_TEXTURE);
set_identity(TOP(texture_matrix[i]));
glstate->texture_matrix[i]->identity = 1;
}
for (int i=0; i<MAX_ARB_MATRIX; i++) {
alloc_matrix(&glstate->arb_matrix[i], MAX_STACK_ARB_MATRIX);
set_identity(TOP(arb_matrix[i]));
glstate->arb_matrix[i]->identity = 1;
}
}
void set_fpe_textureidentity() {
if(glstate->texture_matrix[glstate->texture.active]->identity) // inverted in fpe flags
glstate->fpe_state->texture[glstate->texture.active].texmat = 0;
else
glstate->fpe_state->texture[glstate->texture.active].texmat = 1;
}
void APIENTRY_GL4ES gl4es_glMatrixMode(GLenum mode) {
DBG(printf("glMatrixMode(%s), list=%p\n", PrintEnum(mode), glstate->list.active);)
noerrorShim();
if (glstate->list.active && glstate->list.pending && glstate->matrix_mode==GL_MODELVIEW && mode==GL_MODELVIEW) {
return; // nothing to do...
}
PUSH_IF_COMPILING(glMatrixMode);
if(!((mode==GL_MODELVIEW) || (mode==GL_PROJECTION) || (mode==GL_TEXTURE) || (mode>=GL_MATRIX0_ARB && mode<(GL_MATRIX0_ARB+MAX_ARB_MATRIX)))) {
errorShim(GL_INVALID_ENUM);
return;
}
if(glstate->matrix_mode != mode) {
glstate->matrix_mode = mode;
LOAD_GLES_FPE(glMatrixMode);
gles_glMatrixMode(mode);
}
}
void APIENTRY_GL4ES gl4es_glPushMatrix(void) {
DBG(printf("glPushMatrix(), list=%p\n", glstate->list.active);)
if (glstate->list.active && !glstate->list.pending) {
PUSH_IF_COMPILING(glPushMatrix);
}
// get matrix mode
GLint matrix_mode = glstate->matrix_mode;
noerrorShim();
// go...
switch(matrix_mode) {
#define P(A, B) if(glstate->A->top+1<MAX_STACK_##B) { \
memcpy(TOP(A)+16, TOP(A), 16*sizeof(GLfloat)); \
glstate->A->top++; \
} else errorShim(GL_STACK_OVERFLOW)
case GL_PROJECTION:
P(projection_matrix, PROJECTION);
break;
case GL_MODELVIEW:
P(modelview_matrix, MODELVIEW);
break;
case GL_TEXTURE:
P(texture_matrix[glstate->texture.active], TEXTURE);
break;
default:
if(glstate->matrix_mode>=GL_MATRIX0_ARB && glstate->matrix_mode<GL_MATRIX0_ARB+MAX_ARB_MATRIX) {
P(arb_matrix[glstate->matrix_mode-GL_MATRIX0_ARB], ARB_MATRIX);
} else {
//Warning?
errorShim(GL_INVALID_OPERATION);
//LOGE("PushMatrix with Unrecognise matrix mode (0x%04X)\n", matrix_mode);
//gles_glPushMatrix();
}
#undef P
}
}
void APIENTRY_GL4ES gl4es_glPopMatrix(void) {
DBG(printf("glPopMatrix(), list=%p\n", glstate->list.active);)
if (glstate->list.active
&& !(glstate->list.compiling)
&& (globals4es.beginend)
&& glstate->matrix_mode==GL_MODELVIEW
&& !(glstate->polygon_mode==GL_LINE)
&& glstate->list.pending) {
// check if pop'd matrix is the same as actual...
if(memcmp(TOP(modelview_matrix)-16, TOP(modelview_matrix), 16*sizeof(GLfloat))==0) {
--glstate->modelview_matrix->top;
return;
}
}
PUSH_IF_COMPILING(glPopMatrix);
// get matrix mode
GLint matrix_mode = glstate->matrix_mode;
// go...
noerrorShim();
switch(matrix_mode) {
#define P(A) if(glstate->A->top) { \
--glstate->A->top; \
glstate->A->identity = is_identity(update_current_mat()); \
if (send_to_hardware()) {LOAD_GLES(glLoadMatrixf); gles_glLoadMatrixf(update_current_mat()); } \
} else errorShim(GL_STACK_UNDERFLOW)
case GL_PROJECTION:
P(projection_matrix);
glstate->mvp_matrix_dirty = 1;
break;
case GL_MODELVIEW:
P(modelview_matrix);
glstate->mvp_matrix_dirty = 1;
glstate->inv_mv_matrix_dirty = 1;
glstate->normal_matrix_dirty = 1;
break;
case GL_TEXTURE:
P(texture_matrix[glstate->texture.active]);
if(glstate->fpe_state)
set_fpe_textureidentity();
break;
default:
if(glstate->matrix_mode>=GL_MATRIX0_ARB && glstate->matrix_mode<GL_MATRIX0_ARB+MAX_ARB_MATRIX) {
P(arb_matrix[glstate->matrix_mode-GL_MATRIX0_ARB]);
} else {
//Warning?
errorShim(GL_INVALID_OPERATION);
//LOGE("PopMatrix with Unrecognise matrix mode (0x%04X)\n", matrix_mode);
//gles_glPopMatrix();
}
#undef P
}
}
void APIENTRY_GL4ES gl4es_glLoadMatrixf(const GLfloat * m) {
DBG(printf("glLoadMatrix(%f, %f, %f, %f, %f, %f, %f...), list=%p\n", m[0], m[1], m[2], m[3], m[4], m[5], m[6], glstate->list.active);)
if (glstate->list.active) {
if(glstate->list.pending) gl4es_flush();
else {
NewStage(glstate->list.active, STAGE_MATRIX);
glstate->list.active->matrix_op = 1;
memcpy(glstate->list.active->matrix_val, m, 16*sizeof(GLfloat));
return;
}
}
memcpy(update_current_mat(), m, 16*sizeof(GLfloat));
const int id = update_current_identity(0);
if(glstate->matrix_mode==GL_MODELVIEW)
glstate->normal_matrix_dirty = glstate->inv_mv_matrix_dirty = 1;
if(glstate->matrix_mode==GL_MODELVIEW || glstate->matrix_mode==GL_PROJECTION)
glstate->mvp_matrix_dirty = 1;
else if((glstate->matrix_mode==GL_TEXTURE) && glstate->fpe_state)
set_fpe_textureidentity();
if(send_to_hardware()) {
LOAD_GLES(glLoadMatrixf);
LOAD_GLES(glLoadIdentity);
if(id) gles_glLoadIdentity(); // in case the driver as some special optimisations
else gles_glLoadMatrixf(m);
}
}
void APIENTRY_GL4ES gl4es_glMultMatrixf(const GLfloat * m) {
DBG(printf("glMultMatrix(%f, %f, %f, %f, %f, %f, %f...), list=%p\n", m[0], m[1], m[2], m[3], m[4], m[5], m[6], glstate->list.active);)
if (glstate->list.active) {
if(glstate->list.pending) gl4es_flush();
else {
if(glstate->list.active->stage == STAGE_MATRIX) {
// multiply the matrix mith the current one....
matrix_mul(glstate->list.active->matrix_val, m, glstate->list.active->matrix_val);
return;
}
NewStage(glstate->list.active, STAGE_MATRIX);
glstate->list.active->matrix_op = 2;
memcpy(glstate->list.active->matrix_val, m, 16*sizeof(GLfloat));
return;
}
}
GLfloat *current_mat = update_current_mat();
matrix_mul(current_mat, m, current_mat);
const int id = update_current_identity(0);
if(glstate->matrix_mode==GL_MODELVIEW)
glstate->normal_matrix_dirty = glstate->inv_mv_matrix_dirty = 1;
if(glstate->matrix_mode==GL_MODELVIEW || glstate->matrix_mode==GL_PROJECTION)
glstate->mvp_matrix_dirty = 1;
else if((glstate->matrix_mode==GL_TEXTURE) && glstate->fpe_state)
set_fpe_textureidentity();
DBG(printf(" => (%f, %f, %f, %f, %f, %f, %f...)\n", current_mat[0], current_mat[1], current_mat[2], current_mat[3], current_mat[4], current_mat[5], current_mat[6]);)
if(send_to_hardware()) {
LOAD_GLES(glLoadMatrixf);
LOAD_GLES(glLoadIdentity);
if(id) gles_glLoadIdentity(); // in case the driver as some special optimisations
else gles_glLoadMatrixf(current_mat);
}
}
void APIENTRY_GL4ES gl4es_glLoadIdentity(void) {
DBG(printf("glLoadIdentity(), list=%p\n", glstate->list.active);)
if (glstate->list.active) {
if(glstate->list.pending) gl4es_flush();
else {
NewStage(glstate->list.active, STAGE_MATRIX);
glstate->list.active->matrix_op = 1;
set_identity(glstate->list.active->matrix_val);
return;
}
}
set_identity(update_current_mat());
update_current_identity(1);
if(glstate->matrix_mode==GL_MODELVIEW)
glstate->normal_matrix_dirty = glstate->inv_mv_matrix_dirty = 1;
if(glstate->matrix_mode==GL_MODELVIEW || glstate->matrix_mode==GL_PROJECTION)
glstate->mvp_matrix_dirty = 1;
else if((glstate->matrix_mode==GL_TEXTURE) && glstate->fpe_state)
set_fpe_textureidentity();
if(send_to_hardware()) {
LOAD_GLES(glLoadIdentity);
gles_glLoadIdentity();
}
}
void APIENTRY_GL4ES gl4es_glTranslatef(GLfloat x, GLfloat y, GLfloat z) {
DBG(printf("glTranslatef(%f, %f, %f), list=%p\n", x, y, z, glstate->list.active);)
// create a translation matrix than multiply it...
GLfloat tmp[16];
set_identity(tmp);
tmp[12+0] = x;
tmp[12+1] = y;
tmp[12+2] = z;
gl4es_glMultMatrixf(tmp);
}
void APIENTRY_GL4ES gl4es_glScalef(GLfloat x, GLfloat y, GLfloat z) {
DBG(printf("glScalef(%f, %f, %f), list=%p\n", x, y, z, glstate->list.active);)
// create a scale matrix than multiply it...
GLfloat tmp[16];
memset(tmp, 0, 16*sizeof(GLfloat));
tmp[0+0] = x;
tmp[1+4] = y;
tmp[2+8] = z;
tmp[3+12] = 1.0f;
gl4es_glMultMatrixf(tmp);
}
void APIENTRY_GL4ES gl4es_glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z) {
DBG(printf("glRotatef(%f, %f, %f, %f), list=%p\n", angle, x, y, z, glstate->list.active);)
// create a rotation matrix than multiply it...
GLfloat tmp[16];
memset(tmp, 0, 16*sizeof(GLfloat));
if((x==0 && y==0 && z==0) || angle==0)
return; // nothing to do
// normalize x y z
GLfloat l = 1.0f/sqrtf(x*x+y*y+z*z);
x=x*l; y=y*l; z=z*l;
// calculate sin/cos
angle*=3.1415926535f/180.f;
const GLfloat s=sinf(angle);
const GLfloat c=cosf(angle);
const GLfloat c1 = 1-c;
//build the matrix
tmp[0+0] = x*x*c1+c; tmp[0+4] = x*y*c1-z*s; tmp[0+8] = x*z*c1+y*s;
tmp[1+0] = y*x*c1+z*s; tmp[1+4] = y*y*c1+c; tmp[1+8] = y*z*c1-x*s;
tmp[2+0] = x*z*c1-y*s; tmp[2+4] = y*z*c1+x*s; tmp[2+8] = z*z*c1+c;
tmp[3+12] = 1.0f;
// done...
gl4es_glMultMatrixf(tmp);
}
void APIENTRY_GL4ES gl4es_glOrthof(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat nearVal, GLfloat farVal) {
DBG(printf("glOrthof(%f, %f, %f, %f, %f, %f), list=%p\n", left, right, top, bottom, nearVal, farVal, glstate->list.active);)
GLfloat tmp[16];
memset(tmp, 0, 16*sizeof(GLfloat));
tmp[0+0] = 2.0f/(right-left); tmp[0+12] = -(right+left)/(right-left);
tmp[1+4] = 2.0f/(top-bottom); tmp[1+12] = -(top+bottom)/(top-bottom);
tmp[2+8] =-2.0f/(farVal-nearVal); tmp[2+12] = -(farVal+nearVal)/(farVal-nearVal);
tmp[3+12] = 1.0f;
gl4es_glMultMatrixf(tmp);
}
void APIENTRY_GL4ES gl4es_glFrustumf(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat nearVal, GLfloat farVal) {
DBG(printf("glFrustumf(%f, %f, %f, %f, %f, %f) list=%p\n", left, right, top, bottom, nearVal, farVal, glstate->list.active);)
GLfloat tmp[16];
memset(tmp, 0, 16*sizeof(GLfloat));
tmp[0+0] = 2.0f*nearVal/(right-left); tmp[0+8] = (right+left)/(right-left);
tmp[1+4] = 2.0f*nearVal/(top-bottom); tmp[1+8] = (top+bottom)/(top-bottom);
tmp[2+8] =-(farVal+nearVal)/(farVal-nearVal); tmp[2+12] =-2.0f*farVal*nearVal/(farVal-nearVal);
tmp[3+8] = -1.0f;
gl4es_glMultMatrixf(tmp);
}
AliasExport(void,glMatrixMode,,(GLenum mode));
AliasExport_V(void,glPushMatrix);
AliasExport_V(void,glPopMatrix);
AliasExport(void,glLoadMatrixf,,(const GLfloat * m));
AliasExport(void,glMultMatrixf,,(const GLfloat * m));
AliasExport_V(void,glLoadIdentity);
AliasExport(void,glTranslatef,,(GLfloat x, GLfloat y, GLfloat z));
AliasExport(void,glScalef,,(GLfloat x, GLfloat y, GLfloat z));
AliasExport(void,glRotatef,,(GLfloat angle, GLfloat x, GLfloat y, GLfloat z));
AliasExport(void,glOrthof,,(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat nearVal, GLfloat farVal));
AliasExport(void,glFrustumf,,(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat nearVal, GLfloat farVal));
+59
View File
@@ -0,0 +1,59 @@
#ifndef _GL4ES_MATRIX_H_
#define _GL4ES_MATRIX_H_
#include "gl4es.h"
#include "gles.h"
#include "glstate.h"
#include "list.h"
#include "matvec.h"
void APIENTRY_GL4ES gl4es_glMatrixMode(GLenum mode);
void APIENTRY_GL4ES gl4es_glPushMatrix(void);
void APIENTRY_GL4ES gl4es_glPopMatrix(void);
void APIENTRY_GL4ES gl4es_glLoadMatrixf(const GLfloat * m);
void APIENTRY_GL4ES gl4es_glMultMatrixf(const GLfloat * m);
void APIENTRY_GL4ES gl4es_glLoadIdentity(void);
void APIENTRY_GL4ES gl4es_glTranslatef(GLfloat x, GLfloat y, GLfloat z);
void APIENTRY_GL4ES gl4es_glScalef(GLfloat x, GLfloat y, GLfloat z);
void APIENTRY_GL4ES gl4es_glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
void APIENTRY_GL4ES gl4es_glOrthof(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat nearVal, GLfloat farVal);
void APIENTRY_GL4ES gl4es_glFrustumf(GLfloat left, GLfloat right, GLfloat bottom, GLfloat top, GLfloat nearVal, GLfloat farVal);
static inline GLfloat* getTexMat(int tmu) {
return glstate->texture_matrix[tmu]->stack+glstate->texture_matrix[tmu]->top*16;
}
static inline GLfloat* getMVMat() {
return glstate->modelview_matrix->stack+glstate->modelview_matrix->top*16;
}
static inline GLfloat* getInvMVMat() {
if(glstate->inv_mv_matrix_dirty) {
matrix_inverse(glstate->modelview_matrix->stack+glstate->modelview_matrix->top*16, glstate->inv_mv_matrix);
glstate->inv_mv_matrix_dirty = 0;
}
return glstate->inv_mv_matrix;
}
static inline GLfloat* getNormalMat() {
if(glstate->normal_matrix_dirty) {
matrix_inverse3_transpose(glstate->modelview_matrix->stack+glstate->modelview_matrix->top*16, glstate->normal_matrix);
glstate->normal_matrix_dirty = 0;
}
return glstate->normal_matrix;
}
static inline GLfloat* getPMat() {
return glstate->projection_matrix->stack+glstate->projection_matrix->top*16;
}
static inline GLfloat* getMVPMat()
{
if(glstate->mvp_matrix_dirty) {
matrix_mul(getPMat(), getMVMat(), glstate->mvp_matrix);
glstate->mvp_matrix_dirty = 0;
}
return glstate->mvp_matrix;
}
#endif // _GL4ES_MATRIX_H_
+353
View File
@@ -0,0 +1,353 @@
#include "matvec.h"
#include <string.h>
float FASTMATH dot(const float *a, const float *b) {
return a[0]*b[0] + a[1]*b[1] + a[2]*b[2];
}
float FASTMATH dot4(const float *a, const float *b) {
#if defined(__ARM_NEON__) && !defined(__APPLE__)
register float ret;
asm volatile (
"vld1.f32 {d0-d1}, [%1] \n" //q0 = a(0..3)
"vld1.f32 {d2-d3}, [%2] \n" //q1 = b(0..3)
"vmul.f32 q0, q0, q1 \n" //q0 = a(0)*b(0),a(1)*b(1),a(2)*b(2),a(3)*b(3)
"vadd.f32 d0, d0, d1 \n" //d0 = a(0)*b(0)+a(2)*b(2),a(1)*b(1)+a(3)*b(3)
"vpadd.f32 d0,d0 \n" //d0 = a(0)*b(0)+a(2)*b(2)+a(1)*b(1)+a(3)*b(3),a(0)*b(0)+a(2)*b(2)+a(1)*b(1)+a(3)*b(3)
"vmov.f32 %0, s0 \n"
:"=w"(ret): "r"(a), "r"(b)
: "q0", "q1"
);
return ret;
#else
return a[0]*b[0] + a[1]*b[1] + a[2]*b[2] + a[3]*b[3];
#endif
}
void cross3(const float *a, const float *b, float* c) {
//TODO Neonize? Cross product doesn't seems NEON friendly, and this is not much used.
c[0] = a[1]*b[2] - a[2]*b[1];
c[1] = a[3]*b[0] - a[0]*b[3];
c[2] = a[0]*b[1] - a[1]*b[0];
}
void matrix_vector(const float *a, const float *b, float *c) {
#if defined(__ARM_NEON__) && !defined(__APPLE__)
const float* a1 = a+8;
asm volatile (
"vld4.f32 {d0,d2,d4,d6}, [%1] \n"
"vld4.f32 {d1,d3,d5,d7}, [%2] \n" // q0-q3 = a(0,4,8,12/1,5,9,13/2,6,10,14/3,7,11,15)
"vld1.f32 {q4}, [%3] \n" // q4 = b
"vmul.f32 q0, q0, d8[0] \n" // q0 = a(0,4,8,12)*b[0]
"vmla.f32 q0, q1, d8[1] \n" // q0 = q0 + a(1,5,9,13)*b[1]
"vmla.f32 q0, q2, d9[0] \n" // q0 = q0 + a(2,6,10,14)*b[2]
"vmla.f32 q0, q3, d9[1] \n" // q0 = q0 + a(3,7,11,15)*b[3]
"vst1.f32 {q0}, [%0] \n"
::"r"(c), "r"(a), "r"(a1), "r"(b)
: "q0", "q1", "q2", "q3", "q4", "memory"
);
#else
c[0] = a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
c[1] = a[4] * b[0] + a[5] * b[1] + a[6] * b[2] + a[7] * b[3];
c[2] = a[8] * b[0] + a[9] * b[1] + a[10] * b[2] + a[11] * b[3];
c[3] = a[12] * b[0] + a[13] * b[1] + a[14] * b[2] + a[15] * b[3];
#endif
}
void vector_matrix(const float *a, const float *b, float *c) {
#if defined(__ARM_NEON__) && !defined(__APPLE__)
const float* b2=b+4;
const float* b3=b+8;
const float* b4=b+12;
asm volatile (
"vld1.f32 {q0}, [%1] \n" // %q0 = a(0..3)
"vld1.f32 {q1}, [%2] \n" // %q1 = b(0..3)
"vmul.f32 q1, q1, d0[0] \n" // %q1 = b(0..3)*a[0]
"vld1.f32 {q2}, [%3] \n" // %q2 = b(4..7)
"vmla.f32 q1, q2, d0[1] \n" // %q1 = %q1 + b(4..7)*a[1]
"vld1.f32 {q2}, [%4] \n" // %q2 = b(8..11)
"vmla.f32 q1, q2, d1[0] \n" // %q1 = %q1 + b(8..11)*a[2]
"vld1.f32 {q2}, [%5] \n" // %q2 = b(12..15)
"vmla.f32 q1, q2, d1[1] \n" // %q1 = %q1 + b(12..15)*a[3]
"vst1.f32 {q1}, [%0] \n"
::"r"(c), "r"(a), "r"(b), "r"(b2), "r"(b3), "r"(b4)
: "%2", "q0", "q1", "q2", "memory"
);
#else
const float a0=a[0], a1=a[1], a2=a[2], a3=a[3];
c[0] = a0 * b[0] + a1 * b[4] + a2 * b[8] + a3 * b[12];
c[1] = a0 * b[1] + a1 * b[5] + a2 * b[9] + a3 * b[13];
c[2] = a0 * b[2] + a1 * b[6] + a2 * b[10] + a3 * b[14];
c[3] = a0 * b[3] + a1 * b[7] + a2 * b[11] + a3 * b[15];
#endif
}
void vector3_matrix(const float *a, const float *b, float *c) {
#if defined(__ARM_NEON__) && !defined(__APPLE__)
const float* b2=b+4;
const float* b3=b+8;
const float* b4=b+12;
asm volatile (
//"vld1.f32 {q0}, [%1] \n" // %q0 = a(0..2)
"vld1.32 {d0}, [%1] \n"
"flds s2, [%1, #8] \n"
"vsub.f32 s3, s3, s3 \n"
"vld1.f32 {q1}, [%2] \n" // %q1 = b(0..3)
"vmul.f32 q1, q1, d0[0] \n" // %q1 = b(0..3)*a[0]
"vld1.f32 {q2}, [%3] \n" // %q2 = b(4..7)
"vmla.f32 q1, q2, d0[1] \n" // %q1 = %q1 + b(4..7)*a[1]
"vld1.f32 {q2}, [%4] \n" // %q2 = b(8..11)
"vmla.f32 q1, q2, d1[0] \n" // %q1 = %q1 + b(8..11)*a[2]
"vld1.f32 {q2}, [%5] \n" // %q2 = b(12..15)
"vadd.f32 q1, q1, q2 \n" // %q1 = %q1 + b(12..15)
"vst1.f32 {q1}, [%0] \n"
::"r"(c), "r"(a), "r"(b), "r"(b2), "r"(b3), "r"(b4)
: "q0", "q1", "q2", "memory"
);
#else
c[0] = a[0] * b[0] + a[1] * b[4] + a[2] * b[8] + b[12];
c[1] = a[0] * b[1] + a[1] * b[5] + a[2] * b[9] + b[13];
c[2] = a[0] * b[2] + a[1] * b[6] + a[2] * b[10] + b[14];
c[3] = a[0] * b[3] + a[1] * b[7] + a[2] * b[11] + b[15];
#endif
}
void vector3_matrix4(const float *a, const float *b, float *c) {
c[0] = a[0] * b[0] + a[1] * b[4] + a[2] * b[8];
c[1] = a[0] * b[1] + a[1] * b[5] + a[2] * b[9];
c[2] = a[0] * b[2] + a[1] * b[6] + a[2] * b[10];
}
void vector3_matrix3(const float *a, const float *b, float *c) {
c[0] = a[0] * b[0] + a[1] * b[3] + a[2] * b[6];
c[1] = a[0] * b[1] + a[1] * b[4] + a[2] * b[7];
c[2] = a[0] * b[2] + a[1] * b[5] + a[2] * b[8];
}
void vector_normalize(float *a) {
#if defined(__ARM_NEON__) && !defined(__APPLE__)
asm volatile (
"vld1.32 {d4}, [%0] \n\t" //d4={x0,y0}
"flds s10, [%0, #8] \n\t" //d5[0]={z0}
"vsub.f32 s11, s11, s11 \n\t"
"vmul.f32 d0, d4, d4 \n\t" //d0= d4*d4
"vpadd.f32 d0, d0 \n\t" //d0 = d[0] + d[1]
"vmla.f32 d0, d5, d5 \n\t" //d0 = d0 + d5*d5
"vmov.f32 d1, d0 \n\t" //d1 = d0
"vrsqrte.f32 d0, d0 \n\t" //d0 = ~ 1.0 / sqrt(d0)
"vmul.f32 d2, d0, d1 \n\t" //d2 = d0 * d1
"vrsqrts.f32 d3, d2, d0 \n\t" //d3 = (3 - d0 * d2) / 2
"vmul.f32 d0, d0, d3 \n\t" //d0 = d0 * d3
/* "vmul.f32 d2, d0, d1 \n\t" //d2 = d0 * d1
"vrsqrts.f32 d3, d2, d0 \n\t" //d4 = (3 - d0 * d3) / 2
"vmul.f32 d0, d0, d3 \n\t" //d0 = d0 * d4 */ // 1 iteration should be enough
"vmul.f32 q2, q2, d0[0] \n\t" //d0= d2*d4
"vst1.32 {d4}, [%0] \n\t" //
"fsts s10, [%0, #8] \n\t" //
:"+&r"(a):
: "d0", "d1", "d2", "d3", "d4", "d5", "memory"
);
#else
float det=1.0f/sqrtf(a[0]*a[0]+a[1]*a[1]+a[2]*a[2]);
a[0]*=det;
a[1]*=det;
a[2]*=det;
#endif
}
void vector4_normalize(float *a) {
#if defined(__ARM_NEON__) && !defined(__APPLE__)
asm volatile (
"vld1.32 {q2}, [%0] \n\t" //q2={x0,y0,z0,00}
"vmul.f32 d0, d4, d4 \n\t" //d0= d4*d4
"vpadd.f32 d0, d0 \n\t" //d0 = d[0] + d[1]
"vmla.f32 d0, d5, d5 \n\t" //d0 = d0 + d5*d5
"vmov.f32 d1, d0 \n\t" //d1 = d0
"vrsqrte.f32 d0, d0 \n\t" //d0 = ~ 1.0 / sqrt(d0)
"vmul.f32 d2, d0, d1 \n\t" //d2 = d0 * d1
"vrsqrts.f32 d3, d2, d0 \n\t" //d3 = (3 - d0 * d2) / 2
"vmul.f32 d0, d0, d3 \n\t" //d0 = d0 * d3
/* "vmul.f32 d2, d0, d1 \n\t" //d2 = d0 * d1
"vrsqrts.f32 d3, d2, d0 \n\t" //d4 = (3 - d0 * d3) / 2
"vmul.f32 d0, d0, d3 \n\t" //d0 = d0 * d4 */ // 1 iteration should be enough
"vmul.f32 q2, q2, d0[0] \n\t" //d0= d2*d4
"vst1.32 {q2}, [%0] \n\t" //
:"+&r"(a):
: "d0", "d1", "d2", "d3", "d4", "d5", "memory"
);
#else
float det=1.0f/sqrtf(a[0]*a[0]+a[1]*a[1]+a[2]*a[2]);
a[0]*=det;
a[1]*=det;
a[2]*=det;
// a[3] is ignored and left as 0.0f
#endif
}
void FASTMATH matrix_transpose(const float *a, float *b) {
// column major -> row major
// a(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15) -> b(0,4,8,12,1,5,9,13,2,6,10,14,3,7,11,15)
#if defined(__ARM_NEON__) && !defined(__APPLE__)
const float* a1 = a+8;
float* b1=b+8;
asm volatile (
"vld4.f32 {d0,d2,d4,d6}, [%1] \n"
"vld4.f32 {d1,d3,d5,d7}, [%2] \n" // %q0-%q3 = a(0,4,8,12/1,5,9,13/2,6,10,14/3,7,11,15)
"vst1.f32 {d0-d3}, [%0] \n"
"vst1.f32 {d4-d7}, [%3] \n"
::"r"(b), "r"(a), "r"(a1), "r"(b1)
: "q0", "q1", "q2", "q3", "memory"
);
#else
for (int i=0; i<4; i++)
for (int j=0; j<4; j++)
b[i*4+j]=a[i+j*4];
#endif
}
void matrix_inverse(const float *m, float *r) {
r[0] = m[5]*m[10]*m[15] - m[5]*m[14]*m[11] - m[6]*m[9]*m[15] + m[6]*m[13]*m[11] + m[7]*m[9]*m[14] - m[7]*m[13]*m[10];
r[1] = -m[1]*m[10]*m[15] + m[1]*m[14]*m[11] + m[2]*m[9]*m[15] - m[2]*m[13]*m[11] - m[3]*m[9]*m[14] + m[3]*m[13]*m[10];
r[2] = m[1]*m[6]*m[15] - m[1]*m[14]*m[7] - m[2]*m[5]*m[15] + m[2]*m[13]*m[7] + m[3]*m[5]*m[14] - m[3]*m[13]*m[6];
r[3] = -m[1]*m[6]*m[11] + m[1]*m[10]*m[7] + m[2]*m[5]*m[11] - m[2]*m[9]*m[7] - m[3]*m[5]*m[10] + m[3]*m[9]*m[6];
r[4] = -m[4]*m[10]*m[15] + m[4]*m[14]*m[11] + m[6]*m[8]*m[15] - m[6]*m[12]*m[11] - m[7]*m[8]*m[14] + m[7]*m[12]*m[10];
r[5] = m[0]*m[10]*m[15] - m[0]*m[14]*m[11] - m[2]*m[8]*m[15] + m[2]*m[12]*m[11] + m[3]*m[8]*m[14] - m[3]*m[12]*m[10];
r[6] = -m[0]*m[6]*m[15] + m[0]*m[14]*m[7] + m[2]*m[4]*m[15] - m[2]*m[12]*m[7] - m[3]*m[4]*m[14] + m[3]*m[12]*m[6];
r[7] = m[0]*m[6]*m[11] - m[0]*m[10]*m[7] - m[2]*m[4]*m[11] + m[2]*m[8]*m[7] + m[3]*m[4]*m[10] - m[3]*m[8]*m[6];
r[8] = m[4]*m[9]*m[15] - m[4]*m[13]*m[11] - m[5]*m[8]*m[15] + m[5]*m[12]*m[11] + m[7]*m[8]*m[13] - m[7]*m[12]*m[9];
r[9] = -m[0]*m[9]*m[15] + m[0]*m[13]*m[11] + m[1]*m[8]*m[15] - m[1]*m[12]*m[11] - m[3]*m[8]*m[13] + m[3]*m[12]*m[9];
r[10] = m[0]*m[5]*m[15] - m[0]*m[13]*m[7] - m[1]*m[4]*m[15] + m[1]*m[12]*m[7] + m[3]*m[4]*m[13] - m[3]*m[12]*m[5];
r[11] = -m[0]*m[5]*m[11] + m[0]*m[9]*m[7] + m[1]*m[4]*m[11] - m[1]*m[8]*m[7] - m[3]*m[4]*m[9] + m[3]*m[8]*m[5];
r[12] = -m[4]*m[9]*m[14] + m[4]*m[13]*m[10] + m[5]*m[8]*m[14] - m[5]*m[12]*m[10] - m[6]*m[8]*m[13] + m[6]*m[12]*m[9];
r[13] = m[0]*m[9]*m[14] - m[0]*m[13]*m[10] - m[1]*m[8]*m[14] + m[1]*m[12]*m[10] + m[2]*m[8]*m[13] - m[2]*m[12]*m[9];
r[14] = -m[0]*m[5]*m[14] + m[0]*m[13]*m[6] + m[1]*m[4]*m[14] - m[1]*m[12]*m[6] - m[2]*m[4]*m[13] + m[2]*m[12]*m[5];
r[15] = m[0]*m[5]*m[10] - m[0]*m[9]*m[6] - m[1]*m[4]*m[10] + m[1]*m[8]*m[6] + m[2]*m[4]*m[9] - m[2]*m[8]*m[5];
float det = 1.0f/(m[0]*r[0] + m[1]*r[4] + m[2]*r[8] + m[3]*r[12]);
for (int i = 0; i < 16; i++) r[i] *= det;
}
void matrix_inverse3_transpose(const float *m, float *r) {
r[0] = m[4+1]*m[8+2] - m[4+2]*m[8+1];
r[1] = m[4+2]*m[8+0] - m[4+0]*m[8+2];
r[2] = m[4+0]*m[8+1] - m[4+1]*m[8+0];
r[3] = m[0+2]*m[8+1] - m[0+1]*m[8+2];
r[4] = m[0+0]*m[8+2] - m[0+2]*m[8+0];
r[5] = m[0+1]*m[8+0] - m[0+0]*m[8+1];
r[6] = m[0+1]*m[4+2] - m[0+2]*m[4+1];
r[7] = m[0+2]*m[4+0] - m[0+0]*m[4+2];
r[8] = m[0+0]*m[4+1] - m[0+1]*m[4+0];
float det = 1.0f/(m[0]*r[0] + m[4+0]*r[3] + m[8+0]*r[6]);
for (int i = 0; i < 9; i++) r[i] *= det;
}
void matrix_mul(const float *a, const float *b, float *c) {
#if defined(__ARM_NEON__) && !defined(__APPLE__)
const float* a1 = a+8;
const float* b1=b+8;
float* c1=c+8;
asm volatile (
"vld1.32 {d16-d19}, [%2] \n"
"vld1.32 {d20-d23}, [%3] \n"
"vld1.32 {d0-d3}, [%4] \n"
"vld1.32 {d4-d7}, [%5] \n"
"vmul.f32 q12, q8, d0[0] \n"
"vmul.f32 q13, q8, d2[0] \n"
"vmul.f32 q14, q8, d4[0] \n"
"vmul.f32 q15, q8, d6[0] \n"
"vmla.f32 q12, q9, d0[1] \n"
"vmla.f32 q13, q9, d2[1] \n"
"vmla.f32 q14, q9, d4[1] \n"
"vmla.f32 q15, q9, d6[1] \n"
"vmla.f32 q12, q10, d1[0] \n"
"vmla.f32 q13, q10, d3[0] \n"
"vmla.f32 q14, q10, d5[0] \n"
"vmla.f32 q15, q10, d7[0] \n"
"vmla.f32 q12, q11, d1[1] \n"
"vmla.f32 q13, q11, d3[1] \n"
"vmla.f32 q14, q11, d5[1] \n"
"vmla.f32 q15, q11, d7[1] \n"
"vst1.32 {d24-d27}, [%0] \n"
"vst1.32 {d28-d31}, [%1] \n"
::"r"(c), "r"(c1), "r"(a), "r"(a1), "r"(b), "r"(b1)
: "q0", "q1", "q2", "q3",
"q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15", "memory"
);
#else
float a00 = a[0], a01 = a[1], a02 = a[2], a03 = a[3],
a10 = a[4], a11 = a[5], a12 = a[6], a13 = a[7],
a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
a30 = a[12], a31 = a[13], a32 = a[14], a33 = a[15];
float b0 = b[0], b1 = b[1], b2 = b[2], b3 = b[3];
c[0] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
c[1] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
c[2] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
c[3] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
b0 = b[4]; b1 = b[5]; b2 = b[6]; b3 = b[7];
c[4] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
c[5] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
c[6] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
c[7] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
b0 = b[8]; b1 = b[9]; b2 = b[10]; b3 = b[11];
c[8] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
c[9] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
c[10] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
c[11] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
b0 = b[12]; b1 = b[13]; b2 = b[14]; b3 = b[15];
c[12] = b0*a00 + b1*a10 + b2*a20 + b3*a30;
c[13] = b0*a01 + b1*a11 + b2*a21 + b3*a31;
c[14] = b0*a02 + b1*a12 + b2*a22 + b3*a32;
c[15] = b0*a03 + b1*a13 + b2*a23 + b3*a33;
#endif
}
void vector4_mult(const float *a, const float *b, float *c) {
//TODO: NEON version of this
for (int i=0; i<4; i++)
c[i] = a[i]*b[i];
}
void vector4_add(const float *a, const float *b, float *c) {
//TODO: NEON version of this
for (int i=0; i<4; i++)
c[i] = a[i]+b[i];
}
void vector4_sub(const float *a, const float *b, float *c) {
//TODO: NEON version of this
for (int i=0; i<4; i++)
c[i] = a[i]-b[i];
}
void set_identity(float* mat) {
memset(mat, 0, 16*sizeof(float));
mat[0] = mat[1+4] = mat[2+8] = mat[3+12] = 1.0f;
}
int is_identity(const float* mat) {
static float i1[16];
static int set=0;
if(!set) {set_identity(i1); set=1;}
return memcmp(mat, i1, 16*sizeof(float))==0?1:0;
}
+26
View File
@@ -0,0 +1,26 @@
#ifndef _GL4ES_MATVEC_H_
#define _GL4ES_MATVEC_H_
#include <math.h>
#include "attributes.h"
float dot(const float *a, const float *b) FASTMATH;
float dot4(const float *a, const float *b) FASTMATH;
void cross3(const float *a, const float *b, float* c) FASTMATH;
void matrix_vector(const float *a, const float *b, float *c);
void vector_matrix(const float *a, const float *b, float *c);
void vector3_matrix(const float *a, const float *b, float *c);
void vector3_matrix3(const float *a, const float *b, float *c);
void vector3_matrix4(const float *a, const float *b, float *c);
void vector_normalize(float *a);
void vector4_normalize(float *a);
void vector4_mult(const float *a, const float *b, float *c);
void vector4_add(const float *a, const float *b, float *c);
void matrix_transpose(const float *a, float *b);
void matrix_inverse(const float *m, float *r);
void matrix_inverse3_transpose(const float *m, float *r); // upper3x3 of matrix4 -> inverse -> transposed mat3
void matrix_mul(const float *a, const float *b, float *c);
void set_identity(float* mat);
int is_identity(const float* mat);
#endif // _GL4ES_MATVEC_H_
+855
View File
@@ -0,0 +1,855 @@
#include "debug.h"
#include "fpe.h"
#include "gl4es.h"
#include "glstate.h"
#include "loader.h"
#include "oldprogram.h"
#include "shaderconv.h"
#include "vertexattrib.h"
#include "arbconverter.h"
#include "debug.h"
//#define DEBUG
#ifdef DEBUG
#define DBG(a) a
#else
#define DBG(a)
#endif
// Implement "Old program" handling: so ARB_vertex_program and ARB_fragment_program extensions
// the core of this is a conversion between ARB ASM-like syntax to GLSL, then using regular functions
// Note that a program in this context is in fact a shader in ARB_vertex_shader (and GLSL) extension
KHASH_MAP_INIT_INT(oldprograms, oldprogram_t *);
void freeOldProgram(oldprogram_t* old)
{
if(!old)
return;
if(old->string)
free(old->string);
if(old->shader)
gl4es_glDeleteShader(old->shader->id);
if(old->prog_local_params)
free(old->prog_local_params);
free(old);
}
void InitOldProgramMap(glstate_t* glstate)
{
if(glstate->glsl) {
glstate->glsl->oldprograms = kh_init(oldprograms);
glstate->glsl->error_msg = NULL;
glstate->glsl->error_ptr = -1;
}
}
void FreeOldProgramMap(glstate_t* glstate)
{
if(!glstate->glsl)
return;
if(glstate->glsl->error_msg)
free(glstate->glsl->error_msg);
oldprogram_t* old;
kh_foreach_value(glstate->glsl->oldprograms, old, freeOldProgram(old));
kh_destroy(oldprograms, glstate->glsl->oldprograms);
}
GLuint getUniqueProgramID(GLuint last) {
// avoid recycling prog id (that may messup FPE Cache)
static GLuint upper = 0;
if(last>upper) last = upper;
khint_t k;
do {
++last;
k = kh_get(oldprograms, glstate->glsl->oldprograms, last);
} while(k!=kh_end(glstate->glsl->oldprograms));
upper = last;
return last;
}
oldprogram_t* getOldProgram(GLuint program)
{
kh_oldprograms_t * oldprograms = glstate->glsl->oldprograms;
if(program) {
khint_t k = kh_get(oldprograms, oldprograms, program);
if(k != kh_end(oldprograms))
return kh_value(oldprograms, k);
}
return NULL;
}
// Vertex function are also defined with ARB_vertex_shader
/*
void APIENTRY_GL4ES gl4es_glVertexAttrib1sARB(GLuint index, GLshort x)
void APIENTRY_GL4ES gl4es_glVertexAttrib1fARB(GLuint index, GLfloat x);
void APIENTRY_GL4ES gl4es_glVertexAttrib1dARB(GLuint index, GLdouble x);
void APIENTRY_GL4ES gl4es_glVertexAttrib2sARB(GLuint index, GLshort x, GLshort y);
void APIENTRY_GL4ES gl4es_glVertexAttrib2fARB(GLuint index, GLfloat x, GLfloat y);
void APIENTRY_GL4ES gl4es_glVertexAttrib2dARB(GLuint index, GLdouble x, GLdouble y);
void APIENTRY_GL4ES gl4es_glVertexAttrib3sARB(GLuint index, GLshort x, GLshort y, GLshort z);
void APIENTRY_GL4ES gl4es_glVertexAttrib3fARB(GLuint index, GLfloat x, GLfloat y, GLfloat z);
void APIENTRY_GL4ES gl4es_glVertexAttrib3dARB(GLuint index, GLdouble x, GLdouble y, GLdouble z);
void APIENTRY_GL4ES gl4es_glVertexAttrib4sARB(GLuint index, GLshort x, GLshort y, GLshort z, GLshort w);
void APIENTRY_GL4ES gl4es_glVertexAttrib4fARB(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
void APIENTRY_GL4ES gl4es_glVertexAttrib4dARB(GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
void APIENTRY_GL4ES gl4es_glVertexAttrib4NubARB(GLuint index, GLubyte x, GLubyte y, GLubyte z, GLubyte w);
void APIENTRY_GL4ES gl4es_glVertexAttrib1svARB(GLuint index, const GLshort *v);
void APIENTRY_GL4ES gl4es_glVertexAttrib1fvARB(GLuint index, const GLfloat *v);
void APIENTRY_GL4ES gl4es_glVertexAttrib1dvARB(GLuint index, const GLdouble *v);
void APIENTRY_GL4ES gl4es_glVertexAttrib2svARB(GLuint index, const GLshort *v);
void APIENTRY_GL4ES gl4es_glVertexAttrib2fvARB(GLuint index, const GLfloat *v);
void APIENTRY_GL4ES gl4es_glVertexAttrib2dvARB(GLuint index, const GLdouble *v);
void APIENTRY_GL4ES gl4es_glVertexAttrib3svARB(GLuint index, const GLshort *v);
void APIENTRY_GL4ES gl4es_glVertexAttrib3fvARB(GLuint index, const GLfloat *v);
void APIENTRY_GL4ES gl4es_glVertexAttrib3dvARB(GLuint index, const GLdouble *v);
void APIENTRY_GL4ES gl4es_glVertexAttrib4bvARB(GLuint index, const GLbyte *v);
void APIENTRY_GL4ES gl4es_glVertexAttrib4svARB(GLuint index, const GLshort *v);
void APIENTRY_GL4ES gl4es_glVertexAttrib4ivARB(GLuint index, const GLint *v);
void APIENTRY_GL4ES gl4es_glVertexAttrib4ubvARB(GLuint index, const GLubyte *v);
void APIENTRY_GL4ES gl4es_glVertexAttrib4usvARB(GLuint index, const GLushort *v);
void APIENTRY_GL4ES gl4es_glVertexAttrib4uivARB(GLuint index, const GLuint *v);
void APIENTRY_GL4ES gl4es_glVertexAttrib4fvARB(GLuint index, const GLfloat *v);
void APIENTRY_GL4ES gl4es_glVertexAttrib4dvARB(GLuint index, const GLdouble *v);
void APIENTRY_GL4ES gl4es_glVertexAttrib4NbvARB(GLuint index, const GLbyte *v);
void APIENTRY_GL4ES gl4es_glVertexAttrib4NsvARB(GLuint index, const GLshort *v);
void APIENTRY_GL4ES gl4es_glVertexAttrib4NivARB(GLuint index, const GLint *v);
void APIENTRY_GL4ES gl4es_glVertexAttrib4NubvARB(GLuint index, const GLubyte *v);
void APIENTRY_GL4ES gl4es_glVertexAttrib4NusvARB(GLuint index, const GLushort *v);
void APIENTRY_GL4ES gl4es_glVertexAttrib4NuivARB(GLuint index, const GLuint *v);
void APIENTRY_GL4ES gl4es_glVertexAttribPointerARB(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer);
void APIENTRY_GL4ES gl4es_glEnableVertexAttribArrayARB(GLuint index);
void APIENTRY_GL4ES gl4es_glDisableVertexAttribArrayARB(GLuint index);
*/
void APIENTRY_GL4ES gl4es_glProgramStringARB(GLenum target, GLenum format, GLsizei len, const GLvoid *string) {
DBG(printf("glProgramStringARB(%s, %s, %d, %p), source is\n%s\n=======\n", PrintEnum(target), PrintEnum(format), len, string, (const char*)string);)
oldprogram_t* old = NULL;
int vertex;
switch(target) {
case GL_VERTEX_PROGRAM_ARB:
old = glstate->glsl->vtx_prog;
vertex = 1;
break;
case GL_FRAGMENT_PROGRAM_ARB:
old = glstate->glsl->frg_prog;
vertex = 0;
break;
default:
errorShim(GL_INVALID_VALUE);
return;
}
if(format!=GL_PROGRAM_FORMAT_ASCII_ARB) {
errorShim(GL_INVALID_ENUM);
return;
}
if(old->string)
free(old->string);
// grab the new program
old->string = calloc(1, len + 1);
memcpy(old->string, string, len);
// check if a shader is actually attached
if(!old->shader) {
DBG(printf("Error, no shader attached but glProgramStringARB(...) called\n");)
errorShim(GL_INVALID_OPERATION);
return;
}
// Convert to GLSL
const GLchar * p[1] = {0};
p[0] = gl4es_convertARB(old->string, vertex, &glstate->glsl->error_msg, &glstate->glsl->error_ptr);
if((!p[0]) || (glstate->glsl->error_ptr!=-1)) {
DBG(printf("Error with ARB->GLSL conversion\nsource is:\n%s\n======\n", old->shader->source);)
errorShim(GL_INVALID_OPERATION);
return;
}
gl4es_glShaderSource(old->shader->id, 1, p , NULL);
DBG(printf("converted source is:\n%s\n======\n", old->shader->source?old->shader->source:"**error**");)
if (!old->shader->source) {
DBG(printf("Error with ARB->GLSL conversion\n");)
errorShim(GL_INVALID_OPERATION);
if (glstate->glsl->error_msg) free(glstate->glsl->error_msg);
glstate->glsl->error_msg = strdup("Error with ARB->GLSL conversion");
glstate->glsl->error_ptr = 0;
return;
}
if (!old->shader->converted) {
DBG(printf("Error with GLSL->GLSL:ES conversion\n");)
errorShim(GL_INVALID_OPERATION);
if (glstate->glsl->error_msg) free(glstate->glsl->error_msg);
glstate->glsl->error_msg = strdup("Error with GLSL->GLSL:ES conversion");
glstate->glsl->error_ptr = 0;
return;
}
gl4es_glCompileShader(old->shader->id);
GLint res = 0;
gl4es_glGetShaderiv(old->shader->id, GL_COMPILE_STATUS, &res);
if(res!=GL_TRUE) {
DBG(printf("Error with Compile shader\n");)
errorShim(GL_INVALID_OPERATION);
if (glstate->glsl->error_msg) free(glstate->glsl->error_msg);
glstate->glsl->error_msg = strdup("Error with Compile shader");
glstate->glsl->error_ptr = 0;
return;
}
}
void APIENTRY_GL4ES gl4es_glBindProgramARB(GLenum target, GLuint program) {
DBG(printf("glBindProgramARB(%s, %d)\n", PrintEnum(target), program);)
khint_t k;
oldprogram_t* old = NULL;
kh_oldprograms_t * oldprograms = glstate->glsl->oldprograms;
if(program) {
k = kh_get(oldprograms, oldprograms, program);
if(k == kh_end(oldprograms)) {
// if program as not be generated it's fine, create a new one on-the-fly
int ret;
k = kh_put(oldprograms, oldprograms, program, &ret);
old = kh_value(oldprograms, k) =(oldprogram_t*)calloc(1, sizeof(oldprogram_t));
old->id = program;
} else {
old = kh_value(oldprograms, k);
if(old->type!=0 && old->type!=target) {
errorShim(GL_INVALID_OPERATION);
return;
}
}
}
switch(target) {
case GL_VERTEX_PROGRAM_ARB:
if(program) {
noerrorShimNoPurge();
if(glstate->fpe_state)
glstate->fpe_state->vertex_prg_id = program;
glstate->glsl->vtx_prog = old;
if(!old->type) {
// create an empty shader
old->type = target;
GLuint shader = gl4es_glCreateShader(GL_VERTEX_SHADER);
shader_t *glshader = NULL;
khash_t(shaderlist) *shaders = glstate->glsl->shaders;
k = kh_get(shaderlist, shaders, shader);
glshader = kh_value(shaders, k);
old->shader = glshader;
// alloc memory for locals
old->max_local_params = MAX_VTX_PROG_LOC_PARAMS;
old->prog_local_params = (float*)calloc(MAX_VTX_PROG_LOC_PARAMS*4, sizeof(float));
old->max_env_params = MAX_VTX_PROG_ENV_PARAMS;
old->prog_env_params = glstate->glsl->vtx_env_params;
old->max_loc = -1;
old->max_env = -1;
old->min_loc = MAX_VTX_PROG_LOC_PARAMS;
old->min_env = MAX_VTX_PROG_ENV_PARAMS;
}
} else {
noerrorShimNoPurge();
glstate->glsl->vtx_prog = NULL;
if(glstate->fpe_state)
glstate->fpe_state->vertex_prg_id = 0;
}
break;
case GL_FRAGMENT_PROGRAM_ARB:
if(program) {
noerrorShimNoPurge();
if(glstate->fpe_state)
glstate->fpe_state->fragment_prg_id = program;
glstate->glsl->frg_prog = old;
if(!old->type) {
// create an empty shader
old->type = target;
GLuint shader = gl4es_glCreateShader(GL_FRAGMENT_SHADER);
shader_t *glshader = NULL;
khash_t(shaderlist) *shaders = glstate->glsl->shaders;
k = kh_get(shaderlist, shaders, shader);
glshader = kh_value(shaders, k);
old->shader = glshader;
// alloc memory for locals
old->max_local_params = MAX_FRG_PROG_LOC_PARAMS;
old->prog_local_params = (float*)calloc(MAX_FRG_PROG_LOC_PARAMS*4, sizeof(float));
old->max_env_params = MAX_FRG_PROG_ENV_PARAMS;
old->prog_env_params = glstate->glsl->frg_env_params;
old->max_loc = -1;
old->max_env = -1;
old->min_loc = MAX_FRG_PROG_LOC_PARAMS;
old->min_env = MAX_FRG_PROG_ENV_PARAMS;
}
} else {
noerrorShimNoPurge();
glstate->glsl->frg_prog = NULL;
if(glstate->fpe_state)
glstate->fpe_state->fragment_prg_id = 0;
}
break;
default:
errorShim(GL_INVALID_ENUM);
}
}
void APIENTRY_GL4ES gl4es_glDeleteProgramsARB(GLsizei n, const GLuint *programs) {
DBG(printf("glDeleteProgramsARB(%d, %p)\n", n, programs);)
//TODO, unbind if binded?
khint_t k;
kh_oldprograms_t * oldprograms = glstate->glsl->oldprograms;
for (int i=0; i<n; ++i) {
GLuint id = programs[i];
k = kh_get(oldprograms, oldprograms, id);
if(k!=kh_end(oldprograms)) {
freeOldProgram(kh_value(oldprograms, k));
kh_del(oldprograms, oldprograms, k);
}
}
}
void APIENTRY_GL4ES gl4es_glGenProgramsARB(GLsizei n, GLuint *programs) {
DBG(printf("glGenProgramsARB(%d, %p)\n", n, programs);)
GLuint last = 0;
khint_t k;
kh_oldprograms_t * oldprograms = glstate->glsl->oldprograms;
for (int i=0; i<n; ++i) {
programs[i] = last = getUniqueProgramID(last);
int ret;
k = kh_put(oldprograms, oldprograms, last, &ret);
oldprogram_t *old = kh_value(oldprograms, k) =(oldprogram_t*)calloc(1, sizeof(oldprogram_t));
old->id = last;
}
noerrorShimNoPurge();
}
void APIENTRY_GL4ES gl4es_glProgramEnvParameter4dARB(GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) {
DBG(printf("glProgramEnvParameter4dARB(%s, %u, %f, %f, %f, %f)\n", PrintEnum(target), index, x, y, z, w);)
float *f = NULL;
switch(target) {
case GL_VERTEX_PROGRAM_ARB:
if(index<MAX_VTX_PROG_ENV_PARAMS) {
noerrorShimNoPurge();
f = glstate->glsl->vtx_env_params+index*4;
}
break;
case GL_FRAGMENT_PROGRAM_ARB:
if(index<MAX_FRG_PROG_ENV_PARAMS) {
noerrorShimNoPurge();
f = glstate->glsl->frg_env_params+index*4;
} else
errorShim(GL_INVALID_VALUE);
break;
default:
errorShim(GL_INVALID_ENUM);
return;
}
if(f) {
f[0] = x;
f[1] = y;
f[2] = z;
f[3] = w;
} else
errorShim(GL_INVALID_VALUE);
}
void APIENTRY_GL4ES gl4es_glProgramEnvParameter4dvARB(GLenum target, GLuint index, const GLdouble *params) {
DBG(printf("glProgramEnvParameter4dvARB(%s, %u, %p[%f/%f/%f/%f])\n", PrintEnum(target), index, params, params[0], params[1], params[2], params[3]);)
float *f = NULL;
switch(target) {
case GL_VERTEX_PROGRAM_ARB:
if(index<MAX_VTX_PROG_ENV_PARAMS) {
noerrorShimNoPurge();
f = glstate->glsl->vtx_env_params+index*4;
}
break;
case GL_FRAGMENT_PROGRAM_ARB:
if(index<MAX_FRG_PROG_ENV_PARAMS) {
noerrorShimNoPurge();
f = glstate->glsl->frg_env_params+index*4;
}
break;
default:
errorShim(GL_INVALID_ENUM);
return;
}
if(f) {
f[0] = params[0];
f[1] = params[1];
f[2] = params[2];
f[3] = params[3];
} else
errorShim(GL_INVALID_VALUE);
}
void APIENTRY_GL4ES gl4es_glProgramEnvParameter4fARB(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
DBG(printf("glProgramEnvParameter4fARB(%s, %u, %f, %f, %f, %f)\n", PrintEnum(target), index, x, y, z, w);)
float *f = NULL;
switch(target) {
case GL_VERTEX_PROGRAM_ARB:
if(index<MAX_VTX_PROG_ENV_PARAMS) {
noerrorShimNoPurge();
f = glstate->glsl->vtx_env_params+index*4;
}
break;
case GL_FRAGMENT_PROGRAM_ARB:
if(index<MAX_FRG_PROG_ENV_PARAMS) {
noerrorShimNoPurge();
f = glstate->glsl->frg_env_params+index*4;
}
break;
default:
errorShim(GL_INVALID_ENUM);
}
if(f) {
f[0] = x;
f[1] = y;
f[2] = z;
f[3] = w;
} else
errorShim(GL_INVALID_VALUE);
}
void APIENTRY_GL4ES gl4es_glProgramEnvParameter4fvARB(GLenum target, GLuint index, const GLfloat *params) {
DBG(printf("glProgramEnvParameter4fvARB(%s, %u, %p[%f/%f/%f/%f])\n", PrintEnum(target), index, params, params[0], params[1], params[2], params[3]);)
float *f = NULL;
switch(target) {
case GL_VERTEX_PROGRAM_ARB:
if(index<MAX_VTX_PROG_ENV_PARAMS) {
f = glstate->glsl->vtx_env_params+index*4;
}
break;
case GL_FRAGMENT_PROGRAM_ARB:
if(index<MAX_FRG_PROG_ENV_PARAMS) {
f = glstate->glsl->frg_env_params+index*4;
}
break;
default:
errorShim(GL_INVALID_ENUM);
}
if(f) {
noerrorShimNoPurge();
memcpy(f, params, 4*sizeof(float));
} else
errorShim(GL_INVALID_VALUE);
}
void APIENTRY_GL4ES gl4es_glProgramLocalParameter4dARB(GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w) {
DBG(printf("glProgramLocalParameter4dARB(%s, %u, %f, %f, %f, %f)\n", PrintEnum(target), index, x, y, z, w);)
oldprogram_t *old = NULL;
switch(target) {
case GL_VERTEX_PROGRAM_ARB:
old = glstate->glsl->vtx_prog;
break;
case GL_FRAGMENT_PROGRAM_ARB:
old = glstate->glsl->frg_prog;
break;
default:
errorShim(GL_INVALID_ENUM);
return;
}
if(!old) {
errorShim(GL_INVALID_OPERATION);
return;
}
if(index<old->max_local_params) {
noerrorShimNoPurge();
float* f = old->prog_local_params+index*4;
f[0] = x;
f[1] = y;
f[2] = z;
f[3] = w;
} else
errorShim(GL_INVALID_VALUE);
}
void APIENTRY_GL4ES gl4es_glProgramLocalParameter4dvARB(GLenum target, GLuint index, const GLdouble *params) {
DBG(printf("glProgramLocalParameter4dvARB(%s, %u, %p[%f/%f/%f/%f])\n", PrintEnum(target), index, params, params[0], params[1], params[2], params[3]);)
oldprogram_t *old = NULL;
switch(target) {
case GL_VERTEX_PROGRAM_ARB:
old = glstate->glsl->vtx_prog;
break;
case GL_FRAGMENT_PROGRAM_ARB:
old = glstate->glsl->frg_prog;
break;
default:
errorShim(GL_INVALID_ENUM);
return;
}
if(!old) {
errorShim(GL_INVALID_OPERATION);
return;
}
if(index<old->max_local_params) {
noerrorShimNoPurge();
float* f = old->prog_local_params+index*4;
f[0] = params[0];
f[1] = params[1];
f[2] = params[2];
f[3] = params[3];
} else
errorShim(GL_INVALID_VALUE);
}
void APIENTRY_GL4ES gl4es_glProgramLocalParameter4fARB(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) {
DBG(printf("glProgramLocalParameter4fARB(%s, %u, %f, %f, %f, %f)\n", PrintEnum(target), index, x, y, z, w);)
oldprogram_t *old = NULL;
switch(target) {
case GL_VERTEX_PROGRAM_ARB:
old = glstate->glsl->vtx_prog;
break;
case GL_FRAGMENT_PROGRAM_ARB:
old = glstate->glsl->frg_prog;
break;
default:
errorShim(GL_INVALID_ENUM);
return;
}
if(!old) {
errorShim(GL_INVALID_OPERATION);
return;
}
if(index<old->max_local_params) {
noerrorShimNoPurge();
float* f = old->prog_local_params+index*4;
f[0] = x;
f[1] = y;
f[2] = z;
f[3] = w;
} else
errorShim(GL_INVALID_VALUE);
}
void APIENTRY_GL4ES gl4es_glProgramLocalParameter4fvARB(GLenum target, GLuint index, const GLfloat *params) {
DBG(printf("glProgramLocalParameter4fvARB(%s, %u, %p[%f/%f/%f/%f])\n", PrintEnum(target), index, params, params[0], params[1], params[2], params[3]);)
oldprogram_t *old = NULL;
switch(target) {
case GL_VERTEX_PROGRAM_ARB:
old = glstate->glsl->vtx_prog;
break;
case GL_FRAGMENT_PROGRAM_ARB:
old = glstate->glsl->frg_prog;
break;
default:
errorShim(GL_INVALID_ENUM);
return;
}
if(!old) {
errorShim(GL_INVALID_OPERATION);
return;
}
if(index<old->max_local_params) {
noerrorShimNoPurge();
memcpy(old->prog_local_params+index*4, params, 4*sizeof(float));
} else
errorShim(GL_INVALID_VALUE);
}
void APIENTRY_GL4ES gl4es_glGetProgramEnvParameterdvARB(GLenum target, GLuint index, GLdouble *params) {
DBG(printf("glGetProgramEnvParameterdvARB(%s, %u, %p)\n", PrintEnum(target), index, params);)
float * f = NULL;
switch(target) {
case GL_VERTEX_PROGRAM_ARB:
if(index<MAX_VTX_PROG_ENV_PARAMS) {
noerrorShimNoPurge();
f = glstate->glsl->vtx_env_params+index*4;
}
break;
case GL_FRAGMENT_PROGRAM_ARB:
if(index<MAX_FRG_PROG_ENV_PARAMS) {
noerrorShimNoPurge();
f = glstate->glsl->frg_env_params+index*4;
}
break;
default:
errorShim(GL_INVALID_ENUM);
return;
}
if(f) {
params[0] = f[0];
params[1] = f[1];
params[2] = f[2];
params[3] = f[3];
} else
errorShim(GL_INVALID_VALUE);
}
void APIENTRY_GL4ES gl4es_glGetProgramEnvParameterfvARB(GLenum target, GLuint index, GLfloat *params) {
DBG(printf("glGetProgramEnvParameterfvARB(%s, %u, %p)\n", PrintEnum(target), index, params);)
switch(target) {
case GL_VERTEX_PROGRAM_ARB:
if(index<MAX_VTX_PROG_ENV_PARAMS) {
noerrorShimNoPurge();
memcpy(params, glstate->glsl->vtx_env_params+index*4, 4*sizeof(float));
} else
errorShim(GL_INVALID_VALUE);
break;
case GL_FRAGMENT_PROGRAM_ARB:
if(index<MAX_FRG_PROG_ENV_PARAMS) {
noerrorShimNoPurge();
memcpy(params, glstate->glsl->frg_env_params+index*4, 4*sizeof(float));
} else
errorShim(GL_INVALID_VALUE);
break;
default:
errorShim(GL_INVALID_ENUM);
}
}
void APIENTRY_GL4ES gl4es_glGetProgramLocalParameterdvARB(GLenum target, GLuint index, GLdouble *params) {
DBG(printf("glGetProgramLocalParameterdvARB(%s, %u, %p)\n", PrintEnum(target), index, params);)
oldprogram_t *old = NULL;
switch(target) {
case GL_VERTEX_PROGRAM_ARB:
old = glstate->glsl->vtx_prog;
break;
case GL_FRAGMENT_PROGRAM_ARB:
old = glstate->glsl->frg_prog;
break;
default:
errorShim(GL_INVALID_ENUM);
return;
}
if(!old) {
errorShim(GL_INVALID_OPERATION);
return;
}
if(index<old->max_local_params) {
noerrorShimNoPurge();
float* f = old->prog_local_params+index*4;
params[0] = f[0];
params[1] = f[1];
params[2] = f[2];
params[3] = f[3];
} else
errorShim(GL_INVALID_VALUE);
}
void APIENTRY_GL4ES gl4es_glGetProgramLocalParameterfvARB(GLenum target, GLuint index, GLfloat *params) {
DBG(printf("glGetProgramLocalParameterfvARB(%s, %u, %p)\n", PrintEnum(target), index, params);)
oldprogram_t *old = NULL;
switch(target) {
case GL_VERTEX_PROGRAM_ARB:
old = glstate->glsl->vtx_prog;
break;
case GL_FRAGMENT_PROGRAM_ARB:
old = glstate->glsl->frg_prog;
break;
default:
errorShim(GL_INVALID_ENUM);
return;
}
if(!old) {
errorShim(GL_INVALID_OPERATION);
return;
}
if(index<old->max_local_params) {
noerrorShimNoPurge();
memcpy(params, old->prog_local_params+index*4, 4*sizeof(float));
} else
errorShim(GL_INVALID_VALUE);
}
void APIENTRY_GL4ES gl4es_glGetProgramivARB(GLenum target, GLenum pname, GLint *params) {
DBG(printf("glGetProgramivARB(%s, %s, %p)\n", PrintEnum(target), PrintEnum(pname), params);)
oldprogram_t* old = NULL;
switch(target) {
case GL_VERTEX_PROGRAM_ARB:
old = glstate->glsl->vtx_prog;
break;
case GL_FRAGMENT_PROGRAM_ARB:
old = glstate->glsl->frg_prog;
break;
default:
errorShim(GL_INVALID_VALUE);
return;
}
switch(pname) {
case GL_PROGRAM_LENGTH_ARB:
if(old) {
noerrorShimNoPurge();
*params = old->string?(strlen(old->string)+1):0;
} else
errorShim(GL_INVALID_OPERATION);
break;
case GL_PROGRAM_FORMAT_ARB:
if(old) {
noerrorShimNoPurge();
*params = GL_PROGRAM_FORMAT_ASCII_ARB;
} else
errorShim(GL_INVALID_OPERATION);
break;
case GL_PROGRAM_BINDING_ARB:
if(old) {
noerrorShimNoPurge();
*params = old->id;
} else
errorShim(GL_INVALID_OPERATION);
break;
case GL_MAX_PROGRAM_LOCAL_PARAMETERS_ARB:
*params = (target==GL_VERTEX_PROGRAM_ARB)?MAX_VTX_PROG_LOC_PARAMS:MAX_FRG_PROG_LOC_PARAMS;
break;
case GL_MAX_PROGRAM_ENV_PARAMETERS_ARB:
*params = (target==GL_VERTEX_PROGRAM_ARB)?MAX_VTX_PROG_ENV_PARAMS:MAX_FRG_PROG_ENV_PARAMS;
break;
case GL_MAX_PROGRAM_NATIVE_ATTRIBS_ARB:
case GL_MAX_PROGRAM_ATTRIBS_ARB:
*params = hardext.maxvattrib;
break;
// arbritrary settings...
case GL_MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB:
case GL_MAX_PROGRAM_INSTRUCTIONS_ARB:
*params = 4096;
break;
case GL_MAX_PROGRAM_NATIVE_TEMPORARIES_ARB:
case GL_MAX_PROGRAM_TEMPORARIES_ARB:
*params = 64;
break;
case GL_MAX_PROGRAM_NATIVE_PARAMETERS_ARB:
case GL_MAX_PROGRAM_PARAMETERS_ARB:
*params = 64;
break;
case GL_MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB:
case GL_MAX_PROGRAM_ADDRESS_REGISTERS_ARB:
*params = 4;
break;
case GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB:
case GL_MAX_PROGRAM_ALU_INSTRUCTIONS_ARB:
*params = 1024;
break;
case GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB:
case GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB:
*params = 32;
break;
case GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB:
case GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB:
*params = 8;
break;
/*
// bounded program stats...
case GL_PROGRAM_NATIVE_INSTRUCTIONS_ARB:
case GL_PROGRAM_INSTRUCTIONS_ARB:
case GL_PROGRAM_NATIVE_TEMPORARIES_ARB:
case GL_PROGRAM_TEMPORARIES_ARB:
case GL_PROGRAM_NATIVE_PARAMETERS_ARB:
case GL_PROGRAM_PARAMETERS_ARB:
case GL_PROGRAM_NATIVE_ATTRIBS_ARB:
case GL_PROGRAM_ATTRIBS_ARB:
case GL_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB:
case GL_PROGRAM_ADDRESS_REGISTERS_ARB:
case GL_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB:
case GL_PROGRAM_ALU_INSTRUCTIONS_ARB:
case GL_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB:
case GL_PROGRAM_TEX_INSTRUCTIONS_ARB:
case GL_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB:
case GL_PROGRAM_TEX_INDIRECTIONS_ARB:
*/
case GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB:
*params = 1; // always return OK for now
break;
default:
errorShim(GL_INVALID_ENUM);
}
}
void APIENTRY_GL4ES gl4es_glGetProgramStringARB(GLenum target, GLenum pname, GLvoid *string) {
DBG(printf("glGetProgramStringARB(%s, %u, %p)\n", PrintEnum(target), pname, string);)
oldprogram_t* old = NULL;
switch(target) {
case GL_VERTEX_PROGRAM_ARB:
old = glstate->glsl->vtx_prog;
break;
case GL_FRAGMENT_PROGRAM_ARB:
old = glstate->glsl->frg_prog;
break;
default:
errorShim(GL_INVALID_VALUE);
return;
}
if(pname!=GL_PROGRAM_STRING_ARB) {
errorShim(GL_INVALID_ENUM);
return;
}
if(!old) {
errorShim(GL_INVALID_OPERATION);
return;
}
if(old->string)
strcpy(string, old->string);
noerrorShimNoPurge();
}
/*
// same as GLSL version
void APIENTRY_GL4ES gl4es_glGetVertexAttribdvARB(GLuint index, GLenum pname, GLdouble *params);
void APIENTRY_GL4ES gl4es_glGetVertexAttribfvARB(GLuint index, GLenum pname, GLfloat *params);
void APIENTRY_GL4ES gl4es_glGetVertexAttribivARB(GLuint index, GLenum pname, GLint *params);
void APIENTRY_GL4ES gl4es_glGetVertexAttribPointervARB(GLuint index, GLenum pname, GLvoid **pointer);
*/
GLboolean APIENTRY_GL4ES gl4es_glIsProgramARB(GLuint program) {
DBG(printf("glIsProgramARB(%u)\n", program);)
khint_t k = kh_get(oldprograms, glstate->glsl->oldprograms, program);
return (k==kh_end(glstate->glsl->oldprograms))?GL_FALSE:GL_TRUE;
}
void APIENTRY_GL4ES gl4es_glProgramEnvParameters4fvEXT(GLenum target, GLuint index, GLsizei count, const GLfloat *params)
{
DBG(printf("glProgramEnvParameters4fvEXT(%s, %u, %i, %p)\n", PrintEnum(target), index, count, params);)
float *f = NULL;
int nmax = 0;
switch(target) {
case GL_VERTEX_PROGRAM_ARB:
f = glstate->glsl->vtx_env_params+index*4;
nmax = MAX_VTX_PROG_ENV_PARAMS;
break;
case GL_FRAGMENT_PROGRAM_ARB:
f = glstate->glsl->frg_env_params+index*4;
nmax = MAX_FRG_PROG_ENV_PARAMS;
break;
default:
errorShim(GL_INVALID_ENUM);
}
if(f && index+count<=nmax && count>=0) {
noerrorShimNoPurge();
memcpy(f, params, count*4*sizeof(float));
} else
errorShim(GL_INVALID_VALUE);
}
void APIENTRY_GL4ES gl4es_glProgramLocalParameters4fvEXT(GLenum target, GLuint index, GLsizei count, const GLfloat *params)
{
DBG(printf("glProgramLocalParameters4fvEXT(%s, %u, %i, %p)\n", PrintEnum(target), index, count, params);)
float *f = NULL;
oldprogram_t *old = NULL;
switch(target) {
case GL_VERTEX_PROGRAM_ARB:
old = glstate->glsl->vtx_prog;
break;
case GL_FRAGMENT_PROGRAM_ARB:
old = glstate->glsl->frg_prog;
break;
default:
errorShim(GL_INVALID_ENUM);
return;
}
if(!old) {
errorShim(GL_INVALID_OPERATION);
return;
}
if(index+count<old->max_local_params && count>=0) {
noerrorShimNoPurge();
memcpy(old->prog_local_params+index*4, params, count*4*sizeof(float));
} else
errorShim(GL_INVALID_VALUE);
}
// Mappers for ARB_vertex_program
AliasExport(void,glProgramStringARB,,(GLenum target, GLenum format, GLsizei len, const GLvoid *string));
AliasExport(void,glBindProgramARB,,(GLenum target, GLuint program));
AliasExport(void,glDeleteProgramsARB,,(GLsizei n, const GLuint *programs));
AliasExport(void,glGenProgramsARB,,(GLsizei n, GLuint *programs));
AliasExport_M(void,glProgramEnvParameter4dARB,,(GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w),40);
AliasExport(void,glProgramEnvParameter4dvARB,,(GLenum target, GLuint index, const GLdouble *params));
AliasExport(void,glProgramEnvParameter4fARB,,(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w));
AliasExport(void,glProgramEnvParameter4fvARB,,(GLenum target, GLuint index, const GLfloat *params));
AliasExport_M(void,glProgramLocalParameter4dARB,,(GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w),40);
AliasExport(void,glProgramLocalParameter4dvARB,,(GLenum target, GLuint index, const GLdouble *params));
AliasExport(void,glProgramLocalParameter4fARB,,(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w));
AliasExport(void,glProgramLocalParameter4fvARB,,(GLenum target, GLuint index, const GLfloat *params));
AliasExport(void,glGetProgramEnvParameterdvARB,,(GLenum target, GLuint index, GLdouble *params));
AliasExport(void,glGetProgramEnvParameterfvARB,,(GLenum target, GLuint index, GLfloat *params));
AliasExport(void,glGetProgramLocalParameterdvARB,,(GLenum target, GLuint index, GLdouble *params));
AliasExport(void,glGetProgramLocalParameterfvARB,,(GLenum target, GLuint index, GLfloat *params));
AliasExport(void,glGetProgramivARB,,(GLenum target, GLenum pname, GLint *params));
AliasExport(void,glGetProgramStringARB,,(GLenum target, GLenum pname, GLvoid *string));
AliasExport(GLboolean,glIsProgramARB,,(GLuint program));
AliasExport(void,glProgramEnvParameters4fvEXT,,(GLenum target, GLuint index, GLsizei count, const GLfloat *params));
AliasExport(void,glProgramLocalParameters4fvEXT,,(GLenum target, GLuint index, GLsizei count, const GLfloat *params));
+79
View File
@@ -0,0 +1,79 @@
#ifndef _GL4ES_OLD_PROGRAM_H_
#define _GL4ES_OLD_PROGRAM_H_
#include "gles.h"
#include "buffers.h"
#include "shader.h"
#include "uniform.h"
#include "program.h"
typedef struct kh_oldprograms_s kh_oldprograms_t;
typedef struct glstate_s glstate_t;
typedef struct shader_s shader_t;
typedef struct oldprogram_s {
GLuint id;
GLenum type;
char* string;
shader_t* shader;
int max_local_params;
float* prog_local_params;
int max_env_params;
float* prog_env_params; // link to global array
// tracking of the shader uniforms
int min_loc;
int max_loc;
int* locals;
int min_env;
int max_env;
int* envs;
} oldprogram_t;
void InitOldProgramMap(glstate_t* glstate);
void FreeOldProgramMap(glstate_t* glstate);
oldprogram_t* getOldProgram(GLuint id);
// ARB_vertex_program
// VertexAttrib are the same as ARB_vertex_shader
void APIENTRY_GL4ES gl4es_glProgramStringARB(GLenum target, GLenum format, GLsizei len, const GLvoid *string);
void APIENTRY_GL4ES gl4es_glBindProgramARB(GLenum target, GLuint program);
void APIENTRY_GL4ES gl4es_glDeleteProgramsARB(GLsizei n, const GLuint *programs);
void APIENTRY_GL4ES gl4es_glGenProgramsARB(GLsizei n, GLuint *programs);
void APIENTRY_GL4ES gl4es_glProgramEnvParameter4dARB(GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
void APIENTRY_GL4ES gl4es_glProgramEnvParameter4dvARB(GLenum target, GLuint index, const GLdouble *params);
void APIENTRY_GL4ES gl4es_glProgramEnvParameter4fARB(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
void APIENTRY_GL4ES gl4es_glProgramEnvParameter4fvARB(GLenum target, GLuint index, const GLfloat *params);
void APIENTRY_GL4ES gl4es_glProgramLocalParameter4dARB(GLenum target, GLuint index, GLdouble x, GLdouble y, GLdouble z, GLdouble w);
void APIENTRY_GL4ES gl4es_glProgramLocalParameter4dvARB(GLenum target, GLuint index, const GLdouble *params);
void APIENTRY_GL4ES gl4es_glProgramLocalParameter4fARB(GLenum target, GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
void APIENTRY_GL4ES gl4es_glProgramLocalParameter4fvARB(GLenum target, GLuint index, const GLfloat *params);
void APIENTRY_GL4ES gl4es_glGetProgramEnvParameterdvARB(GLenum target, GLuint index, GLdouble *params);
void APIENTRY_GL4ES gl4es_glGetProgramEnvParameterfvARB(GLenum target, GLuint index, GLfloat *params);
void APIENTRY_GL4ES gl4es_glGetProgramLocalParameterdvARB(GLenum target, GLuint index, GLdouble *params);
void APIENTRY_GL4ES gl4es_glGetProgramLocalParameterfvARB(GLenum target, GLuint index, GLfloat *params);
void APIENTRY_GL4ES gl4es_glGetProgramivARB(GLenum target, GLenum pname, GLint *params);
void APIENTRY_GL4ES gl4es_glGetProgramStringARB(GLenum target, GLenum pname, GLvoid *string);
void APIENTRY_GL4ES gl4es_glGetVertexAttribdvARB(GLuint index, GLenum pname, GLdouble *params);
void APIENTRY_GL4ES gl4es_glGetVertexAttribfvARB(GLuint index, GLenum pname, GLfloat *params);
void APIENTRY_GL4ES gl4es_glGetVertexAttribivARB(GLuint index, GLenum pname, GLint *params);
void APIENTRY_GL4ES gl4es_glGetVertexAttribPointervARB(GLuint index, GLenum pname, GLvoid **pointer);
GLboolean APIENTRY_GL4ES gl4es_glIsProgramARB(GLuint program);
void APIENTRY_GL4ES gl4es_glProgramEnvParameters4fvEXT(GLenum target, GLuint index, GLsizei count, const GLfloat *params);
void APIENTRY_GL4ES gl4es_glProgramLocalParameters4fvEXT(GLenum target, GLuint index, GLsizei count, const GLfloat *params);
#endif //_GL4ES_OLD_PROGRAM_H_
File diff suppressed because it is too large Load Diff
+57
View File
@@ -0,0 +1,57 @@
#ifndef _GL4ES_PIXEL_H_
#define _GL4ES_PIXEL_H_
#include <stdbool.h>
#include "gles.h"
typedef struct {
GLenum type;
GLint red, green, blue, alpha;
int maxv;
} colorlayout_t;
typedef struct {
GLfloat r, g, b, a;
} pixel_t;
#define widthalign(width, align) ((((uintptr_t)(width))+((uintptr_t)(align)-1))&(~((uintptr_t)(align)-1)))
bool pixel_convert(const GLvoid *src, GLvoid **dst,
GLuint width, GLuint height,
GLenum src_format, GLenum src_type,
GLenum dst_format, GLenum dst_type, GLuint stride, GLuint align);
bool pixel_transform(const GLvoid *src, GLvoid **dst,
GLuint width, GLuint height,
GLenum src_format, GLenum src_type,
const GLfloat *scale, const GLfloat *bias);
bool pixel_scale(const GLvoid *src, GLvoid **dst,
GLuint width, GLuint height,
GLuint new_width, GLuint new_height,
GLenum format, GLenum type);
bool pixel_halfscale(const GLvoid *src, GLvoid **dst,
GLuint width, GLuint height,
GLenum format, GLenum type);
bool pixel_thirdscale(const GLvoid *src, GLvoid **dst,
GLuint width, GLuint height,
GLenum format, GLenum type);
bool pixel_quarterscale(const GLvoid *src, GLvoid **dst,
GLuint width, GLuint height,
GLenum format, GLenum type);
bool pixel_doublescale(const GLvoid *src, GLvoid **dst,
GLuint width, GLuint height,
GLenum format, GLenum type);
bool pixel_to_ppm(const GLvoid *pixels,
GLuint width, GLuint height,
GLenum format, GLenum type, GLuint name, GLuint align);
// sRGB ->RGB colorspace conversion, for RGBA data...
void pixel_srgb_inplace(GLvoid* pixels, GLuint width, GLuint height);
#endif // _GL4ES_PIXEL_H_
+33
View File
@@ -0,0 +1,33 @@
#include "planes.h"
#include "../glx/hardext.h"
#include "loader.h"
#include "matrix.h"
#include "matvec.h"
void APIENTRY_GL4ES gl4es_glClipPlanef(GLenum plane, const GLfloat *equation)
{
/*
When glClipPlane is called,
equation is transformed by the inverse of the modelview matrix and stored in the resulting eye coordinates.
Subsequent changes to the modelview matrix have no effect on the stored plane-equation components.
If the dot product of the eye coordinates of a vertex with the stored plane equation components is positive or zero,
the vertex is in with respect to that clipping plane. Otherwise, it is out.
*/
PUSH_IF_COMPILING(glClipPlanef); //TODO: fix that, equation is an array and should be copied before beeing put in the stack
if((plane<GL_CLIP_PLANE0) || (plane>=GL_CLIP_PLANE0+hardext.maxplanes)) {
errorShim(GL_INVALID_ENUM);
return;
}
if(hardext.esversion==1) {
LOAD_GLES2(glClipPlanef);
errorGL();
gles_glClipPlanef(plane, equation);
} else { // TODO: should fist compute the clipplane and compare to stored one before sending to hardware
int p = plane-GL_CLIP_PLANE0;
matrix_vector(getInvMVMat(), equation, glstate->planes[p]); //Tested, seems ok
noerrorShim();
}
}
AliasExport(void,glClipPlanef,,(GLenum pname, const GLfloat* params));
+8
View File
@@ -0,0 +1,8 @@
#ifndef _GL4ES_PLANES_H_
#define _GL4ES_PLANES_H_
#include "gles.h"
void APIENTRY_GL4ES gl4es_glClipPlanef(GLenum plane, const GLfloat *equation);
#endif // _GL4ES_PLANES_H_
+129
View File
@@ -0,0 +1,129 @@
#include "pointsprite.h"
#include "../glx/hardext.h"
#include "debug.h"
#include "fpe.h"
#include "gl4es.h"
#include "glstate.h"
#include "loader.h"
void APIENTRY_GL4ES gl4es_glPointParameteri(GLenum pname, GLint param)
{
gl4es_glPointParameterf(pname, param);
}
AliasExport(void,glPointParameteri,,(GLenum pname, GLint param));
void APIENTRY_GL4ES gl4es_glPointParameteriv(GLenum pname, const GLint * params)
{
GLfloat tmp[3];
int v=(pname==GL_POINT_DISTANCE_ATTENUATION)?3:1;
for (int i=0; i<v; i++) tmp[i] = params[i];
gl4es_glPointParameterfv(pname, tmp);
}
AliasExport(void,glPointParameteriv,,(GLenum pname, const GLint * params));
void APIENTRY_GL4ES gl4es_glPointParameterf(GLenum pname, GLfloat param) {
PUSH_IF_COMPILING(glPointParameterf);
gl4es_glPointParameterfv(pname, &param);
}
AliasExport(void,glPointParameterf,,(GLenum pname, GLfloat param));
AliasExport(void,glPointParameterf,ARB,(GLenum pname, GLfloat param));
AliasExport(void,glPointParameterf,EXT,(GLenum pname, GLfloat param));
void APIENTRY_GL4ES gl4es_glPointParameterfv(GLenum pname, const GLfloat * params)
{
if (glstate->list.active)
if (glstate->list.compiling) {
if (pname == GL_POINT_DISTANCE_ATTENUATION) {
NewStage(glstate->list.active, STAGE_POINTPARAM);
rlPointParamOp(glstate->list.active, 1, params);
return;
} else {
gl4es_glPointParameterf(pname, params[0]);
return;
}
} else gl4es_flush();
switch(pname) {
case GL_POINT_SIZE_MIN:
if(*params<0.0f) {
errorShim(GL_INVALID_VALUE);
return;
}
if(glstate->pointsprite.sizeMin == *params) {
noerrorShim();
return;
}
glstate->pointsprite.sizeMin = *params;
break;
case GL_POINT_SIZE_MAX:
if(*params<0.0f) {
errorShim(GL_INVALID_VALUE);
return;
}
if(glstate->pointsprite.sizeMax == *params) {
noerrorShim();
return;
}
glstate->pointsprite.sizeMax = *params;
break;
case GL_POINT_FADE_THRESHOLD_SIZE:
if(*params<0.0f) {
errorShim(GL_INVALID_VALUE);
return;
}
if(glstate->pointsprite.fadeThresholdSize == *params) {
noerrorShim();
return;
}
glstate->pointsprite.fadeThresholdSize = *params;
break;
case GL_POINT_DISTANCE_ATTENUATION:
if(*params<0.0f) {
errorShim(GL_INVALID_VALUE);
return;
}
if(memcmp(glstate->pointsprite.distance, params, 3*sizeof(GLfloat))==0) {
noerrorShim();
return;
}
memcpy(glstate->pointsprite.distance, params, 3*sizeof(GLfloat));
break;
case GL_POINT_SPRITE_COORD_ORIGIN:
if(*params!=GL_UPPER_LEFT && *params!=GL_LOWER_LEFT) {
errorShim(GL_INVALID_VALUE);
return;
}
if(glstate->pointsprite.coordOrigin == *params) {
noerrorShim();
return;
}
if(glstate->fpe_state) {
if(*params==GL_LOWER_LEFT)
glstate->fpe_state->pointsprite_upper = 0;
else
glstate->fpe_state->pointsprite_upper = 1;
}
glstate->pointsprite.coordOrigin = *params;
break;
}
LOAD_GLES_FPE(glPointParameterfv);
errorGL();
gles_glPointParameterfv(pname, params);
}
AliasExport(void,glPointParameterfv,,(GLenum pname, const GLfloat * params));
AliasExport(void,glPointParameterfv,ARB,(GLenum pname, const GLfloat * params));
AliasExport(void,glPointParameterfv,EXT,(GLenum pname, const GLfloat * params));
void APIENTRY_GL4ES gl4es_glPointSize(GLfloat size) {
if(size<=0.0f) {
errorShim(GL_INVALID_VALUE);
return;
}
glstate->pointsprite.size = size;
errorGL();
LOAD_GLES_FPE(glPointSize);
gles_glPointSize(size);
}
AliasExport(void,glPointSize,,(GLfloat size));
+22
View File
@@ -0,0 +1,22 @@
#ifndef _GL4ES_POINTSPRITE_H_
#define _GL4ES_POINTSPRITE_H_
#include "gles.h"
typedef struct {
GLfloat size;
GLfloat sizeMin;
GLfloat sizeMax;
GLfloat fadeThresholdSize;
GLfloat distance[3];
GLenum coordOrigin;
} pointsprite_t;
void APIENTRY_GL4ES gl4es_glPointParameteri(GLenum pname, GLint param);
void APIENTRY_GL4ES gl4es_glPointParameteriv(GLenum pname, const GLint * params);
void APIENTRY_GL4ES gl4es_glPointParameterf(GLenum pname, GLfloat param);
void APIENTRY_GL4ES gl4es_glPointParameterfv(GLenum pname, const GLfloat * params);
void APIENTRY_GL4ES gl4es_glPointSize(GLfloat size);
#endif // _GL4ES_POINTSPRITE_H_
+825
View File
@@ -0,0 +1,825 @@
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <locale.h>
#include "khash.h"
#include "preproc.h"
#include "string_utils.h"
//#define DEBUG
#ifdef DEBUG
#define DBG(a) a
#pragma GCC optimize 0
#else
#define DBG(a)
#endif
typedef enum _eTokenType {
TK_NULL = 0,
TK_SPACE,
TK_SHARP,
TK_NEWLINE,
TK_INT,
TK_FLOAT,
TK_PLUS,
TK_MINUS,
TK_EQUAL,
TK_SLASH,
TK_DOUBLESLASH, //10
TK_MULTIPLY,
TK_BACKSLASH,
TK_OPENBRACE,
TK_CLOSEBRACE,
TK_OPENCURLY,
TK_CLOSECURLY,
TK_OPENBRAKET,
TK_CLOSEBRAKET,
TK_OPENCOMMENT,
TK_CLOSECOMMENT, //20
TK_COLUMN,
TK_SEMICOLUMN,
TK_COMMA,
TK_DOT,
TK_AMP,
TK_POW,
TK_PIPE,
TK_EXCLAM,
TK_POINT, //30
TK_GREATER,
TK_LESS,
TK_DOUBLEEQUAL,
TK_TILDE,
TK_TEXT,
TK_TEXTCOMMENT
} eTokenType;
#define MAXSTR 500
typedef struct _uToken {
eTokenType type;
char str[MAXSTR];
int integer;
float real;
} uToken;
eTokenType NextTokenComment(char **p, uToken *tok) {
tok->type = TK_NULL;
tok->str[0] = 0;
if(!**p) return tok->type;
char c = **p;
(*p)++;
char nextc = **p;
int nb = 0;
int isfloat = 0;
int isneg = 1; // multiply by it...
float fnb = 0.f;
int cnt = 0;
float fcnt = 0.f;
tok->str[0]=c; tok->str[1]=0;
switch (c) {
case 10:
if(nextc==13)
(*p)++;
strcpy(tok->str, "\n");
tok->type = TK_NEWLINE;
break;
case 13:
if(nextc==10)
(*p)++;
strcpy(tok->str, "\n");
tok->type = TK_NEWLINE;
break;
case ' ':
case '\t':
while(nextc==' ' || nextc=='\t') { int l=strlen(tok->str); tok->str[l]=nextc; tok->str[l+1]=0; (*p)++; nextc=**p; }
tok->type = TK_SPACE;
break;
case '/':
if(nextc=='/') {
(*p)++;
tok->type=TK_DOUBLESLASH;
strcpy(tok->str, "//");
} else if(nextc=='*') {
(*p)++;
tok->type=TK_OPENCOMMENT;
strcpy(tok->str, "/*");
} else {
tok->type=TK_SLASH;
}
break;
case '*':
if(nextc=='/') {
(*p)++;
tok->type=TK_CLOSECOMMENT;
strcpy(tok->str, "*/");
} else {
tok->type=TK_MULTIPLY;
}
break;
default:
// all other are plain Ids...
cnt=1;
tok->type=TK_TEXTCOMMENT;
while(cnt!=(MAXSTR-1) && (nextc=='_' || (nextc>='0' && nextc<='9') || (nextc>='A' && nextc<='Z') || (nextc>='a' && nextc<='z'))) {
tok->str[cnt]=nextc;
(*p)++; nextc=**p;
++cnt;
}
tok->str[cnt]=0;
}
return tok->type;
}
eTokenType NextToken(char **p, uToken *tok) {
tok->type = TK_NULL;
tok->str[0] = 0;
if(!**p) return tok->type;
char c = **p;
(*p)++;
char nextc = **p;
int nb = 0;
int isfloat = 0;
int isneg = 1; // multiply by it...
float fnb = 0.f;
int cnt = 0;
float fcnt = 0.f;
tok->str[0]=c; tok->str[1]=0;
switch (c) {
case 10:
if(nextc==13)
(*p)++;
tok->type = TK_NEWLINE;
strcpy(tok->str, "\n");
break;
case 13:
if(nextc==10)
(*p)++;
tok->type = TK_NEWLINE;
strcpy(tok->str, "\n");
break;
case ' ':
case '\t':
while(nextc==' ' || nextc=='\t') { int l=strlen(tok->str); tok->str[l]=nextc; tok->str[l+1]=0; (*p)++; nextc=**p; }
tok->type = TK_SPACE;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
nb=c-'0';
// we don't know if it's an int or a float at first...
if(nextc=='x' && nb==0) {
// hex number, so int...
(*p)++; nextc=**p;
while((nextc>='0' && nextc<='9') || (nextc>='a' && nextc<='f') || (nextc>='A' && nextc<='F')) {
nb=nb*16;
if(nextc>='0' && nextc<='9')
nb+=nextc-'0';
else if(nextc>='a' && nextc<='f')
nb+=nextc-'a'+10;
else if(nextc>='A' && nextc<='F')
nb+=nextc-'A'+10;
(*p)++; nextc=**p;
}
tok->type = TK_INT;
tok->integer = nb;
sprintf(tok->str, "0x%x", nb);
} else {
while(nextc>='0' && nextc<='9') { nb=nb*10+nextc-'0'; (*p)++; nextc=**p;}
if(nextc=='.' || nextc=='f' || nextc=='e') {
isfloat = 1;
fnb=nb;
if(nextc=='.') {
(*p)++; nextc=**p;
fcnt = 0.1f;
while(nextc>='0' && nextc<='9') {
fnb+=(nextc-'0')*fcnt;
fcnt/=10.f;
(*p)++; nextc=**p;
}
}
if(nextc=='e') {
// exponent
(*p)++; nextc=**p;
nb=0;
int expsign = 1;
if(nextc=='-' || nextc=='+') {
if(nextc=='-') expsign = -1;
(*p)++; nextc=**p;
}
while(nextc>='0' && nextc<='9') { nb=nb*10+nextc-'0'; (*p)++; nextc=**p;}
fnb *= powf(10, nb*expsign); // exp10f is a GNU extension
}
if(nextc=='f') {
(*p)++; nextc=**p;
}
fnb*=isneg;
tok->type = TK_FLOAT;
tok->real = fnb;
sprintf(tok->str, "%#g", fnb);
} else {
tok->type = TK_INT;
tok->integer = nb;
sprintf(tok->str, "%d", nb);
}
}
break;
case '/':
if(nextc=='/') {
(*p)++;
tok->type=TK_DOUBLESLASH;
strcpy(tok->str, "//");
} else if(nextc=='*') {
(*p)++;
tok->type=TK_OPENCOMMENT;
strcpy(tok->str, "/*");
} else {
tok->type=TK_SLASH;
}
break;
case '*':
if(nextc=='/') {
(*p)++;
tok->type=TK_CLOSECOMMENT;
strcpy(tok->str, "*/");
} else {
tok->type=TK_MULTIPLY;
}
break;
case '=': tok->type=TK_EQUAL; break;
case '~': tok->type=TK_TILDE; break;
case '#': tok->type=TK_SHARP; break;
case '(': tok->type=TK_OPENBRACE; break;
case ')': tok->type=TK_CLOSEBRACE; break;
case '{': tok->type=TK_OPENCURLY; break;
case '}': tok->type=TK_CLOSECURLY; break;
case '[': tok->type=TK_OPENBRAKET; break;
case ']': tok->type=TK_CLOSEBRAKET; break;
case '&': tok->type=TK_AMP; break;
case '^': tok->type=TK_POW; break;
case '|': tok->type=TK_PIPE; break;
case '\\': tok->type=TK_BACKSLASH; break;
case '<': tok->type=TK_LESS; break;
case '>': tok->type=TK_GREATER; break;
case '+': tok->type=TK_PLUS; break;
case '-': tok->type=TK_MINUS; break;
case ':': tok->type=TK_COLUMN; break;
case ';': tok->type=TK_SEMICOLUMN; break;
case ',': tok->type=TK_COMMA; break;
case '.': tok->type=TK_DOT; break;
case '!': tok->type=TK_EXCLAM; break;
// todo: char and string?
default:
// all other are plain Ids...
cnt=1;
tok->type=TK_TEXT;
while(cnt!=(MAXSTR-1) && (nextc=='_' || (nextc>='0' && nextc<='9') || (nextc>='A' && nextc<='Z') || (nextc>='a' && nextc<='z'))) {
tok->str[cnt]=nextc;
(*p)++; nextc=**p;
++cnt;
}
tok->str[cnt]=0;
}
return tok->type;
}
eTokenType GetToken(char **p, uToken *tok, int incomment) {
eTokenType ret;
if (incomment)
ret = NextTokenComment(p, tok);
else
ret = NextToken(p, tok);
return ret;
}
typedef struct {
int cap;
int sz;
int *ifs;
} stackif_t;
static void push_if(stackif_t *st, int v) {
if(st->sz == st->cap) {
st->cap += 16;
st->ifs = (int*)realloc(st->ifs, sizeof(int)*st->cap);
}
st->ifs[st->sz++] = v;
}
static int pop_if(stackif_t *st) {
if(st->sz)
return st->ifs[--st->sz];
return -1;
}
static int top_if(stackif_t *st) {
if(st->sz)
return st->ifs[st->sz-1];
return -1;
}
static void not_top_if(stackif_t *st) {
if(st->sz && st->ifs[st->sz-1]!=-1)
st->ifs[st->sz-1] = 1 - st->ifs[st->sz-1];
}
static int result_if(stackif_t *st) {
for (int i=0; i<st->sz; ++i) {
if(st->ifs[i] == 1) return 1;
else if(st->ifs[i] == -1) return -1;
}
return 0;
}
KHASH_MAP_INIT_STR(define, int);
KHASH_MAP_INIT_STR(alldefine, char*);
char* preproc(const char* code, int keepcomments, int gl_es, extensions_t* exts, char** versionString) {
DBG(printf("Preproc on: =========\n%s\n=================\n", code);)
uToken tok;
char* p = (char*)code;
char* oldp = NULL;
int cap=1000;
char* ncode = (char*)malloc(1000);
ncode[0]=0;
int sz=1;
int status=0;
int write=1;
int incomment=0;
int indefined=0;
int newline=0;
int gettok=0;
int notok = 0;
char extname[50];
khint_t k;
int ret;
char *defname; //used for #define or #if
int defval;
stackif_t stackif = {0};
int nowrite_ifs = 0;
int current_if = 0;
int need_pop = 0;
char* old_locale = setlocale(LC_ALL, "C");
khash_t(alldefine) *alldefines = kh_init(alldefine); // will conatin all defines, even the one without int inside
khash_t(define) *defines = kh_init(define);
if(gl_es) {
k = kh_put(define, defines, "GL_ES", &ret);
kh_value(defines, k) = 0;
}
push_if(&stackif, 0); // default to OK
GetToken(&p, &tok, incomment);
while(tok.type!=TK_NULL) {
// pop #if / #endif status
if(need_pop) {
pop_if(&stackif);
nowrite_ifs = result_if(&stackif);
need_pop = 0;
}
// pre get token switch
switch(status) {
case 110: // line comment done...
case 210: // block comment done
if(!write && newline) {
gettok=0;
tok.type=TK_NEWLINE;
strcpy(tok.str, "\n");
}
write = 1;
status = (status==210)?1:0;
incomment=0;
newline=0;
break;
}
// get token (if needed)
if (gettok) GetToken(&p, &tok, incomment);
gettok=1;
// post get token switch
if(tok.type!=TK_NULL) {
switch(status) {
case 0: // regular...
case 1:
if(tok.type==TK_DOUBLESLASH) {
status = 100; // line comment
incomment = 1;
newline = 1;
if(!keepcomments) write=0;
} else if(tok.type==TK_OPENCOMMENT) {
status = 200; // multi-line comment
incomment = 1;
if(!keepcomments) write=0;
} else if(tok.type==TK_SHARP && !incomment && status==0) {
oldp = p-1; // lets buffer the line
status = 300;
} else if(tok.type==TK_NEWLINE)
status = 0;
else if(tok.type!=TK_SPACE)
status = 1; // everything else but space set status to 1...
break;
// line comment...
case 100:
if(tok.type==TK_BACKSLASH) {
status = 120; // is it backslash+endline for multiline?
} else if(tok.type==TK_NEWLINE) {
status = 110;
}
break;
case 120:
status = 100; // continue comment, what ever follow (NewLine or anything else)
break;
// block comment...
case 200:
if(tok.type==TK_NEWLINE)
newline=1;
if(tok.type==TK_CLOSECOMMENT) {
status=210;
}
break;
// # (of ifdef or extension)
case 300:
if(tok.type!=TK_SPACE)
if(tok.type==TK_TEXT) {
if(!strcmp(tok.str, "ifdef"))
status=310;
else if(!strcmp(tok.str, "ifndef"))
status=320;
else if(!strcmp(tok.str, "if")) {
// #if defined(GL_ES) not supported for now
push_if(&stackif, -1);
if(nowrite_ifs==1) {
status = 398; notok = 1;
} else {
status = 390;
{
int l = p - oldp;
memcpy(tok.str, oldp, l);
tok.str[l]='\0';
oldp = 0;
}
}
nowrite_ifs = result_if(&stackif);
} else if(!strcmp(tok.str, "else")) {
status = 399;
// ifs handling
{
not_top_if(&stackif);
int v = result_if(&stackif);
if(v!=-1) {
notok = 1;
status = 398;
}
nowrite_ifs = v;
}
} else if(!strcmp(tok.str, "endif")) {
status = 399;
{
need_pop = 1;
if(nowrite_ifs!=-1) {
notok = 1;
status = 398;
}
}
} else if(!strcmp(tok.str, "extension")) {
status = 410;
} else if(!strcmp(tok.str, "pragma")) {
status = 510;
} else if(!strcmp(tok.str, "define")) {
status = 610;
} else if(!strcmp(tok.str, "version")) {
status = 810;
if(!*versionString)
*versionString = (char*)calloc(1, 51);
} else status=399;
} else status = 399; // meh?
break;
// ifdef
case 310:
if(tok.type==TK_SPACE)
status = 310;
else if(tok.type==TK_TEXT) {
int v = -1;
if(gl_es && (strcmp(tok.str, "GL_ES")==0))
v = 1;
else if(kh_get(alldefine, alldefines, tok.str)!=kh_end(alldefines)) {
v = 0;
} else if (strncmp(tok.str, "GL_", 3)==0)
v = -1;
push_if(&stackif, v);
nowrite_ifs = result_if(&stackif);
if(nowrite_ifs!=-1) {
status = 398; notok = 1;
} else
status = 399;
} else {push_if(&stackif, -1); nowrite_ifs = result_if(&stackif);status = 399;}
break;
// ifndef
case 320:
if(tok.type==TK_SPACE)
status = 320;
else if(tok.type==TK_TEXT) {
int v = -1;
if(gl_es && strcmp(tok.str, "GL_ES")==0)
v = 0;
else if(kh_get(alldefine, alldefines, tok.str)!=kh_end(alldefines)) {
v = 1;
} else if (strncmp(tok.str, "GL_", 3)==0)
v = -1;
push_if(&stackif, v);
nowrite_ifs = result_if(&stackif);
if(nowrite_ifs!=-1) {
status = 398; notok = 1;
} else
status = 399;
} else {push_if(&stackif, -1); nowrite_ifs = result_if(&stackif); status = 399;}
break;
// #if ...
case 390:
if (tok.type == TK_NEWLINE) {
status = 0;
} else if (tok.type == TK_TEXT) {
if(!strcmp(tok.str, "defined"))
status = 710;
}
break;
// end of #ifdef GL_ES and variant..
case 398:
if(tok.type==TK_NEWLINE) {
oldp = NULL;
status = 0;
}
break;
// fallback for #ifdef GL_ES, write the line back...
case 399:
if(oldp)
{
int l = p - oldp;
memcpy(tok.str, oldp, l);
tok.str[l]='\0';
oldp = NULL;
}
status = (tok.type==TK_NEWLINE)?0:1;
break;
// #extension
case 410:
if(tok.type==TK_SPACE) {
// nothing...
} else if(tok.type==TK_TEXT && strlen(tok.str)<50) {
strcpy(extname, tok.str);
status = 420;
} else {
status = 399; // fallback, syntax error...
}
break;
// after the name and before the ':' of #extension
case 420:
if(tok.type==TK_SPACE) {
// nothing...
} else if (tok.type==TK_COLUMN) {
status=430;
} else {
status = 399; // fallback, syntax error...
}
break;
// after the ':' of #extension
case 430:
if(tok.type==TK_SPACE) {
// nothing...
} else if(tok.type==TK_TEXT) {
int state = -1;
if(!strcmp(tok.str, "disable"))
state = 0;
else if(!strcmp(tok.str, "warn"))
state = 1;
else if(!strcmp(tok.str, "enable"))
state = 1;
else if(!strcmp(tok.str, "require"))
state = 1;
if(state!=-1) {
if(exts->size==exts->cap) {
exts->cap += 4;
exts->ext = (extension_t*)realloc(exts->ext, sizeof(extension_t)*exts->cap);
}
strcpy(exts->ext[exts->size].name, extname);
exts->ext[exts->size].state = state;
++exts->size;
status = 398; // all done
} else
status = 399; // error, unknown keyword
} else {
status = 399; // fallback, syntax error...
}
break;
// #pragma
case 510:
if(tok.type==TK_SPACE) {
// nothing...
} else if(tok.type==TK_TEXT && strlen(tok.str)<50) {
if(strcmp(tok.str, "message")==0)
status = 398; //pragma message are removed
else if(strcmp(tok.str, "parameter")==0)
status = 398; //pragma message are removed
else
status = 399; // other pragma as left as-is
} else {
status = 399; // fallback, syntax error...
}
break;
// #define
case 610:
if(tok.type==TK_SPACE) {
// nothing...
} else if(tok.type==TK_TEXT && strlen(tok.str)<50) {
defname = strdup(tok.str);
k = kh_put(alldefine, alldefines, defname, &ret);
kh_value(alldefines, k) = defname;
status = 620; // and now get the value
} else {
status = 399; // fallback, define name too long...
}
break;
case 620:
if(tok.type==TK_SPACE) {
// nothing...
} else if(tok.type==TK_INT) {
defval = tok.integer;
status = 630; // check if end of line (so it's a simple define)
} else if(tok.type==TK_NEWLINE) {
{
int l = p - oldp;
memcpy(tok.str, oldp, l);
tok.str[l]='\0';
oldp = 0;
}
status = 0;
} else {
status = 399; // fallback
}
break;
case 630:
if(tok.type==TK_SPACE) {
// nothing...
} else if(tok.type==TK_NEWLINE) {
k = kh_put(define, defines, defname, &ret);
kh_value(defines, k) = defval;
{
int l = p - oldp;
memcpy(tok.str, oldp, l);
tok.str[l]='\0';
oldp = 0;
}
status = 0; // ok, define added to collection, left the line as-is anyway
} else {
status = 399; // fallback
}
break;
// #defined
case 710:
if(tok.type==TK_SPACE) {
// nothing...
} else if(tok.type==TK_OPENBRACE) {
status = 720; // and now get the value
++indefined;
} else if(tok.type==TK_NEWLINE) {
if(!indefined) status = 0; // ok... no handling of #defined for now, so just write through the line
}/* else {
status = 399; // No fallback...
}*/
break;
case 720:
if(tok.type==TK_SPACE || tok.type==TK_TEXT) {
// nothing...
} else if (tok.type==TK_CLOSEBRACE) {
--indefined;
status = 710;
} else {
indefined = 0;
status = 399;
}
break;
// #version
case 810:
if(tok.type==TK_SPACE) {
// nothing...
} else if(tok.type==TK_TEXT) {
strncat(*versionString, tok.str, 50);
status = 820;
} else if(tok.type==TK_INT) {
char buff[20] = {0};
sprintf(buff, "%d", tok.integer);
strncat(*versionString, buff, 50);
status = 820;
} else if(tok.type==TK_FLOAT) {
char buff[20] = {0};
sprintf(buff, "%g", tok.real);
strncat(*versionString, buff, 50);
status = 820;
} else {
status = 399; // fallback, syntax error...
}
break;
case 820:
if(tok.type==TK_SPACE) {
strncat(*versionString, " ", 50);
status = 830;
} else if(tok.type==TK_TEXT) {
strncat(*versionString, tok.str, 50);
} else if(tok.type==TK_INT) {
char buff[20] = {0};
sprintf(buff, "%d", tok.integer);
strncat(*versionString, buff, 50);
} else if(tok.type==TK_FLOAT) {
char buff[20] = {0};
sprintf(buff, "%g", tok.real);
strncat(*versionString, buff, 50);
} else if(tok.type==TK_NEWLINE) {
oldp = NULL;
status = 0;
} else {
status = 399; // fallback, syntax error...
}
break;
case 830:
if(tok.type==TK_SPACE) {
status = 830;
} else if(tok.type==TK_TEXT) {
strncat(*versionString, tok.str, 50);
status = 820;
} else if(tok.type==TK_INT) {
char buff[20] = {0};
sprintf(buff, "%d", tok.integer);
strncat(*versionString, buff, 50);
status = 820;
} else if(tok.type==TK_FLOAT) {
char buff[20] = {0};
sprintf(buff, "%g", tok.real);
strncat(*versionString, buff, 50);
status = 820;
} else if(tok.type==TK_NEWLINE) {
oldp = NULL;
status = 0;
} else {
status = 399; // fallback, syntax error...
}
break;
}
if(notok)
notok=0;
else
if(write && !oldp && nowrite_ifs!=1) {
if(!incomment && !indefined && tok.type == TK_TEXT) {
k = kh_get(define, defines, tok.str);
if(k!=kh_end(defines)) {
int v = kh_val(defines, k);
sprintf(tok.str, "%d", v); // overide define with defined value
}
}
int l = strlen(tok.str);
if(sz+l>=cap) {
cap+=2000;
ncode = (char*)realloc(ncode, cap);
}
strcat(ncode, tok.str);
sz+=l;
}
}
}
DBG(printf("New code is: ------------\n%s\n------------------\n", ncode);)
kh_destroy(define, defines);
kh_foreach_value(alldefines, defname,
free(defname);
)
kh_destroy(alldefine, alldefines);
if(stackif.ifs)
free(stackif.ifs);
setlocale(LC_ALL, old_locale);
return ncode;
}
+17
View File
@@ -0,0 +1,17 @@
#ifndef _GL4ES_PREPROC_H_
#define _GL4ES_PREPROC_H_
typedef struct {
char name[50];
int state; //0:disable, 1:warn, 1:enable, 2:require
} extension_t;
typedef struct {
extension_t *ext;
int size;
int cap;
} extensions_t;
char* preproc(const char* code, int keepcomments, int gl_es, extensions_t* exts, char** versionString);
#endif // _GL4ES_PREPROC_H_
+999
View File
@@ -0,0 +1,999 @@
#include "program.h"
#include <stdlib.h>
#include <string.h>
#include "../glx/hardext.h"
#include "debug.h"
#include "fpe.h"
#include "gl4es.h"
#include "glstate.h"
#include "loader.h"
#include "shaderconv.h"
#include "fpe_shader.h"
//#define DEBUG
#ifdef DEBUG
#define DBG(a) a
#else
#define DBG(a)
#endif
//KH Map implementations
KHASH_MAP_IMPL_INT(attribloclist, attribloc_t *);
KHASH_MAP_IMPL_INT(uniformlist, uniform_t *);
KHASH_MAP_IMPL_INT(programlist, program_t *);
void APIENTRY_GL4ES gl4es_glAttachShader(GLuint program, GLuint shader) {
DBG(printf("glAttachShader(%d, %d)\n", program, shader);)
FLUSH_BEGINEND;
// sanity tests
CHECK_PROGRAM(void, program)
CHECK_SHADER(void, shader)
// add shader reference to program
if(glprogram->attach_cap == glprogram->attach_size) {
glprogram->attach_cap += 4;
glprogram->attach = (GLuint*)realloc(glprogram->attach, sizeof(GLuint)*glprogram->attach_cap);
}
glprogram->attach[glprogram->attach_size++] = glshader->id;
glshader->attached++;
// save last vertex or fragment attached
if(glshader->type==GL_VERTEX_SHADER && !glprogram->last_vert)
glprogram->last_vert = glshader;
else if(glshader->type==GL_FRAGMENT_SHADER && !glprogram->last_frag)
glprogram->last_frag = glshader;
// send to hadware
LOAD_GLES2(glAttachShader);
if(gles_glAttachShader) {
gles_glAttachShader(glprogram->id, glshader->id);
errorGL();
} else
noerrorShim();
}
void APIENTRY_GL4ES gl4es_glBindAttribLocation(GLuint program, GLuint index, const GLchar *name) {
DBG(printf("glBindAttribLocation(%d, %d, \"%s\")\n", program, index, name);)
FLUSH_BEGINEND;
// sanity tests
CHECK_PROGRAM(void, program)
// look / create attribloc at index
attribloc_t *attribloc = NULL;
{
khint_t k;
int ret;
khash_t(attribloclist) *attribloclist = glprogram->attribloc;
k = kh_get(attribloclist, attribloclist, index);
if (k != kh_end(attribloclist)) {
attribloc = kh_value(attribloclist, k);
} else {
k = kh_put(attribloclist, attribloclist, index, &ret);
attribloc = kh_value(attribloclist, k) = malloc(sizeof(attribloc_t));
memset(attribloc, 0, sizeof(attribloc_t));
attribloc->real_index = -1;
attribloc->index = index;
}
}
// update name
if(attribloc->name) free(attribloc->name);
attribloc->name = strdup(name);
attribloc->glname = attribloc->name;
// send to hardware
LOAD_GLES2(glBindAttribLocation);
if(gles_glBindAttribLocation) {
gles_glBindAttribLocation(glprogram->id, index, attribloc->name);
errorGL();
} else
noerrorShim();
}
GLuint APIENTRY_GL4ES gl4es_glCreateProgram(void) {
DBG(printf("glCreateProgram()\n");)
FLUSH_BEGINEND;
static GLuint lastprogram = 0;
GLuint program;
// create the program
LOAD_GLES2(glCreateProgram);
if(gles_glCreateProgram) {
program = gles_glCreateProgram();
if(!program) {
errorGL();
return 0;
}
} else {
program = ++lastprogram;
noerrorShim();
}
// store the new empty shader in the list for later use
khint_t k;
int ret;
khash_t(programlist) *programs = glstate->glsl->programs;
k = kh_get(programlist, programs, program);
program_t *glprogram = NULL;
if (k == kh_end(programs)){
k = kh_put(programlist, programs, program, &ret);
glprogram = kh_value(programs, k) = (program_t*)calloc(1, sizeof(program_t));
} else {
glprogram = kh_value(programs, k);
if(glprogram->attribloc) {
attribloc_t *m;
kh_foreach_value(glprogram->attribloc, m,
free(m->name); free(m);
)
kh_destroy(attribloclist, glprogram->attribloc);
glprogram->attribloc = NULL;
}
memset(glprogram, 0, sizeof(program_t));
}
glprogram->id = program;
// initialize attribloc hashmap
khash_t(attribloclist) *attribloc = glprogram->attribloc = kh_init(attribloclist);
// initialize uniform hashmap
khash_t(uniformlist) *uniform = glprogram->uniform = kh_init(uniformlist);
// all done
return program;
}
void actualy_deleteshader(GLuint shader);
void actualy_detachshader(GLuint shader);
void deleteProgram(program_t *glprogram, khint_t k_program) {
free(glprogram->attach);
// clean attribloc
if(glprogram->attribloc) {
attribloc_t *m;
kh_foreach_value(glprogram->attribloc, m,
free(m->name); free(m);
)
kh_destroy(attribloclist, glprogram->attribloc);
glprogram->attribloc = NULL;
}
// clean uniform list
if(glprogram->uniform) {
uniform_t *m;
kh_foreach_value(glprogram->uniform, m,
free(m->name); free(m);
)
kh_destroy(uniformlist, glprogram->uniform);
glprogram->uniform = NULL;
}
// clean cache
if(glprogram->cache.cache)
free(glprogram->cache.cache);
// clean fpe cache if it exist
if(glprogram->fpe_cache)
fpe_disposeCache((fpe_cache_t*)glprogram->fpe_cache, 1);
// delete program
kh_del(programlist, glstate->glsl->programs, k_program);
free(glprogram);
}
void APIENTRY_GL4ES gl4es_glDeleteProgram(GLuint program) {
DBG(printf("glDeleteProgram(%d)\n", program);)
if(!glstate) return; // in case a program delete shaders after deleteing all context
FLUSH_BEGINEND;
CHECK_PROGRAM(void, program)
// send to hardware
LOAD_GLES2(glDeleteProgram);
if(gles_glDeleteProgram) {
gles_glDeleteProgram(glprogram->id);
errorGL();
} else
noerrorShim();
// TODO: check GL ERROR to not clean in case of error?
// clean attached shaders
for (int i=0; i<glprogram->attach_size; i++) {
actualy_detachshader(glprogram->attach[i]); // auto delete if marqued as delete!
}
deleteProgram(glprogram, k_program);
}
void APIENTRY_GL4ES gl4es_glDetachShader(GLuint program, GLuint shader) {
DBG(printf("glDetachShader(%d, %d)\n", program, shader);)
FLUSH_BEGINEND;
CHECK_PROGRAM(void, program)
CHECK_SHADER(void, shader)
// is shader attached?
int f = 0;
while(f<glprogram->attach_size && glprogram->attach[f]!=shader)
f++;
// if program is linked, don't try anything....
if(glprogram->linked) {
noerrorShim();
return;
}
// send to hardware
LOAD_GLES2(glDetachShader);
if(gles_glDetachShader) {
gles_glDetachShader(glprogram->id, glshader->id);
errorGL();
} else
noerrorShim();
// marked as detached
actualy_detachshader(shader);
}
void APIENTRY_GL4ES gl4es_glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) {
DBG(printf("glGetActiveAttrib(%d, %d, %d, %p, %p, %p, %p)\n", program, index, bufSize, length, size, type, name);)
FLUSH_BEGINEND;
CHECK_PROGRAM(void, program)
if(glprogram->attribloc) {
attribloc_t *attribloc;
kh_foreach_value(glprogram->attribloc, attribloc,
if(attribloc->real_index == index) {
if(type) *type = attribloc->type;
if(size) *size = attribloc->size;
if(length) *length = strlen(attribloc->glname);
if(bufSize && name) {
strncpy(name, attribloc->glname, bufSize-1);
name[bufSize-1] = '\0';
}
DBG(printf("found, type=%s, size=%d, name=%s/%s\n", PrintEnum(attribloc->type), attribloc->size, attribloc->name, attribloc->glname);)
noerrorShim();
return;
}
);
}
DBG(printf("not found\n");)
errorShim(GL_INVALID_VALUE);
}
void APIENTRY_GL4ES gl4es_glGetAttachedShaders(GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders) {
DBG(printf("glGetAttachedShaders(%d, %d, %p, %p)\n", program, maxCount, count, shaders);)
FLUSH_BEGINEND;
CHECK_PROGRAM(void, program)
int n = glprogram->attach_size;
if(n>maxCount) n = maxCount;
if (count) *count=n;
if (shaders)
for (int i=0; i<n; i++)
shaders[i] = glprogram->attach[i];
noerrorShim();
}
GLint APIENTRY_GL4ES gl4es_glGetAttribLocation(GLuint program, const GLchar *name) {
DBG(printf("glGetAttribLocation(%d, %s)\n", program, name));
FLUSH_BEGINEND;
CHECK_PROGRAM(GLint, program);
if(!glprogram->linked) {
errorShim(GL_INVALID_OPERATION);
DBG(printf(" program unlinked: -1\n"));
return -1;
}
noerrorShim();
if(strncmp(name, "gl_", 3)==0) {
DBG(printf(" internal attrib: -1\n"));
return -1;
}
int rloc = -1;
int loc = -1;
// look in already created attribloc
if(glprogram->attribloc) {
attribloc_t *m;
kh_foreach_value(glprogram->attribloc, m,
if(strcmp(m->glname, name)==0) {
loc = m->index;
rloc = m->real_index;
}
)
}
// if found, just return the value, it's done...
if(loc!=-1) {
DBG(printf(" found in cache: %d\n", loc);)
return loc;
}
// end
DBG(printf(" asked hardware: %d\n", loc);)
return loc;
}
void APIENTRY_GL4ES gl4es_glGetActiveUniform(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) {
DBG(printf("glGetActiveUniform(%d, %d, %d, %p, %p, %p, %p)\n", program, index, bufSize, length, size, type, name);)
FLUSH_BEGINEND;
CHECK_PROGRAM(GLvoid, program);
if(!glprogram->linked) {
errorShim(GL_INVALID_OPERATION);
DBG(printf(" not linked\n");)
return;
}
noerrorShim();
if(strncmp(name, "gl_", 3)==0) {
DBG(printf(" internal uniform\n");)
return;
}
// look in uniform cache, that is filled when program is linked
if(glprogram->uniform) {
uniform_t *m;
kh_foreach_value(glprogram->uniform, m,
if(m->internal_id == index) {
if(type) *type = m->type;
if(size) *size = m->size;
if(length) *length = strlen(m->name);
if(bufSize && name) {
strncpy(name, m->name, bufSize-1);
name[bufSize-1] = '\0';
}
DBG(printf(" found %s (%zd), type=%s, size=%d\n", m->name, strlen(m->name), PrintEnum(m->type), m->size);)
return;
}
);
}
// end
DBG(printf(" not found\n");)
errorShim(GL_INVALID_VALUE);
}
static const char* notlinked = "Program not linked";
static const char* linked = "Program linked, but no shader support";
static const char* validated = "Program validated, but no shader support";
const char* getFakeProgramInfo(program_t* glprogram) {
return (glprogram->linked)?((glprogram->validated)?validated:linked):notlinked;
}
void APIENTRY_GL4ES gl4es_glGetProgramInfoLog(GLuint program, GLsizei maxLength, GLsizei *length, GLchar *infoLog) {
DBG(printf("glGetProgramInfoLog(%d, %d, %p, %p)\n", program, maxLength, length, infoLog);)
FLUSH_BEGINEND;
CHECK_PROGRAM(void, program)
if(maxLength<0) {
errorShim(GL_INVALID_VALUE);
return;
}
if(!maxLength) {
noerrorShim();
return;
}
LOAD_GLES2(glGetProgramInfoLog);
if(gles_glGetProgramInfoLog) {
gles_glGetProgramInfoLog(glprogram->id, maxLength, length, infoLog);
errorGL();
} else {
const char* res = getFakeProgramInfo(glprogram);
int l = strlen(res)+1;
if (l>maxLength) l = maxLength;
if(length) *length = l-1;
if(infoLog) strncpy(infoLog, res, l);
noerrorShim();
}
}
void APIENTRY_GL4ES gl4es_glGetProgramiv(GLuint program, GLenum pname, GLint *params) {
DBG(printf("glGetProgramiv(%d, %s, %p)\n", program, PrintEnum(pname), params);)
FLUSH_BEGINEND;
CHECK_PROGRAM(void, program)
LOAD_GLES2(glGetProgramiv);
noerrorShim();
switch(pname) {
case GL_DELETE_STATUS:
if(gles_glGetProgramiv) {
gles_glGetProgramiv(glprogram->id, pname, params);
errorGL();
} else
*params = GL_FALSE;
break;
case GL_LINK_STATUS:
*params = glprogram->linked?GL_TRUE:GL_FALSE;
break;
case GL_VALIDATE_STATUS:
*params = glprogram->valid_result;
break;
case GL_INFO_LOG_LENGTH:
if(gles_glGetProgramiv) {
gles_glGetProgramiv(glprogram->id, pname, params);
errorGL();
} else
*params = strlen(getFakeProgramInfo(glprogram));
break;
case GL_ATTACHED_SHADERS:
*params = glprogram->attach_size;
break;
case GL_ACTIVE_ATTRIBUTES:
case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
if(gles_glGetProgramiv) {
gles_glGetProgramiv(glprogram->id, pname, params);
errorGL();
} else
*params = 0;
break;
case GL_ACTIVE_UNIFORMS:
*params = (glprogram->uniform)?glprogram->num_uniform:0;
break;
case GL_ACTIVE_UNIFORM_MAX_LENGTH:
{
int l = 0;
uniform_t *m;
kh_foreach_value(glprogram->uniform, m,
if(l<strlen(m->name)+1)
l = strlen(m->name)+1;
)
*params = l;
}
break;
case GL_PROGRAM_BINARY_LENGTH:
// TODO: check if extension is present
if(gles_glGetProgramiv) {
gles_glGetProgramiv(glprogram->id, pname, params);
errorGL();
} else
errorShim(GL_INVALID_ENUM);
break;
default:
if(gles_glGetProgramiv) {
gles_glGetProgramiv(glprogram->id, pname, params);
errorGL();
} else
errorShim(GL_INVALID_ENUM);
break;
}
}
GLint APIENTRY_GL4ES gl4es_glGetUniformLocation(GLuint program, const GLchar *name) {
DBG(printf("glGetUniformLocation(%d, %s)\n", program, name);)
FLUSH_BEGINEND;
CHECK_PROGRAM(GLint, program)
noerrorShim();
int res = -1;
if(strncmp(name, "gl_", 3)==0) {
DBG(printf(" internal uniform: -1\n");)
return res;
}
int index = 0;
int l = strlen(name);
// get array (only if end with ])
if(name[l-1]==']') {
char * p = strrchr(name, '[');
l = p-name;
p++;
while(p && *p>='0' && *p<='9') {
index = index*10 + *(p++)-'0';
}
}
if(glprogram->uniform) {
uniform_t *m;
kh_foreach_value(glprogram->uniform, m,
if(strlen(m->name)==l && strncmp(m->name, name, l)==0) {
res = m->id;
if(index>m->size) {
res = -1; // too big !
} else
res += index;
break;
}
)
}
DBG(printf(" location: %d\n", res);)
return res;
}
GLboolean APIENTRY_GL4ES gl4es_glIsProgram(GLuint program) {
DBG(printf("glIsProgram(%d)\n", program);)
FLUSH_BEGINEND;
noerrorShim();
if(!program) {
return GL_FALSE;
}
program_t *glprogram = NULL;
khint_t k;
khash_t(programlist) *programs = glstate->glsl->programs;
k = kh_get(programlist, programs, program);
if (k != kh_end(programs))
return GL_TRUE;
return GL_FALSE;
}
static void clear_program(program_t *glprogram)
{
// clear all Attrib location cache
if(glprogram->attribloc) {
attribloc_t *m;
khint_t k;
int ret;
//attribloc->glname must not be freed
kh_foreach(glprogram->attribloc, k, m,
free(m->name); free(m);
kh_del(attribloclist, glprogram->attribloc, k);
)
kh_destroy(attribloclist, glprogram->attribloc);
khash_t(attribloclist) *attribloc = glprogram->attribloc = kh_init(attribloclist);
kh_put(attribloclist, attribloc, 1, &ret);
kh_del(attribloclist, attribloc, 1);
}
// clear all Uniform cache
glprogram->num_uniform = 0;
if(glprogram->uniform) {
uniform_t *m;
khint_t k;
kh_foreach(glprogram->uniform, k, m,
free(m->name); free(m);
kh_del(uniformlist, glprogram->uniform, k);
)
}
glprogram->cache.size = 0; // reset cache buffer
}
static void fill_program(program_t *glprogram)
{
LOAD_GLES(glGetError);
LOAD_GLES2(glGetProgramiv);
LOAD_GLES2(glGetActiveUniform);
LOAD_GLES2(glGetUniformLocation);
LOAD_GLES2(glGetActiveAttrib);
LOAD_GLES2(glGetAttribLocation);
int n=0;
int maxsize=0;
khint_t k;
int ret;
DBG(GLenum e2;)
// init bluitin emulation first
builtin_Init(glprogram);
// Grab all Uniform
gles_glGetProgramiv(glprogram->id, GL_ACTIVE_UNIFORMS, &n);
gles_glGetProgramiv(glprogram->id, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxsize);
khash_t(uniformlist) *uniforms = glprogram->uniform;
uniform_t *gluniform = NULL;
int uniform_cache = 0;
GLint size = 0;
GLenum type = 0;
GLchar *name = (char*)malloc(maxsize);
int tu_idx = 0;
for (int i=0; i<n; i++) {
gles_glGetActiveUniform(glprogram->id, i, maxsize, NULL, &size, &type, name);
DBG(e2=gles_glGetError();)
DBG(if(e2==GL_NO_ERROR))
{
// remove any ending "[]" that could be present
if(name[strlen(name)-1]==']' && strrchr(name, '[')) (*strrchr(name, '['))='\0';
GLint id = gles_glGetUniformLocation(glprogram->id, name);
if(id!=-1) {
for (int j = 0; j<size; j++) {
k = kh_put(uniformlist, uniforms, id, &ret);
gluniform = kh_value(uniforms, k) = malloc(sizeof(uniform_t));
memset(gluniform, 0, sizeof(uniform_t));
if(j) {
gluniform->name = malloc(strlen(name)+1+5);
sprintf(gluniform->name, "%s[%d]", name, j);
} else
gluniform->name = strdup(name);
gluniform->id = id;
gluniform->internal_id = i;
gluniform->size = size-j;
gluniform->type = type;
gluniform->cache_offs = uniform_cache+j*uniformsize(type);
gluniform->cache_size = uniformsize(type)*(size-j);
gluniform->builtin = builtin_CheckUniform(glprogram, name, id, size-j);
// TextureUnit grabbing...
if(type==GL_SAMPLER_CUBE) {
glprogram->texunits[tu_idx].id = id;
glprogram->texunits[tu_idx].type=TU_CUBE;
glprogram->texunits[tu_idx].req_tu = glprogram->texunits[tu_idx].act_tu = 0;
++tu_idx;
} else if (type==GL_SAMPLER_2D) {
glprogram->texunits[tu_idx].id = id;
glprogram->texunits[tu_idx].type=TU_TEX2D;
glprogram->texunits[tu_idx].req_tu = glprogram->texunits[tu_idx].act_tu = 0;
++tu_idx;
}
DBG(printf(" uniform #%d : \"%s\"%s type=%s size=%d\n", id, gluniform->name, gluniform->builtin?" (builtin) ":"", PrintEnum(gluniform->type), gluniform->size);)
if(gluniform->size==1) ++glprogram->num_uniform;
id++;
}
uniform_cache += uniformsize(type)*size;
}
}
DBG(else printf("LIBGL: Warning, getting Uniform #%d info failed with %s\n", i, PrintEnum(e2));)
}
free(name);
// reset uniform cache
if(glprogram->cache.cap < uniform_cache) {
glprogram->cache.cap=uniform_cache;
glprogram->cache.cache = malloc(glprogram->cache.cap);
}
memset(glprogram->cache.cache, 0, glprogram->cache.cap);
//Maybe Sampler uniform should not be initialized to 0, but to -1, to be sure the value is initialized?
if(glprogram->uniform) {
uniform_t *m;
khint_t k;
kh_foreach(glprogram->uniform, k, m,
if(m->type == GL_SAMPLER_2D || m->type == GL_SAMPLER_CUBE)
memset((char*)glprogram->cache.cache+m->cache_offs, 0xff, m->cache_size);
)
}
// Grab all Attrib
gles_glGetProgramiv(glprogram->id, GL_ACTIVE_ATTRIBUTES, &n);
gles_glGetProgramiv(glprogram->id, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxsize);
name = (char*)malloc(maxsize);
for (int i=0; i<n; i++) {
DBG(e2=gles_glGetError();)
DBG(if(e2==GL_NO_ERROR))
{
gles_glGetActiveAttrib(glprogram->id, i, maxsize, NULL, &size, &type, name);
GLint id = gles_glGetAttribLocation(glprogram->id, name);
if(id!=-1) {
attribloc_t *glattribloc = NULL;
k = kh_put(attribloclist, glprogram->attribloc, id, &ret);
if(ret==0) {
// already there
glattribloc = kh_value(glprogram->attribloc, k);
if(glattribloc->name)
free(glattribloc->name);
} else {
glattribloc = kh_value(glprogram->attribloc, k) = malloc(sizeof(attribloc_t));
}
memset(glattribloc, 0, sizeof(attribloc_t));
glattribloc->name = strdup(name);
glattribloc->glname = builtinAttribGLName(glattribloc->name);
glattribloc->size = size;
glattribloc->type = type;
glattribloc->index = id;
glattribloc->real_index = i;
int builtin = builtin_CheckVertexAttrib(glprogram, name, id);
glprogram->va_size[id] = n_uniform(type); // same as uniform
DBG(printf(" attrib #%d : \"%s\"%s type=%s size=%d\n", id, glattribloc->name, builtin?" (builtin) ":"", PrintEnum(glattribloc->type), glattribloc->size);)
}
}
DBG(else printf("LIBGL: Warning, getting Attrib #%d info failed with %s\n", i, PrintEnum(e2));)
}
free(name);
}
int gl4es_useProgramBinary(GLuint program, int length, GLenum format, const void* binary)
{
if(hardext.prgbin_n==0)
return 0;
DBG(printf("useProgramBinary(%d, %d, %d, %p)\n", program, length, format, binary);)
CHECK_PROGRAM(int, program)
noerrorShim();
clear_program(glprogram);
LOAD_GLES_OES(glProgramBinary);
LOAD_GLES2(glGetProgramiv);
gles_glProgramBinary(glprogram->id, format, binary, length);
gles_glGetProgramiv(glprogram->id, GL_LINK_STATUS, &glprogram->linked);
DBG(printf(" link status = %d\n", glprogram->linked);)
if(glprogram->linked) {
fill_program(glprogram);
} else {
// should DBG the linker error?
DBG(printf(" Load failed!\n");)
glprogram->linked = 0;
errorGL();
}
return glprogram->linked;
}
int gl4es_getProgramBinary(GLuint program, int *length, GLenum *format, void** binary)
{
if(hardext.prgbin_n==0)
return 0;
DBG(printf("getProgramBinary(%d, %p, %p, %p)\n", program, length, format, binary);)
CHECK_PROGRAM(int, program)
noerrorShim();
LOAD_GLES_OES(glGetProgramBinary);
LOAD_GLES2(glGetProgramiv);
int l;
gles_glGetProgramiv(glprogram->id, GL_PROGRAM_BINARY_LENGTH_OES, &l);
if(!l)
return 0;
*binary = malloc(l);
gles_glGetProgramBinary(glprogram->id, l, length, format, *binary);
return (*length);
}
void APIENTRY_GL4ES gl4es_glGetProgramBinary(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary)
{
if(hardext.prgbin_n==0) {
errorShim(GL_INVALID_OPERATION);
return;
}
DBG(printf("glGetProgramBinary(%d, %d, %p, %p, %p)\n", program, bufSize, length, binaryFormat, binary);)
CHECK_PROGRAM(void, program)
LOAD_GLES_OES(glGetProgramBinary);
gles_glGetProgramBinary(glprogram->id, bufSize, length, binaryFormat, binary);
errorGL();
}
void APIENTRY_GL4ES gl4es_glProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLsizei length)
{
if(hardext.prgbin_n==0) {
errorShim(GL_INVALID_OPERATION);
return;
}
DBG(printf("glProgramBinary(%d, %d, %p, %d)\n", program, binaryFormat, binary, length);)
if(gl4es_useProgramBinary(program, length, binaryFormat, binary))
noerrorShim();
else
errorShim(GL_INVALID_OPERATION);
}
void APIENTRY_GL4ES gl4es_glLinkProgram(GLuint program) {
DBG(printf("glLinkProgram(%d)\n", program);)
FLUSH_BEGINEND;
CHECK_PROGRAM(void, program)
noerrorShim();
clear_program(glprogram);
// check if attached shaders are compatible in term of varying...
shaderconv_need_t needs = {0};
needs.need_texcoord = -1;
// first get the compatible need
for (int i=0; i<glprogram->attach_size; i++) {
accumShaderNeeds(glprogram->attach[i], &needs);
}
// create one vertex shader if needed!
if(!glprogram->last_vert) {
glprogram->default_need = (shaderconv_need_t*)malloc(sizeof(shaderconv_need_t));
memcpy(glprogram->default_need, &needs, sizeof(shaderconv_need_t));
glprogram->default_vertex = 1;
GLenum vtx = gl4es_glCreateShader(GL_VERTEX_SHADER);
gl4es_glShaderSource(vtx, 1, fpe_VertexShader(&needs, NULL), NULL);
gl4es_glCompileShader(vtx);
gl4es_glAttachShader(glprogram->id, vtx);
}
// create one fragment shader if needed!
if(!glprogram->last_frag) {
glprogram->default_need = (shaderconv_need_t*)malloc(sizeof(shaderconv_need_t));
memcpy(glprogram->default_need, &needs, sizeof(shaderconv_need_t));
glprogram->default_fragment = 1;
GLenum vtx = gl4es_glCreateShader(GL_FRAGMENT_SHADER);
gl4es_glShaderSource(vtx, 1, fpe_FragmentShader(&needs, NULL), NULL);
gl4es_glCompileShader(vtx);
gl4es_glAttachShader(glprogram->id, vtx);
}
int compatible = 1;
// now is everyone ok?
for (int i=0; i<glprogram->attach_size && compatible; i++) {
compatible = isShaderCompatible(glprogram->attach[i], &needs);
}
// someone is not compatible, redoing shaders...
if(!compatible) {
DBG(printf("Need to redo some shaders...\n");)
for (int i=0; i<glprogram->attach_size; i++) {
redoShader(glprogram->attach[i], &needs);
}
}
// check if Built-in VA are used, and if so, bind them to their proper location
if(glprogram->last_vert)
for (int i=0; i<ATT_MAX; ++i) {
const char* attribute = hasBuiltinAttrib(glprogram->last_vert->converted, i);
if(attribute)
gl4es_glBindAttribLocation(glprogram->id, i, attribute);
}
// ok, continue with linking
LOAD_GLES2(glLinkProgram);
if(gles_glLinkProgram) {
LOAD_GLES(glGetError);
LOAD_GLES2(glGetProgramiv);
gles_glLinkProgram(glprogram->id);
GLenum err = gles_glGetError();
// Get Link Status
gles_glGetProgramiv(glprogram->id, GL_LINK_STATUS, &glprogram->linked);
DBG(printf(" link status = %d\n", glprogram->linked);)
if(glprogram->linked) {
fill_program(glprogram);
noerrorShimNoPurge();
} else {
// should DBG the linker error?
DBG(printf(" Link failled!\n");)
glprogram->linked = 0;
errorShim(err);
return;
}
} else {
noerrorShim();
}
glprogram->linked = 1;
}
void APIENTRY_GL4ES gl4es_glUseProgram(GLuint program) {
DBG(printf("glUseProgram(%d) old=%d\n", program, glstate->glsl->program);)
PUSH_IF_COMPILING(glUseProgram);
if(program==0) {
glstate->glsl->program=0;
glstate->glsl->glprogram=NULL;
return;
}
CHECK_PROGRAM(void, program)
noerrorShim();
DBG(printf("program id=%d\n", glprogram->id);)
glstate->glsl->program=glprogram->id;
glstate->glsl->glprogram=glprogram;
}
void APIENTRY_GL4ES gl4es_glValidateProgram(GLuint program) {
CHECK_PROGRAM(void, program)
FLUSH_BEGINEND;
noerrorShim();
LOAD_GLES2(glValidateProgram);
if(gles_glValidateProgram) {
LOAD_GLES(glGetError);
LOAD_GLES2(glGetProgramiv);
gles_glValidateProgram(glprogram->id);
GLenum err = gles_glGetError();
gles_glGetProgramiv(glprogram->id, GL_VALIDATE_STATUS, (GLint *) &glprogram->valid_result);
errorShim(err);
// TODO: grab all Uniform and Attrib of the program
} else {
noerrorShim();
}
glprogram->validated = 1;
}
AliasExport(void,glAttachShader,,(GLuint program, GLuint shader));
AliasExport(void,glBindAttribLocation,,(GLuint program, GLuint index, const GLchar *name));
AliasExport_V(GLuint,glCreateProgram);
AliasExport(void,glDeleteProgram,,(GLuint program));
AliasExport(void,glDetachShader,,(GLuint program, GLuint shader));
AliasExport(void,glGetActiveAttrib,,(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name));
AliasExport(void,glGetAttachedShaders,,(GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders));
AliasExport(GLint,glGetAttribLocation,,(GLuint program, const GLchar *name));
AliasExport(void,glGetActiveUniform,,(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name));
AliasExport(void,glGetProgramiv,,(GLuint program, GLenum pname, GLint *params));
AliasExport(GLint,glGetUniformLocation,,(GLuint program, const GLchar *name));
AliasExport(GLboolean,glIsProgram,,(GLuint program));
AliasExport(void,glLinkProgram,,(GLuint program));
AliasExport(void,glUseProgram,,(GLuint program));
AliasExport(void,glValidateProgram,,(GLuint program));
AliasExport(void,glGetProgramInfoLog,,(GLuint program, GLsizei maxLength, GLsizei *length, GLchar *infoLog));
AliasExport(void,glGetProgramBinary,,(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary));
AliasExport(void,glProgramBinary,,(GLuint program, GLenum binaryFormat, const void *binary, GLsizei length));
// ================ GL_ARB_vertex_shader =================
AliasExport(GLvoid,glBindAttribLocation,ARB,(GLhandleARB programObj, GLuint index, const GLcharARB *name));
AliasExport(GLvoid,glGetActiveAttrib,ARB,(GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name));
AliasExport(GLint,glGetAttribLocation,ARB,(GLhandleARB programObj, const GLcharARB *name));
// ============== GL_ARB_shader_objects ==================
// some are not simple alias but wrappers
GLvoid APIENTRY_GL4ES gl4es_glDeleteObject(GLhandleARB obj) {
if(!obj)
return;
// find type of obj (shader or program)
program_t *glprogram = NULL;
khint_t k_program;
{
khash_t(programlist) *programs = glstate->glsl->programs;
k_program = kh_get(programlist, programs, obj);
if (k_program != kh_end(programs))
glprogram = kh_value(programs, k_program);
}
if(glprogram)
gl4es_glDeleteProgram(obj);
else
gl4es_glDeleteShader(obj);
}
GLhandleARB APIENTRY_GL4ES gl4es_glGetHandle(GLenum pname) {
FLUSH_BEGINEND;
if(pname!=GL_PROGRAM_OBJECT_ARB) {
errorShim(GL_INVALID_ENUM);
return 0;
}
return glstate->glsl->program;
}
GLvoid APIENTRY_GL4ES gl4es_glDetachObject(GLhandleARB containerObj, GLhandleARB attachedObj) {
gl4es_glDetachShader(containerObj, attachedObj);
}
GLhandleARB APIENTRY_GL4ES gl4es_glCreateProgramObject(GLvoid) {
return gl4es_glCreateProgram();
}
GLvoid APIENTRY_GL4ES gl4es_glAttachObject(GLhandleARB containerObj, GLhandleARB obj) {
gl4es_glAttachShader(containerObj, obj);
}
GLvoid APIENTRY_GL4ES gl4es_glUseProgramObject(GLhandleARB programObj) {
gl4es_glUseProgram(programObj);
}
GLvoid APIENTRY_GL4ES gl4es_glGetObjectParameterfv(GLhandleARB obj, GLenum pname, GLfloat *params) {
if(!obj)
return;
// find type of obj (shader or program)
program_t *glprogram = NULL;
khint_t k_program;
{
khash_t(programlist) *programs = glstate->glsl->programs;
k_program = kh_get(programlist, programs, obj);
if (k_program != kh_end(programs))
glprogram = kh_value(programs, k_program);
}
// float, really?
GLint p[4];
if(glprogram)
gl4es_glGetProgramiv(obj, pname, p);
else
gl4es_glGetShaderiv(obj, pname, p);
params[0] = p[0]; // only 1-sized array here, right?
}
GLvoid APIENTRY_GL4ES gl4es_glGetObjectParameteriv(GLhandleARB obj, GLenum pname, GLint *params) {
if(!obj)
return;
// find type of obj (shader or program)
program_t *glprogram = NULL;
khint_t k_program;
{
khash_t(programlist) *programs = glstate->glsl->programs;
k_program = kh_get(programlist, programs, obj);
if (k_program != kh_end(programs))
glprogram = kh_value(programs, k_program);
}
if(glprogram)
gl4es_glGetProgramiv(obj, pname, params);
else
gl4es_glGetShaderiv(obj, pname, params);
// hack, some program don't take into account that the lenght return by GL_OBJECT_INFO_LOG_LENGTH_ARB exclude the '\0'.. so adding it here
if(pname==GL_INFO_LOG_LENGTH)
(*params)++;
}
GLvoid APIENTRY_GL4ES gl4es_glGetInfoLog(GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog) {
if(!obj)
return;
// find type of obj (shader or program)
program_t *glprogram = NULL;
khint_t k_program;
{
khash_t(programlist) *programs = glstate->glsl->programs;
k_program = kh_get(programlist, programs, obj);
if (k_program != kh_end(programs))
glprogram = kh_value(programs, k_program);
}
if(glprogram)
gl4es_glGetProgramInfoLog(obj, maxLength, length, infoLog);
else
gl4es_glGetShaderInfoLog(obj, maxLength, length, infoLog);
}
GLvoid APIENTRY_GL4ES gl4es_glGetAttachedObjects(GLhandleARB containerObj, GLsizei maxCount, GLsizei *count, GLhandleARB *obj) {
gl4es_glGetAttachedShaders(containerObj, maxCount, count, obj);
}
AliasExport(GLvoid,glDeleteObject,ARB,(GLhandleARB obj));
AliasExport(GLhandleARB,glGetHandle,ARB,(GLenum pname));
AliasExport(GLvoid,glDetachObject,ARB,(GLhandleARB containerObj, GLhandleARB attachedObj));
AliasExport(GLhandleARB,glCreateProgramObject,ARB,());
AliasExport(GLvoid,glAttachObject,ARB,(GLhandleARB containerObj, GLhandleARB obj));
AliasExport(GLvoid,glLinkProgram,ARB,(GLhandleARB programObj));
AliasExport(GLvoid,glUseProgramObject,ARB,(GLhandleARB programObj));
AliasExport(GLvoid,glValidateProgram,ARB,(GLhandleARB programObj));
AliasExport(GLvoid,glGetObjectParameterfv,ARB,(GLhandleARB obj, GLenum pname, GLfloat *params));
AliasExport(GLvoid,glGetObjectParameteriv,ARB,(GLhandleARB obj, GLenum pname, GLint *params));
AliasExport(GLvoid,glGetInfoLog,ARB,(GLhandleARB obj, GLsizei maxLength, GLsizei *length, GLcharARB *infoLog));
AliasExport(GLvoid,glGetAttachedObjects,ARB,(GLhandleARB containerObj, GLsizei maxCount, GLsizei *count, GLhandleARB *obj));
AliasExport(GLint,glGetUniformLocation,ARB,(GLhandleARB programObj, const GLcharARB *name));
AliasExport(GLvoid,glGetActiveUniform,ARB,(GLhandleARB programObj, GLuint index, GLsizei maxLength, GLsizei *length, GLint *size, GLenum *type, GLcharARB *name));

Some files were not shown because too many files have changed in this diff Show More