Commit 8e7d9d6c by Kenneth Russell Committed by Commit Bot

Add EGL_ANGLE_device_cgl extension.

Supports querying the CGLContextObj and CGLPixelFormatObj associated with ANGLE's underlying OpenGL context on macOS. Minor refactorings to implementation of device attribute queries on all platforms. Bug: angleproject:3973 Change-Id: I24341668be4cbfed0b7f2df4c1402df1effe275e Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1846733 Commit-Queue: Kenneth Russell <kbr@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 7de9f95d
Name
ANGLE_device_cgl
Name Strings
EGL_ANGLE_device_cgl
Contributors
Ken Russell (kbr 'at' google.com)
Geoff Lang (geofflang 'at' google.com)
Contact
Ken Russell (kbr 'at' google.com)
Status
Draft
Version
Version 1, October 4, 2019
Number
EGL Extension #XXX
Extension Type
EGL device extension
Dependencies
This extension is written against the language of EGL 1.5 as
modified by EGL_EXT_device_query.
EGL_EXT_device_query is required.
Overview
ANGLE on macOS internally uses an OpenGL context allocated via CGL.
This extension defines a mapping from an EGL device to the underlying
CGLContextObj and its associated CGLPixelFormatObj, after it's been
queried from an EGL display.
IP Status
No known claims.
New Types
None.
New Procedures and Functions
None.
New Tokens
Accepted as a queried <attribute> in eglQueryDeviceAttribEXT:
EGL_CGL_CONTEXT_ANGLE 0x3485
EGL_CGL_PIXEL_FORMAT_ANGLE 0x3486
Add a new section 2.1.3 (CGL Devices) after 2.1.2 (Devices)
On macOS the underlying CGLContextObj and CGLPixelFormatObj can be queried
from the EGL device. The intented purpose is to allow applications to create
new CGL contexts which share resources with this one.
Changes to section 3.2 (Devices)
Replace the paragraph immediately following the prototype for
eglQueryDeviceAttribEXT:
<attribute> may be either EGL_CGLCONTEXT_DEVICE_ANGLE or
EGL_CGLPIXELFORMAT_DEVICE_ANGLE. On success, EGL_TRUE is returned, and a
valid CGLContextObj or CGLPixelFormatObj corresponding to the EGL device is
returned in <value>. These objects are compatible with OpenGL and CGL API
functions. If the EGL device is not currently associated with a CGL context,
EGL_BAD_ATTRIBUTE is returned, and <value> is left unchanged.
Issues
None
Revision History
Version 1, October 4, 2019 (Ken Russell)
- Initial Draft
Version 2, October 8, 2019 (Ken Russell)
- Address feedback from Geoff Lang
......@@ -243,6 +243,12 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribANGLE(EGLDisplay dpy, EGLint
#define EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE 0x3483
#endif /* EGL_ANGLE_create_context_backwards_compatible */
#ifndef EGL_ANGLE_device_cgl
#define EGL_ANGLE_device_cgl 1
#define EGL_CGL_CONTEXT_ANGLE 0x3485
#define EGL_CGL_PIXEL_FORMAT_ANGLE 0x3486
#endif
// clang-format on
#endif // INCLUDE_EGL_EGLEXT_ANGLE_
......@@ -1234,6 +1234,7 @@ std::vector<std::string> DeviceExtensions::getStrings() const
// clang-format off
// | Extension name | Supported flag | Output vector |
InsertExtensionString("EGL_ANGLE_device_d3d", deviceD3D, &extensionStrings);
InsertExtensionString("EGL_ANGLE_device_cgl", deviceCGL, &extensionStrings);
// clang-format on
return extensionStrings;
......
......@@ -942,6 +942,9 @@ struct DeviceExtensions
// EGL_ANGLE_device_d3d
bool deviceD3D = false;
// EGL_ANGLE_device_cgl
bool deviceCGL = false;
};
struct ClientExtensions
......
......@@ -101,11 +101,12 @@ EGLLabelKHR Device::getLabel() const
return mLabel;
}
Error Device::getDevice(EGLAttrib *value)
Error Device::getAttribute(EGLint attribute, EGLAttrib *value)
{
void *nativeDevice = nullptr;
egl::Error error = getImplementation()->getDevice(&nativeDevice);
*value = reinterpret_cast<EGLAttrib>(nativeDevice);
void *nativeAttribute = nullptr;
egl::Error error =
getImplementation()->getAttribute(getOwningDisplay(), attribute, &nativeAttribute);
*value = reinterpret_cast<EGLAttrib>(nativeAttribute);
return error;
}
......
......@@ -32,7 +32,7 @@ class Device final : public LabeledObject, angle::NonCopyable
void setLabel(EGLLabelKHR label) override;
EGLLabelKHR getLabel() const override;
Error getDevice(EGLAttrib *value);
Error getAttribute(EGLint attribute, EGLAttrib *value);
Display *getOwningDisplay() { return mOwningDisplay; }
EGLint getType();
......
......@@ -15,11 +15,13 @@
namespace egl
{
class Device;
class Display;
}
namespace rx
{
class DisplayImpl;
class DeviceImpl : angle::NonCopyable
{
public:
......@@ -28,7 +30,9 @@ class DeviceImpl : angle::NonCopyable
virtual egl::Error initialize() = 0;
virtual egl::Error getDevice(void **outValue) = 0;
virtual egl::Error getAttribute(const egl::Display *display,
EGLint attribute,
void **outValue) = 0;
virtual EGLint getType() = 0;
virtual void generateExtensions(egl::DeviceExtensions *outExtensions) const = 0;
};
......
......@@ -7,7 +7,6 @@
// DeviceD3D.cpp: D3D implementation of egl::Device
#include "libANGLE/renderer/d3d/DeviceD3D.h"
#include "libANGLE/renderer/d3d/RendererD3D.h"
#include "libANGLE/Device.h"
#include "libANGLE/Display.h"
......@@ -33,9 +32,12 @@ DeviceD3D::~DeviceD3D()
#endif
}
egl::Error DeviceD3D::getDevice(void **outValue)
egl::Error DeviceD3D::getAttribute(const egl::Display *display, EGLint attribute, void **outValue)
{
ASSERT(mIsInitialized);
ANGLE_UNUSED_VARIABLE(display);
// Validated at higher levels.
ASSERT(getType() == attribute);
*outValue = mDevice;
return egl::NoError();
}
......
......@@ -22,7 +22,9 @@ class DeviceD3D : public DeviceImpl
~DeviceD3D() override;
egl::Error initialize() override;
egl::Error getDevice(void **outValue) override;
egl::Error getAttribute(const egl::Display *display,
EGLint attribute,
void **outValue) override;
EGLint getType() override;
void generateExtensions(egl::DeviceExtensions *outExtensions) const override;
......
......@@ -755,7 +755,7 @@ egl::Error Renderer11::initializeD3DDevice()
// We should use the inputted D3D11 device instead
void *device = nullptr;
ANGLE_TRY(deviceD3D->getDevice(&device));
ANGLE_TRY(deviceD3D->getAttribute(mDisplay, EGL_D3D11_DEVICE_ANGLE, &device));
ID3D11Device *d3dDevice = static_cast<ID3D11Device *>(device);
if (FAILED(d3dDevice->GetDeviceRemovedReason()))
......
//
// Copyright 2019 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// DeviceCGL.cpp: CGL implementation of egl::Device
#include "libANGLE/renderer/gl/cgl/DeviceCGL.h"
#include "libANGLE/renderer/gl/cgl/DisplayCGL.h"
#include <EGL/eglext.h>
namespace rx
{
DeviceCGL::DeviceCGL() {}
DeviceCGL::~DeviceCGL() {}
egl::Error DeviceCGL::initialize()
{
return egl::NoError();
}
egl::Error DeviceCGL::getAttribute(const egl::Display *display, EGLint attribute, void **outValue)
{
DisplayCGL *displayImpl = GetImplAs<DisplayCGL>(display);
switch (attribute)
{
case EGL_CGL_CONTEXT_ANGLE:
*outValue = displayImpl->getCGLContext();
break;
case EGL_CGL_PIXEL_FORMAT_ANGLE:
*outValue = displayImpl->getCGLPixelFormat();
break;
default:
return egl::EglBadAttribute();
}
return egl::NoError();
}
EGLint DeviceCGL::getType()
{
return 0;
}
void DeviceCGL::generateExtensions(egl::DeviceExtensions *outExtensions) const
{
outExtensions->deviceCGL = true;
}
} // namespace rx
//
// Copyright 2019 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// DeviceCGL.h: CGL implementation of egl::Device
#ifndef LIBANGLE_RENDERER_GL_CGL_DEVICECGL_H_
#define LIBANGLE_RENDERER_GL_CGL_DEVICECGL_H_
#include "libANGLE/Device.h"
#include "libANGLE/renderer/DeviceImpl.h"
namespace rx
{
class DeviceCGL : public DeviceImpl
{
public:
DeviceCGL();
~DeviceCGL() override;
egl::Error initialize() override;
egl::Error getAttribute(const egl::Display *display,
EGLint attribute,
void **outValue) override;
EGLint getType() override;
void generateExtensions(egl::DeviceExtensions *outExtensions) const override;
};
} // namespace rx
#endif // LIBANGLE_RENDERER_GL_CGL_DEVICECGL_H_
......@@ -71,6 +71,7 @@ class DisplayCGL : public DisplayGL
gl::Version getMaxSupportedESVersion() const override;
CGLContextObj getCGLContext() const;
CGLPixelFormatObj getCGLPixelFormat() const;
WorkerContext *createWorkerContext(std::string *infoLog);
......
......@@ -18,6 +18,7 @@
# include "gpu_info_util/SystemInfo.h"
# include "libANGLE/Display.h"
# include "libANGLE/renderer/gl/cgl/ContextCGL.h"
# include "libANGLE/renderer/gl/cgl/DeviceCGL.h"
# include "libANGLE/renderer/gl/cgl/IOSurfaceSurfaceCGL.h"
# include "libANGLE/renderer/gl/cgl/PbufferSurfaceCGL.h"
# include "libANGLE/renderer/gl/cgl/RendererCGL.h"
......@@ -209,8 +210,7 @@ ContextImpl *DisplayCGL::createContext(const gl::State &state,
DeviceImpl *DisplayCGL::createDevice()
{
UNIMPLEMENTED();
return nullptr;
return new DeviceCGL();
}
egl::ConfigSet DisplayCGL::generateConfigs()
......@@ -323,10 +323,16 @@ CGLContextObj DisplayCGL::getCGLContext() const
return mContext;
}
CGLPixelFormatObj DisplayCGL::getCGLPixelFormat() const
{
return mPixelFormat;
}
void DisplayCGL::generateExtensions(egl::DisplayExtensions *outExtensions) const
{
outExtensions->iosurfaceClientBuffer = true;
outExtensions->surfacelessContext = true;
outExtensions->deviceQuery = true;
// Contexts are virtualized so textures can be shared globally
outExtensions->displayTextureShareGroup = true;
......
......@@ -23,7 +23,7 @@ egl::Error DeviceNULL::initialize()
return egl::NoError();
}
egl::Error DeviceNULL::getDevice(void **outValue)
egl::Error DeviceNULL::getAttribute(const egl::Display *display, EGLint attribute, void **outValue)
{
UNIMPLEMENTED();
return egl::EglBadAccess();
......
......@@ -22,7 +22,9 @@ class DeviceNULL : public DeviceImpl
~DeviceNULL() override;
egl::Error initialize() override;
egl::Error getDevice(void **outValue) override;
egl::Error getAttribute(const egl::Display *display,
EGLint attribute,
void **outValue) override;
EGLint getType() override;
void generateExtensions(egl::DeviceExtensions *outExtensions) const override;
};
......
......@@ -24,7 +24,7 @@ egl::Error DeviceVk::initialize()
return egl::NoError();
}
egl::Error DeviceVk::getDevice(void **outValue)
egl::Error DeviceVk::getAttribute(const egl::Display *display, EGLint attribute, void **outValue)
{
UNIMPLEMENTED();
return egl::EglBadAccess();
......
......@@ -22,7 +22,9 @@ class DeviceVk : public DeviceImpl
~DeviceVk() override;
egl::Error initialize() override;
egl::Error getDevice(void **outValue) override;
egl::Error getAttribute(const egl::Display *display,
EGLint attribute,
void **outValue) override;
EGLint getType() override;
void generateExtensions(egl::DeviceExtensions *outExtensions) const override;
};
......
......@@ -842,6 +842,8 @@ libangle_gl_egl_android_sources = [
libangle_gl_cgl_sources = [
"src/libANGLE/renderer/gl/cgl/ContextCGL.cpp",
"src/libANGLE/renderer/gl/cgl/ContextCGL.h",
"src/libANGLE/renderer/gl/cgl/DeviceCGL.cpp",
"src/libANGLE/renderer/gl/cgl/DeviceCGL.h",
"src/libANGLE/renderer/gl/cgl/DisplayCGL.mm",
"src/libANGLE/renderer/gl/cgl/DisplayCGL.h",
"src/libANGLE/renderer/gl/cgl/IOSurfaceSurfaceCGL.mm",
......
......@@ -299,13 +299,17 @@ EGLBoolean EGLAPIENTRY EGL_QueryDeviceAttribEXT(EGLDeviceEXT device,
GetDeviceIfValid(dev));
return EGL_FALSE;
}
error = dev->getDevice(value);
if (error.isError())
error = dev->getAttribute(attribute, value);
break;
case EGL_CGL_CONTEXT_ANGLE:
case EGL_CGL_PIXEL_FORMAT_ANGLE:
if (!dev->getExtensions().deviceCGL)
{
thread->setError(error, GetDebug(), "eglQueryDeviceAttribEXT",
thread->setError(EglBadAttribute(), GetDebug(), "eglQueryDeviceAttribEXT",
GetDeviceIfValid(dev));
return EGL_FALSE;
}
error = dev->getAttribute(attribute, value);
break;
default:
thread->setError(EglBadAttribute(), GetDebug(), "eglQueryDeviceAttribEXT",
......@@ -313,6 +317,11 @@ EGLBoolean EGLAPIENTRY EGL_QueryDeviceAttribEXT(EGLDeviceEXT device,
return EGL_FALSE;
}
if (error.isError())
{
thread->setError(error, GetDebug(), "eglQueryDeviceAttribEXT", GetDeviceIfValid(dev));
return EGL_FALSE;
}
thread->setSuccess();
return EGL_TRUE;
}
......
......@@ -158,8 +158,10 @@ angle_end2end_tests_sources = [
"test_utils/angle_test_instantiate.h",
"test_utils/gl_raii.h",
]
angle_end2end_tests_mac_sources =
[ "egl_tests/EGLIOSurfaceClientBufferTest.cpp" ]
angle_end2end_tests_mac_sources = [
"egl_tests/EGLDeviceCGLTest.cpp",
"egl_tests/EGLIOSurfaceClientBufferTest.cpp",
]
angle_end2end_tests_win_sources = [
"gl_tests/D3DImageFormatConversionTest.cpp",
"egl_tests/EGLDeviceTest.cpp",
......
//
// Copyright 2019 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// EGLDeviceCGLTest.cpp: tests for the EGL_ANGLE_device_cgl extension.
//
#include "test_utils/ANGLETest.h"
#include "util/EGLWindow.h"
#include "util/OSWindow.h"
#include "util/gles_loader_autogen.h"
using namespace angle;
class EGLDeviceCGLQueryTest : public ANGLETest
{
protected:
EGLDeviceCGLQueryTest() {}
void testSetUp() override
{
const char *extensionString =
static_cast<const char *>(eglQueryString(getEGLWindow()->getDisplay(), EGL_EXTENSIONS));
if (!eglQueryDeviceStringEXT)
{
FAIL() << "ANGLE extension EGL_EXT_device_query export eglQueryDeviceStringEXT was not "
"found";
}
if (!eglQueryDisplayAttribEXT)
{
FAIL() << "ANGLE extension EGL_EXT_device_query export eglQueryDisplayAttribEXT was "
"not found";
}
if (!eglQueryDeviceAttribEXT)
{
FAIL() << "ANGLE extension EGL_EXT_device_query export eglQueryDeviceAttribEXT was not "
"found";
}
EGLAttrib angleDevice = 0;
EXPECT_EGL_TRUE(
eglQueryDisplayAttribEXT(getEGLWindow()->getDisplay(), EGL_DEVICE_EXT, &angleDevice));
extensionString = static_cast<const char *>(
eglQueryDeviceStringEXT(reinterpret_cast<EGLDeviceEXT>(angleDevice), EGL_EXTENSIONS));
if (strstr(extensionString, "EGL_ANGLE_device_cgl") == nullptr)
{
FAIL() << "ANGLE extension EGL_ANGLE_device_cgl was not found";
}
}
};
// This test attempts to query the CGLContextObj and CGLPixelFormatObj from the
// EGLDevice associated with the display.
TEST_P(EGLDeviceCGLQueryTest, QueryDevice)
{
EGLAttrib angleDevice = 0;
EXPECT_EGL_TRUE(
eglQueryDisplayAttribEXT(getEGLWindow()->getDisplay(), EGL_DEVICE_EXT, &angleDevice));
EGLAttrib contextAttrib = 0;
EGLAttrib pixelFormatAttrib = 0;
EXPECT_EGL_TRUE(eglQueryDeviceAttribEXT(reinterpret_cast<EGLDeviceEXT>(angleDevice),
EGL_CGL_CONTEXT_ANGLE, &contextAttrib));
EXPECT_TRUE(contextAttrib != 0);
EXPECT_EGL_TRUE(eglQueryDeviceAttribEXT(reinterpret_cast<EGLDeviceEXT>(angleDevice),
EGL_CGL_PIXEL_FORMAT_ANGLE, &pixelFormatAttrib));
EXPECT_TRUE(pixelFormatAttrib != 0);
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these
// tests should be run against.
ANGLE_INSTANTIATE_TEST(EGLDeviceCGLQueryTest, ES2_OPENGL(), ES3_OPENGL());
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