From 9dc2c20e8c7ac91d932b12492591b65786e24b0f Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Fri, 17 Oct 2014 23:49:10 +0300 Subject: [PATCH] Support OpenGL ES on Android Some features are still likely to be broken, but basic rendering works at least. --- Build | 13 ++- extensions/ext_unpack_subimage.glext | 1 + extensions/msp_draw_buffer.glext | 1 + extensions/msp_legacy_features.glext | 1 + extensions/msp_sized_internal_formats.glext | 1 + extensions/msp_stereo_rendering.glext | 1 + extensions/msp_texture1d.glext | 1 + extensions/nv_non_square_matrices.glext | 1 + gl.fixes.xml | 104 +++++++++++++++++++- source/batch.cpp | 5 + source/extension.cpp | 22 ++++- source/extension.h | 10 ++ source/framebuffer.cpp | 6 +- source/framebuffer.h | 1 + source/gl.h | 10 +- source/light.cpp | 3 + source/lighting.cpp | 2 + source/lightunit.cpp | 3 +- source/material.cpp | 3 + source/matrix.cpp | 3 + source/pixelformat.h | 2 + source/pixelstore.cpp | 3 + source/primitivetype.cpp | 6 ++ source/primitivetype.h | 3 + source/program.cpp | 1 + source/programbuilder.cpp | 19 +++- source/texture1d.cpp | 5 +- source/vertexarray.cpp | 3 + 28 files changed, 220 insertions(+), 14 deletions(-) create mode 100644 extensions/ext_unpack_subimage.glext create mode 100644 extensions/msp_draw_buffer.glext create mode 100644 extensions/msp_legacy_features.glext create mode 100644 extensions/msp_sized_internal_formats.glext create mode 100644 extensions/msp_stereo_rendering.glext create mode 100644 extensions/msp_texture1d.glext create mode 100644 extensions/nv_non_square_matrices.glext diff --git a/Build b/Build index 162e26ca..a20d21cc 100644 --- a/Build +++ b/Build @@ -7,7 +7,14 @@ package "mspgl" require "mspdatafile"; require "mspmath"; require "mspgui"; - require "opengl"; + if_arch "android" + { + require "opengles"; + }; + if_arch "!android" + { + require "opengl"; + }; generate "GLEX" { @@ -15,6 +22,10 @@ package "mspgl" out_suffix ".cpp"; out_suffix ".h"; command "scripts/extgen.py"; + if_arch "android" + { + argument "gles2"; + }; }; library "mspgl" diff --git a/extensions/ext_unpack_subimage.glext b/extensions/ext_unpack_subimage.glext new file mode 100644 index 00000000..c366e604 --- /dev/null +++ b/extensions/ext_unpack_subimage.glext @@ -0,0 +1 @@ +extension EXT_unpack_subimage diff --git a/extensions/msp_draw_buffer.glext b/extensions/msp_draw_buffer.glext new file mode 100644 index 00000000..1c52cfdb --- /dev/null +++ b/extensions/msp_draw_buffer.glext @@ -0,0 +1 @@ +extension MSP_draw_buffer diff --git a/extensions/msp_legacy_features.glext b/extensions/msp_legacy_features.glext new file mode 100644 index 00000000..7128081d --- /dev/null +++ b/extensions/msp_legacy_features.glext @@ -0,0 +1 @@ +extension MSP_legacy_features diff --git a/extensions/msp_sized_internal_formats.glext b/extensions/msp_sized_internal_formats.glext new file mode 100644 index 00000000..23438c77 --- /dev/null +++ b/extensions/msp_sized_internal_formats.glext @@ -0,0 +1 @@ +extension MSP_sized_internal_formats diff --git a/extensions/msp_stereo_rendering.glext b/extensions/msp_stereo_rendering.glext new file mode 100644 index 00000000..cf278f14 --- /dev/null +++ b/extensions/msp_stereo_rendering.glext @@ -0,0 +1 @@ +extension MSP_stereo_rendering diff --git a/extensions/msp_texture1d.glext b/extensions/msp_texture1d.glext new file mode 100644 index 00000000..00cd9120 --- /dev/null +++ b/extensions/msp_texture1d.glext @@ -0,0 +1 @@ +extension MSP_texture1D diff --git a/extensions/nv_non_square_matrices.glext b/extensions/nv_non_square_matrices.glext new file mode 100644 index 00000000..9833f47d --- /dev/null +++ b/extensions/nv_non_square_matrices.glext @@ -0,0 +1 @@ +extension NV_non_square_matrices diff --git a/gl.fixes.xml b/gl.fixes.xml index 5f97fa3c..c6459cf3 100644 --- a/gl.fixes.xml +++ b/gl.fixes.xml @@ -58,7 +58,13 @@ - + + + + + + + @@ -83,5 +89,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/source/batch.cpp b/source/batch.cpp index 3cb0a6ce..859a6ad5 100644 --- a/source/batch.cpp +++ b/source/batch.cpp @@ -1,4 +1,5 @@ #include +#include #include #include "batch.h" #include "bindable.h" @@ -59,6 +60,10 @@ Batch::Batch(PrimitiveType t): max_index(0), restart(false) { + /* Make sure we have glEnable/DisableClientState to go with + NV_primitive_restart */ + if(NV_primitive_restart) + (bool)MSP_legacy_features; } Batch::~Batch() diff --git a/source/extension.cpp b/source/extension.cpp index efa4b1a2..023510da 100644 --- a/source/extension.cpp +++ b/source/extension.cpp @@ -1,5 +1,8 @@ #include -#if !defined(WIN32) && !defined(__APPLE__) +#include +#if defined(__ANDROID__) +#include +#elif !defined(WIN32) && !defined(__APPLE__) #define GLX_GLXEXT_PROTOTYPES #include #endif @@ -105,9 +108,21 @@ bool is_supported(const string &ext) return extensions.count(ext); } +GLApi get_gl_api() +{ +#ifdef GL_ES_VERSION_2_0 + return OPENGL_ES2; +#else + return OPENGL; +#endif +} + inline Version _get_gl_version() { string gl_ver = reinterpret_cast(glGetString(GL_VERSION)); + if(!gl_ver.compare(0, 10, "OpenGL ES ")) + gl_ver.erase(0, 10); + Version ver(gl_ver.substr(0, gl_ver.find(' '))); if(const char *force_ver_ptr = getenv("MSPGL_FORCE_VERSION")) @@ -129,6 +144,9 @@ const Version &get_gl_version() inline Version _get_glsl_version() { string glsl_ver = reinterpret_cast(glGetString(GL_SHADING_LANGUAGE_VERSION)); + if(!glsl_ver.compare(0, 18, "OpenGL ES GLSL ES ")) + glsl_ver.erase(0, 18); + Version ver(glsl_ver.substr(0, glsl_ver.find(' '))); if(const char *force_ver_ptr = getenv("MSPGL_FORCE_GLSL_VERSION")) @@ -159,6 +177,8 @@ ExtFunc *get_proc_address(const string &name) #elif defined(__APPLE__) (void)name; return 0; // Not supported +#elif defined(__ANDROID__) + return eglGetProcAddress(name.c_str()); #else return glXGetProcAddressARB(reinterpret_cast(name.c_str())); #endif diff --git a/source/extension.h b/source/extension.h index e0fe3eff..671e4af9 100644 --- a/source/extension.h +++ b/source/extension.h @@ -6,6 +6,13 @@ namespace Msp { namespace GL { +enum GLApi +{ + OPENGL, + OPENGL_ES2 +}; + + struct Version { unsigned short major; @@ -56,6 +63,9 @@ typedef void ExtFunc(); /** Indicates whether an extension is supported. */ bool is_supported(const std::string &); +/** Returns the API for which the library was compiled. */ +GLApi get_gl_api(); + /** Returns the OpenGL version number, as reported by the implementation. */ const Version &get_gl_version(); diff --git a/source/framebuffer.cpp b/source/framebuffer.cpp index f4e5a944..1c2ae519 100644 --- a/source/framebuffer.cpp +++ b/source/framebuffer.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include "error.h" #include "framebuffer.h" #include "misc.h" @@ -115,10 +116,11 @@ void Framebuffer::update_attachment(unsigned mask) const GLenum first_buffer = (color_bufs.empty() ? GL_NONE : color_bufs.front()); if(ARB_draw_buffers) glDrawBuffers(color_bufs.size(), &color_bufs[0]); - else + else if(MSP_draw_buffer) glDrawBuffer(first_buffer); - glReadBuffer(first_buffer); + if(MSP_draw_buffer) + glReadBuffer(first_buffer); } else dirty |= mask; diff --git a/source/framebuffer.h b/source/framebuffer.h index 07cae867..ab91d9e7 100644 --- a/source/framebuffer.h +++ b/source/framebuffer.h @@ -6,6 +6,7 @@ #include "gl.h" #include "texturecube.h" #include +#include namespace Msp { namespace GL { diff --git a/source/gl.h b/source/gl.h index 255242bf..ae145457 100644 --- a/source/gl.h +++ b/source/gl.h @@ -1,15 +1,19 @@ #ifndef MSP_GL_GL_H_ #define MSP_GL_GL_H_ -#ifdef WIN32 -#include -#endif #ifdef __APPLE__ #define extern extern __attribute__((weak_import)) #include #include #undef extern +#elif defined(__ANDROID__) +#include +#include +typedef double GLdouble; #else +#ifdef WIN32 +#include +#endif #include #include #endif diff --git a/source/light.cpp b/source/light.cpp index 968bffdf..a3b3d014 100644 --- a/source/light.cpp +++ b/source/light.cpp @@ -1,4 +1,5 @@ #include +#include #include #include "light.h" #include "lightunit.h" @@ -116,6 +117,8 @@ void Light::update_shader_data(ProgramData &shdata, const Matrix &view_matrix, u void Light::bind_to(unsigned i) const { + static Require _req(MSP_legacy_features); + LightUnit &unit = LightUnit::get_unit(i); if(unit.set_light(this)) { diff --git a/source/lighting.cpp b/source/lighting.cpp index 7f662c72..d1fd9a70 100644 --- a/source/lighting.cpp +++ b/source/lighting.cpp @@ -1,4 +1,5 @@ #include +#include #include "error.h" #include "light.h" #include "lighting.h" @@ -71,6 +72,7 @@ void Lighting::update_shader_data(ProgramData &shdata, const Matrix &view_matrix void Lighting::bind() const { + static Require _req(MSP_legacy_features); if(lights.size()>LightUnit::get_n_units()) throw invalid_operation("Lighting::bind"); diff --git a/source/lightunit.cpp b/source/lightunit.cpp index d33c9b25..3eb32929 100644 --- a/source/lightunit.cpp +++ b/source/lightunit.cpp @@ -1,4 +1,5 @@ #include +#include #include "gl.h" #include "misc.h" #include "lightunit.h" @@ -24,7 +25,7 @@ bool LightUnit::set_light(const Light *l) unsigned LightUnit::get_n_units() { - static int count = get_i(GL_MAX_LIGHTS); + static int count = (MSP_legacy_features ? get_i(GL_MAX_LIGHTS) : 0); return count; } diff --git a/source/material.cpp b/source/material.cpp index feb97bfa..a2814cff 100644 --- a/source/material.cpp +++ b/source/material.cpp @@ -1,3 +1,4 @@ +#include #include "gl.h" #include "material.h" #include "resources.h" @@ -75,6 +76,8 @@ void Material::set_reflectivity(float r) void Material::bind() const { + static Require _req(MSP_legacy_features); + if(set_current(this)) update_parameter(-1); } diff --git a/source/matrix.cpp b/source/matrix.cpp index 4bf550aa..b05d4bbc 100644 --- a/source/matrix.cpp +++ b/source/matrix.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include "error.h" #include "matrix.h" @@ -195,6 +196,8 @@ void MatrixStack::update() if(!mode) return; + static Require _req(MSP_legacy_features); + if(mode!=current_mode) { glMatrixMode(mode); diff --git a/source/pixelformat.h b/source/pixelformat.h index 6d68bbc1..0fa6609a 100644 --- a/source/pixelformat.h +++ b/source/pixelformat.h @@ -7,6 +7,8 @@ #include #include #include +#include +#include namespace Msp { namespace GL { diff --git a/source/pixelstore.cpp b/source/pixelstore.cpp index 629162cd..e1a7cc0e 100644 --- a/source/pixelstore.cpp +++ b/source/pixelstore.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "gl.h" #include "pixelformat.h" #include "pixelstore.h" @@ -52,6 +53,7 @@ void PixelStore::update_parameter(int mask) const void PixelStore::set_canvas_size(unsigned w, unsigned h) { + static Require _req(EXT_unpack_subimage); row_length = w; image_height = h; update_parameter(SIZE); @@ -59,6 +61,7 @@ void PixelStore::set_canvas_size(unsigned w, unsigned h) void PixelStore::set_origin(unsigned x, unsigned y, unsigned z) { + static Require _req(EXT_unpack_subimage); if(z>0) static Require _req3d(EXT_texture3D); skip_pixels = x; diff --git a/source/primitivetype.cpp b/source/primitivetype.cpp index 98053660..c9a82792 100644 --- a/source/primitivetype.cpp +++ b/source/primitivetype.cpp @@ -28,5 +28,11 @@ void operator>>(const LexicalConverter &conv, PrimitiveType &pt) throw lexical_error(format("conversion of '%s' to PrimitiveType", conv.get())); } +void require_primitive_type(PrimitiveType type) +{ + if(type==QUADS || type==QUAD_STRIP) + static Require _req(MSP_legacy_features); +} + } // namespace GL } // namespace Msp diff --git a/source/primitivetype.h b/source/primitivetype.h index 777558a1..9e65cbf7 100644 --- a/source/primitivetype.h +++ b/source/primitivetype.h @@ -2,6 +2,7 @@ #define MSP_GL_PRIMITIVETYPE_H_ #include +#include #include "gl.h" namespace Msp { @@ -22,6 +23,8 @@ enum PrimitiveType void operator>>(const LexicalConverter &, PrimitiveType &); +void require_primitive_type(PrimitiveType); + } // namespace GL } // namespace Msp diff --git a/source/program.cpp b/source/program.cpp index a4358acb..f56beec7 100644 --- a/source/program.cpp +++ b/source/program.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include "buffer.h" #include "error.h" diff --git a/source/programbuilder.cpp b/source/programbuilder.cpp index 1e8f5577..d8fe22ed 100644 --- a/source/programbuilder.cpp +++ b/source/programbuilder.cpp @@ -345,7 +345,10 @@ void ProgramBuilder::add_shaders(Program &prog) const if(!features.legacy) { - prog.bind_fragment_data(0, "frag_color"); + // OpenGL ES does not support binding fragment shader outputs + if(get_gl_api()!=OPENGL_ES2) + prog.bind_fragment_data(0, "frag_color"); + prog.bind_attribute(VERTEX4, "vertex"); if(features.lighting) prog.bind_attribute(NORMAL3, "normal"); @@ -369,9 +372,17 @@ string ProgramBuilder::create_source(const list &variables, Va if(!features.legacy) { - source += "#version 130\n"; - if(use_blocks) - source += "#extension GL_ARB_uniform_buffer_object: require\n"; + if(get_gl_api()==OPENGL_ES2) + { + if(use_blocks) + source += "#version 300 es\n"; + } + else + { + source += "#version 130\n"; + if(use_blocks) + source += "#extension GL_ARB_uniform_buffer_object: require\n"; + } } set declared_types; diff --git a/source/texture1d.cpp b/source/texture1d.cpp index f700d013..a0876ace 100644 --- a/source/texture1d.cpp +++ b/source/texture1d.cpp @@ -1,3 +1,4 @@ +#include #include "bindable.h" #include "error.h" #include "texture1d.h" @@ -12,7 +13,9 @@ Texture1D::Texture1D(): ifmt(RGB), width(0), allocated(0) -{ } +{ + static Require _req(MSP_texture1D); +} void Texture1D::storage(PixelFormat fmt, unsigned wd) { diff --git a/source/vertexarray.cpp b/source/vertexarray.cpp index db102ab4..5674bbe0 100644 --- a/source/vertexarray.cpp +++ b/source/vertexarray.cpp @@ -1,5 +1,6 @@ #include #include +#include #include "buffer.h" #include "error.h" #include "gl.h" @@ -123,6 +124,8 @@ void VertexArray::apply(bool use_legacy) const if(!use_legacy) static Require _req(ARB_vertex_shader); + else if(legacy) + static Require _req(MSP_legacy_features); const VertexArray *old = current(); /* If the array has been modified, apply it even if it was the last one to -- 2.43.0