summaryrefslogtreecommitdiffstats
path: root/app
diff options
context:
space:
mode:
authorpiman@chromium.org <piman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-06-21 22:20:02 +0000
committerpiman@chromium.org <piman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-06-21 22:20:02 +0000
commit0bec8e295393f7512129be1fe91cbea9f9dc521a (patch)
tree7a9e18365fa1c5d432e566a92b13987825177b53 /app
parent50fb3e7c3445d50bccf9b9d91654c89ab132df3f (diff)
downloadchromium_src-0bec8e295393f7512129be1fe91cbea9f9dc521a.zip
chromium_src-0bec8e295393f7512129be1fe91cbea9f9dc521a.tar.gz
chromium_src-0bec8e295393f7512129be1fe91cbea9f9dc521a.tar.bz2
gpu: add GLES/EGL support on linux
Review URL: http://codereview.chromium.org/2829007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@50397 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'app')
-rw-r--r--app/app_base.gypi8
-rw-r--r--app/gfx/gl/generate_bindings.py8
-rw-r--r--app/gfx/gl/gl_bindings.h15
-rw-r--r--app/gfx/gl/gl_context_egl.cc86
-rw-r--r--app/gfx/gl/gl_context_egl.h1
-rw-r--r--app/gfx/gl/gl_context_linux.cc25
-rw-r--r--app/gfx/gl/gl_implementation_linux.cc93
7 files changed, 204 insertions, 32 deletions
diff --git a/app/app_base.gypi b/app/app_base.gypi
index 247118a..5cd97ee 100644
--- a/app/app_base.gypi
+++ b/app/app_base.gypi
@@ -300,9 +300,17 @@
}],
['OS=="linux"', {
'sources': [
+ 'gfx/gl/gl_context_egl.cc',
+ 'gfx/gl/gl_context_egl.h',
+ '<(gl_binding_output_dir)/gl_bindings_autogen_egl.cc',
+ '<(gl_binding_output_dir)/gl_bindings_autogen_egl.h',
'<(gl_binding_output_dir)/gl_bindings_autogen_glx.cc',
'<(gl_binding_output_dir)/gl_bindings_autogen_glx.h',
],
+ 'include_dirs': [
+ # We don't use angle, but pull the EGL/GLES headers from there.
+ '../third_party/angle/include',
+ ],
'all_dependent_settings': {
'defines': [
'GL_GLEXT_PROTOTYPES',
diff --git a/app/gfx/gl/generate_bindings.py b/app/gfx/gl/generate_bindings.py
index 7aaf6d4..0adf603 100644
--- a/app/gfx/gl/generate_bindings.py
+++ b/app/gfx/gl/generate_bindings.py
@@ -246,7 +246,7 @@ OSMESA_FUNCTIONS = [
EGL_FUNCTIONS = [
['EGLint', ['eglGetError'], 'void'],
-['EGLDisplay', ['eglGetDisplay'], 'void* display_id'],
+['EGLDisplay', ['eglGetDisplay'], 'EGLNativeDisplayType display_id'],
['EGLBoolean', ['eglInitialize'],
'EGLDisplay dpy, EGLint* major, EGLint* minor'],
['EGLBoolean', ['eglTerminate'], 'EGLDisplay dpy'],
@@ -260,11 +260,11 @@ EGL_FUNCTIONS = [
['EGLBoolean', ['eglGetConfigAttrib'],
'EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint* value'],
['EGLSurface', ['eglCreateWindowSurface'],
- 'EGLDisplay dpy, EGLConfig config, void* win, const EGLint* attrib_list'],
+ 'EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint* attrib_list'],
['EGLSurface', ['eglCreatePbufferSurface'],
'EGLDisplay dpy, EGLConfig config, const EGLint* attrib_list'],
['EGLSurface', ['eglCreatePixmapSurface'],
- 'EGLDisplay dpy, EGLConfig config, void* pixmap, '
+ 'EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, '
'const EGLint* attrib_list'],
['EGLBoolean', ['eglDestroySurface'], 'EGLDisplay dpy, EGLSurface surface'],
['EGLBoolean', ['eglQuerySurface'],
@@ -298,7 +298,7 @@ EGL_FUNCTIONS = [
['EGLBoolean', ['eglWaitNative'], 'EGLint engine'],
['EGLBoolean', ['eglSwapBuffers'], 'EGLDisplay dpy, EGLSurface surface'],
['EGLBoolean', ['eglCopyBuffers'],
- 'EGLDisplay dpy, EGLSurface surface, void* target'],
+ 'EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target'],
['__eglMustCastToProperFunctionPointerType', ['eglGetProcAddress'],
'const char* procname'],
]
diff --git a/app/gfx/gl/gl_bindings.h b/app/gfx/gl/gl_bindings.h
index c9dbbee..e384bfd 100644
--- a/app/gfx/gl/gl_bindings.h
+++ b/app/gfx/gl/gl_bindings.h
@@ -42,7 +42,7 @@
typedef struct osmesa_context *OSMesaContext;
typedef void (*OSMESAproc)();
-#if defined(OS_WIN)
+#if defined(OS_WIN) || defined(OS_LINUX)
// Forward declare EGL types.
typedef unsigned int EGLBoolean;
@@ -55,7 +55,17 @@ typedef void *EGLSurface;
typedef void *EGLClientBuffer;
typedef void (*__eglMustCastToProperFunctionPointerType)(void);
-#endif // OS_WIN
+#if defined(OS_WIN)
+typedef HDC EGLNativeDisplayType;
+typedef HBITMAP EGLNativePixmapType;
+typedef HWND EGLNativeWindowType;
+#else
+typedef Display *EGLNativeDisplayType;
+typedef Pixmap EGLNativePixmapType;
+typedef Window EGLNativeWindowType;
+#endif
+
+#endif // OS_WIN || OS_LINUX
#include "gl_bindings_autogen_gl.h"
#include "gl_bindings_autogen_osmesa.h"
@@ -64,6 +74,7 @@ typedef void (*__eglMustCastToProperFunctionPointerType)(void);
#include "gl_bindings_autogen_egl.h"
#include "gl_bindings_autogen_wgl.h"
#elif defined(OS_LINUX)
+#include "gl_bindings_autogen_egl.h"
#include "gl_bindings_autogen_glx.h"
#endif
diff --git a/app/gfx/gl/gl_context_egl.cc b/app/gfx/gl/gl_context_egl.cc
index ec64ae91..4bea175 100644
--- a/app/gfx/gl/gl_context_egl.cc
+++ b/app/gfx/gl/gl_context_egl.cc
@@ -4,6 +4,11 @@
#include <EGL/egl.h>
+#include "build/build_config.h"
+#if defined(OS_LINUX)
+#include "app/x11_util.h"
+#define EGL_HAS_PBUFFERS 1
+#endif
#include "base/scoped_ptr.h"
#include "app/gfx/gl/gl_bindings.h"
#include "app/gfx/gl/gl_context_egl.h"
@@ -21,7 +26,12 @@ bool InitializeOneOff() {
if (initialized)
return true;
- g_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+#ifdef OS_LINUX
+ EGLNativeDisplayType native_display = x11_util::GetXDisplay();
+#else
+ EGLNativeDisplayType native_display = EGL_DEFAULT_DISPLAY;
+#endif
+ g_display = eglGetDisplay(native_display);
if (!g_display)
return false;
@@ -34,9 +44,14 @@ bool InitializeOneOff() {
EGL_ALPHA_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_RED_SIZE, 8,
- EGL_DEPTH_SIZE, 24,
+ EGL_DEPTH_SIZE, 16,
EGL_STENCIL_SIZE, 8,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+#ifdef EGL_HAS_PBUFFERS
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
+#else
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+#endif
EGL_NONE
};
@@ -85,10 +100,10 @@ bool NativeViewEGLContext::Initialize() {
return NULL;
// Create a surface for the native window.
- surface_ = eglCreateWindowSurface(g_display,
- g_config,
- static_cast<EGLNativeWindowType>(window_),
- NULL);
+ EGLNativeWindowType native_window =
+ reinterpret_cast<EGLNativeWindowType>(window_);
+ surface_ = eglCreateWindowSurface(g_display, g_config, native_window, NULL);
+
if (!surface_) {
Destroy();
return false;
@@ -152,8 +167,13 @@ gfx::Size NativeViewEGLContext::GetSize() {
CHECK(GetClientRect(static_cast<HWND>(window_), &rect));
return gfx::Size(rect.right - rect.left, rect.bottom - rect.top);
#else
- NOTREACHED()
- << "NativeViewEGLContext::GetSize not implemented on this platform.";
+ // TODO(piman): This doesn't work correctly on Windows yet, the size doesn't
+ // get updated on resize. When it does, we can share the code.
+ EGLint width;
+ EGLint height;
+ CHECK(eglQuerySurface(g_display, surface_, EGL_WIDTH, &width));
+ CHECK(eglQuerySurface(g_display, surface_, EGL_HEIGHT, &height));
+ return gfx::Size(width, height);
#endif
}
@@ -167,6 +187,7 @@ EGLSurface NativeViewEGLContext::GetSurface() {
SecondaryEGLContext::SecondaryEGLContext()
: surface_(NULL),
+ own_surface_(false),
context_(NULL)
{
}
@@ -175,20 +196,51 @@ SecondaryEGLContext::~SecondaryEGLContext() {
}
bool SecondaryEGLContext::Initialize(GLContext* shared_context) {
- DCHECK(shared_context);
DCHECK(!context_);
if (!InitializeOneOff())
return NULL;
- surface_ = static_cast<BaseEGLContext*>(shared_context)->GetSurface();
+ static const EGLint kContextAttributes[] = {
+ EGL_CONTEXT_CLIENT_VERSION, 2,
+ EGL_NONE
+ };
+
+ if (shared_context) {
+ surface_ = static_cast<BaseEGLContext*>(shared_context)->GetSurface();
+ own_surface_ = false;
+
+ // Create a context.
+ context_ = eglCreateContext(g_display,
+ g_config,
+ shared_context->GetHandle(),
+ kContextAttributes);
+ } else {
+#ifdef EGL_HAS_PBUFFERS
+ static const EGLint kPbufferAttribs[] = {
+ EGL_WIDTH, 1,
+ EGL_HEIGHT, 1,
+ EGL_NONE
+ };
+
+ surface_ = eglCreatePbufferSurface(g_display, g_config, kPbufferAttribs);
+ if (!surface_) {
+ EGLint error = eglGetError();
+ LOG(ERROR) << "Error creating Pbuffer: " << error;
+ return false;
+ }
+ own_surface_ = true;
+
+ context_ = eglCreateContext(g_display, g_config, NULL, kContextAttributes);
+#else
+ NOTIMPLEMENTED() << "Offscreen non-shared GLES context";
+ return false;
+#endif
+ }
- // Create a context.
- context_ = eglCreateContext(g_display,
- g_config,
- shared_context->GetHandle(),
- NULL);
if (!context_) {
+ EGLint error = eglGetError();
+ LOG(ERROR) << "Error creating context: " << error;
Destroy();
return false;
}
@@ -197,6 +249,10 @@ bool SecondaryEGLContext::Initialize(GLContext* shared_context) {
}
void SecondaryEGLContext::Destroy() {
+ if (own_surface_) {
+ eglDestroySurface(g_display, surface_);
+ own_surface_ = false;
+ }
surface_ = NULL;
if (context_) {
diff --git a/app/gfx/gl/gl_context_egl.h b/app/gfx/gl/gl_context_egl.h
index 4bfff9b..016a770 100644
--- a/app/gfx/gl/gl_context_egl.h
+++ b/app/gfx/gl/gl_context_egl.h
@@ -83,6 +83,7 @@ class SecondaryEGLContext : public BaseEGLContext {
private:
// All offscreen
EGLSurface surface_;
+ bool own_surface_;
EGLContext context_;
DISALLOW_COPY_AND_ASSIGN(SecondaryEGLContext);
diff --git a/app/gfx/gl/gl_context_linux.cc b/app/gfx/gl/gl_context_linux.cc
index d2c5a4f..550f967 100644
--- a/app/gfx/gl/gl_context_linux.cc
+++ b/app/gfx/gl/gl_context_linux.cc
@@ -9,6 +9,7 @@
#include "base/scoped_ptr.h"
#include "app/gfx/gl/gl_bindings.h"
#include "app/gfx/gl/gl_context.h"
+#include "app/gfx/gl/gl_context_egl.h"
#include "app/gfx/gl/gl_context_osmesa.h"
#include "app/gfx/gl/gl_context_stub.h"
#include "app/gfx/gl/gl_implementation.h"
@@ -120,9 +121,11 @@ static bool InitializeOneOff() {
// Initialize the GL bindings if they haven't already been initialized. If
// the GPU unit tests are running, the mock GL implementation will already
// have been initialized.
- if (!InitializeGLBindings(kGLImplementationDesktopGL)) {
- LOG(ERROR) << "Could not initialize GL.";
- return false;
+ if (!InitializeGLBindings(kGLImplementationEGLGLES2)) {
+ if (!InitializeGLBindings(kGLImplementationDesktopGL)) {
+ LOG(ERROR) << "Could not initialize GL.";
+ return false;
+ }
}
// Only check the GLX version if we are in fact using GLX. We might actually
@@ -255,6 +258,14 @@ GLContext* GLContext::CreateViewGLContext(gfx::PluginWindowHandle window,
return context.release();
}
+ case kGLImplementationEGLGLES2: {
+ scoped_ptr<NativeViewEGLContext> context(
+ new NativeViewEGLContext(reinterpret_cast<void *>(window)));
+ if (!context->Initialize())
+ return NULL;
+
+ return context.release();
+ }
case kGLImplementationMockGL:
return new StubGLContext;
default:
@@ -518,6 +529,14 @@ GLContext* GLContext::CreateOffscreenGLContext(GLContext* shared_context) {
return NULL;
}
+ case kGLImplementationEGLGLES2: {
+ scoped_ptr<SecondaryEGLContext> context(
+ new SecondaryEGLContext());
+ if (!context->Initialize(shared_context))
+ return NULL;
+
+ return context.release();
+ }
case kGLImplementationMockGL:
return new StubGLContext;
default:
diff --git a/app/gfx/gl/gl_implementation_linux.cc b/app/gfx/gl/gl_implementation_linux.cc
index e27cdae..3bad24e 100644
--- a/app/gfx/gl/gl_implementation_linux.cc
+++ b/app/gfx/gl/gl_implementation_linux.cc
@@ -3,7 +3,9 @@
// found in the LICENSE file.
#include <dlfcn.h>
+#include <vector>
+#include "base/at_exit.h"
#include "base/logging.h"
#include "app/gfx/gl/gl_bindings.h"
#include "app/gfx/gl/gl_context_stub.h"
@@ -14,8 +16,32 @@ namespace {
typedef void* (*GetProcAddressProc)(const char* name);
GLImplementation g_gl_implementation = kGLImplementationNone;
-void* g_shared_library;
+typedef std::vector<void*> PointerArray;
+PointerArray* g_shared_libraries = NULL;
GetProcAddressProc g_get_proc_address;
+
+// TODO(piman): it should be Desktop GL marshalling from double to float. Today
+// on native GLES, we do float->double->float.
+void GL_BINDING_CALL MarshalClearDepthToClearDepthf(GLclampd depth) {
+ glClearDepthf(static_cast<GLclampf>(depth));
+}
+
+void GL_BINDING_CALL MarshalDepthRangeToDepthRangef(GLclampd z_near,
+ GLclampd z_far) {
+ glDepthRangef(static_cast<GLclampf>(z_near), static_cast<GLclampf>(z_far));
+}
+
+void CleanupSharedLibraries(void* unused) {
+ if (g_shared_libraries) {
+ for (PointerArray::iterator it = g_shared_libraries->begin();
+ it != g_shared_libraries->end(); ++it) {
+ dlclose(*it);
+ }
+ delete g_shared_libraries;
+ g_shared_libraries = NULL;
+ }
+}
+
} // namespace anonymous
bool InitializeGLBindings(GLImplementation implementation) {
@@ -25,22 +51,70 @@ bool InitializeGLBindings(GLImplementation implementation) {
if (g_gl_implementation != kGLImplementationNone)
return true;
+ if (!g_shared_libraries) {
+ g_shared_libraries = new PointerArray();
+ base::AtExitManager::RegisterCallback(CleanupSharedLibraries, NULL);
+ }
+
+ void* shared_library = NULL;
+
switch (implementation) {
case kGLImplementationDesktopGL:
- g_shared_library = dlopen("libGL.so.1", RTLD_LAZY | RTLD_LOCAL);
- if (!g_shared_library)
+ DLOG(INFO) << "Initializing Desktop GL";
+ shared_library = dlopen("libGL.so.1", RTLD_LAZY | RTLD_LOCAL);
+ if (!shared_library) {
+ DLOG(ERROR) << "Failed to load libGL.so.1";
return false;
+ }
+
+ g_shared_libraries->push_back(shared_library);
g_gl_implementation = kGLImplementationDesktopGL;
g_get_proc_address = reinterpret_cast<GetProcAddressProc>(
- dlsym(g_shared_library, "glXGetProcAddress"));
+ dlsym(shared_library, "glXGetProcAddress"));
CHECK(g_get_proc_address);
InitializeGLBindingsGL();
InitializeGLBindingsGLX();
break;
+ case kGLImplementationEGLGLES2:
+ DLOG(INFO) << "Initializing EGL";
+ shared_library = dlopen("libEGL.so", RTLD_LAZY | RTLD_LOCAL);
+ if (!shared_library) {
+ DLOG(ERROR) << "Failed to load libEGL.so";
+ return false;
+ }
+
+ g_gl_implementation = kGLImplementationEGLGLES2;
+
+ g_get_proc_address = reinterpret_cast<GetProcAddressProc>(
+ dlsym(shared_library, "eglGetProcAddress"));
+ DCHECK(g_get_proc_address);
+
+ g_shared_libraries->push_back(shared_library);
+
+ shared_library = dlopen("libGLESv2.so", RTLD_LAZY | RTLD_LOCAL);
+ if (!shared_library) {
+ DLOG(ERROR) << "Failed to load libGLESv2.so";
+ g_shared_libraries->clear();
+ return false;
+ }
+
+ DCHECK(shared_library);
+
+ g_shared_libraries->push_back(shared_library);
+
+ InitializeGLBindingsGL();
+ InitializeGLBindingsEGL();
+
+ // These two functions take single precision float rather than double
+ // precision float parameters in GLES.
+ ::gfx::g_glClearDepth = MarshalClearDepthToClearDepthf;
+ ::gfx::g_glDepthRange = MarshalDepthRangeToDepthRangef;
+ break;
+
case kGLImplementationMockGL:
g_get_proc_address = GetMockGLProcAddress;
g_gl_implementation = kGLImplementationMockGL;
@@ -68,10 +142,13 @@ void* GetGLProcAddress(const char* name) {
return proc;
}
- if (g_shared_library) {
- void* proc = dlsym(g_shared_library, name);
- if (proc)
- return proc;
+ if (g_shared_libraries) {
+ for (PointerArray::iterator it = g_shared_libraries->begin();
+ it != g_shared_libraries->end(); ++it) {
+ void* proc = dlsym(*it, name);
+ if (proc)
+ return proc;
+ }
}
return NULL;