Use a surfaceless EGL context if possible instead of a dummy pbuffer
This commit is contained in:
parent
5be5550d7b
commit
a2294b229a
3 changed files with 77 additions and 16 deletions
|
|
@ -125,6 +125,7 @@ set(SOURCES
|
||||||
anbox/graphics/program_family.cpp
|
anbox/graphics/program_family.cpp
|
||||||
anbox/graphics/primitives.h
|
anbox/graphics/primitives.h
|
||||||
anbox/graphics/renderer.h
|
anbox/graphics/renderer.h
|
||||||
|
anbox/graphics/gl_extensions.h
|
||||||
|
|
||||||
anbox/graphics/emugl/ColorBuffer.cpp
|
anbox/graphics/emugl/ColorBuffer.cpp
|
||||||
anbox/graphics/emugl/DisplayManager.cpp
|
anbox/graphics/emugl/DisplayManager.cpp
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@
|
||||||
|
|
||||||
#include "OpenGLESDispatch/EGLDispatch.h"
|
#include "OpenGLESDispatch/EGLDispatch.h"
|
||||||
|
|
||||||
|
#include "anbox/graphics/gl_extensions.h"
|
||||||
|
|
||||||
#include "anbox/logger.h"
|
#include "anbox/logger.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
@ -78,7 +80,6 @@ class ColorBufferHelper : public ColorBuffer::Helper {
|
||||||
private:
|
private:
|
||||||
Renderer *mFb;
|
Renderer *mFb;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
HandleType Renderer::s_nextHandle = 0;
|
HandleType Renderer::s_nextHandle = 0;
|
||||||
|
|
@ -105,11 +106,9 @@ static char *getGLES1ExtensionString(EGLDisplay p_dpy) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const GLint gles1ContextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 1,
|
static const GLint gles1ContextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 1, EGL_NONE};
|
||||||
EGL_NONE};
|
|
||||||
|
|
||||||
EGLContext ctx = s_egl.eglCreateContext(p_dpy, config, EGL_NO_CONTEXT,
|
EGLContext ctx = s_egl.eglCreateContext(p_dpy, config, EGL_NO_CONTEXT, gles1ContextAttribs);
|
||||||
gles1ContextAttribs);
|
|
||||||
if (ctx == EGL_NO_CONTEXT) {
|
if (ctx == EGL_NO_CONTEXT) {
|
||||||
ERROR("%s: Could not create GLES 1.x Context!", __FUNCTION__);
|
ERROR("%s: Could not create GLES 1.x Context!", __FUNCTION__);
|
||||||
s_egl.eglDestroySurface(p_dpy, surface);
|
s_egl.eglDestroySurface(p_dpy, surface);
|
||||||
|
|
@ -156,6 +155,12 @@ bool Renderer::initialize(EGLNativeDisplayType nativeDisplay) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
anbox::graphics::GLExtensions egl_extensions{s_egl.eglQueryString(m_eglDisplay, EGL_EXTENSIONS)};
|
||||||
|
|
||||||
|
const auto surfaceless_supported = egl_extensions.support("EGL_KHR_surfaceless_context");
|
||||||
|
if (!surfaceless_supported)
|
||||||
|
DEBUG("EGL doesn't support surfaceless context");
|
||||||
|
|
||||||
s_egl.eglBindAPI(EGL_OPENGL_ES_API);
|
s_egl.eglBindAPI(EGL_OPENGL_ES_API);
|
||||||
|
|
||||||
// If GLES2 plugin was loaded - try to make GLES2 context and
|
// If GLES2 plugin was loaded - try to make GLES2 context and
|
||||||
|
|
@ -201,24 +206,27 @@ bool Renderer::initialize(EGLNativeDisplayType nativeDisplay) {
|
||||||
// The main purpose of it is to solve a "blanking" behaviour we see on
|
// The main purpose of it is to solve a "blanking" behaviour we see on
|
||||||
// on Mac platform when switching binded drawable for a context however
|
// on Mac platform when switching binded drawable for a context however
|
||||||
// it is more efficient on other platforms as well.
|
// it is more efficient on other platforms as well.
|
||||||
m_pbufContext = s_egl.eglCreateContext(
|
m_pbufContext = s_egl.eglCreateContext(m_eglDisplay, m_eglConfig, m_eglContext, glContextAttribs);
|
||||||
m_eglDisplay, m_eglConfig, m_eglContext, glContextAttribs);
|
|
||||||
if (m_pbufContext == EGL_NO_CONTEXT) {
|
if (m_pbufContext == EGL_NO_CONTEXT) {
|
||||||
ERROR("Failed to create pbuffer context: error=0x%x", s_egl.eglGetError());
|
ERROR("Failed to create pbuffer context: error=0x%x", s_egl.eglGetError());
|
||||||
free(gles1Extensions);
|
free(gles1Extensions);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a 1x1 pbuffer surface which will be used for binding
|
if (!surfaceless_supported) {
|
||||||
// the FB context. The FB output will go to a subwindow, if one exist.
|
// Create a 1x1 pbuffer surface which will be used for binding
|
||||||
static const EGLint pbufAttribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
|
// the FB context. The FB output will go to a subwindow, if one exist.
|
||||||
|
static const EGLint pbufAttribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE};
|
||||||
|
|
||||||
m_pbufSurface = s_egl.eglCreatePbufferSurface(
|
m_pbufSurface = s_egl.eglCreatePbufferSurface(m_eglDisplay, m_eglConfig, pbufAttribs);
|
||||||
m_eglDisplay, m_eglConfig, pbufAttribs);
|
if (m_pbufSurface == EGL_NO_SURFACE) {
|
||||||
if (m_pbufSurface == EGL_NO_SURFACE) {
|
ERROR("Failed to create pbuffer surface: error=0x%x", s_egl.eglGetError());
|
||||||
ERROR("Failed to create pbuffer surface: error=0x%x", s_egl.eglGetError());
|
free(gles1Extensions);
|
||||||
free(gles1Extensions);
|
return false;
|
||||||
return false;
|
}
|
||||||
|
} else {
|
||||||
|
DEBUG("Using a surfaceless EGL context");
|
||||||
|
m_pbufSurface = EGL_NO_SURFACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make the context current
|
// Make the context current
|
||||||
|
|
|
||||||
52
src/anbox/graphics/gl_extensions.h
Normal file
52
src/anbox/graphics/gl_extensions.h
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2017 Simon Fels <morphis@gravedo.de>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 3, as published
|
||||||
|
* by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranties of
|
||||||
|
* MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
|
||||||
|
* PURPOSE. See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ANBOX_GRAPHICS_GL_EXTENSIONS_H_
|
||||||
|
#define ANBOX_GRAPHICS_GL_EXTENSIONS_H_
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
namespace anbox {
|
||||||
|
namespace graphics {
|
||||||
|
class GLExtensions {
|
||||||
|
public:
|
||||||
|
GLExtensions(char const* extensions) : extensions{extensions} {
|
||||||
|
if (!extensions)
|
||||||
|
throw std::runtime_error("Couldn't get list of GL extensions");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool support(char const* ext) const {
|
||||||
|
char const* ext_ptr = extensions;
|
||||||
|
size_t const len = strlen(ext);
|
||||||
|
while ((ext_ptr = strstr(ext_ptr, ext)) != nullptr) {
|
||||||
|
if (ext_ptr[len] == ' ' || ext_ptr[len] == '\0')
|
||||||
|
break;
|
||||||
|
ext_ptr += len;
|
||||||
|
}
|
||||||
|
return ext_ptr != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
char const* raw() { return extensions; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
char const* extensions;
|
||||||
|
};
|
||||||
|
} // namespace graphics
|
||||||
|
} // namespace anbox
|
||||||
|
|
||||||
|
#endif
|
||||||
Loading…
Add table
Add a link
Reference in a new issue