Initial commit of libAgl2 using Pixelflinger2 in external/mesa3d

Somewhat functional, refer to README for details.
Need to enable Android.mk to build.
It builds libGLES_android.so, which needs to replace
 the one in system/lib/egl built by libagl.

Change-Id: Iec3aaa8f3963a4185d81955cd24019eb0c4a5850
Signed-off-by: David Li <davidxli@google.com>
This commit is contained in:
David Li 2011-03-01 16:54:04 -08:00
parent b8759993d0
commit aa1f54d78f
11 changed files with 4162 additions and 0 deletions

58
opengl/libagl2/Android.mk Normal file
View File

@ -0,0 +1,58 @@
LOCAL_PATH:= $(call my-dir)
#
# Build the software OpenGL ES library
#
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
src/api.cpp \
src/egl.cpp \
src/get.cpp \
src/shader.cpp \
src/state.cpp \
src/texture.cpp \
src/vertex.cpp
LOCAL_C_INCLUDES := \
$(LOCAL_PATH) \
external/mesa3d/include \
external/mesa3d/src \
external/stlport/stlport \
bionic
#LOCAL_CFLAGS += -DLOG_TAG=\"libagl2\"
#LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES
#LOCAL_CFLAGS += -fvisibility=hidden
#LOCAL_CFLAGS += -O0 -g -DDEBUG -UNDEBUG
LOCAL_CFLAGS += -O3
LOCAL_STATIC_LIBRARIES := libMesa
LOCAL_SHARED_LIBRARIES := libstlport libcutils libhardware libutils libbcc libdl
LOCAL_LDLIBS := -lpthread
ifeq ($(TARGET_ARCH),arm)
LOCAL_CFLAGS += -fstrict-aliasing
endif
ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
endif
ifneq ($(TARGET_SIMULATOR),true)
# we need to access the private Bionic header <bionic_tls.h>
# on ARM platforms, we need to mirror the ARCH_ARM_HAVE_TLS_REGISTER
# behavior from the bionic Android.mk file
ifeq ($(TARGET_ARCH)-$(ARCH_ARM_HAVE_TLS_REGISTER),arm-true)
LOCAL_CFLAGS += -DHAVE_ARM_TLS_REGISTER
endif
LOCAL_C_INCLUDES += bionic/libc/private
endif
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/egl
#replace libagl for now
LOCAL_MODULE:= libGLES_android
LOCAL_MODULE_TAGS := eng
## Disable this makefile for now
## include $(BUILD_SHARED_LIBRARY)

26
opengl/libagl2/README Normal file
View File

@ -0,0 +1,26 @@
libAgl2 provides software GL ES 2.0 implementation using Pixelflinger2 in external/mesa3d
To build, enable Android.mk, which builds libGLES_android.so, then replace the one built from libAgl in system/lib/egl.
ES 1.0 functions are not implemented and will cause exit, so do not setprop debug.egl.hw 0 until launcher is loaded.
All functions have little to none error checking.
Not thread safe, Pixelflinger2 uses some static data.
Most shader functions are implemented, however, most Get* functions for shaders/programs/uniforms/attribs are not.
No name system for shaders/programs, just using the pointers as names.
Basic glTexImage2D, glTexSubImage2D, glCopyImage2D and glCopySubImage2D are implemented, with a range of 8/16/24/32bpp formats.
Cube map support is minimal. No mipmapping.
TexParameter is mostly implemented, supports texcoord wrap modes, and only linear for both min and mag, or nearest for both min and mag filtering.
Texture names are implemented, but bad.
Frame buffer and render buffers are not implemented.
Depth and stencil are implemented, but not tested.
Blending seems to work.
Colorbuffer supports RGBA_8888 and RGB_565.
Vertex buffer objects are implemented.
Some GL_TRIANGLES and GL_TRIANGLE_STRIPS modes for glDrawArrays and glDrawElements are implemented, but vertex order is probably wrong so culling is disabled.
Basic apps should work, and some libhwui should work, except for frame buffer operations, which will cause exit.

View File

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="utf-8"?>
<CodeLite_Project Name="libagl2" InternalType="Console">
<Plugins>
<Plugin Name="qmake">
<![CDATA[00010001N0005Debug000000000000]]>
</Plugin>
</Plugins>
<Description/>
<Dependencies/>
<Dependencies Name="Release"/>
<VirtualDirectory Name="src">
<File Name="src/egl.cpp"/>
<File Name="src/api.cpp"/>
<File Name="src/gles2context.h"/>
<File Name="src/shader.cpp"/>
<File Name="src/vertex.cpp"/>
<File Name="src/state.cpp"/>
<File Name="src/texture.cpp"/>
<File Name="src/get.cpp"/>
</VirtualDirectory>
<VirtualDirectory Name="include"/>
<Settings Type="Executable">
<Configuration Name="Debug" CompilerType="gnu gcc" DebuggerType="GNU gdb debugger" Type="Executable" BuildCmpWithGlobalSettings="append" BuildLnkWithGlobalSettings="append" BuildResWithGlobalSettings="append">
<Compiler Options="-g;-m32" Required="yes" PreCompiledHeader="">
<IncludePath Value="/usr/include/c++/4.4"/>
<IncludePath Value="/usr/include/c++/4.4/ext"/>
<IncludePath Value="."/>
<IncludePath Value="include"/>
<IncludePath Value="../../../../external/mesa3d/include"/>
<IncludePath Value="../../../../external/mesa3d/src"/>
<IncludePath Value="../../../../hardware/libhardware/include"/>
<IncludePath Value="../../../../system/core/include"/>
<IncludePath Value="../include"/>
<IncludePath Value="../../include"/>
<IncludePath Value="../../../../development/ndk/platforms/android-9/include"/>
<IncludePath Value="../../../../bionic/libc/include/"/>
<IncludePath Value="/../../../../development/ndk/platforms/android-5/arch-x86/include"/>
<IncludePath Value="../../../../bionic/libc/arch-x86/include"/>
<IncludePath Value="../../../../bionic/libc/kernel/arch-x86"/>
<IncludePath Value="/../../../../external/kernel-headers/original"/>
<IncludePath Value="../../../../prebuilt/ndk/android-ndk-r4/platforms/android-8/arch-x86/usr/include"/>
</Compiler>
<Linker Options="-m32;-lstdc++" Required="yes"/>
<ResourceCompiler Options="" Required="no"/>
<General OutputFile="$(IntermediateDirectory)/$(ProjectName)" IntermediateDirectory="./Debug" Command="./$(ProjectName)" CommandArguments="" WorkingDirectory="$(IntermediateDirectory)" PauseExecWhenProcTerminates="yes"/>
<Debugger IsRemote="no" RemoteHostName="" RemoteHostPort="" DebuggerPath="">
<PostConnectCommands/>
<StartupCommands/>
</Debugger>
<PreBuild/>
<PostBuild/>
<CustomBuild Enabled="no">
<RebuildCommand/>
<CleanCommand/>
<BuildCommand/>
<PreprocessFileCommand/>
<SingleFileCommand/>
<MakefileGenerationCommand/>
<ThirdPartyToolName>None</ThirdPartyToolName>
<WorkingDirectory/>
</CustomBuild>
<AdditionalRules>
<CustomPostBuild/>
<CustomPreBuild/>
</AdditionalRules>
</Configuration>
<Configuration Name="Release" CompilerType="gnu gcc" DebuggerType="GNU gdb debugger" Type="" BuildCmpWithGlobalSettings="append" BuildLnkWithGlobalSettings="append" BuildResWithGlobalSettings="append">
<Compiler Options="" Required="yes" PreCompiledHeader="">
<IncludePath Value="."/>
</Compiler>
<Linker Options="-O2" Required="yes"/>
<ResourceCompiler Options="" Required="no"/>
<General OutputFile="$(IntermediateDirectory)/$(ProjectName)" IntermediateDirectory="./Release" Command="./$(ProjectName)" CommandArguments="" WorkingDirectory="$(IntermediateDirectory)" PauseExecWhenProcTerminates="yes"/>
<Debugger IsRemote="no" RemoteHostName="" RemoteHostPort="" DebuggerPath="">
<PostConnectCommands/>
<StartupCommands/>
</Debugger>
<PreBuild/>
<PostBuild/>
<CustomBuild Enabled="no">
<RebuildCommand/>
<CleanCommand/>
<BuildCommand/>
<PreprocessFileCommand/>
<SingleFileCommand/>
<MakefileGenerationCommand/>
<ThirdPartyToolName>None</ThirdPartyToolName>
<WorkingDirectory/>
</CustomBuild>
<AdditionalRules>
<CustomPostBuild/>
<CustomPreBuild/>
</AdditionalRules>
</Configuration>
<GlobalSettings>
<Compiler Options="">
<IncludePath Value="."/>
</Compiler>
<Linker Options="">
<LibraryPath Value="."/>
</Linker>
<ResourceCompiler Options=""/>
</GlobalSettings>
</Settings>
<Dependencies Name="Debug">
<Project Name="libMesa"/>
</Dependencies>
</CodeLite_Project>

266
opengl/libagl2/src/api.cpp Normal file
View File

@ -0,0 +1,266 @@
#include "gles2context.h"
#define API_ENTRY
#define CALL_GL_API(NAME,...) LOGD("?"#NAME); assert(0);
#define CALL_GL_API_RETURN(NAME,...) LOGD("?"#NAME); assert(0); return 0;
void API_ENTRY(glBindFramebuffer)(GLenum target, GLuint framebuffer)
{
CALL_GL_API(glBindFramebuffer, target, framebuffer);
}
void API_ENTRY(glBindRenderbuffer)(GLenum target, GLuint renderbuffer)
{
CALL_GL_API(glBindRenderbuffer, target, renderbuffer);
}
GLenum API_ENTRY(glCheckFramebufferStatus)(GLenum target)
{
CALL_GL_API_RETURN(glCheckFramebufferStatus, target);
}
void API_ENTRY(glColorMask)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
{
CALL_GL_API(glColorMask, red, green, blue, alpha);
}
void API_ENTRY(glDeleteFramebuffers)(GLsizei n, const GLuint* framebuffers)
{
CALL_GL_API(glDeleteFramebuffers, n, framebuffers);
}
void API_ENTRY(glDeleteRenderbuffers)(GLsizei n, const GLuint* renderbuffers)
{
CALL_GL_API(glDeleteRenderbuffers, n, renderbuffers);
}
void API_ENTRY(glDepthFunc)(GLenum func)
{
CALL_GL_API(glDepthFunc, func);
}
void API_ENTRY(glDepthMask)(GLboolean flag)
{
CALL_GL_API(glDepthMask, flag);
}
void API_ENTRY(glDepthRangef)(GLclampf zNear, GLclampf zFar)
{
CALL_GL_API(glDepthRangef, zNear, zFar);
}
void API_ENTRY(glFramebufferRenderbuffer)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
{
CALL_GL_API(glFramebufferRenderbuffer, target, attachment, renderbuffertarget, renderbuffer);
}
void API_ENTRY(glFramebufferTexture2D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
{
CALL_GL_API(glFramebufferTexture2D, target, attachment, textarget, texture, level);
}
void glGenerateMipmap(GLenum target)
{
//CALL_GL_API(glGenerateMipmap, target);
LOGD("agl2: glGenerateMipmap not implemented");
}
void API_ENTRY(glGenFramebuffers)(GLsizei n, GLuint* framebuffers)
{
CALL_GL_API(glGenFramebuffers, n, framebuffers);
}
void API_ENTRY(glGenRenderbuffers)(GLsizei n, GLuint* renderbuffers)
{
CALL_GL_API(glGenRenderbuffers, n, renderbuffers);
}
void API_ENTRY(glGetActiveAttrib)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
{
CALL_GL_API(glGetActiveAttrib, program, index, bufsize, length, size, type, name);
}
void API_ENTRY(glGetActiveUniform)(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
{
CALL_GL_API(glGetActiveUniform, program, index, bufsize, length, size, type, name);
}
void API_ENTRY(glGetAttachedShaders)(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
{
CALL_GL_API(glGetAttachedShaders, program, maxcount, count, shaders);
}
void API_ENTRY(glGetBooleanv)(GLenum pname, GLboolean* params)
{
CALL_GL_API(glGetBooleanv, pname, params);
}
void API_ENTRY(glGetBufferParameteriv)(GLenum target, GLenum pname, GLint* params)
{
CALL_GL_API(glGetBufferParameteriv, target, pname, params);
}
GLenum glGetError(void)
{
puts("agl2: glGetError");
return GL_NO_ERROR;
//CALL_GL_API_RETURN(glGetError);
}
void API_ENTRY(glGetFloatv)(GLenum pname, GLfloat* params)
{
CALL_GL_API(glGetFloatv, pname, params);
}
void API_ENTRY(glGetFramebufferAttachmentParameteriv)(GLenum target, GLenum attachment, GLenum pname, GLint* params)
{
CALL_GL_API(glGetFramebufferAttachmentParameteriv, target, attachment, pname, params);
}
void API_ENTRY(glGetRenderbufferParameteriv)(GLenum target, GLenum pname, GLint* params)
{
CALL_GL_API(glGetRenderbufferParameteriv, target, pname, params);
}
void API_ENTRY(glGetShaderPrecisionFormat)(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
{
CALL_GL_API(glGetShaderPrecisionFormat, shadertype, precisiontype, range, precision);
}
void API_ENTRY(glGetShaderSource)(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
{
CALL_GL_API(glGetShaderSource, shader, bufsize, length, source);
}
void API_ENTRY(glGetUniformfv)(GLuint program, GLint location, GLfloat* params)
{
CALL_GL_API(glGetUniformfv, program, location, params);
}
void API_ENTRY(glGetUniformiv)(GLuint program, GLint location, GLint* params)
{
CALL_GL_API(glGetUniformiv, program, location, params);
}
void API_ENTRY(glGetVertexAttribfv)(GLuint index, GLenum pname, GLfloat* params)
{
CALL_GL_API(glGetVertexAttribfv, index, pname, params);
}
void API_ENTRY(glGetVertexAttribiv)(GLuint index, GLenum pname, GLint* params)
{
CALL_GL_API(glGetVertexAttribiv, index, pname, params);
}
void API_ENTRY(glGetVertexAttribPointerv)(GLuint index, GLenum pname, GLvoid** pointer)
{
CALL_GL_API(glGetVertexAttribPointerv, index, pname, pointer);
}
GLboolean API_ENTRY(glIsBuffer)(GLuint buffer)
{
CALL_GL_API_RETURN(glIsBuffer, buffer);
}
GLboolean API_ENTRY(glIsEnabled)(GLenum cap)
{
CALL_GL_API_RETURN(glIsEnabled, cap);
}
GLboolean API_ENTRY(glIsFramebuffer)(GLuint framebuffer)
{
CALL_GL_API_RETURN(glIsFramebuffer, framebuffer);
}
GLboolean API_ENTRY(glIsProgram)(GLuint program)
{
CALL_GL_API_RETURN(glIsProgram, program);
}
GLboolean API_ENTRY(glIsRenderbuffer)(GLuint renderbuffer)
{
CALL_GL_API_RETURN(glIsRenderbuffer, renderbuffer);
}
GLboolean API_ENTRY(glIsShader)(GLuint shader)
{
CALL_GL_API_RETURN(glIsShader, shader);
}
void API_ENTRY(glLineWidth)(GLfloat width)
{
CALL_GL_API(glLineWidth, width);
}
void API_ENTRY(glPolygonOffset)(GLfloat factor, GLfloat units)
{
CALL_GL_API(glPolygonOffset, factor, units);
}
void API_ENTRY(glReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
{
CALL_GL_API(glReadPixels, x, y, width, height, format, type, pixels);
}
void API_ENTRY(glReleaseShaderCompiler)(void)
{
CALL_GL_API(glReleaseShaderCompiler);
}
void API_ENTRY(glRenderbufferStorage)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
{
CALL_GL_API(glRenderbufferStorage, target, internalformat, width, height);
}
void API_ENTRY(glSampleCoverage)(GLclampf value, GLboolean invert)
{
CALL_GL_API(glSampleCoverage, value, invert);
}
void API_ENTRY(glShaderBinary)(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
{
CALL_GL_API(glShaderBinary, n, shaders, binaryformat, binary, length);
}
void API_ENTRY(glStencilFunc)(GLenum func, GLint ref, GLuint mask)
{
CALL_GL_API(glStencilFunc, func, ref, mask);
}
void API_ENTRY(glStencilFuncSeparate)(GLenum face, GLenum func, GLint ref, GLuint mask)
{
CALL_GL_API(glStencilFuncSeparate, face, func, ref, mask);
}
void API_ENTRY(glStencilMask)(GLuint mask)
{
CALL_GL_API(glStencilMask, mask);
}
void API_ENTRY(glStencilMaskSeparate)(GLenum face, GLuint mask)
{
CALL_GL_API(glStencilMaskSeparate, face, mask);
}
void API_ENTRY(glStencilOp)(GLenum fail, GLenum zfail, GLenum zpass)
{
CALL_GL_API(glStencilOp, fail, zfail, zpass);
}
void API_ENTRY(glStencilOpSeparate)(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
{
CALL_GL_API(glStencilOpSeparate, face, fail, zfail, zpass);
}
void API_ENTRY(glUniform1fv)(GLint location, GLsizei count, const GLfloat* v)
{
CALL_GL_API(glUniform1fv, location, count, v);
}
void API_ENTRY(glUniform1iv)(GLint location, GLsizei count, const GLint* v)
{
CALL_GL_API(glUniform1iv, location, count, v);
}
void API_ENTRY(glUniform2fv)(GLint location, GLsizei count, const GLfloat* v)
{
CALL_GL_API(glUniform2fv, location, count, v);
}
void API_ENTRY(glUniform2i)(GLint location, GLint x, GLint y)
{
CALL_GL_API(glUniform2i, location, x, y);
}
void API_ENTRY(glUniform2iv)(GLint location, GLsizei count, const GLint* v)
{
CALL_GL_API(glUniform2iv, location, count, v);
}
void API_ENTRY(glUniform3f)(GLint location, GLfloat x, GLfloat y, GLfloat z)
{
CALL_GL_API(glUniform3f, location, x, y, z);
}
void API_ENTRY(glUniform3fv)(GLint location, GLsizei count, const GLfloat* v)
{
CALL_GL_API(glUniform3fv, location, count, v);
}
void API_ENTRY(glUniform3i)(GLint location, GLint x, GLint y, GLint z)
{
CALL_GL_API(glUniform3i, location, x, y, z);
}
void API_ENTRY(glUniform3iv)(GLint location, GLsizei count, const GLint* v)
{
CALL_GL_API(glUniform3iv, location, count, v);
}
void API_ENTRY(glUniform4fv)(GLint location, GLsizei count, const GLfloat* v)
{
CALL_GL_API(glUniform4fv, location, count, v);
}
void API_ENTRY(glUniform4i)(GLint location, GLint x, GLint y, GLint z, GLint w)
{
CALL_GL_API(glUniform4i, location, x, y, z, w);
}
void API_ENTRY(glUniform4iv)(GLint location, GLsizei count, const GLint* v)
{
CALL_GL_API(glUniform4iv, location, count, v);
}
void API_ENTRY(glUniformMatrix2fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
{
CALL_GL_API(glUniformMatrix2fv, location, count, transpose, value);
}
void API_ENTRY(glUniformMatrix3fv)(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
{
CALL_GL_API(glUniformMatrix3fv, location, count, transpose, value);
}
void API_ENTRY(glValidateProgram)(GLuint program)
{
CALL_GL_API(glValidateProgram, program);
}

2232
opengl/libagl2/src/egl.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,79 @@
#include "gles2context.h"
static char const * const gVendorString = "Android";
static char const * const gRendererString = "Android PixelFlinger2 0.0";
static char const * const gVersionString = "OpenGL ES 2.0";
static char const * const gExtensionsString =
// "GL_OES_byte_coordinates " // OK
// "GL_OES_fixed_point " // OK
// "GL_OES_single_precision " // OK
// "GL_OES_read_format " // OK
// "GL_OES_compressed_paletted_texture " // OK
// "GL_OES_draw_texture " // OK
// "GL_OES_matrix_get " // OK
// "GL_OES_query_matrix " // OK
// // "GL_OES_point_size_array " // TODO
// // "GL_OES_point_sprite " // TODO
// "GL_OES_EGL_image " // OK
//#ifdef GL_OES_compressed_ETC1_RGB8_texture
// "GL_OES_compressed_ETC1_RGB8_texture " // OK
//#endif
// "GL_ARB_texture_compression " // OK
// "GL_ARB_texture_non_power_of_two " // OK
// "GL_ANDROID_user_clip_plane " // OK
// "GL_ANDROID_vertex_buffer_object " // OK
// "GL_ANDROID_generate_mipmap " // OK
""
;
void glGetIntegerv(GLenum pname, GLint* params)
{
switch (pname) {
case GL_MAX_TEXTURE_SIZE :
*params = 4096; // limit is in precision of texcoord calculation, which uses 16.16
break;
case GL_MAX_VERTEX_ATTRIBS:
*params = GGL_MAXVERTEXATTRIBS;
break;
case GL_MAX_VERTEX_UNIFORM_VECTORS:
*params = GGL_MAXVERTEXUNIFORMVECTORS;
break;
case GL_MAX_VARYING_VECTORS:
*params = GGL_MAXVARYINGVECTORS;
break;
case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
*params = GGL_MAXCOMBINEDTEXTUREIMAGEUNITS;
break;
case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
*params = GGL_MAXVERTEXTEXTUREIMAGEUNITS;
break;
case GL_MAX_TEXTURE_IMAGE_UNITS:
*params = GGL_MAXTEXTUREIMAGEUNITS;
break;
case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
*params = GGL_MAXFRAGMENTUNIFORMVECTORS;
break;
case GL_ALIASED_LINE_WIDTH_RANGE:
*params = 1; // TODO: not implemented
break;
default:
LOGD("agl2: glGetIntegerv 0x%.4X", pname);
assert(0);
}
}
const GLubyte* glGetString(GLenum name)
{
switch (name) {
case GL_VENDOR:
return (const GLubyte*)gVendorString;
case GL_RENDERER:
return (const GLubyte*)gRendererString;
case GL_VERSION:
return (const GLubyte*)gVersionString;
case GL_EXTENSIONS:
return (const GLubyte*)gExtensionsString;
}
assert(0); //(c, GL_INVALID_ENUM);
return 0;
}

View File

@ -0,0 +1,166 @@
#define _SIZE_T_DEFINED_
typedef unsigned int size_t;
#include <stdio.h>
#include <stdlib.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES/gl.h>
#include <GLES/glext.h>
#include <utils/threads.h>
#include <pthread.h>
#include <cutils/log.h>
#include <assert.h>
#ifdef __arm__
#ifndef __location__
#define __HIERALLOC_STRING_0__(s) #s
#define __HIERALLOC_STRING_1__(s) __HIERALLOC_STRING_0__(s)
#define __HIERALLOC_STRING_2__ __HIERALLOC_STRING_1__(__LINE__)
#define __location__ __FILE__ ":" __HIERALLOC_STRING_2__
#endif
#undef assert
#define assert(EXPR) { do { if (!(EXPR)) {LOGD("\n*\n*\n*\n* assert fail: '"#EXPR"' at "__location__"\n*\n*\n*\n*"); exit(EXIT_FAILURE); } } while (false); }
//#define printf LOGD
#else // #ifdef __arm__
//#define LOGD printf
#endif // #ifdef __arm__
#include <pixelflinger2/pixelflinger2_format.h>
#include <pixelflinger2/pixelflinger2.h>
#include <map>
typedef uint8_t GGLubyte; // ub
#define ggl_likely(x) __builtin_expect(!!(x), 1)
#define ggl_unlikely(x) __builtin_expect(!!(x), 0)
#undef NELEM
#define NELEM(x) (sizeof(x)/sizeof(*(x)))
template<typename T>
inline T max(T a, T b)
{
return a<b ? b : a;
}
template<typename T>
inline T min(T a, T b)
{
return a<b ? a : b;
}
struct egl_context_t {
enum {
IS_CURRENT = 0x00010000,
NEVER_CURRENT = 0x00020000
};
uint32_t flags;
EGLDisplay dpy;
EGLConfig config;
EGLSurface read;
EGLSurface draw;
unsigned frame;
clock_t lastSwapTime;
float accumulateSeconds;
static inline egl_context_t* context(EGLContext ctx);
};
struct GLES2Context;
#ifdef HAVE_ANDROID_OS
#include <bionic_tls.h>
// We have a dedicated TLS slot in bionic
inline void setGlThreadSpecific(GLES2Context *value)
{
((uint32_t *)__get_tls())[TLS_SLOT_OPENGL] = (uint32_t)value;
}
inline GLES2Context* getGlThreadSpecific()
{
return (GLES2Context *)(((unsigned *)__get_tls())[TLS_SLOT_OPENGL]);
}
#else
extern pthread_key_t gGLKey;
inline void setGlThreadSpecific(GLES2Context *value)
{
pthread_setspecific(gGLKey, value);
}
inline GLES2Context* getGlThreadSpecific()
{
return static_cast<GLES2Context*>(pthread_getspecific(gGLKey));
}
#endif
struct VBO {
unsigned size;
GLenum usage;
void * data;
};
struct GLES2Context {
GGLContext rasterizer;
egl_context_t egl;
GGLInterface * iface; // shortcut to &rasterizer.interface
struct VertexState {
struct VertAttribPointer {
unsigned size; // number of values per vertex
GLenum type; // data type
unsigned stride; // bytes
const void * ptr;
bool normalized :
1;
bool enabled :
1;
} attribs [GGL_MAXVERTEXATTRIBS];
VBO * vbo, * indices;
std::map<GLuint, VBO *> vbos;
GLuint free;
Vector4 defaultAttribs [GGL_MAXVERTEXATTRIBS];
} vert;
struct TextureState {
GGLTexture * tmus[GGL_MAXCOMBINEDTEXTUREIMAGEUNITS];
int sampler2tmu[GGL_MAXCOMBINEDTEXTUREIMAGEUNITS]; // sampler2tmu[sampler] is index of tmu, -1 means not used
unsigned active;
std::map<GLuint, GGLTexture *> textures;
GLuint free; // first possible free name
GGLTexture * tex2D, * texCube; // default textures
unsigned unpack;
void UpdateSampler(GGLInterface * iface, unsigned tmu);
} tex;
GLES2Context();
void InitializeTextures();
void InitializeVertices();
~GLES2Context();
void UninitializeTextures();
void UninitializeVertices();
static inline GLES2Context* get() {
return getGlThreadSpecific();
}
};
inline egl_context_t* egl_context_t::context(EGLContext ctx)
{
GLES2Context* const gl = static_cast<GLES2Context*>(ctx);
return static_cast<egl_context_t*>(&gl->egl);
}
#define GLES2_GET_CONTEXT(ctx) GLES2Context * ctx = GLES2Context::get(); \
/*puts(__FUNCTION__);*/
#define GLES2_GET_CONST_CONTEXT(ctx) GLES2Context * ctx = GLES2Context::get(); \
/*puts(__FUNCTION__);*/

View File

@ -0,0 +1,191 @@
#include "gles2context.h"
//#undef LOGD
//#define LOGD(...)
static inline GLuint s2n(gl_shader * s)
{
return (GLuint)s ^ 0xaf3c532d;
}
static inline gl_shader * n2s(GLuint n)
{
return (gl_shader *)(n ^ 0xaf3c532d);
}
static inline GLuint p2n(gl_shader_program * p)
{
return (GLuint)p ^ 0x04dc18f9;
}
static inline gl_shader_program * n2p(GLuint n)
{
return (gl_shader_program *)(n ^ 0x04dc18f9);
}
void glAttachShader(GLuint program, GLuint shader)
{
GLES2_GET_CONST_CONTEXT(ctx);
ctx->iface->ShaderAttach(ctx->iface, n2p(program), n2s(shader));
}
void glBindAttribLocation(GLuint program, GLuint index, const GLchar* name)
{
GLES2_GET_CONST_CONTEXT(ctx);
ctx->iface->ShaderAttributeBind(n2p(program), index, name);
// assert(0);
}
GLuint glCreateShader(GLenum type)
{
GLES2_GET_CONST_CONTEXT(ctx);
return s2n(ctx->iface->ShaderCreate(ctx->iface, type));
}
GLuint glCreateProgram(void)
{
GLES2_GET_CONST_CONTEXT(ctx);
return p2n(ctx->iface->ShaderProgramCreate(ctx->iface));
}
void glCompileShader(GLuint shader)
{
GLES2_GET_CONST_CONTEXT(ctx);
ctx->iface->ShaderCompile(ctx->iface, n2s(shader), NULL, NULL);
}
void glDeleteProgram(GLuint program)
{
GLES2_GET_CONST_CONTEXT(ctx);
ctx->iface->ShaderProgramDelete(ctx->iface, n2p(program));
}
void glDeleteShader(GLuint shader)
{
GLES2_GET_CONST_CONTEXT(ctx);
ctx->iface->ShaderDelete(ctx->iface, n2s(shader));
}
void glDetachShader(GLuint program, GLuint shader)
{
GLES2_GET_CONST_CONTEXT(ctx);
ctx->iface->ShaderDetach(ctx->iface, n2p(program), n2s(shader));
}
GLint glGetAttribLocation(GLuint program, const GLchar* name)
{
GLES2_GET_CONST_CONTEXT(ctx);
GLint location = ctx->iface->ShaderAttributeLocation(n2p(program), name);
// LOGD("\n*\n*\n* agl2: glGetAttribLocation program=%u name=%s location=%d \n*\n*",
// program, name, location);
return location;
}
void glGetProgramiv(GLuint program, GLenum pname, GLint* params)
{
GLES2_GET_CONST_CONTEXT(ctx);
ctx->iface->ShaderProgramGetiv(n2p(program), pname, params);
LOGD("agl2: glGetProgramiv 0x%.4X=%d \n", pname, *params);
}
void glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
{
GLES2_GET_CONST_CONTEXT(ctx);
ctx->iface->ShaderProgramGetInfoLog(n2p(program), bufsize, length, infolog);
}
void glGetShaderiv(GLuint shader, GLenum pname, GLint* params)
{
GLES2_GET_CONST_CONTEXT(ctx);
ctx->iface->ShaderGetiv(n2s(shader), pname, params);
LOGD("agl2: glGetShaderiv 0x%.4X=%d \n", pname, *params);
}
void glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
{
GLES2_GET_CONST_CONTEXT(ctx);
ctx->iface->ShaderGetInfoLog(n2s(shader), bufsize, length, infolog);
}
int glGetUniformLocation(GLuint program, const GLchar* name)
{
GLES2_GET_CONST_CONTEXT(ctx);
return ctx->iface->ShaderUniformLocation(n2p(program), name);
}
void glLinkProgram(GLuint program)
{
GLES2_GET_CONST_CONTEXT(ctx);
GLboolean linked = ctx->iface->ShaderProgramLink(n2p(program), NULL);
assert(linked);
}
void glShaderSource(GLuint shader, GLsizei count, const GLchar** string, const GLint* length)
{
GLES2_GET_CONST_CONTEXT(ctx);
ctx->iface->ShaderSource(n2s(shader), count, string, length);
}
void glUniform1f(GLint location, GLfloat x)
{
GLES2_GET_CONST_CONTEXT(ctx);
int sampler = ctx->iface->ShaderUniform(ctx->rasterizer.CurrentProgram, location, 1, &x, GL_FLOAT);
assert(0 > sampler); // should be assigning to sampler
}
void glUniform1i(GLint location, GLint x)
{
GLES2_GET_CONST_CONTEXT(ctx);
const float params[1] = {x};
int sampler = ctx->iface->ShaderUniform(ctx->rasterizer.CurrentProgram, location, 1, params, GL_INT);
if (0 <= sampler) {
// LOGD("\n*\n* agl2: glUniform1i updated sampler=%d tmu=%d location=%d\n*", sampler, x, location);
assert(0 <= x && GGL_MAXCOMBINEDTEXTUREIMAGEUNITS > x);
// LOGD("tmu%u: format=0x%.2X w=%u h=%u levels=%p", x, ctx->tex.tmus[x]->format,
// ctx->tex.tmus[x]->width, ctx->tex.tmus[x]->height, ctx->tex.tmus[x]->format);
ctx->tex.sampler2tmu[sampler] = x;
ctx->tex.UpdateSampler(ctx->iface, x);
}
}
void glUniform2f(GLint location, GLfloat x, GLfloat y)
{
GLES2_GET_CONST_CONTEXT(ctx);
const float params[4] = {x, y};
ctx->iface->ShaderUniform(ctx->rasterizer.CurrentProgram, location, 1, params, GL_FLOAT_VEC2);
}
void glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
{
GLES2_GET_CONST_CONTEXT(ctx);
const float params[4] = {x, y, z, w};
// LOGD("agl2: glUniform4f location=%d %f,%f,%f,%f", location, x, y, z, w);
ctx->iface->ShaderUniform(ctx->rasterizer.CurrentProgram, location, 1, params, GL_FLOAT_VEC4);
}
void glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
{
GLES2_GET_CONST_CONTEXT(ctx);
// const gl_shader_program * program = ctx->rasterizer.CurrentProgram;
// if (strstr(program->Shaders[MESA_SHADER_FRAGMENT]->Source, ").a;")) {
// LOGD("agl2: glUniformMatrix4fv location=%d count=%d transpose=%d", location, count, transpose);
// for (unsigned i = 0; i < 4; i++)
// LOGD("agl2: glUniformMatrix4fv %.2f \t %.2f \t %.2f \t %.2f", value[i * 4 + 0],
// value[i * 4 + 1], value[i * 4 + 2], value[i * 4 + 3]);
// }
ctx->iface->ShaderUniformMatrix(ctx->rasterizer.CurrentProgram, 4, 4, location, count, transpose, value);
// while (true)
// ;
// assert(0);
}
void glUseProgram(GLuint program)
{
GLES2_GET_CONST_CONTEXT(ctx);
// LOGD("\n*\n*\n* agl2: glUseProgram %d \n*\n*\n*", program);
ctx->iface->ShaderUse(ctx->iface, n2p(program));
ctx->iface->ShaderUniformGetSamplers(n2p(program), ctx->tex.sampler2tmu);
for (unsigned i = 0; i < GGL_MAXCOMBINEDTEXTUREIMAGEUNITS; i++)
if (0 <= ctx->tex.sampler2tmu[i])
ctx->iface->SetSampler(ctx->iface, i, ctx->tex.tmus[ctx->tex.sampler2tmu[i]]);
}

View File

@ -0,0 +1,129 @@
#include "gles2context.h"
GLES2Context::GLES2Context()
{
memset(this, 0, sizeof *this);
assert((void *)&rasterizer == &rasterizer.interface);
InitializeGGLState(&rasterizer.interface);
iface = &rasterizer.interface;
printf("gl->rasterizer.PickScanLine(%p) = %p \n", &rasterizer.PickScanLine, rasterizer.PickScanLine);
assert(rasterizer.PickRaster);
assert(rasterizer.PickScanLine);
InitializeTextures();
InitializeVertices();
}
GLES2Context::~GLES2Context()
{
UninitializeTextures();
UninitializeVertices();
UninitializeGGLState(&rasterizer.interface);
}
void glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
{
GLES2_GET_CONST_CONTEXT(ctx);
ctx->iface->BlendColor(ctx->iface, red, green, blue, alpha);
}
void glBlendEquation( GLenum mode )
{
GLES2_GET_CONST_CONTEXT(ctx);
ctx->iface->BlendEquationSeparate(ctx->iface, mode, mode);
}
void glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
{
GLES2_GET_CONST_CONTEXT(ctx);
ctx->iface->BlendEquationSeparate(ctx->iface, modeRGB, modeAlpha);
}
void glBlendFunc(GLenum sfactor, GLenum dfactor)
{
GLES2_GET_CONST_CONTEXT(ctx);
ctx->iface->BlendFuncSeparate(ctx->iface, sfactor, dfactor, sfactor, dfactor);
}
void glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
{
GLES2_GET_CONST_CONTEXT(ctx);
ctx->iface->BlendFuncSeparate(ctx->iface, srcRGB, dstRGB, srcAlpha, dstAlpha);
}
void glClear(GLbitfield mask)
{
GLES2_GET_CONST_CONTEXT(ctx);
ctx->iface->Clear(ctx->iface, mask);
}
void glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
{
GLES2_GET_CONST_CONTEXT(ctx);
ctx->iface->ClearColor(ctx->iface, red, green, blue, alpha);
}
void glClearDepthf(GLclampf depth)
{
GLES2_GET_CONST_CONTEXT(ctx);
ctx->iface->ClearDepthf(ctx->iface, depth);
}
void glClearStencil(GLint s)
{
GLES2_GET_CONST_CONTEXT(ctx);
ctx->iface->ClearStencil(ctx->iface, s);
}
void glCullFace(GLenum mode)
{
GLES2_GET_CONST_CONTEXT(ctx);
ctx->iface->CullFace(ctx->iface, mode);
}
void glDisable(GLenum cap)
{
GLES2_GET_CONST_CONTEXT(ctx);
ctx->iface->EnableDisable(ctx->iface, cap, false);
}
void glEnable(GLenum cap)
{
GLES2_GET_CONST_CONTEXT(ctx);
ctx->iface->EnableDisable(ctx->iface, cap, true);
}
void glFinish(void)
{
// do nothing
}
void glFrontFace(GLenum mode)
{
GLES2_GET_CONST_CONTEXT(ctx);
ctx->iface->FrontFace(ctx->iface, mode);
}
void glFlush(void)
{
// do nothing
}
void glHint(GLenum target, GLenum mode)
{
// do nothing
}
void glScissor(GLint x, GLint y, GLsizei width, GLsizei height)
{
// LOGD("agl2: glScissor not implemented x=%d y=%d width=%d height=%d", x, y, width, height);
//CALL_GL_API(glScissor, x, y, width, height);
}
void glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
{
GLES2_GET_CONST_CONTEXT(ctx);
// LOGD("agl2: glViewport x=%d y=%d width=%d height=%d", x, y, width, height);
ctx->iface->Viewport(ctx->iface, x, y, width, height);
}

View File

@ -0,0 +1,534 @@
#include "gles2context.h"
//#undef LOGD
//#define LOGD(...)
#define API_ENTRY
#define CALL_GL_API(NAME,...) LOGD("?"#NAME); assert(0);
#define CALL_GL_API_RETURN(NAME,...) LOGD("?"#NAME); assert(0); return 0;
static inline GGLTexture * AllocTexture()
{
GGLTexture * tex = (GGLTexture *)calloc(1, sizeof(GGLTexture));
tex->minFilter = GGLTexture::GGL_LINEAR; // should be NEAREST_ MIPMAP_LINEAR
tex->magFilter = GGLTexture::GGL_LINEAR;
return tex;
}
void GLES2Context::InitializeTextures()
{
tex.textures = std::map<GLuint, GGLTexture *>(); // the entire struct has been zeroed in constructor
tex.tex2D = AllocTexture();
tex.textures[GL_TEXTURE_2D] = tex.tex2D;
tex.texCube = AllocTexture();
tex.textures[GL_TEXTURE_CUBE_MAP] = tex.texCube;
for (unsigned i = 0; i < GGL_MAXCOMBINEDTEXTUREIMAGEUNITS; i++) {
tex.tmus[i] = NULL;
tex.sampler2tmu[i] = NULL;
}
tex.active = 0;
tex.free = max(GL_TEXTURE_2D, GL_TEXTURE_CUBE_MAP) + 1;
tex.tex2D->format = GGL_PIXEL_FORMAT_RGBA_8888;
tex.tex2D->type = GL_TEXTURE_2D;
tex.tex2D->levelCount = 1;
tex.tex2D->wrapS = tex.tex2D->wrapT = GGLTexture::GGL_REPEAT;
tex.tex2D->minFilter = tex.tex2D->magFilter = GGLTexture::GGL_NEAREST;
tex.tex2D->width = tex.tex2D->height = 1;
tex.tex2D->levels = malloc(4);
*(unsigned *)tex.tex2D->levels = 0xff000000;
tex.texCube->format = GGL_PIXEL_FORMAT_RGBA_8888;
tex.texCube->type = GL_TEXTURE_CUBE_MAP;
tex.texCube->levelCount = 1;
tex.texCube->wrapS = tex.texCube->wrapT = GGLTexture::GGL_REPEAT;
tex.texCube->minFilter = tex.texCube->magFilter = GGLTexture::GGL_NEAREST;
tex.texCube->width = tex.texCube->height = 1;
tex.texCube->levels = malloc(4 * 6);
static unsigned texels [6] = {0xff0000ff, 0xff00ff00, 0xffff0000,
0xff00ffff, 0xffffff00, 0xffff00ff
};
memcpy(tex.texCube->levels, texels, sizeof texels);
//texture.levelCount = GenerateMipmaps(texture.levels, texture.width, texture.height);
// static unsigned texels [6] = {0xff0000ff, 0xff00ff00, 0xffff0000,
// 0xff00ffff, 0xffffff00, 0xffff00ff};
// memcpy(texture.levels[0], texels, sizeof texels);
// texture.format = GGL_PIXEL_FORMAT_RGBA_8888;
// texture.width = texture.height = 1;
//texture.height /= 6;
//texture.type = GL_TEXTURE_CUBE_MAP;
tex.unpack = 4;
}
void GLES2Context::TextureState::UpdateSampler(GGLInterface * iface, unsigned tmu)
{
for (unsigned i = 0; i < GGL_MAXCOMBINEDTEXTUREIMAGEUNITS; i++)
if (tmu == sampler2tmu[i])
iface->SetSampler(iface, i, tmus[tmu]);
}
void GLES2Context::UninitializeTextures()
{
for (std::map<GLuint, GGLTexture *>::iterator it = tex.textures.begin(); it != tex.textures.end(); it++) {
if (!it->second)
continue;
free(it->second->levels);
free(it->second);
}
}
static inline void GetFormatAndBytesPerPixel(const GLenum format, unsigned * bytesPerPixel,
GGLPixelFormat * texFormat)
{
switch (format) {
case GL_ALPHA:
*texFormat = GGL_PIXEL_FORMAT_A_8;
*bytesPerPixel = 1;
break;
case GL_LUMINANCE:
*texFormat = GGL_PIXEL_FORMAT_L_8;
*bytesPerPixel = 1;
break;
case GL_LUMINANCE_ALPHA:
*texFormat = GGL_PIXEL_FORMAT_LA_88;
*bytesPerPixel = 2;
break;
case GL_RGB:
*texFormat = GGL_PIXEL_FORMAT_RGB_888;
*bytesPerPixel = 3;
break;
case GL_RGBA:
*texFormat = GGL_PIXEL_FORMAT_RGBA_8888;
*bytesPerPixel = 4;
break;
// internal formats to avoid conversion
case GL_UNSIGNED_SHORT_5_6_5:
*texFormat = GGL_PIXEL_FORMAT_RGB_565;
*bytesPerPixel = 2;
break;
default:
assert(0);
return;
}
}
static inline void CopyTexture(char * dst, const char * src, const unsigned bytesPerPixel,
const unsigned sx, const unsigned sy, const unsigned sw,
const unsigned dx, const unsigned dy, const unsigned dw,
const unsigned w, const unsigned h)
{
const unsigned bpp = bytesPerPixel;
if (dw == sw && dw == w && sx == 0 && dx == 0)
memcpy(dst + dy * dw * bpp, src + sy * sw * bpp, w * h * bpp);
else
for (unsigned y = 0; y < h; y++)
memcpy(dst + ((dy + y) * dw + dx) * bpp, src + ((sy + y) * sw + sx) * bpp, w * bpp);
}
void glActiveTexture(GLenum texture)
{
GLES2_GET_CONST_CONTEXT(ctx);
unsigned index = texture - GL_TEXTURE0;
assert(NELEM(ctx->tex.tmus) > index);
// LOGD("agl2: glActiveTexture %u", index);
ctx->tex.active = index;
}
void glBindTexture(GLenum target, GLuint texture)
{
GLES2_GET_CONST_CONTEXT(ctx);
// LOGD("agl2: glBindTexture target=0x%.4X texture=%u active=%u", target, texture, ctx->tex.active);
std::map<GLuint, GGLTexture *>::iterator it = ctx->tex.textures.find(texture);
GGLTexture * tex = NULL;
if (it != ctx->tex.textures.end()) {
tex = it->second;
if (!tex) {
tex = AllocTexture();
tex->type = target;
it->second = tex;
// LOGD("agl2: glBindTexture allocTexture");
}
// else
// LOGD("agl2: glBindTexture bind existing texture");
assert(target == tex->type);
} else if (0 == texture) {
if (GL_TEXTURE_2D == target)
{
tex = ctx->tex.tex2D;
// LOGD("agl2: glBindTexture bind default tex2D");
}
else if (GL_TEXTURE_CUBE_MAP == target)
{
tex = ctx->tex.texCube;
// LOGD("agl2: glBindTexture bind default texCube");
}
else
assert(0);
} else {
if (texture <= ctx->tex.free)
ctx->tex.free = texture + 1;
tex = AllocTexture();
tex->type = target;
ctx->tex.textures[texture] = tex;
// LOGD("agl2: glBindTexture new texture=%u", texture);
}
ctx->tex.tmus[ctx->tex.active] = tex;
// LOGD("agl2: glBindTexture format=0x%.2X w=%u h=%u levels=%p", tex->format,
// tex->width, tex->height, tex->levels);
ctx->tex.UpdateSampler(ctx->iface, ctx->tex.active);
}
void API_ENTRY(glCompressedTexImage2D)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data)
{
CALL_GL_API(glCompressedTexImage2D, target, level, internalformat, width, height, border, imageSize, data);
}
void API_ENTRY(glCompressedTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data)
{
CALL_GL_API(glCompressedTexSubImage2D, target, level, xoffset, yoffset, width, height, format, imageSize, data);
}
void glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat,
GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
{
GLES2_GET_CONST_CONTEXT(ctx);
// LOGD("agl2: glCopyTexImage2D target=0x%.4X internalformat=0x%.4X", target, internalformat);
// LOGD("x=%d y=%d width=%d height=%d border=%d level=%d ", x, y, width, height, border, level);
assert(0 == border);
assert(0 == level);
unsigned bytesPerPixel = 0;
GGLPixelFormat texFormat = GGL_PIXEL_FORMAT_UNKNOWN;
GetFormatAndBytesPerPixel(internalformat, &bytesPerPixel, &texFormat);
assert(texFormat == ctx->rasterizer.frameSurface.format);
// LOGD("texFormat=0x%.2X bytesPerPixel=%d \n", texFormat, bytesPerPixel);
unsigned offset = 0, size = width * height * bytesPerPixel, totalSize = size;
assert(ctx->tex.tmus[ctx->tex.active]);
assert(y + height <= ctx->rasterizer.frameSurface.height);
assert(x + width <= ctx->rasterizer.frameSurface.width);
GGLTexture & tex = *ctx->tex.tmus[ctx->tex.active];
tex.width = width;
tex.height = height;
tex.levelCount = 1;
tex.format = texFormat;
switch (target) {
case GL_TEXTURE_2D:
tex.levels = realloc(tex.levels, totalSize);
CopyTexture((char *)tex.levels, (const char *)ctx->rasterizer.frameSurface.data, bytesPerPixel,
x, y, ctx->rasterizer.frameSurface.width, 0, 0, width, width, height);
break;
default:
assert(0);
return;
}
ctx->tex.UpdateSampler(ctx->iface, ctx->tex.active);
}
void glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
{
// x, y are src offset
// xoffset and yoffset are dst offset
GLES2_GET_CONST_CONTEXT(ctx);
// LOGD("agl2: glCopyTexSubImage2D target=0x%.4X level=%d", target, level);
// LOGD("xoffset=%d yoffset=%d x=%d y=%d width=%d height=%d", xoffset, yoffset, x, y, width, height);
assert(0 == level);
unsigned bytesPerPixel = 4;
unsigned offset = 0, size = width * height * bytesPerPixel, totalSize = size;
assert(ctx->tex.tmus[ctx->tex.active]);
GGLTexture & tex = *ctx->tex.tmus[ctx->tex.active];
assert(tex.format == ctx->rasterizer.frameSurface.format);
assert(GGL_PIXEL_FORMAT_RGBA_8888 == tex.format);
const unsigned srcWidth = ctx->rasterizer.frameSurface.width;
const unsigned srcHeight = ctx->rasterizer.frameSurface.height;
assert(x >= 0 && y >= 0);
assert(xoffset >= 0 && yoffset >= 0);
assert(x + width <= srcWidth);
assert(y + height <= srcHeight);
assert(xoffset + width <= tex.width);
assert(yoffset + height <= tex.height);
switch (target) {
case GL_TEXTURE_2D:
CopyTexture((char *)tex.levels, (const char *)ctx->rasterizer.frameSurface.data, bytesPerPixel,
x, y, srcWidth, xoffset, yoffset, tex.width, width, height);
break;
default:
assert(0);
return;
}
ctx->tex.UpdateSampler(ctx->iface, ctx->tex.active);
}
void glDeleteTextures(GLsizei n, const GLuint* textures)
{
GLES2_GET_CONST_CONTEXT(ctx);
for (unsigned i = 0; i < n; i++) {
std::map<GLuint, GGLTexture *>::iterator it = ctx->tex.textures.find(textures[i]);
if (it == ctx->tex.textures.end())
continue;
ctx->tex.free = min(ctx->tex.free, textures[i]);
for (unsigned i = 0; i < GGL_MAXCOMBINEDTEXTUREIMAGEUNITS; i++)
if (ctx->tex.tmus[i] == it->second) {
if (GL_TEXTURE_2D == it->second->type)
ctx->tex.tmus[i] = ctx->tex.tex2D;
else if (GL_TEXTURE_CUBE_MAP == it->second->type)
ctx->tex.tmus[i] = ctx->tex.texCube;
else
assert(0);
ctx->tex.UpdateSampler(ctx->iface, i);
}
if (it->second) {
free(it->second->levels);
free(it->second);
}
ctx->tex.textures.erase(it);
}
}
void glGenTextures(GLsizei n, GLuint* textures)
{
GLES2_GET_CONST_CONTEXT(ctx);
for (unsigned i = 0; i < n; i++) {
textures[i] = 0;
for (ctx->tex.free; ctx->tex.free < 0xffffffffu; ctx->tex.free++)
if (ctx->tex.textures.find(ctx->tex.free) == ctx->tex.textures.end()) {
ctx->tex.textures[ctx->tex.free] = NULL;
textures[i] = ctx->tex.free;
ctx->tex.free++;
break;
}
assert(textures[i]);
}
}
void API_ENTRY(glGetTexParameterfv)(GLenum target, GLenum pname, GLfloat* params)
{
CALL_GL_API(glGetTexParameterfv, target, pname, params);
}
void API_ENTRY(glGetTexParameteriv)(GLenum target, GLenum pname, GLint* params)
{
CALL_GL_API(glGetTexParameteriv, target, pname, params);
}
GLboolean glIsTexture(GLuint texture)
{
GLES2_GET_CONST_CONTEXT(ctx);
if (ctx->tex.textures.find(texture) == ctx->tex.textures.end())
return GL_FALSE;
else
return GL_TRUE;
}
void glPixelStorei(GLenum pname, GLint param)
{
GLES2_GET_CONST_CONTEXT(ctx);
assert(GL_UNPACK_ALIGNMENT == pname);
assert(1 == param || 2 == param || 4 == param || 8 == param);
// LOGD("\n*\n* agl2: glPixelStorei not implemented pname=0x%.4X param=%d \n*", pname, param);
ctx->tex.unpack = param;
// CALL_GL_API(glPixelStorei, pname, param);
}
void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width,
GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels)
{
GLES2_GET_CONST_CONTEXT(ctx);
// LOGD("agl2: glTexImage2D internalformat=0x%.4X format=0x%.4X type=0x%.4X \n", internalformat, format, type);
// LOGD("width=%d height=%d border=%d level=%d pixels=%p \n", width, height, border, level, pixels);
switch (type) {
case GL_UNSIGNED_BYTE:
break;
case GL_UNSIGNED_SHORT_5_6_5:
internalformat = format = GL_UNSIGNED_SHORT_5_6_5;
assert(4 == ctx->tex.unpack);
break;
default:
assert(0);
}
assert(internalformat == format);
assert(0 == border);
if (0 != level) {
LOGD("agl2: glTexImage2D level=%d", level);
return;
}
unsigned bytesPerPixel = 0;
GGLPixelFormat texFormat = GGL_PIXEL_FORMAT_UNKNOWN;
GetFormatAndBytesPerPixel(format, &bytesPerPixel, &texFormat);
assert(texFormat && bytesPerPixel);
// LOGD("texFormat=0x%.2X bytesPerPixel=%d active=%u", texFormat, bytesPerPixel, ctx->tex.active);
unsigned offset = 0, size = width * height * bytesPerPixel, totalSize = size;
assert(ctx->tex.tmus[ctx->tex.active]);
GGLTexture & tex = *ctx->tex.tmus[ctx->tex.active];
tex.width = width;
tex.height = height;
tex.levelCount = 1;
tex.format = texFormat;
switch (target) {
case GL_TEXTURE_2D:
assert(GL_TEXTURE_2D == ctx->tex.tmus[ctx->tex.active]->type);
offset = 0;
break;
break;
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
assert(GL_TEXTURE_CUBE_MAP == ctx->tex.tmus[ctx->tex.active]->type);
assert(width == height);
offset = (target - GL_TEXTURE_CUBE_MAP_POSITIVE_X) * size;
totalSize = 6 * size;
break;
default:
assert(0);
return;
}
tex.levels = realloc(tex.levels, totalSize);
if (pixels)
CopyTexture((char *)tex.levels, (const char *)pixels, bytesPerPixel, 0, 0, width, 0, 0, width, width, height);
ctx->tex.UpdateSampler(ctx->iface, ctx->tex.active);
}
void glTexParameterf(GLenum target, GLenum pname, GLfloat param)
{
// LOGD("agl2: glTexParameterf target=0x%.4X pname=0x%.4X param=%f", target, pname, param);
glTexParameteri(target, pname, param);
}
void API_ENTRY(glTexParameterfv)(GLenum target, GLenum pname, const GLfloat* params)
{
CALL_GL_API(glTexParameterfv, target, pname, params);
}
void glTexParameteri(GLenum target, GLenum pname, GLint param)
{
GLES2_GET_CONST_CONTEXT(ctx);
// LOGD("alg2: glTexParameteri target=0x%.0X pname=0x%.4X param=0x%.4X",
// target, pname, param);
assert(ctx->tex.tmus[ctx->tex.active]);
assert(target == ctx->tex.tmus[ctx->tex.active]->type);
GGLTexture & tex = *ctx->tex.tmus[ctx->tex.active];
switch (pname) {
case GL_TEXTURE_WRAP_S:
case GL_TEXTURE_WRAP_T:
GGLTexture::GGLTextureWrap wrap;
switch (param) {
case GL_REPEAT:
wrap = GGLTexture::GGL_REPEAT;
break;
case GL_CLAMP_TO_EDGE:
wrap = GGLTexture::GGL_CLAMP_TO_EDGE;
break;
case GL_MIRRORED_REPEAT:
wrap = GGLTexture::GGL_MIRRORED_REPEAT;
break;
default:
assert(0);
return;
}
if (GL_TEXTURE_WRAP_S == pname)
tex.wrapS = wrap;
else
tex.wrapT = wrap;
break;
case GL_TEXTURE_MIN_FILTER:
switch (param) {
case GL_NEAREST:
tex.minFilter = GGLTexture::GGL_NEAREST;
break;
case GL_LINEAR:
tex.minFilter = GGLTexture::GGL_LINEAR;
break;
case GL_NEAREST_MIPMAP_NEAREST:
// tex.minFilter = GGLTexture::GGL_NEAREST_MIPMAP_NEAREST;
break;
case GL_NEAREST_MIPMAP_LINEAR:
// tex.minFilter = GGLTexture::GGL_NEAREST_MIPMAP_LINEAR;
break;
case GL_LINEAR_MIPMAP_NEAREST:
// tex.minFilter = GGLTexture::GGL_LINEAR_MIPMAP_NEAREST;
break;
case GL_LINEAR_MIPMAP_LINEAR:
// tex.minFilter = GGLTexture::GGL_LINEAR_MIPMAP_LINEAR;
break;
default:
assert(0);
return;
}
break;
case GL_TEXTURE_MAG_FILTER:
switch (param) {
case GL_NEAREST:
tex.minFilter = GGLTexture::GGL_NEAREST;
break;
case GL_LINEAR:
tex.minFilter = GGLTexture::GGL_LINEAR;
break;
default:
assert(0);
return;
}
break;
default:
assert(0);
return;
}
// implementation restriction
if (tex.magFilter != tex.minFilter)
tex.magFilter = tex.minFilter = GGLTexture::GGL_LINEAR;
ctx->tex.UpdateSampler(ctx->iface, ctx->tex.active);
}
void API_ENTRY(glTexParameteriv)(GLenum target, GLenum pname, const GLint* params)
{
CALL_GL_API(glTexParameteriv, target, pname, params);
}
void glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels)
{
GLES2_GET_CONST_CONTEXT(ctx);
// LOGD("agl2: glTexSubImage2D target=0x%.4X level=%d xoffset=%d yoffset=%d width=%d height=%d format=0x%.4X type=0x%.4X pixels=%p",
// target, level, xoffset, yoffset, width, height, format, type, pixels);
assert(0 == level);
assert(target == ctx->tex.tmus[ctx->tex.active]->type);
switch (type) {
case GL_UNSIGNED_BYTE:
break;
case GL_UNSIGNED_SHORT_5_6_5:
format = GL_UNSIGNED_SHORT_5_6_5;
assert(4 == ctx->tex.unpack);
break;
default:
assert(0);
}
GGLTexture & tex = *ctx->tex.tmus[ctx->tex.active];
GGLPixelFormat texFormat = GGL_PIXEL_FORMAT_UNKNOWN;
unsigned bytesPerPixel = 0;
GetFormatAndBytesPerPixel(format, &bytesPerPixel, &texFormat);
assert(texFormat == tex.format);
assert(GL_UNSIGNED_BYTE == type);
switch (target) {
case GL_TEXTURE_2D:
CopyTexture((char *)tex.levels, (const char *)pixels, bytesPerPixel, 0, 0, width, xoffset,
yoffset, tex.width, width, height);
break;
default:
assert(0);
}
ctx->tex.UpdateSampler(ctx->iface, ctx->tex.active);
}

View File

@ -0,0 +1,373 @@
#include "gles2context.h"
//#undef LOGD
//#define LOGD(...)
void GLES2Context::InitializeVertices()
{
vert.vbos = std::map<GLuint, VBO *>(); // the entire struct has been zeroed in constructor
vert.free = 1;
vert.vbo = NULL;
vert.indices = NULL;
for (unsigned i = 0; i < GGL_MAXVERTEXATTRIBS; i++)
vert.defaultAttribs[i] = Vector4(0,0,0,1);
}
void GLES2Context::UninitializeVertices()
{
for (std::map<GLuint, VBO *>::iterator it = vert.vbos.begin(); it != vert.vbos.end(); it++) {
if (!it->second)
continue;
free(it->second->data);
free(it->second);
}
}
static inline void FetchElement(const GLES2Context * ctx, const unsigned index,
const unsigned maxAttrib, VertexInput * elem)
{
for (unsigned i = 0; i < maxAttrib; i++) {
{
unsigned size = 0;
if (ctx->vert.attribs[i].enabled) {
const char * ptr = (const char *)ctx->vert.attribs[i].ptr;
ptr += ctx->vert.attribs[i].stride * index;
memcpy(elem->attributes + i, ptr, ctx->vert.attribs[i].size * sizeof(float));
size = ctx->vert.attribs[i].size;
// LOGD("agl2: FetchElement %d attribs size=%d %.2f,%.2f,%.2f,%.2f", i, size, elem->attributes[i].x,
// elem->attributes[i].y, elem->attributes[i].z, elem->attributes[i].w);
} else {
// LOGD("agl2: FetchElement %d default %.2f,%.2f,%.2f,%.2f", i, ctx->vert.defaultAttribs[i].x,
// ctx->vert.defaultAttribs[i].y, ctx->vert.defaultAttribs[i].z, ctx->vert.defaultAttribs[i].w);
}
switch (size) {
case 0: // fall through
elem->attributes[i].x = ctx->vert.defaultAttribs[i].x;
case 1: // fall through
elem->attributes[i].y = ctx->vert.defaultAttribs[i].y;
case 2: // fall through
elem->attributes[i].z = ctx->vert.defaultAttribs[i].z;
case 3: // fall through
elem->attributes[i].w = ctx->vert.defaultAttribs[i].w;
case 4:
break;
default:
assert(0);
break;
}
// LOGD("agl2: FetchElement %d size=%d %.2f,%.2f,%.2f,%.2f", i, size, elem->attributes[i].x,
// elem->attributes[i].y, elem->attributes[i].z, elem->attributes[i].w);
}
}
}
template<typename IndexT> static void DrawElementsTriangles(const GLES2Context * ctx,
const unsigned count, const IndexT * indices, const unsigned maxAttrib)
{
VertexInput v[3];
if (ctx->vert.indices)
indices = (IndexT *)((char *)ctx->vert.indices->data + (long)indices);
for (unsigned i = 0; i < count; i += 3) {
for (unsigned j = 0; j < 3; j++)
FetchElement(ctx, indices[i + j], maxAttrib, v + j);
ctx->iface->DrawTriangle(ctx->iface, v, v + 1, v + 2);
}
}
static void DrawArraysTriangles(const GLES2Context * ctx, const unsigned first,
const unsigned count, const unsigned maxAttrib)
{
// LOGD("agl: DrawArraysTriangles=%p", DrawArraysTriangles);
VertexInput v[3];
for (unsigned i = 2; i < count; i+=3) {
// TODO: fix order
FetchElement(ctx, first + i - 2, maxAttrib, v + 0);
FetchElement(ctx, first + i - 1, maxAttrib, v + 1);
FetchElement(ctx, first + i - 0, maxAttrib, v + 2);
ctx->iface->DrawTriangle(ctx->iface, v + 0, v + 1, v + 2);
}
// LOGD("agl: DrawArraysTriangles end");
}
template<typename IndexT> static void DrawElementsTriangleStrip(const GLES2Context * ctx,
const unsigned count, const IndexT * indices, const unsigned maxAttrib)
{
VertexInput v[3];
if (ctx->vert.indices)
indices = (IndexT *)((char *)ctx->vert.indices->data + (long)indices);
// LOGD("agl2: DrawElementsTriangleStrip");
// for (unsigned i = 0; i < count; i++)
// LOGD("indices[%d] = %d", i, indices[i]);
FetchElement(ctx, indices[0], maxAttrib, v + 0);
FetchElement(ctx, indices[1], maxAttrib, v + 1);
for (unsigned i = 2; i < count; i ++) {
FetchElement(ctx, indices[i], maxAttrib, v + i % 3);
ctx->iface->DrawTriangle(ctx->iface, v + (i - 2) % 3, v + (i - 1) % 3 , v + (i + 0) % 3);
}
// for (unsigned i = 2; i < count; i++) {
// FetchElement(ctx, indices[i - 2], maxAttrib, v + 0);
// FetchElement(ctx, indices[i - 1], maxAttrib, v + 1);
// FetchElement(ctx, indices[i - 0], maxAttrib, v + 2);
// ctx->iface->DrawTriangle(ctx->iface, v + 0, v + 1, v + 2);
// }
}
static void DrawArraysTriangleStrip(const GLES2Context * ctx, const unsigned first,
const unsigned count, const unsigned maxAttrib)
{
VertexInput v[3];
FetchElement(ctx, first, maxAttrib, v + 0);
FetchElement(ctx, first + 1, maxAttrib, v + 1);
for (unsigned i = 2; i < count; i++) {
// TODO: fix order
FetchElement(ctx, first + i, maxAttrib, v + i % 3);
ctx->iface->DrawTriangle(ctx->iface, v + (i - 2) % 3, v + (i - 1) % 3 , v + (i + 0) % 3);
}
}
void glBindBuffer(GLenum target, GLuint buffer)
{
GLES2_GET_CONST_CONTEXT(ctx);
VBO * vbo = NULL;
if (0 != buffer) {
std::map<GLuint, VBO *>::iterator it = ctx->vert.vbos.find(buffer);
if (it != ctx->vert.vbos.end()) {
vbo = it->second;
if (!vbo)
vbo = (VBO *)calloc(1, sizeof(VBO));
it->second = vbo;
} else
assert(0);
}
if (GL_ARRAY_BUFFER == target)
ctx->vert.vbo = vbo;
else if (GL_ELEMENT_ARRAY_BUFFER == target)
ctx->vert.indices = vbo;
else
assert(0);
assert(vbo || buffer == 0);
// LOGD("\n*\n glBindBuffer 0x%.4X=%d ", target, buffer);
}
void glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
{
GLES2_GET_CONST_CONTEXT(ctx);
if (GL_ARRAY_BUFFER == target) {
assert(ctx->vert.vbo);
ctx->vert.vbo->data = realloc(ctx->vert.vbo->data, size);
ctx->vert.vbo->size = size;
ctx->vert.vbo->usage = usage;
if (data)
memcpy(ctx->vert.vbo->data, data, size);
} else if (GL_ELEMENT_ARRAY_BUFFER == target) {
assert(ctx->vert.indices);
ctx->vert.indices->data = realloc(ctx->vert.indices->data, size);
ctx->vert.indices->size = size;
ctx->vert.indices->usage = usage;
if (data)
memcpy(ctx->vert.indices->data, data, size);
} else
assert(0);
// LOGD("\n*\n glBufferData target=0x%.4X size=%u data=%p usage=0x%.4X \n",
// target, size, data, usage);
}
void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)
{
GLES2_GET_CONST_CONTEXT(ctx);
if (GL_ARRAY_BUFFER == target)
{
assert(ctx->vert.vbo);
assert(0 <= offset);
assert(0 <= size);
assert(offset + size <= ctx->vert.vbo->size);
memcpy((char *)ctx->vert.vbo->data + offset, data, size);
}
else
assert(0);
}
void glDeleteBuffers(GLsizei n, const GLuint* buffers)
{
GLES2_GET_CONST_CONTEXT(ctx);
for (unsigned i = 0; i < n; i++) {
std::map<GLuint, VBO*>::iterator it = ctx->vert.vbos.find(buffers[i]);
if (it == ctx->vert.vbos.end())
continue;
ctx->vert.free = min(ctx->vert.free, buffers[i]);
if (it->second == ctx->vert.vbo)
ctx->vert.vbo = NULL;
else if (it->second == ctx->vert.indices)
ctx->vert.indices = NULL;
if (it->second) {
free(it->second->data);
free(it->second);
}
}
}
void glDisableVertexAttribArray(GLuint index)
{
GLES2_GET_CONST_CONTEXT(ctx);
assert(GGL_MAXVERTEXATTRIBS > index);
ctx->vert.attribs[index].enabled = false;
}
void glDrawArrays(GLenum mode, GLint first, GLsizei count)
{
GLES2_GET_CONST_CONTEXT(ctx);
// LOGD("agl2: glDrawArrays=%p", glDrawArrays);
assert(ctx->rasterizer.CurrentProgram);
assert(0 <= first);
int maxAttrib = -1;
ctx->iface->ShaderProgramGetiv(ctx->rasterizer.CurrentProgram, GL_ACTIVE_ATTRIBUTES, &maxAttrib);
assert(0 <= maxAttrib && GGL_MAXVERTEXATTRIBS >= maxAttrib);
switch (mode) {
case GL_TRIANGLE_STRIP:
DrawArraysTriangleStrip(ctx, first, count, maxAttrib);
break;
case GL_TRIANGLES:
DrawArraysTriangles(ctx, first, count, maxAttrib);
break;
default:
LOGE("agl2: glDrawArrays unsupported mode: 0x%.4X \n", mode);
assert(0);
break;
}
// LOGD("agl2: glDrawArrays end");
}
void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
{
GLES2_GET_CONST_CONTEXT(ctx);
// LOGD("agl2: glDrawElements=%p mode=0x%.4X count=%d type=0x%.4X indices=%p",
// glDrawElements, mode, count, type, indices);
if (!ctx->rasterizer.CurrentProgram)
return;
int maxAttrib = -1;
ctx->iface->ShaderProgramGetiv(ctx->rasterizer.CurrentProgram, GL_ACTIVE_ATTRIBUTES, &maxAttrib);
assert(0 <= maxAttrib && GGL_MAXVERTEXATTRIBS >= maxAttrib);
// LOGD("agl2: glDrawElements mode=0x%.4X type=0x%.4X count=%d program=%p indices=%p \n",
// mode, type, count, ctx->rasterizer.CurrentProgram, indices);
switch (mode) {
case GL_TRIANGLES:
if (GL_UNSIGNED_SHORT == type)
DrawElementsTriangles<unsigned short>(ctx, count, (unsigned short *)indices, maxAttrib);
else
assert(0);
break;
case GL_TRIANGLE_STRIP:
if (GL_UNSIGNED_SHORT == type)
DrawElementsTriangleStrip<unsigned short>(ctx, count, (unsigned short *)indices, maxAttrib);
else
assert(0);
break;
default:
assert(0);
}
// LOGD("agl2: glDrawElements end");
}
void glEnableVertexAttribArray(GLuint index)
{
GLES2_GET_CONST_CONTEXT(ctx);
ctx->vert.attribs[index].enabled = true;
// LOGD("agl2: glEnableVertexAttribArray %d \n", index);
}
void glGenBuffers(GLsizei n, GLuint* buffers)
{
GLES2_GET_CONST_CONTEXT(ctx);
for (unsigned i = 0; i < n; i++) {
buffers[i] = 0;
for (ctx->vert.free; ctx->vert.free < 0xffffffffu; ctx->vert.free++) {
if (ctx->vert.vbos.find(ctx->vert.free) == ctx->vert.vbos.end()) {
ctx->vert.vbos[ctx->vert.free] = NULL;
buffers[i] = ctx->vert.free;
// LOGD("glGenBuffers %d \n", buffers[i]);
ctx->vert.free++;
break;
}
}
assert(buffers[i]);
}
}
void glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized,
GLsizei stride, const GLvoid* ptr)
{
GLES2_GET_CONST_CONTEXT(ctx);
assert(GL_FLOAT == type);
assert(0 < size && 4 >= size);
ctx->vert.attribs[index].size = size;
ctx->vert.attribs[index].type = type;
ctx->vert.attribs[index].normalized = normalized;
if (0 == stride)
ctx->vert.attribs[index].stride = size * sizeof(float);
else if (stride > 0)
ctx->vert.attribs[index].stride = stride;
else
assert(0);
// LOGD("\n*\n*\n* agl2: glVertexAttribPointer program=%u index=%d size=%d stride=%d ptr=%p \n*\n*",
// unsigned(ctx->rasterizer.CurrentProgram) ^ 0x04dc18f9, index, size, stride, ptr);
if (ctx->vert.vbo)
ctx->vert.attribs[index].ptr = (char *)ctx->vert.vbo->data + (long)ptr;
else
ctx->vert.attribs[index].ptr = ptr;
// const float * attrib = (const float *)ctx->vert.attribs[index].ptr;
// for (unsigned i = 0; i < 3; i++)
// if (3 == size)
// LOGD("%.2f %.2f %.2f", attrib[i * 3 + 0], attrib[i * 3 + 1], attrib[i * 3 + 2]);
// else if (2 == size)
// LOGD("%.2f %.2f", attrib[i * 3 + 0], attrib[i * 3 + 1]);
}
void glVertexAttrib1f(GLuint indx, GLfloat x)
{
glVertexAttrib4f(indx, x,0,0,1);
}
void glVertexAttrib1fv(GLuint indx, const GLfloat* values)
{
glVertexAttrib4f(indx, values[0],0,0,1);
}
void glVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y)
{
glVertexAttrib4f(indx, x,y,0,1);
}
void glVertexAttrib2fv(GLuint indx, const GLfloat* values)
{
glVertexAttrib4f(indx, values[0],values[1],0,1);
}
void glVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z)
{
glVertexAttrib4f(indx, x,y,z,1);
}
void glVertexAttrib3fv(GLuint indx, const GLfloat* values)
{
glVertexAttrib4f(indx, values[0],values[1],values[2],1);
}
void glVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
{
assert(GGL_MAXVERTEXATTRIBS > indx);
GLES2_GET_CONST_CONTEXT(ctx);
// LOGD("\n*\n*\n agl2: glVertexAttrib4f %d %.2f,%.2f,%.2f,%.2f \n*\n*", indx, x, y, z, w);
ctx->vert.defaultAttribs[indx] = Vector4(x,y,z,w);
assert(0);
}
void glVertexAttrib4fv(GLuint indx, const GLfloat* values)
{
glVertexAttrib4f(indx, values[0], values[1], values[2], values[3]);
}