Commit 063d9e78 by Austin Kinross Committed by Jamie Madill

Add support for EGL_EXT_platform_device

This allows an application to use EGLDeviceEXT to initialize EGL. For example, if an application wants to initialize EGL using an existing D3D11 device (instead of ANGLE creating its D3D device), then the app may create an EGLDeviceEXT using EGL_ANGLE_device_creation_d3d11, and use this device to initialize EGL via EGL_EXT_platform_device. BUG=angleproject:1190 Change-Id: Ife91ce95a63e29eb2b3f05aedfb668e4cac8f5ce Reviewed-on: https://chromium-review.googlesource.com/313444Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Tested-by: 's avatarAustin Kinross <aukinros@microsoft.com>
parent fc1a44a1
......@@ -648,6 +648,7 @@ std::vector<std::string> DeviceExtensions::getStrings() const
ClientExtensions::ClientExtensions()
: clientExtensions(false),
platformBase(false),
platformDevice(false),
platformANGLE(false),
platformANGLED3D(false),
platformANGLEOpenGL(false),
......@@ -666,6 +667,7 @@ std::vector<std::string> ClientExtensions::getStrings() const
// | Extension name | Supported flag | Output vector |
InsertExtensionString("EGL_EXT_client_extensions", clientExtensions, &extensionStrings);
InsertExtensionString("EGL_EXT_platform_base", platformBase, &extensionStrings);
InsertExtensionString("EGL_EXT_platform_device", platformDevice, &extensionStrings);
InsertExtensionString("EGL_ANGLE_platform_angle", platformANGLE, &extensionStrings);
InsertExtensionString("EGL_ANGLE_platform_angle_d3d", platformANGLED3D, &extensionStrings);
InsertExtensionString("EGL_ANGLE_platform_angle_opengl", platformANGLEOpenGL, &extensionStrings);
......
......@@ -471,6 +471,9 @@ struct ClientExtensions
// EGL_EXT_platform_base
bool platformBase;
// EGL_EXT_platform_device
bool platformDevice;
// EGL_ANGLE_platform_angle
bool platformANGLE;
......
......@@ -85,14 +85,52 @@ static WindowSurfaceMap *GetWindowSurfaces()
return &windowSurfaces;
}
typedef std::map<EGLNativeDisplayType, Display*> DisplayMap;
static DisplayMap *GetDisplayMap()
typedef std::map<EGLNativeDisplayType, Display *> ANGLEPlatformDisplayMap;
static ANGLEPlatformDisplayMap *GetANGLEPlatformDisplayMap()
{
static DisplayMap displays;
static ANGLEPlatformDisplayMap displays;
return &displays;
}
rx::DisplayImpl *CreateDisplayImpl(const AttributeMap &attribMap)
typedef std::map<Device *, Display *> DevicePlatformDisplayMap;
static DevicePlatformDisplayMap *GetDevicePlatformDisplayMap()
{
static DevicePlatformDisplayMap displays;
return &displays;
}
rx::DisplayImpl *CreateDisplayFromDevice(Device *eglDevice)
{
rx::DisplayImpl *impl = nullptr;
switch (eglDevice->getType())
{
#if defined(ANGLE_ENABLE_D3D11)
case EGL_D3D11_DEVICE_ANGLE:
impl = new rx::DisplayD3D();
break;
#endif
#if defined(ANGLE_ENABLE_D3D9)
case EGL_D3D9_DEVICE_ANGLE:
// Currently the only way to get EGLDeviceEXT representing a D3D9 device
// is to retrieve one from an already-existing EGLDisplay.
// When eglGetPlatformDisplayEXT is called with a D3D9 EGLDeviceEXT,
// the already-existing display should be returned.
// Therefore this codepath to create a new display from the device
// should never be hit.
UNREACHABLE();
break;
#endif
default:
UNREACHABLE();
break;
}
ASSERT(impl != nullptr);
return impl;
}
rx::DisplayImpl *CreateDisplayFromAttribs(const AttributeMap &attribMap)
{
rx::DisplayImpl *impl = nullptr;
EGLint displayType = attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
......@@ -149,15 +187,17 @@ rx::DisplayImpl *CreateDisplayImpl(const AttributeMap &attribMap)
}
Display *Display::getDisplay(EGLNativeDisplayType displayId, const AttributeMap &attribMap)
Display *Display::GetDisplayFromAttribs(void *native_display, const AttributeMap &attribMap)
{
// Initialize the global platform if not already
InitDefaultPlatformImpl();
Display *display = NULL;
Display *display = nullptr;
EGLNativeDisplayType displayId = static_cast<EGLNativeDisplayType>(native_display);
DisplayMap *displays = GetDisplayMap();
DisplayMap::const_iterator iter = displays->find(displayId);
ANGLEPlatformDisplayMap *displays = GetANGLEPlatformDisplayMap();
ANGLEPlatformDisplayMap::const_iterator iter = displays->find(displayId);
if (iter != displays->end())
{
display = iter->second;
......@@ -171,21 +211,71 @@ Display *Display::getDisplay(EGLNativeDisplayType displayId, const AttributeMap
return NULL;
}
display = new Display(displayId);
display = new Display(EGL_PLATFORM_ANGLE_ANGLE, displayId, nullptr);
displays->insert(std::make_pair(displayId, display));
}
// Apply new attributes if the display is not initialized yet.
if (!display->isInitialized())
{
rx::DisplayImpl* impl = CreateDisplayImpl(attribMap);
rx::DisplayImpl *impl = CreateDisplayFromAttribs(attribMap);
display->setAttributes(impl, attribMap);
}
return display;
}
Display::Display(EGLNativeDisplayType displayId)
Display *Display::GetDisplayFromDevice(void *native_display)
{
// Initialize the global platform if not already
InitDefaultPlatformImpl();
Display *display = nullptr;
Device *eglDevice = reinterpret_cast<Device *>(native_display);
ASSERT(Device::IsValidDevice(eglDevice));
ANGLEPlatformDisplayMap *anglePlatformDisplays = GetANGLEPlatformDisplayMap();
DevicePlatformDisplayMap *devicePlatformDisplays = GetDevicePlatformDisplayMap();
// First see if this eglDevice is in use by a Display created using ANGLE platform
for (auto &displayMapEntry : *anglePlatformDisplays)
{
egl::Display *iterDisplay = displayMapEntry.second;
if (iterDisplay->getDevice() == eglDevice)
{
display = iterDisplay;
}
}
if (display == nullptr)
{
// See if the eglDevice is in use by a Display created using the DEVICE platform
DevicePlatformDisplayMap::const_iterator iter = devicePlatformDisplays->find(eglDevice);
if (iter != devicePlatformDisplays->end())
{
display = iter->second;
}
}
if (display == nullptr)
{
// Otherwise create a new Display
display = new Display(EGL_PLATFORM_DEVICE_EXT, 0, eglDevice);
devicePlatformDisplays->insert(std::make_pair(eglDevice, display));
}
// Apply new attributes if the display is not initialized yet.
if (!display->isInitialized())
{
rx::DisplayImpl *impl = CreateDisplayFromDevice(eglDevice);
display->setAttributes(impl, egl::AttributeMap());
}
return display;
}
Display::Display(EGLenum platform, EGLNativeDisplayType displayId, Device *eglDevice)
: mImplementation(nullptr),
mDisplayId(displayId),
mAttributeMap(),
......@@ -196,7 +286,8 @@ Display::Display(EGLNativeDisplayType displayId)
mDisplayExtensions(),
mDisplayExtensionString(),
mVendorString(),
mDevice(nullptr)
mDevice(eglDevice),
mPlatform(platform)
{
}
......@@ -204,11 +295,27 @@ Display::~Display()
{
terminate();
DisplayMap *displays = GetDisplayMap();
DisplayMap::iterator iter = displays->find(mDisplayId);
if (iter != displays->end())
if (mPlatform == EGL_PLATFORM_ANGLE_ANGLE)
{
ANGLEPlatformDisplayMap *displays = GetANGLEPlatformDisplayMap();
ANGLEPlatformDisplayMap::iterator iter = displays->find(mDisplayId);
if (iter != displays->end())
{
displays->erase(iter);
}
}
else if (mPlatform == EGL_PLATFORM_DEVICE_EXT)
{
DevicePlatformDisplayMap *displays = GetDevicePlatformDisplayMap();
DevicePlatformDisplayMap::iterator iter = displays->find(mDevice);
if (iter != displays->end())
{
displays->erase(iter);
}
}
else
{
displays->erase(iter);
UNREACHABLE();
}
SafeDelete(mDevice);
......@@ -264,24 +371,34 @@ Error Display::initialize()
initDisplayExtensions();
initVendorString();
if (mDisplayExtensions.deviceQuery)
// Populate the Display's EGLDeviceEXT if the Display wasn't created using one
if (mPlatform != EGL_PLATFORM_DEVICE_EXT)
{
rx::DeviceImpl *impl = nullptr;
error = mImplementation->getDevice(&impl);
if (error.isError())
if (mDisplayExtensions.deviceQuery)
{
return error;
}
rx::DeviceImpl *impl = nullptr;
error = mImplementation->getDevice(&impl);
if (error.isError())
{
return error;
}
error = Device::CreateDevice(this, impl, &mDevice);
if (error.isError())
error = Device::CreateDevice(this, impl, &mDevice);
if (error.isError())
{
return error;
}
}
else
{
return error;
mDevice = nullptr;
}
}
else
{
mDevice = nullptr;
// For EGL_PLATFORM_DEVICE_EXT, mDevice should always be populated using
// an external device
ASSERT(mDevice != nullptr);
}
mInitialized = true;
......@@ -305,7 +422,12 @@ void Display::terminate()
mConfigSet.clear();
SafeDelete(mDevice);
if (mDevice != nullptr && mDevice->getOwningDisplay() != nullptr)
{
// Don't delete the device if it was created externally using eglCreateDeviceANGLE
// We also shouldn't set it to null in case eglInitialize() is called again later
SafeDelete(mDevice);
}
mImplementation->terminate();
......@@ -712,6 +834,7 @@ static ClientExtensions GenerateClientExtensions()
#if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
extensions.platformANGLED3D = true;
extensions.platformDevice = true;
#endif
#if defined(ANGLE_ENABLE_OPENGL)
......@@ -771,8 +894,17 @@ bool Display::isValidNativeWindow(EGLNativeWindowType window) const
bool Display::isValidDisplay(const egl::Display *display)
{
const DisplayMap *displayMap = GetDisplayMap();
for (const auto &displayPair : *displayMap)
const ANGLEPlatformDisplayMap *anglePlatformDisplayMap = GetANGLEPlatformDisplayMap();
for (const auto &displayPair : *anglePlatformDisplayMap)
{
if (displayPair.second == display)
{
return true;
}
}
const DevicePlatformDisplayMap *devicePlatformDisplayMap = GetDevicePlatformDisplayMap();
for (const auto &displayPair : *devicePlatformDisplayMap)
{
if (displayPair.second == display)
{
......
......@@ -44,7 +44,8 @@ class Display final : angle::NonCopyable
Error initialize();
void terminate();
static egl::Display *getDisplay(EGLNativeDisplayType displayId, const AttributeMap &attribMap);
static egl::Display *GetDisplayFromDevice(void *native_display);
static egl::Display *GetDisplayFromAttribs(void *native_display, const AttributeMap &attribMap);
static const ClientExtensions &getClientExtensions();
static const std::string &getClientExtensionString();
......@@ -101,9 +102,10 @@ class Display final : angle::NonCopyable
rx::DisplayImpl *getImplementation() { return mImplementation; }
Device *getDevice() const;
EGLenum getPlatform() const { return mPlatform; }
private:
Display(EGLNativeDisplayType displayId);
Display(EGLenum platform, EGLNativeDisplayType displayId, Device *eglDevice);
void setAttributes(rx::DisplayImpl *impl, const AttributeMap &attribMap);
......@@ -135,6 +137,7 @@ class Display final : angle::NonCopyable
std::string mVendorString;
Device *mDevice;
EGLenum mPlatform;
};
}
......
......@@ -55,10 +55,13 @@ egl::Error CreateRendererD3D(egl::Display *display, RendererD3D **outRenderer)
std::vector<CreateRendererD3DFunction> rendererCreationFunctions;
const auto &attribMap = display->getAttributeMap();
EGLNativeDisplayType nativeDisplay = display->getNativeDisplayId();
if (display->getPlatform() == EGL_PLATFORM_ANGLE_ANGLE)
{
const auto &attribMap = display->getAttributeMap();
EGLNativeDisplayType nativeDisplay = display->getNativeDisplayId();
EGLint requestedDisplayType = attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
EGLint requestedDisplayType =
attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
# if defined(ANGLE_ENABLE_D3D11)
if (nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ||
......@@ -77,27 +80,41 @@ egl::Error CreateRendererD3D(egl::Display *display, RendererD3D **outRenderer)
}
# endif
if (nativeDisplay != EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE &&
nativeDisplay != EGL_D3D11_ONLY_DISPLAY_ANGLE &&
requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE)
{
if (nativeDisplay != EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE &&
nativeDisplay != EGL_D3D11_ONLY_DISPLAY_ANGLE &&
requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE)
{
// The default display is requested, try the D3D9 and D3D11 renderers, order them using
// the definition of ANGLE_DEFAULT_D3D11
# if ANGLE_DEFAULT_D3D11
# if defined(ANGLE_ENABLE_D3D11)
rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>);
rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>);
# endif
# if defined(ANGLE_ENABLE_D3D9)
rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer9>);
rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer9>);
# endif
# else
# if defined(ANGLE_ENABLE_D3D9)
rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer9>);
rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer9>);
# endif
# if defined(ANGLE_ENABLE_D3D11)
rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>);
rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>);
# endif
# endif
}
}
else if (display->getPlatform() == EGL_PLATFORM_DEVICE_EXT)
{
#if defined(ANGLE_ENABLE_D3D11)
if (display->getDevice()->getType() == EGL_D3D11_DEVICE_ANGLE)
{
rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>);
}
#endif
}
else
{
UNIMPLEMENTED();
}
egl::Error result(EGL_NOT_INITIALIZED, "No available renderers.");
......
......@@ -45,8 +45,7 @@ RendererD3D::RendererD3D(egl::Display *display)
mDeviceLost(false),
mAnnotator(nullptr),
mScratchMemoryBufferResetCounter(0),
mWorkaroundsInitialized(false),
mEGLDevice(nullptr)
mWorkaroundsInitialized(false)
{
}
......@@ -57,8 +56,6 @@ RendererD3D::~RendererD3D()
void RendererD3D::cleanup()
{
SafeDelete(mEGLDevice);
mScratchMemoryBuffer.resize(0);
for (auto &incompleteTexture : mIncompleteTextures)
{
......@@ -736,20 +733,4 @@ gl::DebugAnnotator *RendererD3D::getAnnotator()
ASSERT(mAnnotator);
return mAnnotator;
}
egl::Error RendererD3D::getEGLDevice(DeviceImpl **device)
{
if (mEGLDevice == nullptr)
{
egl::Error error = createEGLDevice(&mEGLDevice);
if (error.isError())
{
return error;
}
}
*device = static_cast<DeviceImpl *>(mEGLDevice);
return egl::Error(EGL_SUCCESS);
}
}
......@@ -254,7 +254,7 @@ class RendererD3D : public Renderer, public BufferFactoryD3D
// In D3D11, faster than calling setTexture a jillion times
virtual gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd) = 0;
egl::Error getEGLDevice(DeviceImpl **device);
virtual egl::Error getEGLDevice(DeviceImpl **device) = 0;
protected:
virtual bool getLUID(LUID *adapterLuid) const = 0;
......@@ -264,8 +264,6 @@ class RendererD3D : public Renderer, public BufferFactoryD3D
virtual void createAnnotator() = 0;
virtual egl::Error createEGLDevice(DeviceD3D **outDevice) = 0;
// dirtyPointer is a special value that will make the comparison with any valid pointer fail and force the renderer to re-apply the state.
static const uintptr_t DirtyPointer;
......@@ -333,8 +331,6 @@ class RendererD3D : public Renderer, public BufferFactoryD3D
mutable bool mWorkaroundsInitialized;
mutable WorkaroundsD3D mWorkarounds;
DeviceD3D *mEGLDevice;
};
struct dx_VertexConstants
......
......@@ -283,13 +283,13 @@ class Renderer11 : public RendererD3D
void onSwap();
void onBufferDelete(const Buffer11 *deleted);
egl::Error getEGLDevice(DeviceImpl **device) override;
protected:
void createAnnotator() override;
gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd) override;
gl::Error applyShadersImpl(const gl::Data &data, GLenum drawMode) override;
egl::Error createEGLDevice(DeviceD3D **outDevice) override;
void syncState(const gl::State &state, const gl::State::DirtyBits &bitmask) override;
private:
......@@ -335,9 +335,12 @@ class Renderer11 : public RendererD3D
HMODULE mDxgiModule;
std::vector<D3D_FEATURE_LEVEL> mAvailableFeatureLevels;
D3D_DRIVER_TYPE mDriverType;
bool mCreatedWithDeviceEXT;
DeviceD3D *mEGLDevice;
HLSLCompiler mCompiler;
egl::Error initializeD3DDevice();
void initializeDevice();
void releaseDeviceResources();
void release();
......
......@@ -132,6 +132,8 @@ Renderer9::Renderer9(egl::Display *display)
mAppliedProgramSerial = 0;
initializeDebugAnnotator();
mEGLDevice = nullptr;
}
Renderer9::~Renderer9()
......@@ -154,6 +156,7 @@ void Renderer9::release()
releaseDeviceResources();
SafeDelete(mEGLDevice);
SafeRelease(mDevice);
SafeRelease(mDeviceEx);
SafeRelease(mD3d9);
......@@ -3061,20 +3064,23 @@ gl::Error Renderer9::clearTextures(gl::SamplerType samplerType, size_t rangeStar
return gl::Error(GL_NO_ERROR);
}
egl::Error Renderer9::createEGLDevice(DeviceD3D **outDevice)
egl::Error Renderer9::getEGLDevice(DeviceImpl **device)
{
ASSERT(mDevice != nullptr);
DeviceD3D *device = new DeviceD3D();
egl::Error error =
device->initialize(reinterpret_cast<void *>(mDevice), EGL_D3D9_DEVICE_ANGLE, EGL_FALSE);
if (error.isError())
if (mEGLDevice == nullptr)
{
SafeDelete(device);
return error;
ASSERT(mDevice != nullptr);
mEGLDevice = new DeviceD3D();
egl::Error error = mEGLDevice->initialize(reinterpret_cast<void *>(mDevice),
EGL_D3D9_DEVICE_ANGLE, EGL_FALSE);
if (error.isError())
{
SafeDelete(mEGLDevice);
return error;
}
}
*outDevice = device;
*device = static_cast<DeviceImpl *>(mEGLDevice);
return egl::Error(EGL_SUCCESS);
}
......
......@@ -251,13 +251,13 @@ class Renderer9 : public RendererD3D
D3DDEVTYPE getD3D9DeviceType() const { return mDeviceType; }
egl::Error getEGLDevice(DeviceImpl **device) override;
protected:
void createAnnotator() override;
gl::Error clearTextures(gl::SamplerType samplerType, size_t rangeStart, size_t rangeEnd) override;
gl::Error applyShadersImpl(const gl::Data &data, GLenum drawMode) override;
egl::Error createEGLDevice(DeviceD3D **outDevice) override;
private:
gl::Error drawArraysImpl(const gl::Data &data,
GLenum mode,
......@@ -415,6 +415,8 @@ class Renderer9 : public RendererD3D
gl::FramebufferAttachment *buffer;
} mNullColorbufferCache[NUM_NULL_COLORBUFFER_CACHE_ENTRIES];
UINT mMaxNullColorbufferLRU;
DeviceD3D *mEGLDevice;
};
}
......
......@@ -41,7 +41,7 @@ EGLDisplay EGLAPIENTRY GetDisplay(EGLNativeDisplayType display_id)
{
EVENT("(EGLNativeDisplayType display_id = 0x%0.8p)", display_id);
return Display::getDisplay(display_id, AttributeMap());
return Display::GetDisplayFromAttribs(reinterpret_cast<void *>(display_id), AttributeMap());
}
EGLBoolean EGLAPIENTRY Initialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
......
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