| Index: gpu/gles2_conform_support/egl/egl.cc
|
| diff --git a/gpu/gles2_conform_support/egl/egl.cc b/gpu/gles2_conform_support/egl/egl.cc
|
| index b14479bc3b944ae23809a3b8e3502d3d79f95d19..5a81954bd10d4ad4368cd603df5a20dfe3306663 100644
|
| --- a/gpu/gles2_conform_support/egl/egl.cc
|
| +++ b/gpu/gles2_conform_support/egl/egl.cc
|
| @@ -5,58 +5,184 @@
|
| #include <EGL/egl.h>
|
| #include <stdint.h>
|
|
|
| +#include "base/command_line.h"
|
| +#include "base/environment.h"
|
| +#include "base/strings/string_split.h"
|
| +#include "base/strings/string_util.h"
|
| +#include "base/strings/utf_string_conversions.h"
|
| #include "gpu/command_buffer/client/gles2_lib.h"
|
| -#include "gpu/gles2_conform_support/egl/config.h"
|
| -#include "gpu/gles2_conform_support/egl/context.h"
|
| +#include "gpu/command_buffer/service/gpu_switches.h"
|
| +#include "gpu/config/gpu_info_collector.h"
|
| +#include "gpu/config/gpu_util.h"
|
| #include "gpu/gles2_conform_support/egl/display.h"
|
| -#include "gpu/gles2_conform_support/egl/surface.h"
|
| -#include "gpu/gles2_conform_support/egl/thread_state.h"
|
| +#include "ui/gl/gl_context.h"
|
| +#include "ui/gl/gl_surface.h"
|
| +
|
| +#if REGAL_STATIC_EGL
|
| +extern "C" {
|
| +
|
| +typedef EGLContext RegalSystemContext;
|
| +#define REGAL_DECL
|
| +REGAL_DECL void RegalMakeCurrent( RegalSystemContext ctx );
|
| +
|
| +} // extern "C"
|
| +#endif
|
| +
|
| +namespace {
|
| +void SetCurrentError(EGLint error_code) {
|
| +}
|
| +
|
| +template<typename T>
|
| +T EglError(EGLint error_code, T return_value) {
|
| + SetCurrentError(error_code);
|
| + return return_value;
|
| +}
|
| +
|
| +template<typename T>
|
| +T EglSuccess(T return_value) {
|
| + SetCurrentError(EGL_SUCCESS);
|
| + return return_value;
|
| +}
|
| +
|
| +EGLint ValidateDisplay(EGLDisplay dpy) {
|
| + if (dpy == EGL_NO_DISPLAY)
|
| + return EGL_BAD_DISPLAY;
|
| +
|
| + egl::Display* display = static_cast<egl::Display*>(dpy);
|
| + if (!display->is_initialized())
|
| + return EGL_NOT_INITIALIZED;
|
| +
|
| + return EGL_SUCCESS;
|
| +}
|
| +
|
| +EGLint ValidateDisplayConfig(EGLDisplay dpy, EGLConfig config) {
|
| + EGLint error_code = ValidateDisplay(dpy);
|
| + if (error_code != EGL_SUCCESS)
|
| + return error_code;
|
| +
|
| + egl::Display* display = static_cast<egl::Display*>(dpy);
|
| + if (!display->IsValidConfig(config))
|
| + return EGL_BAD_CONFIG;
|
| +
|
| + return EGL_SUCCESS;
|
| +}
|
| +
|
| +EGLint ValidateDisplaySurface(EGLDisplay dpy, EGLSurface surface) {
|
| + EGLint error_code = ValidateDisplay(dpy);
|
| + if (error_code != EGL_SUCCESS)
|
| + return error_code;
|
| +
|
| + egl::Display* display = static_cast<egl::Display*>(dpy);
|
| + if (!display->IsValidSurface(surface))
|
| + return EGL_BAD_SURFACE;
|
| +
|
| + return EGL_SUCCESS;
|
| +}
|
| +
|
| +EGLint ValidateDisplayContext(EGLDisplay dpy, EGLContext context) {
|
| + EGLint error_code = ValidateDisplay(dpy);
|
| + if (error_code != EGL_SUCCESS)
|
| + return error_code;
|
| +
|
| + egl::Display* display = static_cast<egl::Display*>(dpy);
|
| + if (!display->IsValidContext(context))
|
| + return EGL_BAD_CONTEXT;
|
| +
|
| + return EGL_SUCCESS;
|
| +}
|
| +} // namespace
|
|
|
| extern "C" {
|
| EGLAPI EGLint EGLAPIENTRY eglGetError() {
|
| - return egl::ThreadState::Get()->ConsumeErrorCode();
|
| + // TODO(alokp): Fix me.
|
| + return EGL_SUCCESS;
|
| }
|
|
|
| EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id) {
|
| - if (display_id != EGL_DEFAULT_DISPLAY)
|
| - return EGL_NO_DISPLAY;
|
| - return egl::ThreadState::Get()->GetDefaultDisplay();
|
| + return new egl::Display(display_id);
|
| }
|
|
|
| EGLAPI EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay dpy,
|
| EGLint* major,
|
| EGLint* minor) {
|
| - egl::ThreadState* ts = egl::ThreadState::Get();
|
| - egl::Display* display = ts->GetDisplay(dpy);
|
| - if (!display)
|
| - return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE);
|
| - return display->Initialize(ts, major, minor);
|
| + if (dpy == EGL_NO_DISPLAY)
|
| + return EglError(EGL_BAD_DISPLAY, EGL_FALSE);
|
| +
|
| + egl::Display* display = static_cast<egl::Display*>(dpy);
|
| + if (!display->Initialize())
|
| + return EglError(EGL_NOT_INITIALIZED, EGL_FALSE);
|
| +
|
| + // eglInitialize can be called multiple times, prevent InitializeOneOff from
|
| + // being called multiple times.
|
| + if (gfx::GetGLImplementation() == gfx::kGLImplementationNone) {
|
| + base::CommandLine::StringVector argv;
|
| + scoped_ptr<base::Environment> env(base::Environment::Create());
|
| + std::string env_string;
|
| + env->GetVar("CHROME_COMMAND_BUFFER_GLES2_ARGS", &env_string);
|
| +#if defined(OS_WIN)
|
| + argv = base::SplitString(base::UTF8ToUTF16(env_string),
|
| + base::kWhitespaceUTF16, base::TRIM_WHITESPACE,
|
| + base::SPLIT_WANT_NONEMPTY);
|
| + argv.insert(argv.begin(), base::UTF8ToUTF16("dummy"));
|
| +#else
|
| + argv = base::SplitString(env_string,
|
| + base::kWhitespaceASCII, base::TRIM_WHITESPACE,
|
| + base::SPLIT_WANT_NONEMPTY);
|
| + argv.insert(argv.begin(), "dummy");
|
| +#endif
|
| + base::CommandLine::Init(0, nullptr);
|
| + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
|
| + // Need to call both Init and InitFromArgv, since Windows does not use
|
| + // argc, argv in CommandLine::Init(argc, argv).
|
| + command_line->InitFromArgv(argv);
|
| + if (!command_line->HasSwitch(switches::kDisableGpuDriverBugWorkarounds)) {
|
| + gpu::GPUInfo gpu_info;
|
| + gpu::CollectBasicGraphicsInfo(&gpu_info);
|
| + gpu::ApplyGpuDriverBugWorkarounds(gpu_info, command_line);
|
| + }
|
| +
|
| + gfx::GLSurface::InitializeOneOff();
|
| + }
|
| + if (major)
|
| + *major = 1;
|
| + if (minor)
|
| + *minor = 4;
|
| + return EglSuccess(EGL_TRUE);
|
| }
|
|
|
| EGLAPI EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay dpy) {
|
| - egl::ThreadState* ts = egl::ThreadState::Get();
|
| - egl::Display* display = ts->GetDisplay(dpy);
|
| - if (!display)
|
| - return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE);
|
| - return display->Terminate(ts);
|
| + EGLint error_code = ValidateDisplay(dpy);
|
| + if (error_code != EGL_SUCCESS)
|
| + return EglError(error_code, EGL_FALSE);
|
| +
|
| + egl::Display* display = static_cast<egl::Display*>(dpy);
|
| + delete display;
|
| +
|
| + // TODO: EGL specifies that the objects are marked for deletion and they will
|
| + // remain alive as long as "contexts or surfaces associated with display is
|
| + // current to any thread".
|
| + // Currently we delete the display here, and may also call exit handlers.
|
| +
|
| + return EglSuccess(EGL_TRUE);
|
| }
|
|
|
| EGLAPI const char* EGLAPIENTRY eglQueryString(EGLDisplay dpy, EGLint name) {
|
| - egl::ThreadState* ts = egl::ThreadState::Get();
|
| - if (dpy == EGL_NO_DISPLAY) {
|
| - switch (name) {
|
| - case EGL_EXTENSIONS:
|
| - return ts->ReturnSuccess("");
|
| - case EGL_VERSION:
|
| - return ts->ReturnSuccess("1.4");
|
| - default:
|
| - break;
|
| - }
|
| + EGLint error_code = ValidateDisplay(dpy);
|
| + if (error_code != EGL_SUCCESS)
|
| + return EglError(error_code, static_cast<const char*>(NULL));
|
| +
|
| + switch (name) {
|
| + case EGL_CLIENT_APIS:
|
| + return EglSuccess("OpenGL_ES");
|
| + case EGL_EXTENSIONS:
|
| + return EglSuccess("");
|
| + case EGL_VENDOR:
|
| + return EglSuccess("Google Inc.");
|
| + case EGL_VERSION:
|
| + return EglSuccess("1.4");
|
| + default:
|
| + return EglError(EGL_BAD_PARAMETER, static_cast<const char*>(NULL));
|
| }
|
| - egl::Display* display = ts->GetDisplay(dpy);
|
| - if (!display)
|
| - return ts->ReturnError<const char*>(EGL_BAD_DISPLAY, nullptr);
|
| - return display->QueryString(ts, name);
|
| }
|
|
|
| EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay dpy,
|
| @@ -64,57 +190,103 @@
|
| EGLConfig* configs,
|
| EGLint config_size,
|
| EGLint* num_config) {
|
| - egl::ThreadState* ts = egl::ThreadState::Get();
|
| - egl::Display* display = ts->GetDisplay(dpy);
|
| - if (!display)
|
| - return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE);
|
| - return display->ChooseConfig(ts, attrib_list, configs, config_size,
|
| - num_config);
|
| + EGLint error_code = ValidateDisplay(dpy);
|
| + if (error_code != EGL_SUCCESS)
|
| + return EglError(error_code, EGL_FALSE);
|
| +
|
| + if (num_config == NULL)
|
| + return EglError(EGL_BAD_PARAMETER, EGL_FALSE);
|
| +
|
| + egl::Display* display = static_cast<egl::Display*>(dpy);
|
| + if (!display->ChooseConfigs(configs, config_size, num_config))
|
| + return EglError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
|
| +
|
| + return EglSuccess(EGL_TRUE);
|
| }
|
|
|
| EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs(EGLDisplay dpy,
|
| EGLConfig* configs,
|
| EGLint config_size,
|
| EGLint* num_config) {
|
| - egl::ThreadState* ts = egl::ThreadState::Get();
|
| - egl::Display* display = ts->GetDisplay(dpy);
|
| - if (!display)
|
| - return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE);
|
| - return display->GetConfigs(ts, configs, config_size, num_config);
|
| + EGLint error_code = ValidateDisplay(dpy);
|
| + if (error_code != EGL_SUCCESS)
|
| + return EglError(error_code, EGL_FALSE);
|
| +
|
| + if (num_config == NULL)
|
| + return EglError(EGL_BAD_PARAMETER, EGL_FALSE);
|
| +
|
| + egl::Display* display = static_cast<egl::Display*>(dpy);
|
| + if (!display->GetConfigs(configs, config_size, num_config))
|
| + return EglError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
|
| +
|
| + return EglSuccess(EGL_TRUE);
|
| }
|
|
|
| EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib(EGLDisplay dpy,
|
| - EGLConfig cfg,
|
| + EGLConfig config,
|
| EGLint attribute,
|
| EGLint* value) {
|
| - egl::ThreadState* ts = egl::ThreadState::Get();
|
| - egl::Display* display = ts->GetDisplay(dpy);
|
| - if (!display)
|
| - return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE);
|
| - return display->GetConfigAttrib(ts, cfg, attribute, value);
|
| + EGLint error_code = ValidateDisplayConfig(dpy, config);
|
| + if (error_code != EGL_SUCCESS)
|
| + return EglError(error_code, EGL_FALSE);
|
| +
|
| + egl::Display* display = static_cast<egl::Display*>(dpy);
|
| + if (!display->GetConfigAttrib(config, attribute, value))
|
| + return EglError(EGL_BAD_ATTRIBUTE, EGL_FALSE);
|
| +
|
| + return EglSuccess(EGL_TRUE);
|
| }
|
|
|
| EGLAPI EGLSurface EGLAPIENTRY
|
| eglCreateWindowSurface(EGLDisplay dpy,
|
| - EGLConfig cfg,
|
| + EGLConfig config,
|
| EGLNativeWindowType win,
|
| const EGLint* attrib_list) {
|
| - egl::ThreadState* ts = egl::ThreadState::Get();
|
| - egl::Display* display = ts->GetDisplay(dpy);
|
| - if (!display)
|
| - return ts->ReturnError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
|
| - return display->CreateWindowSurface(ts, cfg, win, attrib_list);
|
| + EGLint error_code = ValidateDisplayConfig(dpy, config);
|
| + if (error_code != EGL_SUCCESS)
|
| + return EglError(error_code, EGL_NO_SURFACE);
|
| +
|
| + egl::Display* display = static_cast<egl::Display*>(dpy);
|
| + if (!display->IsValidNativeWindow(win))
|
| + return EglError(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
|
| +
|
| + EGLSurface surface = display->CreateWindowSurface(config, win, attrib_list);
|
| + if (surface == EGL_NO_SURFACE)
|
| + return EglError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
|
| +
|
| + return EglSuccess(surface);
|
| }
|
|
|
| EGLAPI EGLSurface EGLAPIENTRY
|
| eglCreatePbufferSurface(EGLDisplay dpy,
|
| - EGLConfig cfg,
|
| + EGLConfig config,
|
| const EGLint* attrib_list) {
|
| - egl::ThreadState* ts = egl::ThreadState::Get();
|
| - egl::Display* display = ts->GetDisplay(dpy);
|
| - if (!display)
|
| - return ts->ReturnError(EGL_BAD_DISPLAY, EGL_NO_SURFACE);
|
| - return display->CreatePbufferSurface(ts, cfg, attrib_list);
|
| + EGLint error_code = ValidateDisplayConfig(dpy, config);
|
| + if (error_code != EGL_SUCCESS)
|
| + return EglError(error_code, EGL_NO_SURFACE);
|
| +
|
| + egl::Display* display = static_cast<egl::Display*>(dpy);
|
| + int width = 1;
|
| + int height = 1;
|
| + if (attrib_list) {
|
| + for (const int32_t* attr = attrib_list; attr[0] != EGL_NONE; attr += 2) {
|
| + switch (attr[0]) {
|
| + case EGL_WIDTH:
|
| + width = attr[1];
|
| + break;
|
| + case EGL_HEIGHT:
|
| + height = attr[1];
|
| + break;
|
| + }
|
| + }
|
| + }
|
| + display->SetCreateOffscreen(width, height);
|
| +
|
| + EGLSurface surface = display->CreateWindowSurface(config, 0, attrib_list);
|
| + if (surface == EGL_NO_SURFACE)
|
| + return EglError(EGL_BAD_ALLOC, EGL_NO_SURFACE);
|
| +
|
| + return EglSuccess(surface);
|
| }
|
|
|
| EGLAPI EGLSurface EGLAPIENTRY
|
| @@ -126,12 +298,14 @@
|
| }
|
|
|
| EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay dpy,
|
| - EGLSurface sfe) {
|
| - egl::ThreadState* ts = egl::ThreadState::Get();
|
| - egl::Display* display = ts->GetDisplay(dpy);
|
| - if (!display)
|
| - return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE);
|
| - return display->DestroySurface(ts, sfe);
|
| + EGLSurface surface) {
|
| + EGLint error_code = ValidateDisplaySurface(dpy, surface);
|
| + if (error_code != EGL_SUCCESS)
|
| + return EglError(error_code, EGL_FALSE);
|
| +
|
| + egl::Display* display = static_cast<egl::Display*>(dpy);
|
| + display->DestroySurface(surface);
|
| + return EglSuccess(EGL_TRUE);
|
| }
|
|
|
| EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay dpy,
|
| @@ -154,8 +328,7 @@
|
| }
|
|
|
| EGLAPI EGLBoolean EGLAPIENTRY eglReleaseThread(void) {
|
| - egl::ThreadState::ReleaseThread();
|
| - return EGL_TRUE;
|
| + return EGL_FALSE;
|
| }
|
|
|
| EGLAPI EGLSurface EGLAPIENTRY
|
| @@ -191,42 +364,64 @@
|
| }
|
|
|
| EGLAPI EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay dpy,
|
| - EGLConfig cfg,
|
| - EGLContext share_ctx,
|
| + EGLConfig config,
|
| + EGLContext share_context,
|
| const EGLint* attrib_list) {
|
| - egl::ThreadState* ts = egl::ThreadState::Get();
|
| - egl::Display* display = ts->GetDisplay(dpy);
|
| - if (!display)
|
| - return ts->ReturnError(EGL_BAD_DISPLAY, EGL_NO_CONTEXT);
|
| - return display->CreateContext(ts, cfg, share_ctx, attrib_list);
|
| + EGLint error_code = ValidateDisplayConfig(dpy, config);
|
| + if (error_code != EGL_SUCCESS)
|
| + return EglError(error_code, EGL_NO_CONTEXT);
|
| +
|
| + if (share_context != EGL_NO_CONTEXT) {
|
| + error_code = ValidateDisplayContext(dpy, share_context);
|
| + if (error_code != EGL_SUCCESS)
|
| + return EglError(error_code, EGL_NO_CONTEXT);
|
| + }
|
| +
|
| + egl::Display* display = static_cast<egl::Display*>(dpy);
|
| + EGLContext context = display->CreateContext(
|
| + config, share_context, attrib_list);
|
| + if (context == EGL_NO_CONTEXT)
|
| + return EglError(EGL_BAD_ALLOC, EGL_NO_CONTEXT);
|
| +
|
| + return EglSuccess(context);
|
| }
|
|
|
| EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy,
|
| EGLContext ctx) {
|
| - egl::ThreadState* ts = egl::ThreadState::Get();
|
| - egl::Display* display = ts->GetDisplay(dpy);
|
| - if (!display)
|
| - return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE);
|
| - return display->DestroyContext(ts, ctx);
|
| + EGLint error_code = ValidateDisplayContext(dpy, ctx);
|
| + if (error_code != EGL_SUCCESS)
|
| + return EglError(error_code, EGL_FALSE);
|
| +
|
| + egl::Display* display = static_cast<egl::Display*>(dpy);
|
| + display->DestroyContext(ctx);
|
| + return EGL_TRUE;
|
| }
|
|
|
| EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay dpy,
|
| EGLSurface draw,
|
| EGLSurface read,
|
| EGLContext ctx) {
|
| - egl::ThreadState* ts = egl::ThreadState::Get();
|
| - if (draw == EGL_NO_SURFACE && read == EGL_NO_SURFACE &&
|
| - ctx == EGL_NO_CONTEXT) {
|
| - egl::Display* display =
|
| - dpy == EGL_NO_DISPLAY ? ts->GetDefaultDisplay() : ts->GetDisplay(dpy);
|
| - if (!display)
|
| - return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE);
|
| - return display->ReleaseCurrent(ts);
|
| + if (ctx != EGL_NO_CONTEXT) {
|
| + EGLint error_code = ValidateDisplaySurface(dpy, draw);
|
| + if (error_code != EGL_SUCCESS)
|
| + return EglError(error_code, EGL_FALSE);
|
| + error_code = ValidateDisplaySurface(dpy, read);
|
| + if (error_code != EGL_SUCCESS)
|
| + return EglError(error_code, EGL_FALSE);
|
| + error_code = ValidateDisplayContext(dpy, ctx);
|
| + if (error_code != EGL_SUCCESS)
|
| + return EglError(error_code, EGL_FALSE);
|
| }
|
| - egl::Display* display = ts->GetDisplay(dpy);
|
| - if (!display)
|
| - return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE);
|
| - return display->MakeCurrent(ts, draw, read, ctx);
|
| +
|
| + egl::Display* display = static_cast<egl::Display*>(dpy);
|
| + if (!display->MakeCurrent(draw, read, ctx))
|
| + return EglError(EGL_CONTEXT_LOST, EGL_FALSE);
|
| +
|
| +#if REGAL_STATIC_EGL
|
| + RegalMakeCurrent(ctx);
|
| +#endif
|
| +
|
| + return EGL_TRUE;
|
| }
|
|
|
| EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext() {
|
| @@ -256,12 +451,15 @@
|
| return EGL_FALSE;
|
| }
|
|
|
| -EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface sfe) {
|
| - egl::ThreadState* ts = egl::ThreadState::Get();
|
| - egl::Display* display = ts->GetDisplay(dpy);
|
| - if (!display)
|
| - return ts->ReturnError(EGL_BAD_DISPLAY, EGL_FALSE);
|
| - return display->SwapBuffers(ts, sfe);
|
| +EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy,
|
| + EGLSurface surface) {
|
| + EGLint error_code = ValidateDisplaySurface(dpy, surface);
|
| + if (error_code != EGL_SUCCESS)
|
| + return EglError(error_code, EGL_FALSE);
|
| +
|
| + egl::Display* display = static_cast<egl::Display*>(dpy);
|
| + display->SwapBuffers(surface);
|
| + return EglSuccess(EGL_TRUE);
|
| }
|
|
|
| EGLAPI EGLBoolean EGLAPIENTRY eglCopyBuffers(EGLDisplay dpy,
|
|
|