diff options
author | piman@google.com <piman@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-08 20:32:40 +0000 |
---|---|---|
committer | piman@google.com <piman@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-08 20:32:40 +0000 |
commit | 177002925b7152b6eafe92912fe922eb823d21c6 (patch) | |
tree | eb6d9268a6d0cddb49d9fba6c707f0f157275878 /o3d | |
parent | a669d57df371e525d2ca93f129c0fdec7f7e76ed (diff) | |
download | chromium_src-177002925b7152b6eafe92912fe922eb823d21c6.zip chromium_src-177002925b7152b6eafe92912fe922eb823d21c6.tar.gz chromium_src-177002925b7152b6eafe92912fe922eb823d21c6.tar.bz2 |
linux: native OpenGL ES support
This includes Gregg's CL 548023
There are still a few hard-coded paths, and issues to solve, but hellocube-textures-glsl is running on an actual device.
Review URL: http://codereview.chromium.org/572029
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@38385 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'o3d')
-rw-r--r-- | o3d/build/common.gypi | 93 | ||||
-rw-r--r-- | o3d/build/libs.gyp | 90 | ||||
-rw-r--r-- | o3d/core/cross/gles2/buffer_gles2.cc | 71 | ||||
-rw-r--r-- | o3d/core/cross/gles2/buffer_gles2.h | 16 | ||||
-rw-r--r-- | o3d/core/cross/gles2/effect_gles2.cc | 13 | ||||
-rw-r--r-- | o3d/core/cross/gles2/gles2_headers.h | 50 | ||||
-rw-r--r-- | o3d/core/cross/gles2/render_surface_gles2.cc | 51 | ||||
-rw-r--r-- | o3d/core/cross/gles2/renderer_gles2.cc | 295 | ||||
-rw-r--r-- | o3d/core/cross/gles2/renderer_gles2.h | 15 | ||||
-rw-r--r-- | o3d/core/cross/gles2/sampler_gles2.cc | 30 | ||||
-rw-r--r-- | o3d/core/cross/gles2/stream_bank_gles2.cc | 3 | ||||
-rw-r--r-- | o3d/core/cross/gles2/texture_gles2.cc | 74 | ||||
-rw-r--r-- | o3d/plugin/cross/o3d_glue.h | 2 | ||||
-rw-r--r-- | o3d/plugin/plugin.gyp | 5 |
14 files changed, 619 insertions, 189 deletions
diff --git a/o3d/build/common.gypi b/o3d/build/common.gypi index 492bd54..ee2324f 100644 --- a/o3d/build/common.gypi +++ b/o3d/build/common.gypi @@ -27,6 +27,7 @@ 'variables': { # If the DEPS file exists two levels up, then we're in a Chrome tree. 'o3d_in_chrome%': '<!(python <(DEPTH)/o3d/build/file_exists.py <(DEPTH)/DEPS)', + 'gles2_backend%': 'desktop_gl', 'conditions' : [ # These have to come first because GYP doesn't like it when # they're part of the same conditional as a conditions clause that @@ -57,6 +58,7 @@ 'o3d_in_chrome%': '<(o3d_in_chrome)', 'renderer%': '<(renderer)', 'cgdir%': '<(cgdir)', + 'gles2_backend%': '<(gles2_backend)', 'swiftshaderdir%': '<(swiftshaderdir)', # We default to building everything only if the assets exist. @@ -88,44 +90,67 @@ }, }], ], - }, - 'conditions' : [ - ['OS == "win"', - { - 'target_defaults': { + 'conditions' : [ + ['renderer == "d3d9"', + { 'defines': [ - '_CRT_SECURE_NO_WARNINGS', - 'OS_WIN', - 'UNICODE', - 'NACL_WINDOWS', - '_X86_', + 'RENDERER_D3D9', + ], + }, + ], + ['renderer == "gl"', + { + 'defines': [ + 'RENDERER_GL', + ], + }, + ], + ['renderer == "gles2"', + { + 'defines': [ + 'RENDERER_GLES2', ], - # Disable warning: "'this' : used in base member initialization list." - 'msvs_disabled_warnings': [4355], 'conditions': [ - ['renderer == "d3d9"', + ['gles2_backend == "desktop_gl"', { 'defines': [ - 'RENDERER_D3D9', + 'GLES2_BACKEND_DESKTOP_GL', ], }, ], - ['renderer == "gl"', + ['gles2_backend == "native_gles2"', { 'defines': [ - 'RENDERER_GL', + 'GLES2_BACKEND_NATIVE_GLES2', ], }, ], - ['renderer == "gles2"', + ['gles2_backend == "gles2_command_buffers"', { 'defines': [ - 'RENDERER_GLES2', + 'GLES2_BACKEND_GLES2_COMMAND_BUFFERS', ], }, ], ], }, + ], + ], + }, + 'conditions' : [ + ['OS == "win"', + { + 'target_defaults': { + 'defines': [ + '_CRT_SECURE_NO_WARNINGS', + 'OS_WIN', + 'UNICODE', + 'NACL_WINDOWS', + '_X86_', + ], + # Disable warning: "'this' : used in base member initialization list." + 'msvs_disabled_warnings': [4355], + }, }, ], ['OS == "mac"', @@ -155,22 +180,6 @@ 'WARNING_CXXFLAGS': ['-Wstrict-aliasing', '-Wno-deprecated',], }, - 'conditions': [ - ['renderer == "gl"', - { - 'defines': [ - 'RENDERER_GL', - ], - }, - ], - ['renderer == "gles2"', - { - 'defines': [ - 'RENDERER_GLES2', - ], - }, - ], - ], }, }, ], @@ -190,22 +199,6 @@ '-fvisibility=hidden', '-Wstrict-aliasing', ], - 'conditions': [ - ['renderer == "gl"', - { - 'defines': [ - 'RENDERER_GL', - ], - }, - ], - ['renderer == "gles2"', - { - 'defines': [ - 'RENDERER_GLES2', - ], - }, - ], - ], }, }, ], diff --git a/o3d/build/libs.gyp b/o3d/build/libs.gyp index fdb1ccf..94f624b 100644 --- a/o3d/build/libs.gyp +++ b/o3d/build/libs.gyp @@ -75,54 +75,74 @@ { 'target_name': 'gles2_libs', 'type': 'none', - 'all_dependent_settings': { - 'include_dirs': [ - '../../<(glewdir)/include', - ], - }, 'conditions': [ - [ 'OS=="linux"', + ['gles2_backend=="desktop_gl"', { 'all_dependent_settings': { - 'defines': [ - 'GL_GLEXT_PROTOTYPES', + 'include_dirs': [ + '../../<(glewdir)/include', ], - 'ldflags': [ - '-L<(PRODUCT_DIR)', + }, + 'conditions': [ + [ 'OS=="linux"', + { + 'all_dependent_settings': { + 'defines': [ + 'GL_GLEXT_PROTOTYPES', + ], + 'ldflags': [ + '-L<(PRODUCT_DIR)', + ], + 'libraries': [ + '-lGL', + '-lGLEW', + '-lX11', + ], + }, + }, ], - 'libraries': [ - '-lGL', - '-lGLEW', - '-lX11', + [ 'OS=="mac"', + { + 'direct_dependent_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/OpenGL.framework', + ], + }, + }, ], - }, - }, - ], - [ 'OS=="mac"', - { - 'direct_dependent_settings': { - 'libraries': [ - '$(SDKROOT)/System/Library/Frameworks/OpenGL.framework', + [ 'OS=="win"', + { + 'all_dependent_settings': { + 'libraries': [ + '-lOpenGL32.lib', + '../../<(glewdir)/lib/glew32.lib', + ], + }, + 'copies': [ + { + 'destination': '<(PRODUCT_DIR)', + 'files': [ + "../../<(glewdir)/bin/glew32.dll", + ] + }, + ], + }, ], - }, + ], }, ], - [ 'OS=="win"', + #['gles2_backend=="gles2_command_buffers"', + # { + # }, + #], + ['gles2_backend=="native_gles2"', { 'all_dependent_settings': { 'libraries': [ - '-lOpenGL32.lib', - '../../<(glewdir)/lib/glew32.lib', + '-lEGL', + '-lGLESv2', ], - }, - 'copies': [ - { - 'destination': '<(PRODUCT_DIR)', - 'files': [ - "../../<(glewdir)/bin/glew32.dll", - ] - }, - ], + } }, ], ], diff --git a/o3d/core/cross/gles2/buffer_gles2.cc b/o3d/core/cross/gles2/buffer_gles2.cc index d8f4bc4..8cd7838 100644 --- a/o3d/core/cross/gles2/buffer_gles2.cc +++ b/o3d/core/cross/gles2/buffer_gles2.cc @@ -48,6 +48,7 @@ namespace o3d { namespace { +#if defined(GLES2_BACKEND_DESKTOP_GL) GLenum BufferAccessModeToGLenum(Buffer::AccessMode access_mode) { switch (access_mode) { case Buffer::READ_ONLY: @@ -62,6 +63,7 @@ GLenum BufferAccessModeToGLenum(Buffer::AccessMode access_mode) { DCHECK(false); return GL_READ_WRITE_ARB; } +#endif } // anonymous namespace @@ -73,6 +75,10 @@ VertexBufferGLES2::VertexBufferGLES2(ServiceLocator* service_locator) : VertexBuffer(service_locator), renderer_(static_cast<RendererGLES2*>( service_locator->GetService<Renderer>())), +#if !defined(GLES2_BACKEND_DESKTOP_GL) + shadow_(NULL), + read_only_(true), +#endif gl_buffer_(0) { DLOG(INFO) << "VertexBufferGLES2 Construct"; } @@ -95,11 +101,15 @@ bool VertexBufferGLES2::ConcreteAllocate(size_t size_in_bytes) { // Give the VBO a size, but no data, and set the hint to "STATIC_DRAW" // to mark the buffer as set up once then used often. - glBindBufferARB(GL_ARRAY_BUFFER_ARB, gl_buffer_); - glBufferDataARB(GL_ARRAY_BUFFER_ARB, + glBindBufferARB(GL_ARRAY_BUFFER, gl_buffer_); + glBufferDataARB(GL_ARRAY_BUFFER, size_in_bytes, NULL, - GL_STATIC_DRAW_ARB); + GL_STATIC_DRAW); + +#if !defined(GLES2_BACKEND_DESKTOP_GL) + shadow_.reset(new char[size_in_bytes]); +#endif CHECK_GL_ERROR(); return true; } @@ -111,6 +121,9 @@ void VertexBufferGLES2::ConcreteFree() { gl_buffer_ = 0; CHECK_GL_ERROR(); } +#if !defined(GLES2_BACKEND_DESKTOP_GL) + shadow_.reset(NULL); +#endif } // Calls Lock on the OpenGLES2 buffer to get the address in memory of where the @@ -119,8 +132,9 @@ bool VertexBufferGLES2::ConcreteLock(Buffer::AccessMode access_mode, void **buffer_data) { DLOG(INFO) << "VertexBufferGLES2 Lock \"" << name() << "\""; renderer_->MakeCurrentLazy(); - glBindBufferARB(GL_ARRAY_BUFFER_ARB, gl_buffer_); - *buffer_data = glMapBufferARB(GL_ARRAY_BUFFER_ARB, + glBindBufferARB(GL_ARRAY_BUFFER, gl_buffer_); +#if defined(GLES2_BACKEND_DESKTOP_GL) + *buffer_data = glMapBufferARB(GL_ARRAY_BUFFER, BufferAccessModeToGLenum(access_mode)); if (*buffer_data == NULL) { GLenum error = glGetError(); @@ -131,6 +145,10 @@ bool VertexBufferGLES2::ConcreteLock(Buffer::AccessMode access_mode, } return false; } +#else + *buffer_data = shadow_.get(); + read_only_ = (access_mode == READ_ONLY); +#endif CHECK_GL_ERROR(); return true; } @@ -140,7 +158,8 @@ bool VertexBufferGLES2::ConcreteLock(Buffer::AccessMode access_mode, bool VertexBufferGLES2::ConcreteUnlock() { DLOG(INFO) << "VertexBufferGLES2 Unlock \"" << name() << "\""; renderer_->MakeCurrentLazy(); - glBindBufferARB(GL_ARRAY_BUFFER_ARB, gl_buffer_); + glBindBufferARB(GL_ARRAY_BUFFER, gl_buffer_); +#if defined(GLES2_BACKEND_DESKTOP_GL) if (!glUnmapBufferARB(GL_ARRAY_BUFFER)) { GLenum error = glGetError(); if (error == GL_INVALID_OPERATION) { @@ -152,6 +171,11 @@ bool VertexBufferGLES2::ConcreteUnlock() { } return false; } +#else + if (!read_only_) { + glBufferSubData(GL_ARRAY_BUFFER, 0, GetSizeInBytes(), shadow_.get()); + } +#endif CHECK_GL_ERROR(); return true; } @@ -166,6 +190,10 @@ IndexBufferGLES2::IndexBufferGLES2(ServiceLocator* service_locator) : IndexBuffer(service_locator), renderer_(static_cast<RendererGLES2*>( service_locator->GetService<Renderer>())), +#if !defined(GLES2_BACKEND_DESKTOP_GL) + shadow_(NULL), + read_only_(true), +#endif gl_buffer_(0) { DLOG(INFO) << "IndexBufferGLES2 Construct"; } @@ -186,11 +214,14 @@ bool IndexBufferGLES2::ConcreteAllocate(size_t size_in_bytes) { if (!gl_buffer_) return false; // Give the VBO a size, but no data, and set the hint to "STATIC_DRAW" // to mark the buffer as set up once then used often. - glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, gl_buffer_); - glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, + glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, gl_buffer_); + glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER, size_in_bytes, NULL, - GL_STATIC_DRAW_ARB); + GL_STATIC_DRAW); +#if !defined(GLES2_BACKEND_DESKTOP_GL) + shadow_.reset(new char[size_in_bytes]); +#endif CHECK_GL_ERROR(); return true; } @@ -202,6 +233,9 @@ void IndexBufferGLES2::ConcreteFree() { gl_buffer_ = 0; CHECK_GL_ERROR(); } +#if !defined(GLES2_BACKEND_DESKTOP_GL) + shadow_.reset(NULL); +#endif } // Maps the OpenGLES2 buffer to get the address in memory of the buffer data. @@ -209,10 +243,11 @@ bool IndexBufferGLES2::ConcreteLock(Buffer::AccessMode access_mode, void **buffer_data) { DLOG(INFO) << "IndexBufferGLES2 Lock \"" << name() << "\""; renderer_->MakeCurrentLazy(); - glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, gl_buffer_); + glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, gl_buffer_); if (!num_elements()) return true; - *buffer_data = glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, +#if defined(GLES2_BACKEND_DESKTOP_GL) + *buffer_data = glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER, BufferAccessModeToGLenum(access_mode)); if (*buffer_data == NULL) { GLenum error = glGetError(); @@ -224,6 +259,10 @@ bool IndexBufferGLES2::ConcreteLock(Buffer::AccessMode access_mode, } return false; } +#else + *buffer_data = shadow_.get(); + read_only_ = (access_mode == READ_ONLY); +#endif CHECK_GL_ERROR(); return true; } @@ -235,7 +274,8 @@ bool IndexBufferGLES2::ConcreteUnlock() { renderer_->MakeCurrentLazy(); if (!num_elements()) return true; - glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, gl_buffer_); + glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, gl_buffer_); +#if defined(GLES2_BACKEND_DESKTOP_GL) if (!glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER)) { GLenum error = glGetError(); if (error == GL_INVALID_OPERATION) { @@ -247,8 +287,13 @@ bool IndexBufferGLES2::ConcreteUnlock() { } return false; } +#else + if (!read_only_) { + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, GetSizeInBytes(), + shadow_.get()); + } +#endif CHECK_GL_ERROR(); return true; } } // namespace o3d - diff --git a/o3d/core/cross/gles2/buffer_gles2.h b/o3d/core/cross/gles2/buffer_gles2.h index 7dda7e1..b1956f8 100644 --- a/o3d/core/cross/gles2/buffer_gles2.h +++ b/o3d/core/cross/gles2/buffer_gles2.h @@ -36,6 +36,7 @@ #ifndef O3D_CORE_CROSS_GLES2_BUFFER_GLES2_H_ #define O3D_CORE_CROSS_GLES2_BUFFER_GLES2_H_ +#include "base/scoped_ptr.h" #include "core/cross/buffer.h" #include "core/cross/gles2/gles2_headers.h" @@ -80,6 +81,13 @@ class VertexBufferGLES2 : public VertexBuffer { private: RendererGLES2* renderer_; +#if !defined(GLES2_BACKEND_DESKTOP_GL) + // GLES doesn't support glMapBuffers (only WRITE_ONLY if an extension is + // present), or even glGetBufferSubData, so we need to keep a shadow of the + // data. + scoped_array<char> shadow_; + bool read_only_; +#endif GLuint gl_buffer_; }; @@ -112,6 +120,13 @@ class IndexBufferGLES2 : public IndexBuffer { private: RendererGLES2* renderer_; +#if !defined(GLES2_BACKEND_DESKTOP_GL) + // GLES doesn't support glMapBuffers (only WRITE_ONLY if an extension is + // present), or even glGetBufferSubData, so we need to keep a shadow of the + // data. + scoped_array<char> shadow_; + bool read_only_; +#endif GLuint gl_buffer_; }; @@ -119,4 +134,3 @@ class IndexBufferGLES2 : public IndexBuffer { #endif // O3D_CORE_CROSS_GLES2_BUFFER_GLES2_H_ - diff --git a/o3d/core/cross/gles2/effect_gles2.cc b/o3d/core/cross/gles2/effect_gles2.cc index 1e24e5b..060f46b 100644 --- a/o3d/core/cross/gles2/effect_gles2.cc +++ b/o3d/core/cross/gles2/effect_gles2.cc @@ -203,6 +203,15 @@ bool GetIdentifierAfterString(const String& original, return false; } +#ifdef GLES2_BACKEND_DESKTOP_GL +const char kVertexHeader[] = ""; +const char kFragmentHeader[] = "// "; +#else +const char kVertexHeader[] = "precision highp float; precision highp int;\n"; +const char kFragmentHeader[] = + "precision mediump float; precision mediump int;\n// "; +#endif + } // anonymous namespace // Initializes the Effect object using the shaders found in an FX formatted @@ -235,8 +244,8 @@ bool EffectGLES2::LoadFromFXString(const String& effect) { return false; } - String vertex_shader(effect.substr(0, split_pos)); - String fragment_shader("// " + effect.substr(split_pos)); + String vertex_shader(kVertexHeader + effect.substr(0, split_pos)); + String fragment_shader(kFragmentHeader + effect.substr(split_pos)); set_matrix_load_order(matrix_load_order); diff --git a/o3d/core/cross/gles2/gles2_headers.h b/o3d/core/cross/gles2/gles2_headers.h index e31de99..545a9d7 100644 --- a/o3d/core/cross/gles2/gles2_headers.h +++ b/o3d/core/cross/gles2/gles2_headers.h @@ -32,6 +32,8 @@ #ifndef O3D_CORE_CROSS_GLES2_GL_HEADERS_H_ #define O3D_CORE_CROSS_GLES2_GL_HEADERS_H_ +#if defined(GLES2_BACKEND_DESKTOP_GL) + #include <GL/glew.h> #if defined(OS_WIN) #include <GL/wglew.h> @@ -39,4 +41,52 @@ #include <GL/glx.h> #endif +#elif defined(GLES2_BACKEND_NATIVE_GLES2) + +#include <EGL/egl.h> +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> + +#define glClearDepth glClearDepthf +#define glDepthRange glDepthRangef + +// Buffer Objects +#define glBindBufferARB glBindBuffer +#define glBufferDataARB glBufferData +#define glBufferSubDataARB glBufferSubData +#define glDeleteBuffersARB glDeleteBuffers +#define glGenBuffersARB glGenBuffers + +// Framebuffer Objects +#define glBindFramebufferEXT glBindFramebuffer +#define glBindRenderbufferEXT glBindRenderbuffer +#define glCheckFramebufferStatusEXT glCheckFramebufferStatus +#define glDeleteRenderbuffersEXT glDeleteRenderbuffers +#define glDeleteFramebuffersEXT glDeleteFramebuffers +#define glFramebufferRenderbufferEXT glFramebufferRenderbuffer +#define glFramebufferTexture2DEXT glFramebufferTexture2D +#define glGenFramebuffersEXT glGenFramebuffers +#define glGenRenderbuffersEXT glGenRenderbuffers +#define glRenderbufferStorageEXT glRenderbufferStorage + +#define GLEW_VERSION_2_0 true +#define GLEW_VERSION_1_4 true + +// TODO(piman): handle gracefully the case where GL_EXT_bgra isn't present. +#define GL_BGRA 0x80E1 + +// TODO(piman): handle gracefully the case where GL_OES_half_float isn't +// present. +#define GL_HALF_FLOAT_ARB GL_HALF_FLOAT_OES + +#elif defined(GLES2_BACKEND_GLES2_COMMAND_BUFFERS) + +#include <GLES2/gl2.h> + +#else // GLES2_BACKEND_xxx not defined + +#error "GLES2_BACKEND_xxx not defined" + +#endif // GLES2_BACKEND_xxx + #endif // O3D_CORE_CROSS_GLES2_GL_HEADERS_H_ diff --git a/o3d/core/cross/gles2/render_surface_gles2.cc b/o3d/core/cross/gles2/render_surface_gles2.cc index ee0aff9..6d21dc8 100644 --- a/o3d/core/cross/gles2/render_surface_gles2.cc +++ b/o3d/core/cross/gles2/render_surface_gles2.cc @@ -86,44 +86,57 @@ RenderDepthStencilSurfaceGLES2::RenderDepthStencilSurfaceGLES2( : RenderDepthStencilSurface(service_locator, width, height) { #ifndef DISABLE_FBO +#if defined(GLES2_BACKEND_DESKTOP_GL) // If packed depth stencil is supported, create only one buffer for both // depth and stencil. + // TODO(piman): on GLES, test GL_OES_packed_depth_stencil if (GLEW_EXT_packed_depth_stencil) { glGenRenderbuffersEXT(1, render_buffers_); - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, render_buffers_[0]); - glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, + glBindRenderbufferEXT(GL_RENDERBUFFER, render_buffers_[0]); + glRenderbufferStorageEXT(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_EXT, width, height); CHECK_GL_ERROR(); render_buffers_[1] = render_buffers_[0]; - } else { - glGenRenderbuffersEXT(2, render_buffers_); - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, render_buffers_[0]); - glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, - GL_DEPTH_COMPONENT24, - width, - height); - CHECK_GL_ERROR(); - - glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, render_buffers_[1]); - glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, - GL_STENCIL_INDEX8_EXT, - width, - height); - CHECK_GL_ERROR(); + return; } #endif + glGenRenderbuffersEXT(2, render_buffers_); + glBindRenderbufferEXT(GL_RENDERBUFFER, render_buffers_[0]); + glRenderbufferStorageEXT(GL_RENDERBUFFER, +#if defined(GLES2_BACKEND_DESKTOP_GL) + GL_DEPTH_COMPONENT24, +#else + // On GLES, only 16bit depth is available by default. + // TODO(piman): test for GL_OES_depth24 or 32 and + // use those. + GL_DEPTH_COMPONENT16, +#endif + width, + height); + CHECK_GL_ERROR(); + + glBindRenderbufferEXT(GL_RENDERBUFFER, render_buffers_[1]); + glRenderbufferStorageEXT(GL_RENDERBUFFER, + GL_STENCIL_INDEX8, + width, + height); + CHECK_GL_ERROR(); +#endif } RenderDepthStencilSurfaceGLES2::~RenderDepthStencilSurfaceGLES2() { #ifndef DISABLE_FBO +#if defined(GLES2_BACKEND_DESKTOP_GL) + // TODO(piman): on GLES, test GL_OES_packed_depth_stencil if (GLEW_EXT_packed_depth_stencil) { glDeleteRenderbuffersEXT(1, render_buffers_); - } else { - glDeleteRenderbuffersEXT(2, render_buffers_); + return; } #endif + glDeleteRenderbuffersEXT(2, render_buffers_); +#endif } } // end namespace o3d diff --git a/o3d/core/cross/gles2/renderer_gles2.cc b/o3d/core/cross/gles2/renderer_gles2.cc index 7a0d3b7..e6012f4 100644 --- a/o3d/core/cross/gles2/renderer_gles2.cc +++ b/o3d/core/cross/gles2/renderer_gles2.cc @@ -81,6 +81,7 @@ GLenum ConvertCmpFunc(State::Comparison cmp) { return GL_ALWAYS; } +#if defined(GLES2_BACKEND_DESKTOP_GL) GLenum ConvertFillMode(State::Fill mode) { switch (mode) { case State::POINT: @@ -94,6 +95,7 @@ GLenum ConvertFillMode(State::Fill mode) { } return GL_FILL; } +#endif GLenum ConvertBlendFunc(State::BlendingFunction blend_func) { switch (blend_func) { @@ -133,10 +135,17 @@ GLenum ConvertBlendEquation(State::BlendingEquation blend_equation) { return GL_FUNC_SUBTRACT; case State::BLEND_REVERSE_SUBTRACT: return GL_FUNC_REVERSE_SUBTRACT; +#if defined(GLES2_BACKEND_DESKTOP_GL) case State::BLEND_MIN: return GL_MIN; case State::BLEND_MAX: return GL_MAX; +#else + case State::BLEND_MIN: + case State::BLEND_MAX: + NOTIMPLEMENTED() << "MIN/MAX blend equation"; + break; +#endif default: break; } @@ -177,24 +186,24 @@ bool InstallFramebufferObjects(const RenderSurface* surface, const RenderDepthStencilSurface* surface_depth) { #ifdef _DEBUG GLint bound_framebuffer; - ::glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &bound_framebuffer); + ::glGetIntegerv(GL_FRAMEBUFFER_BINDING, &bound_framebuffer); DCHECK(bound_framebuffer != 0); #endif // Reset the bound attachments to the current framebuffer object. - ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, - GL_COLOR_ATTACHMENT0_EXT, - GL_RENDERBUFFER_EXT, + ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, + GL_RENDERBUFFER, 0); - ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, - GL_DEPTH_ATTACHMENT_EXT, - GL_RENDERBUFFER_EXT, + ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, + GL_DEPTH_ATTACHMENT, + GL_RENDERBUFFER, 0); - ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, - GL_STENCIL_ATTACHMENT_EXT, - GL_RENDERBUFFER_EXT, + ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, + GL_STENCIL_ATTACHMENT, + GL_RENDERBUFFER, 0); if (surface) { @@ -205,15 +214,15 @@ bool InstallFramebufferObjects(const RenderSurface* surface, texture->GetTextureHandle())); if (texture->IsA(Texture2D::GetApparentClass())) { ::glFramebufferTexture2DEXT( - GL_FRAMEBUFFER_EXT, - GL_COLOR_ATTACHMENT0_EXT, + GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, handle, gl_surface->mip_level()); } else if (texture->IsA(TextureCUBE::GetApparentClass())) { ::glFramebufferTexture2DEXT( - GL_FRAMEBUFFER_EXT, - GL_COLOR_ATTACHMENT0_EXT, + GL_FRAMEBUFFER, + GL_COLOR_ATTACHMENT0, gl_surface->cube_face(), handle, gl_surface->mip_level()); @@ -224,17 +233,17 @@ bool InstallFramebufferObjects(const RenderSurface* surface, // Bind both the depth and stencil attachments. const RenderDepthStencilSurfaceGLES2* gl_surface = down_cast<const RenderDepthStencilSurfaceGLES2*>(surface_depth); - ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, - GL_DEPTH_ATTACHMENT_EXT, - GL_RENDERBUFFER_EXT, + ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, + GL_DEPTH_ATTACHMENT, + GL_RENDERBUFFER, gl_surface->depth_buffer()); - ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, - GL_STENCIL_ATTACHMENT_EXT, - GL_RENDERBUFFER_EXT, + ::glFramebufferRenderbufferEXT(GL_FRAMEBUFFER, + GL_STENCIL_ATTACHMENT, + GL_RENDERBUFFER, gl_surface->stencil_buffer()); } - GLenum framebuffer_status = ::glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); - if (GL_FRAMEBUFFER_COMPLETE_EXT != framebuffer_status) { + GLenum framebuffer_status = ::glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); + if (GL_FRAMEBUFFER_COMPLETE != framebuffer_status) { return false; } @@ -285,6 +294,15 @@ class TypedStateHandler : public RendererGLES2::StateHandler { } }; +template <class T> +class NoOpHandler : public TypedStateHandler<T> { + public: + virtual void SetStateFromTypedParam(RendererGLES2* renderer, + T* param) const { + } +}; + + // A template the generates a handler for enable/disable states. // Parameters: // state_constant: GLenum of state we want to enable/disable @@ -385,8 +403,12 @@ class FillModeHandler : public TypedStateHandler<ParamInteger> { public: virtual void SetStateFromTypedParam(RendererGLES2* renderer, ParamInteger* param) const { +#if defined(GLES2_BACKEND_DESKTOP_GL) ::glPolygonMode(GL_FRONT_AND_BACK, ConvertFillMode(static_cast<State::Fill>(param->value()))); +#else + NOTIMPLEMENTED() << "Fill mode"; +#endif } }; @@ -503,6 +525,7 @@ class PointSpriteEnableHandler : public TypedStateHandler<ParamBoolean> { public: virtual void SetStateFromTypedParam(RendererGLES2* renderer, ParamBoolean* param) const { +#if defined(GLES2_BACKEND_DESKTOP_GL) if (param->value()) { ::glEnable(GL_POINT_SPRITE); // TODO(o3d): It's not clear from D3D docs that point sprites affect @@ -514,6 +537,9 @@ class PointSpriteEnableHandler : public TypedStateHandler<ParamBoolean> { ::glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_FALSE); ::glDisable(GL_POINT_SPRITE); } +#else + NOTIMPLEMENTED() << "Point Sprites"; +#endif } }; @@ -521,7 +547,11 @@ class PointSizeHandler : public TypedStateHandler<ParamFloat> { public: virtual void SetStateFromTypedParam(RendererGLES2* renderer, ParamFloat* param) const { +#if defined(GLES2_BACKEND_DESKTOP_GL) ::glPointSize(param->value()); +#else + NOTIMPLEMENTED() << "Point Size"; +#endif } }; @@ -539,8 +569,14 @@ RendererGLES2::RendererGLES2(ServiceLocator* service_locator) #ifdef OS_LINUX display_(NULL), window_(0), +#if defined(GLES2_BACKEND_DESKTOP_GL) context_(0), -#endif +#elif defined(GLES2_BACKEND_NATIVE_GLES2) + egl_display_(NULL), + egl_surface_(NULL), + egl_context_(NULL), +#endif // GLES_BACKEND_xxx +#endif // OS_LINUX #ifdef OS_MACOSX mac_agl_context_(0), mac_cgl_context_(0), @@ -572,8 +608,15 @@ RendererGLES2::RendererGLES2(ServiceLocator* service_locator) } // Setup state handlers +#if defined(GLES2_BACKEND_DESKTOP_GL) AddStateHandler(State::kAlphaTestEnableParamName, new StateEnableHandler<GL_ALPHA_TEST>); +#else + // TODO(piman): Alpha test isn't supported in GLES2, because it can be done + // in a shader. Solution here would be to add instructions to the shader... + AddStateHandler(State::kAlphaTestEnableParamName, + new NoOpHandler<ParamBoolean>); +#endif AddStateHandler(State::kAlphaReferenceParamName, new AlphaReferenceHandler); AddStateHandler(State::kAlphaComparisonFunctionParamName, @@ -583,8 +626,13 @@ RendererGLES2::RendererGLES2(ServiceLocator* service_locator) new CullModeHandler); AddStateHandler(State::kDitherEnableParamName, new StateEnableHandler<GL_DITHER>); +#if defined(GLES2_BACKEND_DESKTOP_GL) AddStateHandler(State::kLineSmoothEnableParamName, new StateEnableHandler<GL_LINE_SMOOTH>); +#else + AddStateHandler(State::kLineSmoothEnableParamName, + new NoOpHandler<ParamBoolean>); +#endif AddStateHandler(State::kPointSpriteEnableParamName, new PointSpriteEnableHandler); AddStateHandler(State::kPointSizeParamName, @@ -660,6 +708,7 @@ RendererGLES2::~RendererGLES2() { // platform neutral initialization code // Renderer::InitStatus RendererGLES2::InitCommonGLES2() { +#if defined(GLES2_BACKEND_DESKTOP_GL) GLenum glew_error = glewInit(); if (glew_error != GLEW_OK) { DLOG(ERROR) << "Unable to initialise GLEW : " @@ -715,9 +764,13 @@ Renderer::InitStatus RendererGLES2::InitCommonGLES2() { if (!GLEW_VERSION_2_0 && !GLEW_EXT_blend_equation_separate) { DLOG(ERROR) << "Separate blend function extension missing."; } +#elif defined(GLES2_BACKEND_NATIVE_GLES2) + // GLES specific initialization ? +#endif // GLES2_BACKEND DLOG(INFO) << "OpenGLES2 Vendor: " << ::glGetString(GL_VENDOR); DLOG(INFO) << "OpenGLES2 Renderer: " << ::glGetString(GL_RENDERER); DLOG(INFO) << "OpenGLES2 Version: " << ::glGetString(GL_VERSION); + DLOG(INFO) << "OpenGLES2 Extensions: " << ::glGetString(GL_EXTENSIONS); // get some limits for this profile. GLint max_vertex_attribs = 0; ::glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &max_vertex_attribs); @@ -726,9 +779,14 @@ Renderer::InitStatus RendererGLES2::InitCommonGLES2() { // Tell GLES2 that texture buffers can be single-byte aligned. ::glPixelStorei(GL_PACK_ALIGNMENT, 1); ::glPixelStorei(GL_UNPACK_ALIGNMENT, 1); +#if defined(GLES2_BACKEND_DESKTOP_GL) ::glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); ::glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); +#endif CHECK_GL_ERROR(); + // TODO(piman): by default, GLES2 has some minimal support for NPOT. Is it + // enough for what we use ? + SetSupportsNPOT(true); GLint viewport[4]; ::glGetIntegerv(GL_VIEWPORT, &viewport[0]); @@ -1032,6 +1090,7 @@ Renderer::InitStatus RendererGLES2::InitPlatformSpecific( static_cast<const DisplayWindowLinux&>(display_window); Display *display = display_platform.display(); Window window = display_platform.window(); +#if defined(GLES2_BACKEND_DESKTOP_GL) XWindowAttributes attributes; ::XGetWindowAttributes(display, window, &attributes); XVisualInfo visual_info_template; @@ -1072,16 +1131,148 @@ Renderer::InitStatus RendererGLES2::InitPlatformSpecific( window_ = 0; } return init_status; +#elif defined(GLES2_BACKEND_NATIVE_GLES2) + EGLDisplay egl_display = eglGetDisplay(display); + if (eglGetError() != EGL_SUCCESS) { + DLOG(ERROR) << "eglGetDisplay failed."; + return INITIALIZATION_ERROR; + } + + EGLint major; + EGLint minor; + // TODO(piman): is it ok to do this several times ? + if (!eglInitialize(egl_display, &major, &minor)) { + DLOG(ERROR) << "eglInitialize failed."; + return INITIALIZATION_ERROR; + } + DLOG(INFO) << "EGL vendor:" << eglQueryString(egl_display, EGL_VENDOR); + DLOG(INFO) << "EGL version:" << eglQueryString(egl_display, EGL_VERSION); + DLOG(INFO) << "EGL extensions:" + << eglQueryString(egl_display, EGL_EXTENSIONS); + DLOG(INFO) << "EGL client apis:" + << eglQueryString(egl_display, EGL_CLIENT_APIS); + + EGLint attribs[] = { +#if 0 + // On some platforms X is started in 16-bit mode, and making a 32-bit + // framebuffer causes tons of problems. + // TODO(piman): fix this. + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_DEPTH_SIZE, 24, + EGL_STENCIL_SIZE, 8, +#else + EGL_RED_SIZE, 5, + EGL_GREEN_SIZE, 6, + EGL_BLUE_SIZE, 5, + EGL_DEPTH_SIZE, 16, + EGL_STENCIL_SIZE, 0, +#endif + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_NONE + }; + + EGLint num_configs = -1; + if (!eglGetConfigs(egl_display, NULL, 0, &num_configs)) { + DLOG(ERROR) << "eglGetConfigs failed."; + return INITIALIZATION_ERROR; + } + + EGLConfig config; + if (!eglChooseConfig(egl_display, attribs, &config, 1, &num_configs)) { + DLOG(ERROR) << "eglChooseConfig failed."; + return INITIALIZATION_ERROR; + } + + EGLint red_size, green_size, blue_size, alpha_size, depth_size, stencil_size; + eglGetConfigAttrib(egl_display, config, EGL_RED_SIZE, &red_size); + eglGetConfigAttrib(egl_display, config, EGL_GREEN_SIZE, &green_size); + eglGetConfigAttrib(egl_display, config, EGL_BLUE_SIZE, &blue_size); + eglGetConfigAttrib(egl_display, config, EGL_ALPHA_SIZE, &alpha_size); + eglGetConfigAttrib(egl_display, config, EGL_DEPTH_SIZE, &depth_size); + eglGetConfigAttrib(egl_display, config, EGL_STENCIL_SIZE, &stencil_size); + DLOG(INFO) << "R,G,B,A: " << red_size << "," << green_size + << "," << blue_size << "," << alpha_size << " bits"; + DLOG(INFO) << "Depth: " << depth_size << " bits, Stencil:" << stencil_size + << "bits"; + + EGLSurface egl_surface = eglCreateWindowSurface(egl_display, config, + window, NULL); + if (!egl_surface) { + DLOG(ERROR) << "eglCreateWindowSurface failed."; + return INITIALIZATION_ERROR; + } + + EGLContext egl_context = eglCreateContext(egl_display, config, NULL, NULL); + if (!egl_context) { + DLOG(ERROR) << "eglCreateContext failed."; + eglDestroySurface(egl_display, egl_surface); + return INITIALIZATION_ERROR; + } + + display_ = display; + window_ = window; + egl_display_ = egl_display; + egl_surface_ = egl_surface; + egl_context_ = egl_context; + if (!MakeCurrent()) { + eglDestroyContext(egl_display, egl_context); + eglDestroySurface(egl_display, egl_surface); + display_ = NULL; + window_ = 0; + egl_display_ = NULL; + egl_surface_ = NULL; + egl_context_ = NULL; + return INITIALIZATION_ERROR; + } + + EGLint width; + EGLint height; + eglQuerySurface(egl_display, egl_surface, EGL_WIDTH, &width); + eglQuerySurface(egl_display, egl_surface, EGL_HEIGHT, &height); + glViewport(0, 0, width, height); + + InitStatus init_status = InitCommonGLES2(); + if (init_status != SUCCESS) { + Destroy(); + return INITIALIZATION_ERROR; + } + return init_status; +#else +#error Not Implemented +#endif } void RendererGLES2::Destroy() { DestroyCommonGLES2(); if (display_) { +#if defined(GLES2_BACKEND_DESKTOP_GL) ::glXMakeCurrent(display_, 0, 0); if (context_) { ::glXDestroyContext(display_, context_); context_ = 0; } +#elif defined(GLES2_BACKEND_NATIVE_GLES2) + if (egl_display_) { + eglMakeCurrent(egl_display_, EGL_NO_SURFACE, EGL_NO_SURFACE, + EGL_NO_CONTEXT); + if (egl_context_) { + eglDestroyContext(egl_display_, egl_context_); + egl_context_ = NULL; + } + if (egl_surface_) { + eglDestroySurface(egl_display_, egl_surface_); + egl_surface_ = NULL; + } + // TODO(piman): is it ok to do this if we have multiple clients ? + eglTerminate(egl_display_); + egl_display_ = NULL; + } +#else +#error Not Implemented +#endif display_ = NULL; window_ = 0; } @@ -1107,12 +1298,24 @@ bool RendererGLES2::MakeCurrent() { } #endif #ifdef OS_LINUX +#if defined(GLES2_BACKEND_DESKTOP_GL) if (context_ != NULL) { bool result = ::glXMakeCurrent(display_, window_, context_) == True; return result; } else { return false; } +#elif defined(GLES2_BACKEND_NATIVE_GLES2) + if (egl_context_ != NULL) { + EGLBoolean result = eglMakeCurrent(egl_display_, egl_surface_, + egl_surface_, egl_context_); + return result == EGL_TRUE; + } else { + return false; + } +#else +#error Not Implemented +#endif #endif } @@ -1140,22 +1343,7 @@ void RendererGLES2::UpdateHelperConstant(float width, float height) { // If render-targets are active, pass -1 to invert the Y axis. OpenGLES2 uses // a different viewport orientation than DX. Without the inversion, the // output of render-target rendering will be upside down. - if (RenderSurfaceActive()) { - ::glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, - 0, - 1.0f / width, - -1.0f / height, - 2.0f, - -1.0f); - } else { - // Only apply the origin offset when rendering to the client area. - ::glProgramEnvParameter4fARB(GL_VERTEX_PROGRAM_ARB, - 0, - (1.0f + (2.0f * -dest_x_offset())) / width, - (-1.0f + (2.0f * dest_y_offset())) / height, - 2.0f, - 1.0f); - } + // TODO(piman): actually implement this. CHECK_GL_ERROR(); } @@ -1341,7 +1529,13 @@ void RendererGLES2::PlatformSpecificPresent() { #endif #endif #ifdef OS_LINUX +#if defined(GLES2_BACKEND_DESKTOP_GL) ::glXSwapBuffers(display_, window_); +#elif defined(GLES2_BACKEND_NATIVE_GLES2) + eglSwapBuffers(egl_display_, egl_surface_); +#else +#error Not Implemented +#endif // GLES2_BACKEND_xxx #endif } @@ -1379,7 +1573,9 @@ void RendererGLES2::SetStencilStates(GLenum face, stencil_state.op_[StencilStates::PASS_OP]); ::glStencilMaskSeparate(face, stencil_mask_[WRITE_MASK]); - } else if (GLEW_EXT_stencil_two_side) { + } +#if defined(GLES2_BACKEND_DESKTOP_GL) + else if (GLEW_EXT_stencil_two_side) { ::glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT); ::glActiveStencilFaceEXT(face); ::glStencilFunc(stencil_state.func_, @@ -1391,6 +1587,7 @@ void RendererGLES2::SetStencilStates(GLenum face, ::glStencilMask(stencil_mask_[WRITE_MASK]); ::glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT); } +#endif CHECK_GL_ERROR(); } @@ -1405,33 +1602,43 @@ void RendererGLES2::ApplyDirtyStates() { blend_function_[DST][RGB], blend_function_[SRC][ALPHA], blend_function_[DST][ALPHA]); - } else if (GLEW_EXT_blend_func_separate) { + } +#if defined(GLES2_BACKEND_DESKTOP_GL) + else if (GLEW_EXT_blend_func_separate) { ::glBlendFuncSeparateEXT(blend_function_[SRC][RGB], blend_function_[DST][RGB], blend_function_[SRC][ALPHA], blend_function_[DST][ALPHA]); } +#endif if (GLEW_VERSION_2_0) { ::glBlendEquationSeparate(blend_equation_[RGB], blend_equation_[ALPHA]); - } else if (GLEW_EXT_blend_equation_separate) { + } +#if defined(GLES2_BACKEND_DESKTOP_GL) + else if (GLEW_EXT_blend_equation_separate) { ::glBlendEquationSeparateEXT(blend_equation_[RGB], blend_equation_[ALPHA]); } +#endif } else { ::glBlendFunc(blend_function_[SRC][RGB], blend_function_[DST][RGB]); +#if defined(GLES2_BACKEND_DESKTOP_GL) if (::glBlendEquation != NULL) +#endif ::glBlendEquation(blend_equation_[RGB]); } alpha_blend_settings_changed_ = false; } +#if defined(GLES2_BACKEND_DESKTOP_GL) // Set alpha settings. if (alpha_function_ref_changed_) { ::glAlphaFunc(alpha_function_, alpha_ref_); alpha_function_ref_changed_ = false; } +#endif // Set stencil settings. if (stencil_settings_changed_) { @@ -1448,13 +1655,17 @@ void RendererGLES2::ApplyDirtyStates() { bool enable = (polygon_offset_factor_ != 0.f) || (polygon_offset_bias_ != 0.f); if (enable) { +#if defined(GLES2_BACKEND_DESKTOP_GL) ::glEnable(GL_POLYGON_OFFSET_POINT); ::glEnable(GL_POLYGON_OFFSET_LINE); +#endif ::glEnable(GL_POLYGON_OFFSET_FILL); ::glPolygonOffset(polygon_offset_factor_, polygon_offset_bias_); } else { +#if defined(GLES2_BACKEND_DESKTOP_GL) ::glDisable(GL_POLYGON_OFFSET_POINT); ::glDisable(GL_POLYGON_OFFSET_LINE); +#endif ::glDisable(GL_POLYGON_OFFSET_FILL); } polygon_offset_changed_ = false; diff --git a/o3d/core/cross/gles2/renderer_gles2.h b/o3d/core/cross/gles2/renderer_gles2.h index eeb7260..289101c 100644 --- a/o3d/core/cross/gles2/renderer_gles2.h +++ b/o3d/core/cross/gles2/renderer_gles2.h @@ -143,10 +143,18 @@ class RendererGLES2 : public Renderer { return true; } #elif defined(OS_LINUX) +#if defined(GLES2_BACKEND_DESKTOP_GL) if ((context_ != NULL) && (context_ == glXGetCurrentContext())) { return true; } +#elif defined(GLES2_BACKEND_NATIVE_GLES2) + if (egl_context_ && egl_context_ == eglGetCurrentContext()) { + return true; + } +#elif defined(GLES2_BACKEND_GLES2_COMMAND_BUFFERS) +#error RendererGLES2::IsCurrent() Not implemented. +#endif #else Error: must port RendererGLES2::IsCurrent() to your platform. #endif @@ -267,7 +275,13 @@ class RendererGLES2 : public Renderer { #ifdef OS_LINUX Display *display_; Window window_; +#if defined(GLES2_BACKEND_DESKTOP_GL) GLXContext context_; +#elif defined(GLES2_BACKEND_NATIVE_GLES2) + EGLDisplay egl_display_; + EGLSurface egl_surface_; + EGLContext egl_context_; +#endif #endif // Handle to the framebuffer-object used while rendering to off-screen @@ -345,4 +359,3 @@ class RendererGLES2 : public Renderer { } // namespace o3d #endif // O3D_CORE_CROSS_GLES2_RENDERER_GLES2_H_ - diff --git a/o3d/core/cross/gles2/sampler_gles2.cc b/o3d/core/cross/gles2/sampler_gles2.cc index a52affa..6f4769b 100644 --- a/o3d/core/cross/gles2/sampler_gles2.cc +++ b/o3d/core/cross/gles2/sampler_gles2.cc @@ -66,7 +66,12 @@ unsigned int GLAddressMode(Sampler::AddressMode o3d_mode, gl_mode = GL_CLAMP_TO_EDGE; break; case Sampler::BORDER: +#if defined(GLES2_BACKEND_DESKTOP_GL) gl_mode = GL_CLAMP_TO_BORDER; +#else + NOTIMPLEMENTED() << "Sampler::BORDER"; + gl_mode = GL_CLAMP_TO_EDGE; +#endif break; default: DLOG(ERROR) << "Unknown Address mode " << static_cast<int>(o3d_mode); @@ -167,7 +172,7 @@ GLint SamplerGLES2::SetTextureAndStates(GLES2Parameter gl_param) { texture_unit_group_set_count_ = renderer_texture_unit_group_set_count; texture_unit_ = renderer_->GetNextTextureUnit(); } - ::glActiveTextureARB(GL_TEXTURE0 + texture_unit_); + ::glActiveTexture(GL_TEXTURE0 + texture_unit_); glBindTexture(target, handle); glTexParameteri(target, GL_TEXTURE_WRAP_S, @@ -175,22 +180,26 @@ GLint SamplerGLES2::SetTextureAndStates(GLES2Parameter gl_param) { glTexParameteri(target, GL_TEXTURE_WRAP_T, GLAddressMode(address_mode_v(), GL_REPEAT)); - if (texture_object->IsA(TextureCUBE::GetApparentClass())) { - glTexParameteri(target, - GL_TEXTURE_WRAP_R, - GLAddressMode(address_mode_w(), GL_REPEAT)); - } + // disable mipmapping if we have only one level. + FilterType clamped_mip_filter = + texture_object->levels() == 1 ? NONE : mip_filter(); glTexParameteri(target, GL_TEXTURE_MIN_FILTER, - GLMinFilter(min_filter(), mip_filter())); + GLMinFilter(min_filter(), clamped_mip_filter)); glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GLMagFilter(mag_filter())); +#if defined(GLES2_BACKEND_DESKTOP_GL) Float4 color = border_color(); GLfloat gl_color[4] = {color[0], color[1], color[2], color[3]}; glTexParameterfv(target, GL_TEXTURE_BORDER_COLOR, gl_color); +#else + // Not implemented +#endif + +#if defined(GLES2_BACKEND_DESKTOP_GL) // Check for anisotropic texture filtering. if (GLEW_EXT_texture_filter_anisotropic) { int gl_max_anisotropy = @@ -198,6 +207,10 @@ GLint SamplerGLES2::SetTextureAndStates(GLES2Parameter gl_param) { glTexParameteri(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, gl_max_anisotropy); } +#else + // TODO(piman): test for GL_EXT_texture_filter_anisotropic and implement + // as above. +#endif } } @@ -211,10 +224,9 @@ void SamplerGLES2::ResetTexture(GLES2Parameter gl_param) { // time. GLenum target = GLTextureTarget(the_texture); if (target) { - glActiveTextureARB(GL_TEXTURE0 + texture_unit_); + glActiveTexture(GL_TEXTURE0 + texture_unit_); glBindTexture(target, 0); } } } } // namespace o3d - diff --git a/o3d/core/cross/gles2/stream_bank_gles2.cc b/o3d/core/cross/gles2/stream_bank_gles2.cc index 1501f35..1657a0a 100644 --- a/o3d/core/cross/gles2/stream_bank_gles2.cc +++ b/o3d/core/cross/gles2/stream_bank_gles2.cc @@ -67,7 +67,7 @@ GLenum GLDataType(const Field& field) { } String GetAttribName(GLuint gl_program, GLES2Parameter gl_param) { - GLchar buffer[1024]; + char buffer[1024]; GLsizei name_len; GLint size; GLenum type; @@ -223,4 +223,3 @@ int StreamBankGLES2::FindVertexStream(Stream::Semantic semantic, int index) { } } // namespace o3d - diff --git a/o3d/core/cross/gles2/texture_gles2.cc b/o3d/core/cross/gles2/texture_gles2.cc index f03340e..ef37c2e 100644 --- a/o3d/core/cross/gles2/texture_gles2.cc +++ b/o3d/core/cross/gles2/texture_gles2.cc @@ -67,30 +67,52 @@ static GLenum GLFormatFromO3DFormat(Texture::Format format, GLenum *data_type) { switch (format) { case Texture::XRGB8: { +#if defined(GLES2_BACKEND_DESKTOP_GL) *internal_format = GL_RGB; +#else + // On GLES, the internal_format must match format. + *internal_format = GL_BGRA; +#endif *data_type = GL_UNSIGNED_BYTE; return GL_BGRA; } case Texture::ARGB8: { +#if defined(GLES2_BACKEND_DESKTOP_GL) *internal_format = GL_RGBA; +#else + *internal_format = GL_BGRA; +#endif *data_type = GL_UNSIGNED_BYTE; return GL_BGRA; } case Texture::ABGR16F: { +#if defined(GLES2_BACKEND_DESKTOP_GL) *internal_format = GL_RGBA16F_ARB; +#else + *internal_format = GL_RGBA; +#endif *data_type = GL_HALF_FLOAT_ARB; return GL_RGBA; } case Texture::R32F: { +#if defined(GLES2_BACKEND_DESKTOP_GL) *internal_format = GL_LUMINANCE32F_ARB; +#else + *internal_format = GL_LUMINANCE; +#endif *data_type = GL_FLOAT; return GL_LUMINANCE; } case Texture::ABGR32F: { +#if defined(GLES2_BACKEND_DESKTOP_GL) *internal_format = GL_RGBA32F_ARB; +#else + *internal_format = GL_BGRA; +#endif *data_type = GL_FLOAT; return GL_BGRA; } +#if defined(GLES2_BACKEND_DESKTOP_GL) case Texture::DXT1: { if (GL_EXT_texture_compression_s3tc) { *internal_format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; @@ -136,6 +158,15 @@ static GLenum GLFormatFromO3DFormat(Texture::Format format, return 0; } } +#else + case Texture::DXT1: + case Texture::DXT3: + case Texture::DXT5: + NOTIMPLEMENTED() << "DXT textures"; + *internal_format = 0; + *data_type = GL_BYTE; + return 0; +#endif case Texture::UNKNOWN_FORMAT: break; } @@ -184,8 +215,12 @@ static bool UpdateGLImageFromBitmap(GLenum target, glTexSubImage2D(target, level, 0, 0, mip_width, mip_height, gl_format, gl_data_type, mip_data); } else { +#if defined(GLES2_BACKEND_DESKTOP_GL) glCompressedTexSubImage2D(target, level, 0, 0, mip_width, mip_height, gl_internal_format, mip_size, mip_data); +#else + NOTIMPLEMENTED() << "DXT textures"; +#endif } return glGetError() == GL_NO_ERROR; } @@ -226,6 +261,7 @@ static bool CreateGLImages(GLenum target, return false; } } else { +#if defined(GLES2_BACKEND_DESKTOP_GL) size_t mip_size = image::ComputeBufferSize(mip_width, mip_height, format); glCompressedTexImage2DARB(target, i, internal_format, mip_width, mip_height, 0, mip_size, temp_data.get()); @@ -233,6 +269,10 @@ static bool CreateGLImages(GLenum target, DLOG(ERROR) << "glCompressedTexImage2D failed"; return false; } +#else + NOTIMPLEMENTED() << "DXT textures"; + return false; +#endif } mip_width = std::max(1U, mip_width >> 1); mip_height = std::max(1U, mip_height >> 1); @@ -299,8 +339,16 @@ Texture2DGLES2* Texture2DGLES2::Create(ServiceLocator* service_locator, GLuint gl_texture = 0; glGenTextures(1, &gl_texture); glBindTexture(GL_TEXTURE_2D, gl_texture); +#if defined(GLES2_BACKEND_DESKTOP_GL) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, levels - 1); +#else + // On GLES2, we can't specify GL_TEXTURE_MAX_LEVEL, so we either allocate + // only the base image, and clamp the min filter, or we allocate all of them. + if (levels > 1) { + levels = image::ComputeMipMapCount(width, height); + } +#endif if (!CreateGLImages(GL_TEXTURE_2D, gl_internal_format, gl_format, gl_data_type, TextureCUBE::FACE_POSITIVE_X, @@ -316,13 +364,6 @@ Texture2DGLES2* Texture2DGLES2::Create(ServiceLocator* service_locator, glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - GLint gl_width; - GLint gl_height; - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &gl_width); - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &gl_height); - - DLOG(INFO) << "Created 2D texture (size=" << gl_width << "x" << gl_height - << ", GLuint=" << gl_texture << ")"; Texture2DGLES2 *texture = new Texture2DGLES2(service_locator, gl_texture, format, @@ -478,6 +519,7 @@ bool Texture2DGLES2::PlatformSpecificLock( } if (mode != kWriteOnly && !HasLevel(level)) { DCHECK(!resize_to_pot_); +#if defined(GLES2_BACKEND_DESKTOP_GL) GLenum gl_internal_format = 0; GLenum gl_data_type = 0; GLenum gl_format = GLFormatFromO3DFormat(format(), @@ -485,6 +527,9 @@ bool Texture2DGLES2::PlatformSpecificLock( &gl_data_type); glBindTexture(GL_TEXTURE_2D, gl_texture_); glGetTexImage(GL_TEXTURE_2D, level, gl_format, gl_data_type, *data); +#else + NOTIMPLEMENTED() << "Texture read back"; +#endif has_levels_ |= 1 << level; } locked_levels_ |= 1 << level; @@ -617,8 +662,16 @@ TextureCUBEGLES2* TextureCUBEGLES2::Create(ServiceLocator* service_locator, GLuint gl_texture = 0; glGenTextures(1, &gl_texture); glBindTexture(GL_TEXTURE_CUBE_MAP, gl_texture); +#if defined(GLES2_BACKEND_DESKTOP_GL) glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, levels - 1); +#else + // On GLES2, we can't specify GL_TEXTURE_MAX_LEVEL, so we either allocate + // only the base image, and clamp the min filter, or we allocate all of them. + if (levels > 1) { + levels = image::ComputeMipMapCount(edge_length, edge_length); + } +#endif for (int face = 0; face < static_cast<int>(NUMBER_OF_FACES); ++face) { CreateGLImages(kCubemapFaceList[face], gl_internal_format, @@ -816,18 +869,22 @@ bool TextureCUBEGLES2::PlatformSpecificLock( unsigned bytes_per_row = bytes_per_block * blocks_across; *pitch = bytes_per_row; } - GLenum gl_target = kCubemapFaceList[face]; if (mode != kWriteOnly && !HasLevel(face, level)) { // TODO(o3d): add some API so we don't have to copy back the data if we // will rewrite it all. DCHECK(!resize_to_pot_); +#if defined(GLES2_BACKEND_DESKTOP_GL) GLenum gl_internal_format = 0; GLenum gl_data_type = 0; GLenum gl_format = GLFormatFromO3DFormat(format(), &gl_internal_format, &gl_data_type); glBindTexture(GL_TEXTURE_CUBE_MAP, gl_texture_); + GLenum gl_target = kCubemapFaceList[face]; glGetTexImage(gl_target, level, gl_format, gl_data_type, *data); +#else + NOTIMPLEMENTED() << "Texture read back"; +#endif has_levels_[face] |= 1 << level; } CHECK_GL_ERROR(); @@ -875,4 +932,3 @@ const Texture::RGBASwizzleIndices& } } // namespace o3d - diff --git a/o3d/plugin/cross/o3d_glue.h b/o3d/plugin/cross/o3d_glue.h index d732c13..3e7f8a7 100644 --- a/o3d/plugin/cross/o3d_glue.h +++ b/o3d/plugin/cross/o3d_glue.h @@ -41,7 +41,7 @@ #endif #ifdef OS_LINUX -#include <GL/glx.h> +#include <X11/Xlib.h> #include <X11/Intrinsic.h> #include <gtk/gtk.h> #endif diff --git a/o3d/plugin/plugin.gyp b/o3d/plugin/plugin.gyp index 9fca8f9..1e18f0b 100644 --- a/o3d/plugin/plugin.gyp +++ b/o3d/plugin/plugin.gyp @@ -212,11 +212,6 @@ '-Wl,-znodelete', '-Wl,--gc-sections', ], - 'link_settings': { - 'libraries': [ - '-lGL', - ], - }, 'conditions' : [ ['plugin_rpath != ""', { |