Commit 23299813 authored by yuweih's avatar yuweih Committed by Commit bot

[Remoting Android] Make EglThreadContext create OpenGL ES 3 context

Currently EglThreadContext only creates OpenGL ES 2 context. OpenGL ES 3 is
backward compatible with ES 2 and has new interfaces (e.g. GL_PACK_ROW_LENGTH)
that can improve the performance of the client OpenGL renderer.

This CL makes EglThreadContext create OpenGL ES context of the highest
version supported by the software or hardward of the device.

BUG=385924

Review-Url: https://codereview.chromium.org/2175913002
Cr-Commit-Position: refs/heads/master@{#407589}
parent faa507ce
......@@ -14,29 +14,18 @@ EglThreadContext::EglThreadContext() {
CHECK(eglGetCurrentContext() == EGL_NO_CONTEXT);
display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (!display_ || !eglInitialize(display_, NULL, NULL)) {
LOG(FATAL) << "Failed to initialize EGL display.";
LOG(FATAL) << "Failed to initialize EGL display: " << eglGetError();
}
const EGLint config_attribs[] = {
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_NONE
};
EGLint numConfigs;
if (!eglChooseConfig(display_, config_attribs, &config_, 1, &numConfigs)) {
LOG(FATAL) << "Failed to choose config.";
}
const EGLint context_attribs[] = {
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE
};
context_ = eglCreateContext(display_, config_, EGL_NO_CONTEXT,
context_attribs);
if (!context_) {
LOG(FATAL) << "Failed to create context.";
if (CreateContextWithClientVersion(EGL_OPENGL_ES3_BIT, GlVersion::ES_3)) {
client_version_ = GlVersion::ES_3;
} else if (CreateContextWithClientVersion(EGL_OPENGL_ES2_BIT,
GlVersion::ES_2)) {
LOG(WARNING) << "OpenGL ES 3 context not supported."
<< "Falled back to OpenGL ES 2";
client_version_ = GlVersion::ES_2;
} else {
LOG(FATAL) << "Failed to create context: " << eglGetError();
}
}
......@@ -59,13 +48,13 @@ void EglThreadContext::BindToWindow(EGLNativeWindowType window) {
if (window) {
surface_ = eglCreateWindowSurface(display_, config_, window, NULL);
if (!surface_) {
LOG(FATAL) << "Failed to create window surface.";
LOG(FATAL) << "Failed to create window surface: " << eglGetError();
}
} else {
surface_ = EGL_NO_SURFACE;
}
if (!eglMakeCurrent(display_, surface_, surface_, context_)) {
LOG(FATAL) << "Failed to make current.";
LOG(FATAL) << "Failed to make current: " << eglGetError();
}
}
......@@ -74,12 +63,46 @@ bool EglThreadContext::IsWindowBound() const {
return surface_ != EGL_NO_SURFACE;
}
void EglThreadContext::SwapBuffers() {
bool EglThreadContext::SwapBuffers() {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(IsWindowBound());
if (!IsWindowBound()) {
return false;
}
if (!eglSwapBuffers(display_, surface_)) {
LOG(FATAL) << "Failed to swap buffer.";
// Not fatal since the surface may be destroyed on a different thread
// earlier than the window is unbound. The context can still be reused
// after rebinding to the right window.
LOG(WARNING) << "Failed to swap buffer: " << eglGetError();
return false;
}
return true;
}
bool EglThreadContext::CreateContextWithClientVersion(
int renderable_type,
GlVersion client_version) {
DCHECK(client_version != GlVersion::UNKNOWN);
EGLint config_attribs[] = {
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_RENDERABLE_TYPE, renderable_type,
EGL_NONE
};
EGLint num_configs;
if (!eglChooseConfig(display_, config_attribs, &config_, 1, &num_configs)) {
LOG(WARNING) << "Failed to choose config: " << eglGetError();
return false;
}
EGLint context_attribs[] = {
EGL_CONTEXT_CLIENT_VERSION, static_cast<int>(client_version),
EGL_NONE
};
context_ = eglCreateContext(display_, config_, EGL_NO_CONTEXT,
context_attribs);
return context_ != EGL_NO_CONTEXT;
}
} // namespace remoting
......@@ -12,22 +12,18 @@
namespace remoting {
// Establishes an EGL-OpenGL|ES2 context on current thread. Must be constructed,
// used, and deleted on single thread (i.e. the display thread). Each thread can
// have no more than one EglThreadContext.
//
// An example use case:
// class DisplayHandler {
// void OnSurfaceCreated(ANativeWindow* surface) {
// context_.BindToWindow(surface);
// }
// void OnSurfaceDestroyed() {
// context_.BindToWindow(nullptr);
// }
// EglThreadContext context_;
// };
// Establishes an EGL-OpenGL|ES 2 (if 3 is not supported) or 3 (backward
// compatible with 2) context on current thread. Must be constructed, used, and
// deleted on single thread (i.e. the display thread). Each thread can have no
// more than one EglThreadContext.
class EglThreadContext {
public:
enum class GlVersion {
UNKNOWN = 0,
ES_2 = 2,
ES_3 = 3
};
EglThreadContext();
~EglThreadContext();
......@@ -36,19 +32,32 @@ class EglThreadContext {
// EGLNativeWindowType is platform specific. E.g. ANativeWindow* on Android.
void BindToWindow(EGLNativeWindowType window);
// Returns true IFF the context is bound to a window (i.e. current surface is
// Returns true if the context is bound to a window (i.e. current surface is
// not NULL).
bool IsWindowBound() const;
// Posts EGL surface buffer to the window being bound. Window must be bound
// before calling this function.
void SwapBuffers();
// Posts EGL surface buffer to the window being bound.
// Returns true if the buffer is successfully swapped.
bool SwapBuffers();
// Returns the current OpenGL ES client version of the EGL context.
GlVersion client_version() const {
return client_version_;
}
private:
// Creates an EGLContext with given |renderable_type| and |client_version|.
// |renderable_type| and |client_version| must match with each other.
// E.g. renderable_type = EGL_OPENGL_ES3_BIT,
// client_version = CLIENT_VERSION_ES_3.
bool CreateContextWithClientVersion(int renderable_type,
GlVersion client_version);
EGLDisplay display_ = EGL_NO_DISPLAY;
EGLConfig config_ = nullptr;
EGLSurface surface_ = EGL_NO_SURFACE;
EGLContext context_ = EGL_NO_CONTEXT;
GlVersion client_version_ = GlVersion::UNKNOWN;
base::ThreadChecker thread_checker_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment