OpenGL: Create ContextExternal for use without EGL

Allows passing in appropriate callbacks for managing
the OpenGL context, as opposed to relying on Dawn+EGL
for OpenGL context management.
This commit is contained in:
Luke Street 2022-08-29 17:00:37 -04:00
parent 3ebcf4b88a
commit ed15d7c193
8 changed files with 125 additions and 7 deletions

View File

@ -26,6 +26,10 @@ struct DAWN_NATIVE_EXPORT AdapterDiscoveryOptions : public AdapterDiscoveryOptio
explicit AdapterDiscoveryOptions(WGPUBackendType type);
void* (*getProc)(const char*);
// Context
void (*makeCurrent)(void*);
void (*destroy)(void*);
void* userData;
};
// TODO(crbug.com/dawn/810): This struct can be removed once Chrome is no longer using it.

View File

@ -444,6 +444,8 @@ if (DAWN_ENABLE_OPENGL)
"opengl/ComputePipelineGL.h"
"opengl/ContextEGL.cpp"
"opengl/ContextEGL.h"
"opengl/ContextExternal.cpp"
"opengl/ContextExternal.h"
"opengl/DeviceGL.cpp"
"opengl/DeviceGL.h"
"opengl/EGLFunctions.cpp"

View File

@ -21,6 +21,7 @@
#include "dawn/common/GPUInfo.h"
#include "dawn/native/Instance.h"
#include "dawn/native/opengl/ContextEGL.h"
#include "dawn/native/opengl/ContextExternal.h"
#include "dawn/native/opengl/DeviceGL.h"
namespace dawn::native::opengl {
@ -53,12 +54,21 @@ uint32_t GetVendorIdFromVendors(const char* vendor) {
} // anonymous namespace
Adapter::Adapter(InstanceBase* instance, wgpu::BackendType backendType)
: AdapterBase(instance, backendType) {}
Adapter::Adapter(InstanceBase* instance,
wgpu::BackendType backendType,
void (*makeCurrent)(void*),
void (*destroy)(void*),
void* userData)
: AdapterBase(instance, backendType),
mMakeCurrent(makeCurrent),
mDestroy(destroy),
mUserData(userData) {}
MaybeError Adapter::InitializeGLFunctions(void* (*getProc)(const char*)) {
if (mMakeCurrent == nullptr) {
// Use getProc to populate the dispatch table
mEGLFunctions.Init(getProc);
}
return mFunctions.Initialize(getProc);
}
@ -153,7 +163,11 @@ ResultOrError<Ref<DeviceBase>> Adapter::CreateDeviceImpl(const DeviceDescriptor*
EGLenum api =
GetBackendType() == wgpu::BackendType::OpenGL ? EGL_OPENGL_API : EGL_OPENGL_ES_API;
std::unique_ptr<Device::Context> context;
if (mMakeCurrent != nullptr) {
DAWN_TRY_ASSIGN(context, ContextExternal::Create(mMakeCurrent, mDestroy, mUserData));
} else {
DAWN_TRY_ASSIGN(context, ContextEGL::Create(mEGLFunctions, api));
}
return Device::Create(this, descriptor, mFunctions, std::move(context));
}

View File

@ -23,7 +23,11 @@ namespace dawn::native::opengl {
class Adapter : public AdapterBase {
public:
Adapter(InstanceBase* instance, wgpu::BackendType backendType);
Adapter(InstanceBase* instance,
wgpu::BackendType backendType,
void (*makeCurrent)(void*),
void (*destroy)(void*),
void* userData);
MaybeError InitializeGLFunctions(void* (*getProc)(const char*));
@ -40,6 +44,9 @@ class Adapter : public AdapterBase {
OpenGLFunctions mFunctions;
EGLFunctions mEGLFunctions;
void (*mMakeCurrent)(void*);
void (*mDestroy)(void*);
void* mUserData;
};
} // namespace dawn::native::opengl

View File

@ -96,7 +96,8 @@ ResultOrError<std::vector<Ref<AdapterBase>>> Backend::DiscoverAdapters(
DAWN_INVALID_IF(options->getProc == nullptr, "AdapterDiscoveryOptions::getProc must be set");
Ref<Adapter> adapter = AcquireRef(
new Adapter(GetInstance(), static_cast<wgpu::BackendType>(optionsBase->backendType)));
new Adapter(GetInstance(), static_cast<wgpu::BackendType>(optionsBase->backendType),
options->makeCurrent, options->destroy, options->userData));
DAWN_TRY(adapter->InitializeGLFunctions(options->getProc));
DAWN_TRY(adapter->Initialize());

View File

@ -0,0 +1,39 @@
// 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/ContextExternal.h"
#include <memory>
namespace dawn::native::opengl {
ResultOrError<std::unique_ptr<ContextExternal>> ContextExternal::Create(void (*makeCurrent)(void*),
void (*destroy)(void*),
void* userData) {
return std::unique_ptr<ContextExternal>(new ContextExternal(makeCurrent, destroy, userData));
}
void ContextExternal::MakeCurrent() {
if (mMakeCurrent) {
mMakeCurrent(mUserData);
}
}
ContextExternal::~ContextExternal() {
if (mDestroy) {
mDestroy(mUserData);
}
}
} // namespace dawn::native::opengl

View File

@ -0,0 +1,43 @@
// 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_CONTEXTEXTERNAL_H_
#define SRC_DAWN_NATIVE_OPENGL_CONTEXTEXTERNAL_H_
#include <memory>
#include "dawn/native/opengl/DeviceGL.h"
namespace dawn::native::opengl {
class ContextExternal : public Device::Context {
public:
static ResultOrError<std::unique_ptr<ContextExternal>> Create(void (*makeCurrent)(void*),
void (*destroy)(void*),
void* userData);
void MakeCurrent() override;
~ContextExternal() override;
private:
ContextExternal(void (*makeCurrent)(void*), void (*destroy)(void*), void* userData)
: mMakeCurrent(makeCurrent), mDestroy(destroy), mUserData(userData) {}
void (*mMakeCurrent)(void*);
void (*mDestroy)(void*);
void* mUserData;
};
} // namespace dawn::native::opengl
#endif // SRC_DAWN_NATIVE_OPENGL_CONTEXTEXTERNAL_H_

View File

@ -25,8 +25,16 @@ MaybeError OpenGLVersion::Initialize(GetProcAddress getProc) {
if (getString == nullptr) {
return DAWN_INTERNAL_ERROR("Couldn't load glGetString");
}
PFNGLGETERRORPROC getError = reinterpret_cast<PFNGLGETERRORPROC>(getProc("glGetError"));
if (getError == nullptr) {
return DAWN_INTERNAL_ERROR("Couldn't load glGetError");
}
const char* version = reinterpret_cast<const char*>(getString(GL_VERSION));
if (version == nullptr) {
GLenum error = getError();
return DAWN_INTERNAL_ERROR("glGetString failed: {}");
}
if (strstr(version, "OpenGL ES") != nullptr) {
// ES spec states that the GL_VERSION string will be in the following format: