Implement EGL error handling.

Implement a CheckEGL function (a la CheckVkSuccess/CheckHRESULT)
that transforms EGL errors to Dawn errors.

Use DAWN_TRY and ResultOrError and friends.

Change-Id: I51fcd6e084c2f824f7d71185e0e1ad0e0ff56e34
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/94561
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Stephen White <senorblanco@chromium.org>
This commit is contained in:
Stephen White 2022-06-30 16:26:42 +00:00 committed by Dawn LUCI CQ
parent eab404cb17
commit c2d830700a
10 changed files with 136 additions and 21 deletions

View File

@ -575,6 +575,8 @@ source_set("sources") {
"opengl/SwapChainGL.h", "opengl/SwapChainGL.h",
"opengl/TextureGL.cpp", "opengl/TextureGL.cpp",
"opengl/TextureGL.h", "opengl/TextureGL.h",
"opengl/UtilsEGL.cpp",
"opengl/UtilsEGL.h",
"opengl/UtilsGL.cpp", "opengl/UtilsGL.cpp",
"opengl/UtilsGL.h", "opengl/UtilsGL.h",
"opengl/opengl_platform.h", "opengl/opengl_platform.h",

View File

@ -453,6 +453,8 @@ if (DAWN_ENABLE_OPENGL)
"opengl/SwapChainGL.h" "opengl/SwapChainGL.h"
"opengl/TextureGL.cpp" "opengl/TextureGL.cpp"
"opengl/TextureGL.h" "opengl/TextureGL.h"
"opengl/UtilsEGL.cpp"
"opengl/UtilsEGL.h"
"opengl/UtilsGL.cpp" "opengl/UtilsGL.cpp"
"opengl/UtilsGL.h" "opengl/UtilsGL.h"
"opengl/opengl_platform.h" "opengl/opengl_platform.h"

View File

@ -152,9 +152,8 @@ MaybeError Adapter::InitializeSupportedLimitsImpl(CombinedLimits* limits) {
ResultOrError<Ref<DeviceBase>> Adapter::CreateDeviceImpl(const DeviceDescriptor* descriptor) { ResultOrError<Ref<DeviceBase>> Adapter::CreateDeviceImpl(const DeviceDescriptor* descriptor) {
EGLenum api = EGLenum api =
GetBackendType() == wgpu::BackendType::OpenGL ? EGL_OPENGL_API : EGL_OPENGL_ES_API; GetBackendType() == wgpu::BackendType::OpenGL ? EGL_OPENGL_API : EGL_OPENGL_ES_API;
std::unique_ptr<Device::Context> context;
std::unique_ptr<Device::Context> context = ContextEGL::Create(mEGLFunctions, api); DAWN_TRY_ASSIGN(context, ContextEGL::Create(mEGLFunctions, api));
return Device::Create(this, descriptor, mFunctions, std::move(context)); return Device::Create(this, descriptor, mFunctions, std::move(context));
} }

View File

@ -57,8 +57,8 @@ std::vector<Ref<AdapterBase>> Backend::DiscoverDefaultAdapters() {
egl.Init(options.getProc); egl.Init(options.getProc);
EGLenum api = GetType() == wgpu::BackendType::OpenGLES ? EGL_OPENGL_ES_API : EGL_OPENGL_API; EGLenum api = GetType() == wgpu::BackendType::OpenGLES ? EGL_OPENGL_ES_API : EGL_OPENGL_API;
std::unique_ptr<Device::Context> context = ContextEGL::Create(egl, api); std::unique_ptr<ContextEGL> context;
if (!context) { if (GetInstance()->ConsumedError(ContextEGL::Create(egl, api), &context)) {
return {}; return {};
} }

View File

@ -17,22 +17,29 @@
#include <memory> #include <memory>
#include <vector> #include <vector>
#include "dawn/native/opengl/UtilsEGL.h"
namespace dawn::native::opengl { namespace dawn::native::opengl {
std::unique_ptr<ContextEGL> ContextEGL::Create(const EGLFunctions& egl, EGLenum api) { ResultOrError<std::unique_ptr<ContextEGL>> ContextEGL::Create(const EGLFunctions& egl,
EGLenum api) {
EGLDisplay display = egl.GetCurrentDisplay(); EGLDisplay display = egl.GetCurrentDisplay();
if (display == EGL_NO_DISPLAY) { if (display == EGL_NO_DISPLAY) {
display = egl.GetDisplay(EGL_DEFAULT_DISPLAY); display = egl.GetDisplay(EGL_DEFAULT_DISPLAY);
} }
if (display == EGL_NO_DISPLAY) { DAWN_INVALID_IF(display == EGL_NO_DISPLAY, "eglGetDisplay");
return nullptr;
}
EGLint renderableType = api == EGL_OPENGL_ES_API ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_BIT; EGLint renderableType = api == EGL_OPENGL_ES_API ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_BIT;
egl.Initialize(display, nullptr, nullptr); EGLint major, minor;
DAWN_TRY(CheckEGL(egl, egl.Initialize(display, &major, &minor), "eglInitialize"));
// We use EGLImage unconditionally, which only became core in 1.5.
DAWN_INVALID_IF(major < 1 || (major == 1 && minor < 5),
"EGL version (%u.%u) must be at least 1.5", major, minor);
// Since we're creating a surfaceless context, the only thing we really care // Since we're creating a surfaceless context, the only thing we really care
// about is the RENDERABLE_TYPE. // about is the RENDERABLE_TYPE.
@ -40,15 +47,13 @@ std::unique_ptr<ContextEGL> ContextEGL::Create(const EGLFunctions& egl, EGLenum
EGLint num_config; EGLint num_config;
EGLConfig config; EGLConfig config;
if (egl.ChooseConfig(display, config_attribs, &config, 1, &num_config) == EGL_FALSE) { DAWN_TRY(CheckEGL(egl, egl.ChooseConfig(display, config_attribs, &config, 1, &num_config),
return nullptr; "eglChooseConfig"));
}
if (!egl.BindAPI(api)) { DAWN_INVALID_IF(num_config == 0, "eglChooseConfig returned zero configs");
return nullptr;
} DAWN_TRY(CheckEGL(egl, egl.BindAPI(api), "eglBindAPI"));
EGLint major, minor;
if (api == EGL_OPENGL_ES_API) { if (api == EGL_OPENGL_ES_API) {
major = 3; major = 3;
minor = 1; minor = 1;
@ -60,9 +65,7 @@ std::unique_ptr<ContextEGL> ContextEGL::Create(const EGLFunctions& egl, EGLenum
EGL_CONTEXT_MAJOR_VERSION, major, EGL_CONTEXT_MINOR_VERSION, minor, EGL_NONE, EGL_NONE, EGL_CONTEXT_MAJOR_VERSION, major, EGL_CONTEXT_MINOR_VERSION, minor, EGL_NONE, EGL_NONE,
}; };
EGLContext context = egl.CreateContext(display, config, EGL_NO_CONTEXT, attrib_list); EGLContext context = egl.CreateContext(display, config, EGL_NO_CONTEXT, attrib_list);
if (!context) { DAWN_TRY(CheckEGL(egl, context != EGL_NO_CONTEXT, "eglCreateContext"));
return nullptr;
}
return std::unique_ptr<ContextEGL>(new ContextEGL(egl, display, context)); return std::unique_ptr<ContextEGL>(new ContextEGL(egl, display, context));
} }

View File

@ -26,7 +26,8 @@ namespace dawn::native::opengl {
class ContextEGL : public Device::Context { class ContextEGL : public Device::Context {
public: public:
static std::unique_ptr<ContextEGL> Create(const EGLFunctions& functions, EGLenum api); static ResultOrError<std::unique_ptr<ContextEGL>> Create(const EGLFunctions& functions,
EGLenum api);
void MakeCurrent() override; void MakeCurrent() override;
~ContextEGL() override; ~ContextEGL() override;

View File

@ -35,6 +35,7 @@ void EGLFunctions::Init(void* (*getProc)(const char*)) {
GetCurrentSurface = GetCurrentSurface =
reinterpret_cast<PFNEGLGETCURRENTSURFACEPROC>(GetProcAddress("eglGetCurrentSurface")); reinterpret_cast<PFNEGLGETCURRENTSURFACEPROC>(GetProcAddress("eglGetCurrentSurface"));
GetDisplay = reinterpret_cast<PFNEGLGETDISPLAYPROC>(GetProcAddress("eglGetDisplay")); GetDisplay = reinterpret_cast<PFNEGLGETDISPLAYPROC>(GetProcAddress("eglGetDisplay"));
GetError = reinterpret_cast<PFNEGLGETERRORPROC>(GetProcAddress("eglGetError"));
Initialize = reinterpret_cast<PFNEGLINITIALIZEPROC>(GetProcAddress("eglInitialize")); Initialize = reinterpret_cast<PFNEGLINITIALIZEPROC>(GetProcAddress("eglInitialize"));
MakeCurrent = reinterpret_cast<PFNEGLMAKECURRENTPROC>(GetProcAddress("eglMakeCurrent")); MakeCurrent = reinterpret_cast<PFNEGLMAKECURRENTPROC>(GetProcAddress("eglMakeCurrent"));
} }

View File

@ -32,6 +32,7 @@ struct EGLFunctions {
PFNEGLGETCURRENTDISPLAYPROC GetCurrentDisplay; PFNEGLGETCURRENTDISPLAYPROC GetCurrentDisplay;
PFNEGLGETCURRENTSURFACEPROC GetCurrentSurface; PFNEGLGETCURRENTSURFACEPROC GetCurrentSurface;
PFNEGLGETDISPLAYPROC GetDisplay; PFNEGLGETDISPLAYPROC GetDisplay;
PFNEGLGETERRORPROC GetError;
PFNEGLGETPROCADDRESSPROC GetProcAddress; PFNEGLGETPROCADDRESSPROC GetProcAddress;
PFNEGLINITIALIZEPROC Initialize; PFNEGLINITIALIZEPROC Initialize;
PFNEGLMAKECURRENTPROC MakeCurrent; PFNEGLMAKECURRENTPROC MakeCurrent;

View File

@ -0,0 +1,75 @@
// Copyright 2022 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "dawn/native/opengl/UtilsEGL.h"
#include <string>
#include "dawn/native/opengl/EGLFunctions.h"
namespace dawn::native::opengl {
const char* EGLErrorAsString(EGLint error) {
switch (error) {
case EGL_SUCCESS:
return "EGL_SUCCESS";
case EGL_NOT_INITIALIZED:
return "EGL_NOT_INITIALIZED";
case EGL_BAD_ACCESS:
return "EGL_BAD_ACCESS";
case EGL_BAD_ALLOC:
return "EGL_BAD_ALLOC";
case EGL_BAD_ATTRIBUTE:
return "EGL_BAD_ATTRIBUTE";
case EGL_BAD_CONTEXT:
return "EGL_BAD_CONTEXT";
case EGL_BAD_CONFIG:
return "EGL_BAD_CONFIG";
case EGL_BAD_CURRENT_SURFACE:
return "EGL_BAD_CURRENT_SURFACE";
case EGL_BAD_DISPLAY:
return "EGL_BAD_DISPLAY";
case EGL_BAD_SURFACE:
return "EGL_BAD_SURFACE";
case EGL_BAD_MATCH:
return "EGL_BAD_MATCH";
case EGL_BAD_PARAMETER:
return "EGL_BAD_PARAMETER";
case EGL_BAD_NATIVE_PIXMAP:
return "EGL_BAD_NATIVE_PIXMAP";
case EGL_BAD_NATIVE_WINDOW:
return "EGL_BAD_NATIVE_WINDOW";
case EGL_CONTEXT_LOST:
return "EGL_CONTEXT_LOST";
default:
return "<Unknown EGL error>";
}
}
MaybeError CheckEGL(const EGLFunctions& egl, EGLBoolean result, const char* context) {
if (DAWN_LIKELY(result == EGL_TRUE)) {
return {};
}
EGLint error = egl.GetError();
std::string message = std::string(context) + " failed with " + EGLErrorAsString(error);
if (error == EGL_BAD_ALLOC) {
return DAWN_OUT_OF_MEMORY_ERROR(message);
} else if (error == EGL_CONTEXT_LOST) {
return DAWN_DEVICE_LOST_ERROR(message);
} else {
return DAWN_INTERNAL_ERROR(message);
}
}
} // namespace dawn::native::opengl

View File

@ -0,0 +1,31 @@
// Copyright 2022 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef SRC_DAWN_NATIVE_OPENGL_UTILSEGL_H_
#define SRC_DAWN_NATIVE_OPENGL_UTILSEGL_H_
#include <EGL/egl.h>
#include "dawn/native/Error.h"
namespace dawn::native::opengl {
struct EGLFunctions;
const char* EGLErrorAsString(EGLint error);
MaybeError CheckEGL(const EGLFunctions& egl, EGLBoolean result, const char* context);
} // namespace dawn::native::opengl
#endif // SRC_DAWN_NATIVE_OPENGL_UTILSEGL_H_