Commit fc1a44a1 by Austin Kinross Committed by Jamie Madill

Revert "Revert "Add and implement EGL_ANGLE_device_creation[_d3d11]""

This reverts commit dd5c5b79. BUG=angleproject:1190 Change-Id: I1bc1b232b6a916da6d18b546baf20e0854a2768f Reviewed-on: https://chromium-review.googlesource.com/315169Tested-by: 's avatarAustin Kinross <aukinros@microsoft.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 502f3df6
Name
ANGLE_device_creation
Name Strings
EGL_ANGLE_device_creation
Contributors
Austin Kinross (aukinros 'at' microsoft.com)
Contact
Austin Kinross (aukinros 'at' microsoft.com)
Status
Draft
Version
Version 1, Nov 02, 2015
Number
EGL Extension #XXX
Extension Type
EGL client extension
Dependencies
Requires EGL_EXT_device_query.
Written against the wording of EGL 1.5 as modified by EGL_EXT_device_query.
Overview
Increasingly, EGL and its client APIs are being used in place of "native"
rendering APIs to implement the basic graphics functionality of native
windowing systems. This extension defines a way to create an EGL device
which maps to an inputted "native" rendering API device.
This extension is intended to be used with EGL_EXT_platform_device to
initialize a display using an existing "native" rendering device, but
EGL_EXT_platform_device is not required.
IP Status
No known claims.
New Types
None.
New Procedures and Functions
EGLDeviceEXT eglCreateDeviceANGLE(EGLint device_type,
void *native_device,
cost EGLAttrib *attrib_list)
EGLBoolean eglReleaseDeviceANGLE(EGLDeviceEXT device)
New Tokens
None.
Changes to section 3.2 (Devices)
Add the following after the final paragraph to section 3.2 (Devices):
To create an EGL device wrapping an existing native rendering device, use:
EGLDeviceEXT eglCreateDeviceANGLE(EGLint device_type,
void *native_device,
cost EGLAttrib *attrib_list);
On success, a valid EGLDeviceEXT is returned. On failure, EGL_NO_DEVICE_EXT
is returned.
An EGL_BAD_ATTRIBUTE error is generated if <device_type> is not a valid
device type. This extension defines no valid values for <device_type>.
All attribute names in <attrib_list> are immediately followed by the
corresponding desired value. The list is terminated with EGL_NONE. The
<attrib_list> is considered empty if either <attrib_list> is NULL or if its
first element is EGL_NONE. This specification defines no valid attribute
names for inclusion in <attrib_list>. If <attrib_list> is not empty then
an EGL_BAD_ATTRIBUTE error is generated.
If a device is created using eglCreateDeviceANGLE then it is the
caller's responsibility to manage the lifetime of the device, and to call
eglReleaseDeviceANGLE at an appropriate time.
To release a device, use:
EGLBoolean eglReleaseDeviceANGLE(EGLDeviceEXT device);
On success, EGL_TRUE is returned. On failure, EGL_FALSE is returned.
If <device> equals EGL_NO_DEVICE_EXT then an EGL_BAD_DEVICE_EXT error is
generated. If <device> is not a valid device then the behavior is undefined.
<device> must have been created using eglGetDeviceANGLE. If <device> was
obtained by other means, such as through eglQueryDisplayAttribEXT, then an
EGL_BAD_DEVICE_EXT error is generated.
If eglReleaseDeviceANGLE is called on a device that is still in use by other
EGL objects, then the resulting behavior of those objects is undefined.
Issues
None.
Revision History
Version 1, Nov 2, 2015 (Austin Kinross)
- Initial Draft
Name
ANGLE_device_creation_d3d11
Name Strings
EGL_ANGLE_device_creation_d3d11
Contributors
Austin Kinross (aukinros 'at' microsoft.com)
Contact
Austin Kinross (aukinros 'at' microsoft.com)
Status
Draft
Version
Version 1, Nov 02, 2015
Number
EGL Extension #XXX
Extension Type
EGL client extension
Dependencies
Requires EGL_ANGLE_device_d3d and EGL_ANGLE_device_creation.
Written against the wording of EGL 1.5 as modified by EGL_ANGLE_device_d3d
and EGL_ANGLE_device_creation.
Overview
ANGLE has the ability to run GPU commands on a native D3D device. This
extension defines a way to create a EGL device which maps to an inputted
Direct3D 11 device.
This extension is intended to be used with EGL_EXT_platform_device to
initialize a display using an existing Direct3D 11 device, but
EGL_EXT_platform_device is not required.
IP Status
No known claims.
New Types
None.
New Procedures and Functions
None.
New Tokens
None.
Changes to section 3.2 (Devices)
Modify the language in section 3.2 (Devices) describing valid attribute
names passed into eglCreateDeviceANGLE via <device_type>:
"This specification defines one value for <device_type>:
EGL_D3D11_DEVICE_ANGLE. If this device type is specified then
<native_device> must be a valid pointer to a Direct3D 11 device. If
<native_device> is not a valid pointer to a Direct3D 11 device then the
resulting behavior is undefined."
Append the following to the end of section 3.2 (Devices):
"If a Direct3D 11 device used to create a device experiences a "lost device"
then all resulting behavior of the device (and any dependent EGL objects) is
undefined. It is the caller's responsibility to monitor for "lost device"
and to create a new device (and dependent EGL objects) as appropriate. For
more information on "lost device", see the Direct3D documentation."
Issues
None.
Revision History
Version 1, Nov 2, 2015 (Austin Kinross)
- Initial Draft
......@@ -544,6 +544,16 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribEXT (EGLDisplay dpy, EGLint a
#endif
#endif /* EGL_EXT_device_base */
#ifndef EGL_ANGLE_device_creation
#define EGL_ANGLE_device_creation 1
typedef EGLDeviceEXT (EGLAPIENTRYP PFNEGLCREATEDEVICEANGLEPROC) (EGLint device_type, void *native_device, const EGLAttrib *attrib_list);
typedef EGLBoolean (EGLAPIENTRYP PFNEGLRELEASEDEVICEANGLEPROC) (EGLDeviceEXT device);
#ifdef EGL_EGLEXT_PROTOTYPES
EGLAPI EGLDeviceEXT EGLAPIENTRY eglCreateDeviceANGLE (EGLint device_type, void *native_device, const EGLAttrib *attrib_list);
EGLAPI EGLBoolean EGLAPIENTRY eglReleaseDeviceANGLE (EGLDeviceEXT device);
#endif
#endif /* EGL_ANGLE_device_creation */
#ifndef EGL_EXT_device_drm
#define EGL_EXT_device_drm 1
#define EGL_DRM_DEVICE_FILE_EXT 0x3233
......
......@@ -651,6 +651,8 @@ ClientExtensions::ClientExtensions()
platformANGLE(false),
platformANGLED3D(false),
platformANGLEOpenGL(false),
deviceCreation(false),
deviceCreationD3D11(false),
x11Visual(false),
clientGetAllProcAddresses(false)
{
......@@ -667,6 +669,8 @@ std::vector<std::string> ClientExtensions::getStrings() const
InsertExtensionString("EGL_ANGLE_platform_angle", platformANGLE, &extensionStrings);
InsertExtensionString("EGL_ANGLE_platform_angle_d3d", platformANGLED3D, &extensionStrings);
InsertExtensionString("EGL_ANGLE_platform_angle_opengl", platformANGLEOpenGL, &extensionStrings);
InsertExtensionString("EGL_ANGLE_device_creation", deviceCreation, &extensionStrings);
InsertExtensionString("EGL_ANGLE_device_creation_d3d11", deviceCreationD3D11, &extensionStrings);
InsertExtensionString("EGL_ANGLE_x11_visual", x11Visual, &extensionStrings);
InsertExtensionString("EGL_KHR_client_get_all_proc_addresses", clientGetAllProcAddresses, &extensionStrings);
// clang-format on
......
......@@ -480,9 +480,15 @@ struct ClientExtensions
// EGL_ANGLE_platform_angle_opengl
bool platformANGLEOpenGL;
// EGL_ANGLE_device_creation
bool deviceCreation;
// EGL_ANGLE_device_creation_d3d11
bool deviceCreationD3D11;
// EGL_ANGLE_x11_visual
bool x11Visual;
// EGL_KHR_client_get_all_proc_addresses
bool clientGetAllProcAddresses;
};
......
......@@ -18,6 +18,10 @@
#include "common/platform.h"
#include "libANGLE/renderer/DeviceImpl.h"
#if defined(ANGLE_ENABLE_D3D11)
#include "libANGLE/renderer/d3d/DeviceD3D.h"
#endif
namespace egl
{
......@@ -31,16 +35,67 @@ static std::string GenerateExtensionsString(const T &extensions)
return stream.str();
}
Device::Device(Display *display, rx::DeviceImpl *impl)
: mDisplay(display),
mImplementation(impl)
typedef std::set<egl::Device *> DeviceSet;
static DeviceSet *GetDeviceSet()
{
static DeviceSet devices;
return &devices;
}
// Static factory methods
egl::Error Device::CreateDevice(void *devicePointer, EGLint deviceType, Device **outDevice)
{
#if defined(ANGLE_ENABLE_D3D11)
if (deviceType == EGL_D3D11_DEVICE_ANGLE)
{
rx::DeviceD3D *deviceD3D = new rx::DeviceD3D();
egl::Error error = deviceD3D->initialize(devicePointer, deviceType, EGL_TRUE);
if (error.isError())
{
*outDevice = nullptr;
return error;
}
*outDevice = new Device(nullptr, deviceD3D);
GetDeviceSet()->insert(*outDevice);
return egl::Error(EGL_SUCCESS);
}
#endif
// Note that creating an EGL device from inputted D3D9 parameters isn't currently supported
*outDevice = nullptr;
return egl::Error(EGL_BAD_ATTRIBUTE);
}
egl::Error Device::CreateDevice(Display *owningDisplay, rx::DeviceImpl *impl, Device **outDevice)
{
*outDevice = new Device(owningDisplay, impl);
GetDeviceSet()->insert(*outDevice);
return egl::Error(EGL_SUCCESS);
}
bool Device::IsValidDevice(Device *device)
{
const DeviceSet *deviceSet = GetDeviceSet();
return deviceSet->find(device) != deviceSet->end();
}
Device::Device(Display *owningDisplay, rx::DeviceImpl *impl)
: mOwningDisplay(owningDisplay), mImplementation(impl)
{
initDeviceExtensions();
}
Device::~Device()
{
ASSERT(GetDeviceSet()->find(this) != GetDeviceSet()->end());
GetDeviceSet()->erase(this);
if (mImplementation->deviceExternallySourced())
{
// If the device isn't externally sourced then it is up to the renderer to delete the impl
SafeDelete(mImplementation);
}
}
Error Device::getDevice(EGLAttrib *value)
......
......@@ -24,11 +24,10 @@ namespace egl
class Device final : angle::NonCopyable
{
public:
Device(Display *display, rx::DeviceImpl *impl);
virtual ~Device();
Error getDevice(EGLAttrib *value);
Display *getDisplay() { return mDisplay; };
Display *getOwningDisplay() { return mOwningDisplay; };
EGLint getType();
const DeviceExtensions &getExtensions() const;
......@@ -36,10 +35,18 @@ class Device final : angle::NonCopyable
rx::DeviceImpl *getImplementation() { return mImplementation; }
static egl::Error CreateDevice(void *devicePointer, EGLint deviceType, Device **outDevice);
static egl::Error CreateDevice(Display *owningDisplay,
rx::DeviceImpl *impl,
Device **outDevice);
static bool IsValidDevice(Device *device);
private:
Device(Display *owningDisplay, rx::DeviceImpl *impl);
void initDeviceExtensions();
Display *mDisplay;
Display *mOwningDisplay;
rx::DeviceImpl *mImplementation;
DeviceExtensions mDeviceExtensions;
......
......@@ -272,7 +272,12 @@ Error Display::initialize()
{
return error;
}
mDevice = new Device(this, impl);
error = Device::CreateDevice(this, impl, &mDevice);
if (error.isError())
{
return error;
}
}
else
{
......@@ -300,6 +305,8 @@ void Display::terminate()
mConfigSet.clear();
SafeDelete(mDevice);
mImplementation->terminate();
mInitialized = false;
......@@ -711,6 +718,11 @@ static ClientExtensions GenerateClientExtensions()
extensions.platformANGLEOpenGL = true;
#endif
#if defined(ANGLE_ENABLE_D3D11)
extensions.deviceCreation = true;
extensions.deviceCreationD3D11 = true;
#endif
#if defined(ANGLE_USE_X11)
extensions.x11Visual = true;
#endif
......
......@@ -29,6 +29,7 @@ class DeviceImpl : angle::NonCopyable
virtual egl::Error getDevice(void **outValue) = 0;
virtual EGLint getType() = 0;
virtual void generateExtensions(egl::DeviceExtensions *outExtensions) const = 0;
virtual bool deviceExternallySourced() = 0;
};
}
......
......@@ -17,16 +17,78 @@
namespace rx
{
DeviceD3D::DeviceD3D(void *device, EGLint deviceType) : mDevice(device), mDeviceType(deviceType)
DeviceD3D::DeviceD3D()
: mDevice(0), mDeviceType(0), mDeviceExternallySourced(false), mIsInitialized(false)
{
}
DeviceD3D::~DeviceD3D()
{
#if defined(ANGLE_ENABLE_D3D11)
if (mDeviceType == EGL_D3D11_DEVICE_ANGLE)
{
// DeviceD3D holds a ref to an externally-sourced D3D11 device. We must release it.
ID3D11Device *device = reinterpret_cast<ID3D11Device *>(mDevice);
device->Release();
}
#endif
}
egl::Error DeviceD3D::getDevice(void **outValue)
{
if (!mIsInitialized)
{
*outValue = nullptr;
return egl::Error(EGL_BAD_DEVICE_EXT);
}
*outValue = mDevice;
return egl::Error(EGL_SUCCESS);
}
egl::Error DeviceD3D::initialize(void *device,
EGLint deviceType,
EGLBoolean deviceExternallySourced)
{
ASSERT(!mIsInitialized);
if (mIsInitialized)
{
return egl::Error(EGL_BAD_DEVICE_EXT);
}
mDevice = device;
mDeviceType = deviceType;
mDeviceExternallySourced = !!deviceExternallySourced;
#if defined(ANGLE_ENABLE_D3D11)
if (mDeviceType == EGL_D3D11_DEVICE_ANGLE)
{
// Validate the device
IUnknown *iunknown = reinterpret_cast<IUnknown *>(device);
ID3D11Device *d3dDevice = nullptr;
HRESULT hr =
iunknown->QueryInterface(__uuidof(ID3D11Device), reinterpret_cast<void **>(&d3dDevice));
if (FAILED(hr))
{
return egl::Error(EGL_BAD_ATTRIBUTE, "Invalid D3D device passed into EGLDeviceEXT");
}
// The QI to ID3D11Device adds a ref to the D3D11 device.
// Deliberately don't release the ref here, so that the DeviceD3D holds a ref to the
// D3D11 device.
}
else
#endif
{
ASSERT(!mDeviceExternallySourced);
}
mIsInitialized = true;
return egl::Error(EGL_SUCCESS);
}
EGLint DeviceD3D::getType()
{
return mDeviceType;
......
......@@ -18,15 +18,20 @@ namespace rx
class DeviceD3D : public DeviceImpl
{
public:
DeviceD3D(void *device, EGLint deviceType);
DeviceD3D();
~DeviceD3D() override;
egl::Error initialize(void *device, EGLint deviceType, EGLBoolean external);
egl::Error getDevice(void **outValue) override;
EGLint getType() override;
void generateExtensions(egl::DeviceExtensions *outExtensions) const override;
bool deviceExternallySourced() override { return mDeviceExternallySourced; }
private:
void *mDevice;
EGLint mDeviceType;
bool mDeviceExternallySourced;
bool mIsInitialized;
};
}
......
......@@ -739,10 +739,13 @@ gl::DebugAnnotator *RendererD3D::getAnnotator()
egl::Error RendererD3D::getEGLDevice(DeviceImpl **device)
{
egl::Error error = initializeEGLDevice(&mEGLDevice);
if (error.isError())
if (mEGLDevice == nullptr)
{
return error;
egl::Error error = createEGLDevice(&mEGLDevice);
if (error.isError())
{
return error;
}
}
*device = static_cast<DeviceImpl *>(mEGLDevice);
......
......@@ -264,7 +264,7 @@ class RendererD3D : public Renderer, public BufferFactoryD3D
virtual void createAnnotator() = 0;
virtual egl::Error initializeEGLDevice(DeviceD3D **outDevice) = 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;
......
......@@ -4086,14 +4086,20 @@ gl::Error Renderer11::clearTextures(gl::SamplerType samplerType, size_t rangeSta
return gl::Error(GL_NO_ERROR);
}
egl::Error Renderer11::initializeEGLDevice(DeviceD3D **outDevice)
egl::Error Renderer11::createEGLDevice(DeviceD3D **outDevice)
{
if (*outDevice == nullptr)
ASSERT(mDevice != nullptr);
DeviceD3D *device = new DeviceD3D();
egl::Error error =
device->initialize(reinterpret_cast<void *>(mDevice), EGL_D3D11_DEVICE_ANGLE, EGL_FALSE);
if (error.isError())
{
ASSERT(mDevice != nullptr);
*outDevice = new DeviceD3D(reinterpret_cast<void *>(mDevice), EGL_D3D11_DEVICE_ANGLE);
SafeDelete(device);
return error;
}
*outDevice = device;
return egl::Error(EGL_SUCCESS);
}
}
......@@ -288,7 +288,7 @@ class Renderer11 : public RendererD3D
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 initializeEGLDevice(DeviceD3D **outDevice) override;
egl::Error createEGLDevice(DeviceD3D **outDevice) override;
void syncState(const gl::State &state, const gl::State::DirtyBits &bitmask) override;
......
......@@ -3061,14 +3061,20 @@ gl::Error Renderer9::clearTextures(gl::SamplerType samplerType, size_t rangeStar
return gl::Error(GL_NO_ERROR);
}
egl::Error Renderer9::initializeEGLDevice(DeviceD3D **outDevice)
egl::Error Renderer9::createEGLDevice(DeviceD3D **outDevice)
{
if (*outDevice == nullptr)
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())
{
ASSERT(mDevice != nullptr);
*outDevice = new DeviceD3D(reinterpret_cast<void *>(mDevice), EGL_D3D9_DEVICE_ANGLE);
SafeDelete(device);
return error;
}
*outDevice = device;
return egl::Error(EGL_SUCCESS);
}
......
......@@ -256,7 +256,7 @@ class Renderer9 : public RendererD3D
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 initializeEGLDevice(DeviceD3D **outDevice) override;
egl::Error createEGLDevice(DeviceD3D **outDevice) override;
private:
gl::Error drawArraysImpl(const gl::Data &data,
......
......@@ -11,6 +11,7 @@
#include "common/utilities.h"
#include "libANGLE/Config.h"
#include "libANGLE/Context.h"
#include "libANGLE/Device.h"
#include "libANGLE/Display.h"
#include "libANGLE/Image.h"
#include "libANGLE/Surface.h"
......@@ -934,4 +935,56 @@ Error ValidateDestroyImageKHR(const Display *display, const Image *image)
return Error(EGL_SUCCESS);
}
Error ValidateCreateDeviceANGLE(EGLint device_type,
void *native_device,
const EGLAttrib *attrib_list)
{
const ClientExtensions &clientExtensions = Display::getClientExtensions();
if (!clientExtensions.deviceCreation)
{
return Error(EGL_BAD_ACCESS, "Device creation extension not active");
}
if (attrib_list != nullptr && attrib_list[0] != EGL_NONE)
{
return Error(EGL_BAD_ATTRIBUTE, "Invalid attrib_list parameter");
}
switch (device_type)
{
case EGL_D3D11_DEVICE_ANGLE:
if (!clientExtensions.deviceCreationD3D11)
{
return Error(EGL_BAD_ATTRIBUTE, "D3D11 device creation extension not active");
}
break;
default:
return Error(EGL_BAD_ATTRIBUTE, "Invalid device_type parameter");
}
return Error(EGL_SUCCESS);
}
Error ValidateReleaseDeviceANGLE(Device *device)
{
const ClientExtensions &clientExtensions = Display::getClientExtensions();
if (!clientExtensions.deviceCreation)
{
return Error(EGL_BAD_ACCESS, "Device creation extension not active");
}
if (device == EGL_NO_DEVICE_EXT || !Device::IsValidDevice(device))
{
return Error(EGL_BAD_DEVICE_EXT, "Invalid device parameter");
}
Display *owningDisplay = device->getOwningDisplay();
if (owningDisplay != nullptr)
{
return Error(EGL_BAD_DEVICE_EXT, "Device must have been created using eglCreateDevice");
}
return Error(EGL_SUCCESS);
}
}
......@@ -23,6 +23,7 @@ namespace egl
class AttributeMap;
struct Config;
class Device;
class Display;
class Image;
class Surface;
......@@ -52,6 +53,11 @@ Error ValidateCreateImageKHR(const Display *display,
const AttributeMap &attributes);
Error ValidateDestroyImageKHR(const Display *display, const Image *image);
Error ValidateCreateDeviceANGLE(EGLint device_type,
void *native_device,
const EGLAttrib *attrib_list);
Error ValidateReleaseDeviceANGLE(Device *device);
// Other validation
Error ValidateCompatibleConfigs(const Config *config1, const Config *config2, EGLint surfaceType);
......
......@@ -271,6 +271,18 @@ EGLBoolean EGLAPIENTRY eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)
return egl::DestroyImageKHR(dpy, image);
}
EGLDeviceEXT EGLAPIENTRY eglCreateDeviceANGLE(EGLint device_type,
void *native_device,
const EGLAttrib *attrib_list)
{
return egl::CreateDeviceANGLE(device_type, native_device, attrib_list);
}
EGLBoolean EGLAPIENTRY eglReleaseDeviceANGLE(EGLDeviceEXT device)
{
return egl::ReleaseDeviceANGLE(device);
}
__eglMustCastToProperFunctionPointerType EGLAPIENTRY eglGetProcAddress(const char *procname)
{
return egl::GetProcAddress(procname);
......
......@@ -44,6 +44,8 @@ EXPORTS
eglQueryDeviceStringEXT @50
eglCreateImageKHR @51
eglDestroyImageKHR @52
eglCreateDeviceANGLE @53
eglReleaseDeviceANGLE @54
; 1.5 entry points
eglCreateSync @38
......
......@@ -1540,6 +1540,10 @@ __eglMustCastToProperFunctionPointerType EGLAPIENTRY GetProcAddress(const char *
INSERT_PROC_ADDRESS(egl, CreateImageKHR);
INSERT_PROC_ADDRESS(egl, DestroyImageKHR);
// EGL_EXT_device_creation
INSERT_PROC_ADDRESS(egl, CreateDeviceANGLE);
INSERT_PROC_ADDRESS(egl, ReleaseDeviceANGLE);
#undef INSERT_PROC_ADDRESS
return map;
};
......
......@@ -290,21 +290,25 @@ EGLBoolean EGLAPIENTRY QueryDeviceAttribEXT(EGLDeviceEXT device, EGLint attribut
device, attribute, value);
Device *dev = static_cast<Device*>(device);
if (dev == EGL_NO_DEVICE_EXT)
if (dev == EGL_NO_DEVICE_EXT || !Device::IsValidDevice(dev))
{
SetGlobalError(Error(EGL_BAD_ACCESS));
return EGL_FALSE;
}
Display *display = dev->getDisplay();
Error error(EGL_SUCCESS);
if (!display->getExtensions().deviceQuery)
// If the device was created by (and is owned by) a display, and that display doesn't support
// device querying, then this call should fail
Display *owningDisplay = dev->getOwningDisplay();
if (owningDisplay != nullptr && !owningDisplay->getExtensions().deviceQuery)
{
SetGlobalError(Error(EGL_BAD_ACCESS));
SetGlobalError(Error(EGL_BAD_ACCESS,
"Device wasn't created using eglCreateDeviceANGLE, and the Display "
"that created it doesn't support device querying"));
return EGL_FALSE;
}
Error error(EGL_SUCCESS);
// validate the attribute parameter
switch (attribute)
{
......@@ -333,7 +337,7 @@ const char * EGLAPIENTRY QueryDeviceStringEXT(EGLDeviceEXT device, EGLint name)
device, name);
Device *dev = static_cast<Device*>(device);
if (dev == EGL_NO_DEVICE_EXT)
if (dev == EGL_NO_DEVICE_EXT || !Device::IsValidDevice(dev))
{
SetGlobalError(Error(EGL_BAD_DEVICE_EXT));
return nullptr;
......@@ -436,4 +440,50 @@ ANGLE_EXPORT EGLBoolean EGLAPIENTRY DestroyImageKHR(EGLDisplay dpy, EGLImageKHR
return EGL_TRUE;
}
ANGLE_EXPORT EGLDeviceEXT EGLAPIENTRY CreateDeviceANGLE(EGLint device_type,
void *native_device,
const EGLAttrib *attrib_list)
{
EVENT(
"(EGLint device_type = %d, void* native_device = 0x%0.8p, const EGLAttrib* attrib_list = "
"0x%0.8p)",
device_type, native_device, attrib_list);
Error error = ValidateCreateDeviceANGLE(device_type, native_device, attrib_list);
if (error.isError())
{
SetGlobalError(error);
return EGL_NO_DEVICE_EXT;
}
Device *device = nullptr;
error = Device::CreateDevice(native_device, device_type, &device);
if (error.isError())
{
ASSERT(device == nullptr);
SetGlobalError(error);
return EGL_NO_DEVICE_EXT;
}
return device;
}
ANGLE_EXPORT EGLBoolean EGLAPIENTRY ReleaseDeviceANGLE(EGLDeviceEXT device)
{
EVENT("(EGLDeviceEXT device = 0x%0.8p)", device);
Device *dev = static_cast<Device *>(device);
Error error = ValidateReleaseDeviceANGLE(dev);
if (error.isError())
{
SetGlobalError(error);
return EGL_FALSE;
}
SafeDelete(dev);
return EGL_TRUE;
}
}
......@@ -37,6 +37,12 @@ ANGLE_EXPORT EGLImageKHR EGLAPIENTRY CreateImageKHR(EGLDisplay dpy,
EGLClientBuffer buffer,
const EGLint *attrib_list);
ANGLE_EXPORT EGLBoolean EGLAPIENTRY DestroyImageKHR(EGLDisplay dpy, EGLImageKHR image);
// EGL_EXT_device_creation
ANGLE_EXPORT EGLDeviceEXT EGLAPIENTRY CreateDeviceANGLE(EGLint device_type,
void *native_device,
const EGLAttrib *attrib_list);
ANGLE_EXPORT EGLBoolean EGLAPIENTRY ReleaseDeviceANGLE(EGLDeviceEXT device);
}
#endif // LIBGLESV2_ENTRYPOINTSEGLEXT_H_
......@@ -77,7 +77,7 @@
'<(angle_path)/src/tests/gl_tests/D3D11EmulatedIndexedBufferTest.cpp',
'<(angle_path)/src/tests/gl_tests/D3D11FormatTablesTest.cpp',
'<(angle_path)/src/tests/gl_tests/D3D11InputLayoutCacheTest.cpp',
'<(angle_path)/src/tests/gl_tests/QueryDisplayAttribTest.cpp',
'<(angle_path)/src/tests/egl_tests/EGLDeviceTest.cpp',
# TODO(cwallez) for Linux, requires a portable implementation of threads
'<(angle_path)/src/tests/egl_tests/EGLThreadTest.cpp',
],
......
//
// Copyright 2015 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.
//
#ifndef ANGLE_ENABLE_D3D9
#define ANGLE_ENABLE_D3D9
#endif
#ifndef ANGLE_ENABLE_D3D11
#define ANGLE_ENABLE_D3D11
#endif
#include "test_utils/ANGLETest.h"
#include "com_utils.h"
using namespace angle;
class QueryDisplayAttributeTest : public ANGLETest
{
protected:
QueryDisplayAttributeTest()
{
mQueryDisplayAttribEXT = nullptr;
mQueryDeviceAttribEXT = nullptr;
mQueryDeviceStringEXT = nullptr;
}
void SetUp() override
{
ANGLETest::SetUp();
const char *extensionString = static_cast<const char*>(eglQueryString(getEGLWindow()->getDisplay(), EGL_EXTENSIONS));
if (strstr(extensionString, "EGL_EXT_device_query"))
{
mQueryDisplayAttribEXT = (PFNEGLQUERYDISPLAYATTRIBEXTPROC)eglGetProcAddress("eglQueryDisplayAttribEXT");
mQueryDeviceAttribEXT = (PFNEGLQUERYDEVICEATTRIBEXTPROC)eglGetProcAddress("eglQueryDeviceAttribEXT");
mQueryDeviceStringEXT = (PFNEGLQUERYDEVICESTRINGEXTPROC)eglGetProcAddress("eglQueryDeviceStringEXT");
}
if (!mQueryDeviceStringEXT)
{
FAIL() << "ANGLE extension EGL_EXT_device_query export eglQueryDeviceStringEXT was not found";
}
if (!mQueryDisplayAttribEXT)
{
FAIL() << "ANGLE extension EGL_EXT_device_query export eglQueryDisplayAttribEXT was not found";
}
if (!mQueryDeviceAttribEXT)
{
FAIL() << "ANGLE extension EGL_EXT_device_query export eglQueryDeviceAttribEXT was not found";
}
EGLAttrib angleDevice = 0;
EXPECT_EQ(EGL_TRUE, mQueryDisplayAttribEXT(getEGLWindow()->getDisplay(), EGL_DEVICE_EXT, &angleDevice));
extensionString = static_cast<const char*>(mQueryDeviceStringEXT(reinterpret_cast<EGLDeviceEXT>(angleDevice), EGL_EXTENSIONS));
if (strstr(extensionString, "EGL_ANGLE_device_d3d") == NULL)
{
FAIL() << "ANGLE extension EGL_ANGLE_device_d3d was not found";
}
}
void TearDown() override
{
ANGLETest::TearDown();
}
PFNEGLQUERYDISPLAYATTRIBEXTPROC mQueryDisplayAttribEXT;
PFNEGLQUERYDEVICEATTRIBEXTPROC mQueryDeviceAttribEXT;
PFNEGLQUERYDEVICESTRINGEXTPROC mQueryDeviceStringEXT;
};
// This test attempts to obtain a D3D11 device and a D3D9 device using the eglQueryDeviceAttribEXT function.
// If the test is configured to use D3D11 then it should succeed to obtain a D3D11 device.
// If the test is confitured to use D3D9, then it should succeed to obtain a D3D9 device.
TEST_P(QueryDisplayAttributeTest, QueryDevice)
{
EGLAttrib device = 0;
EGLAttrib angleDevice = 0;
if (getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
{
EXPECT_EQ(EGL_TRUE, mQueryDisplayAttribEXT(getEGLWindow()->getDisplay(), EGL_DEVICE_EXT, &angleDevice));
EXPECT_EQ(EGL_TRUE, mQueryDeviceAttribEXT(reinterpret_cast<EGLDeviceEXT>(angleDevice), EGL_D3D11_DEVICE_ANGLE, &device));
ID3D11Device *d3d11Device = reinterpret_cast<ID3D11Device*>(device);
IDXGIDevice *dxgiDevice = DynamicCastComObject<IDXGIDevice>(d3d11Device);
EXPECT_TRUE(dxgiDevice != nullptr);
SafeRelease(dxgiDevice);
}
if (getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE)
{
EXPECT_EQ(EGL_TRUE, mQueryDisplayAttribEXT(getEGLWindow()->getDisplay(), EGL_DEVICE_EXT, &angleDevice));
EXPECT_EQ(EGL_TRUE, mQueryDeviceAttribEXT(reinterpret_cast<EGLDeviceEXT>(angleDevice), EGL_D3D9_DEVICE_ANGLE, &device));
IDirect3DDevice9 *d3d9Device = reinterpret_cast<IDirect3DDevice9*>(device);
IDirect3D9 *d3d9 = nullptr;
EXPECT_EQ(S_OK, d3d9Device->GetDirect3D(&d3d9));
EXPECT_TRUE(d3d9 != nullptr);
SafeRelease(d3d9);
}
}
// This test attempts to obtain a D3D11 device from a D3D9 configured system and a D3D9 device from
// a D3D11 configured system using the eglQueryDeviceAttribEXT function.
// If the test is configured to use D3D11 then it should fail to obtain a D3D11 device.
// If the test is confitured to use D3D9, then it should fail to obtain a D3D9 device.
TEST_P(QueryDisplayAttributeTest, QueryDeviceBadAttrbiute)
{
EGLAttrib device = 0;
EGLAttrib angleDevice = 0;
if (getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
{
EXPECT_EQ(EGL_TRUE, mQueryDisplayAttribEXT(getEGLWindow()->getDisplay(), EGL_DEVICE_EXT, &angleDevice));
EXPECT_EQ(EGL_FALSE, mQueryDeviceAttribEXT(reinterpret_cast<EGLDeviceEXT>(angleDevice), EGL_D3D9_DEVICE_ANGLE, &device));
}
if (getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE)
{
EXPECT_EQ(EGL_TRUE, mQueryDisplayAttribEXT(getEGLWindow()->getDisplay(), EGL_DEVICE_EXT, &angleDevice));
EXPECT_EQ(EGL_FALSE, mQueryDeviceAttribEXT(reinterpret_cast<EGLDeviceEXT>(angleDevice), EGL_D3D11_DEVICE_ANGLE, &device));
}
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
ANGLE_INSTANTIATE_TEST(QueryDisplayAttributeTest, ES2_D3D9(), ES2_D3D11());
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