Commit 6dacaff4 by Cooper Partin Committed by Geoff Lang

Add extension EGL_ANGLE_device_d3d

Access to the D3D device is needed for some advanced scenarios. New entry points eglQueryDisplayAttribANGLE and eglQueryDeviceAttribANGLE have been added in this change to implement this extension. BUG=angleproject:935 Change-Id: Id1560b0887fa5882b9858af7bad9043ada67038d Reviewed-on: https://chromium-review.googlesource.com/251610Tested-by: 's avatarCooper Partin <coopp@microsoft.com> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 72ed20d4
......@@ -464,6 +464,12 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSu
#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x320E
#endif /* EGL_ANGLE_platform_angle_opengl */
#ifndef EGL_ANGLE_device_d3d
#define EGL_ANGLE_device_d3d 1
#define EGL_D3D9_DEVICE_ANGLE 0x33A0
#define EGL_D3D11_DEVICE_ANGLE 0x33A1
#endif /* EGL_ANGLE_device_d3d */
#ifndef EGL_ARM_pixmap_multisample_discard
#define EGL_ARM_pixmap_multisample_discard 1
#define EGL_DISCARD_SAMPLES_ARM 0x3286
......@@ -504,6 +510,10 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribEXT (EGLDisplay dpy, EGLint a
#endif
#endif /* EGL_EXT_device_base */
#ifndef EGL_EXT_device_query
#define EGL_EXT_device_query 1
#endif /* EGL_EXT_device_query */
#ifndef EGL_EXT_image_dma_buf_import
#define EGL_EXT_image_dma_buf_import 1
#define EGL_LINUX_DMA_BUF_EXT 0x3270
......
......@@ -482,7 +482,8 @@ DisplayExtensions::DisplayExtensions()
querySurfacePointer(false),
windowFixedSize(false),
postSubBuffer(false),
createContext(false)
createContext(false),
deviceQuery(false)
{
}
......@@ -498,10 +499,25 @@ std::vector<std::string> DisplayExtensions::getStrings() const
InsertExtensionString("EGL_ANGLE_window_fixed_size", windowFixedSize, &extensionStrings);
InsertExtensionString("EGL_NV_post_sub_buffer", postSubBuffer, &extensionStrings);
InsertExtensionString("EGL_KHR_create_context", createContext, &extensionStrings);
InsertExtensionString("EGL_EXT_device_query", deviceQuery, &extensionStrings);
return extensionStrings;
}
DeviceExtensions::DeviceExtensions()
: deviceD3D(false)
{
}
std::vector<std::string> DeviceExtensions::getStrings() const
{
std::vector<std::string> extensionStrings;
// | Extension name | Supported flag | Output vector |
InsertExtensionString("EGL_ANGLE_device_d3d", deviceD3D, &extensionStrings);
return extensionStrings;
}
ClientExtensions::ClientExtensions()
: clientExtensions(false),
......
......@@ -347,6 +347,20 @@ struct DisplayExtensions
// EGL_KHR_create_context
bool createContext;
// EGL_EXT_device_query
bool deviceQuery;
};
struct DeviceExtensions
{
DeviceExtensions();
// Generate a vector of supported extension strings
std::vector<std::string> getStrings() const;
// EGL_ANGLE_device_d3d
bool deviceD3D;
};
struct ClientExtensions
......
//
// Copyright (c) 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.
//
// Device.cpp: Implements the egl::Device class, representing the abstract
// device. Implements EGLDevice.
#include "libANGLE/Device.h"
#include <platform/Platform.h>
#include <EGL/eglext.h>
#include "common/debug.h"
#include "common/platform.h"
#include "libANGLE/Renderer/DeviceImpl.h"
namespace egl
{
template <typename T>
static std::string GenerateExtensionsString(const T &extensions)
{
std::vector<std::string> extensionsVector = extensions.getStrings();
std::ostringstream stream;
std::copy(extensionsVector.begin(), extensionsVector.end(), std::ostream_iterator<std::string>(stream, " "));
return stream.str();
}
Device::Device(Display *display, rx::DeviceImpl *impl)
: mDisplay(display),
mImplementation(impl)
{
initDeviceExtensions();
}
Device::~Device()
{
}
Error Device::getDevice(EGLAttrib *value)
{
return getImplementation()->getDevice(value);
}
EGLint Device::getType()
{
return getImplementation()->getType();
}
void Device::initDeviceExtensions()
{
mImplementation->generateExtensions(&mDeviceExtensions);
mDeviceExtensionString = GenerateExtensionsString(mDeviceExtensions);
}
const DeviceExtensions &Device::getExtensions() const
{
return mDeviceExtensions;
}
const std::string &Device::getExtensionString() const
{
return mDeviceExtensionString;
}
}
//
// Copyright (c) 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.
//
// Device.h: Implements the egl::Device class, representing the abstract
// device. Implements EGLDevice.
#ifndef LIBANGLE_DEVICE_H_
#define LIBANGLE_DEVICE_H_
#include "common/angleutils.h"
#include "libANGLE/Error.h"
#include "libANGLE/Display.h"
namespace rx
{
class DeviceImpl;
}
namespace egl
{
class Device final : angle::NonCopyable
{
public:
Device(Display *display, rx::DeviceImpl *impl);
virtual ~Device();
Error getDevice(EGLAttrib *value);
Display *getDisplay() { return mDisplay; };
EGLint getType();
const DeviceExtensions &getExtensions() const;
const std::string &getExtensionString() const;
rx::DeviceImpl *getImplementation() { return mImplementation; }
private:
void initDeviceExtensions();
Display *mDisplay;
rx::DeviceImpl *mImplementation;
DeviceExtensions mDeviceExtensions;
std::string mDeviceExtensionString;
};
}
#endif // LIBANGLE_DEVICE_H_
......@@ -190,7 +190,8 @@ Display::Display(EGLNativeDisplayType displayId)
mCaps(),
mDisplayExtensions(),
mDisplayExtensionString(),
mVendorString()
mVendorString(),
mDevice(nullptr)
{
}
......@@ -205,6 +206,7 @@ Display::~Display()
displays->erase(iter);
}
SafeDelete(mDevice);
SafeDelete(mImplementation);
}
......@@ -246,6 +248,21 @@ Error Display::initialize()
initDisplayExtensions();
initVendorString();
if (mDisplayExtensions.deviceQuery)
{
rx::DeviceImpl *impl = nullptr;
error = mImplementation->getDevice(&impl);
if (error.isError())
{
return error;
}
mDevice = new Device(this, impl);
}
else
{
mDevice = nullptr;
}
mInitialized = true;
return Error(EGL_SUCCESS);
}
......@@ -262,6 +279,7 @@ void Display::terminate()
mConfigSet.clear();
mImplementation->terminate();
mInitialized = false;
// De-init default platform
......@@ -672,4 +690,9 @@ const std::string &Display::getVendorString() const
return mVendorString;
}
Device *Display::getDevice() const
{
return mDevice;
}
}
......@@ -18,6 +18,7 @@
#include "libANGLE/Caps.h"
#include "libANGLE/Config.h"
#include "libANGLE/AttributeMap.h"
#include "libANGLE/renderer/renderer.h"
namespace gl
{
......@@ -32,6 +33,7 @@ class DisplayImpl;
namespace egl
{
class Surface;
class Device;
class Display final : angle::NonCopyable
{
......@@ -88,6 +90,7 @@ class Display final : angle::NonCopyable
EGLNativeDisplayType getNativeDisplayId() const { return mDisplayId; }
rx::DisplayImpl *getImplementation() { return mImplementation; }
Device *getDevice() const;
private:
Display(EGLNativeDisplayType displayId);
......@@ -117,6 +120,8 @@ class Display final : angle::NonCopyable
std::string mDisplayExtensionString;
std::string mVendorString;
Device* mDevice;
};
}
......
//
// Copyright (c) 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.
//
// DeviceImpl.cpp: Implementation methods of egl::Device
#include "libANGLE/renderer/DeviceImpl.h"
namespace rx
{
DeviceImpl::DeviceImpl()
{
}
DeviceImpl::~DeviceImpl()
{
}
}
//
// Copyright (c) 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.
//
// DeviceImpl.h: Implementation methods of egl::Device
#ifndef LIBANGLE_RENDERER_DEVICEIMPL_H_
#define LIBANGLE_RENDERER_DEVICEIMPL_H_
#include "common/angleutils.h"
#include "libANGLE/Error.h"
#include "libANGLE/Caps.h"
namespace egl
{
class Device;
}
namespace rx
{
class DeviceImpl : angle::NonCopyable
{
public:
DeviceImpl();
virtual ~DeviceImpl();
virtual egl::Error getDevice(EGLAttrib *value) = 0;
virtual EGLint getType() = 0;
virtual void generateExtensions(egl::DeviceExtensions *outExtensions) const = 0;
};
}
#endif // LIBANGLE_RENDERER_DEVICEIMPL_H_
......@@ -35,6 +35,7 @@ namespace rx
{
class SurfaceImpl;
struct ConfigDesc;
class DeviceImpl;
class DisplayImpl : angle::NonCopyable
{
......@@ -68,6 +69,8 @@ class DisplayImpl : angle::NonCopyable
virtual std::string getVendorString() const = 0;
virtual egl::Error getDevice(DeviceImpl **device) = 0;
const egl::Caps &getCaps() const;
typedef std::set<egl::Surface*> SurfaceSet;
......
//
// Copyright (c) 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.
//
// 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"
#include <EGL/eglext.h>
namespace rx
{
DeviceD3D::DeviceD3D(rx::RendererD3D *renderer)
: mRenderer(renderer)
{
}
egl::Error DeviceD3D::getDevice(EGLAttrib *value)
{
*value = reinterpret_cast<EGLAttrib>(mRenderer->getD3DDevice());
if (*value == 0)
{
return egl::Error(EGL_BAD_DEVICE_EXT);
}
return egl::Error(EGL_SUCCESS);
}
EGLint DeviceD3D::getType()
{
switch (mRenderer->getRendererClass())
{
case RENDERER_D3D11:
return EGL_D3D11_DEVICE_ANGLE;
case RENDERER_D3D9:
return EGL_D3D9_DEVICE_ANGLE;
default:
UNREACHABLE();
return EGL_NONE;
}
}
void DeviceD3D::generateExtensions(egl::DeviceExtensions *outExtensions) const
{
outExtensions->deviceD3D = true;
}
}
//
// Copyright (c) 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.
//
// DeviceD3D.h: D3D implementation of egl::Device
#ifndef LIBANGLE_RENDERER_D3D_DEVICED3D_H_
#define LIBANGLE_RENDERER_D3D_DEVICED3D_H_
#include "libANGLE/Device.h"
#include "libANGLE/renderer/DeviceImpl.h"
#include "libANGLE/renderer/d3d/rendererd3d.h"
namespace rx
{
class DeviceD3D : public DeviceImpl
{
public:
DeviceD3D(RendererD3D *renderer);
egl::Error getDevice(EGLAttrib *value) override;
EGLint getType() override;
void generateExtensions(egl::DeviceExtensions *outExtensions) const override;
private:
RendererD3D *mRenderer;
};
}
#endif // LIBANGLE_RENDERER_D3D_DEVICED3D_H_
......@@ -16,6 +16,7 @@
#include "libANGLE/renderer/d3d/SurfaceD3D.h"
#include "libANGLE/renderer/d3d/SwapChainD3D.h"
#include "platform/Platform.h"
#include "libANGLE/renderer/d3d/deviced3d.h"
#include <EGL/eglext.h>
......@@ -142,7 +143,8 @@ egl::Error CreateRendererD3D(egl::Display *display, RendererD3D **outRenderer)
}
DisplayD3D::DisplayD3D()
: mRenderer(nullptr)
: mRenderer(nullptr),
mDevice(nullptr)
{
}
......@@ -225,6 +227,13 @@ egl::Error DisplayD3D::createPixmapSurface(const egl::Config *configuration, Nat
return egl::Error(EGL_BAD_DISPLAY);
}
egl::Error DisplayD3D::getDevice(DeviceImpl **device)
{
*device = reinterpret_cast<DeviceImpl*>(mDevice);
ASSERT(*device != nullptr);
return egl::Error(EGL_SUCCESS);
}
egl::Error DisplayD3D::createContext(const egl::Config *config, const gl::Context *shareContext, const egl::AttributeMap &attribs,
gl::Context **outContext)
{
......@@ -247,11 +256,20 @@ egl::Error DisplayD3D::initialize(egl::Display *display)
{
ASSERT(mRenderer == nullptr && display != nullptr);
mDisplay = display;
return CreateRendererD3D(display, &mRenderer);
egl::Error error = CreateRendererD3D(display, &mRenderer);
if (error.isError())
{
return error;
}
ASSERT(mDevice == nullptr);
mDevice = new DeviceD3D(mRenderer);
return error;
}
void DisplayD3D::terminate()
{
SafeDelete(mDevice);
SafeDelete(mRenderer);
}
......@@ -331,6 +349,8 @@ void DisplayD3D::generateExtensions(egl::DisplayExtensions *outExtensions) const
}
outExtensions->createContext = true;
outExtensions->deviceQuery = true;
}
std::string DisplayD3D::getVendorString() const
......
......@@ -10,6 +10,7 @@
#define LIBANGLE_RENDERER_D3D_DISPLAYD3D_H_
#include "libANGLE/renderer/DisplayImpl.h"
#include "libANGLE/Device.h"
namespace rx
{
......@@ -45,6 +46,8 @@ class DisplayD3D : public DisplayImpl
bool isValidNativeWindow(EGLNativeWindowType window) const override;
egl::Error getDevice(DeviceImpl **device) override;
std::string getVendorString() const override;
private:
......@@ -54,6 +57,8 @@ class DisplayD3D : public DisplayImpl
egl::Display *mDisplay;
rx::RendererD3D *mRenderer;
DeviceImpl *mDevice;
};
}
......
......@@ -51,7 +51,7 @@ enum ShaderType
enum RendererClass
{
RENDERER_D3D11,
RENDERER_D3D9,
RENDERER_D3D9
};
// Useful for unit testing
......@@ -177,8 +177,8 @@ class RendererD3D : public Renderer, public BufferFactoryD3D
// Device lost
void notifyDeviceLost() override;
virtual bool resetDevice() = 0;
virtual RendererClass getRendererClass() const = 0;
virtual void *getD3DDevice() = 0;
gl::Error getScratchMemoryBuffer(size_t requestedSize, MemoryBuffer **bufferOut);
......
......@@ -671,6 +671,11 @@ SwapChainD3D *Renderer11::createSwapChain(NativeWindow nativeWindow, HANDLE shar
return new SwapChain11(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat);
}
void *Renderer11::getD3DDevice()
{
return reinterpret_cast<void*>(mDevice);
}
gl::Error Renderer11::generateSwizzle(gl::Texture *texture)
{
if (texture)
......
......@@ -199,6 +199,7 @@ class Renderer11 : public RendererD3D
// D3D11-renderer specific methods
ID3D11Device *getDevice() { return mDevice; }
void *getD3DDevice() override;
ID3D11DeviceContext *getDeviceContext() { return mDeviceContext; };
ID3D11DeviceContext1 *getDeviceContext1IfSupported() { return mDeviceContext1; };
DXGIFactory *getDxgiFactory() { return mDxgiFactory; };
......
......@@ -49,6 +49,7 @@
#include "third_party/trace_event/trace_event.h"
#include <sstream>
#include <EGL/eglext.h>
#include <EGL/eglext.h>
......@@ -641,6 +642,11 @@ SwapChainD3D *Renderer9::createSwapChain(NativeWindow nativeWindow, HANDLE share
return new SwapChain9(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat);
}
void *Renderer9::getD3DDevice()
{
return reinterpret_cast<void*>(mDevice);
}
gl::Error Renderer9::allocateEventQuery(IDirect3DQuery9 **outQuery)
{
if (mEventQueryPool.empty())
......
......@@ -133,6 +133,7 @@ class Renderer9 : public RendererD3D
GUID getAdapterIdentifier() const override;
IDirect3DDevice9 *getDevice() { return mDevice; }
void *getD3DDevice() override;
virtual unsigned int getReservedVertexUniformVectors() const;
virtual unsigned int getReservedFragmentUniformVectors() const;
......
......@@ -394,6 +394,12 @@ static int QueryWGLFormatAttrib(HDC dc, int format, int attribName, const Functi
return result;
}
egl::Error DisplayWGL::getDevice(DeviceImpl **device)
{
UNIMPLEMENTED();
return egl::Error(EGL_BAD_DISPLAY);
}
egl::ConfigSet DisplayWGL::generateConfigs() const
{
egl::ConfigSet configs;
......
......@@ -44,6 +44,8 @@ class DisplayWGL : public DisplayGL
bool isValidNativeWindow(EGLNativeWindowType window) const override;
egl::Error getDevice(DeviceImpl **device) override;
std::string getVendorString() const override;
private:
......
......@@ -242,6 +242,21 @@ EGLDisplay EGLAPIENTRY eglGetPlatformDisplayEXT(EGLenum platform, void *native_d
return egl::GetPlatformDisplayEXT(platform, native_display, attrib_list);
}
EGLBoolean EGLAPIENTRY eglQueryDisplayAttribEXT(EGLDisplay dpy, EGLint attribute, EGLAttrib *value)
{
return egl::QueryDisplayAttribEXT(dpy, attribute, value);
}
EGLBoolean EGLAPIENTRY eglQueryDeviceAttribEXT(EGLDeviceEXT device, EGLint attribute, EGLAttrib *value)
{
return egl::QueryDeviceAttribEXT(device, attribute, value);
}
const char * EGLAPIENTRY eglQueryDeviceStringEXT(EGLDeviceEXT device, EGLint name)
{
return egl::QueryDeviceStringEXT(device, name);
}
__eglMustCastToProperFunctionPointerType EGLAPIENTRY eglGetProcAddress(const char *procname)
{
return egl::GetProcAddress(procname);
......
......@@ -39,6 +39,9 @@ EXPORTS
eglGetPlatformDisplayEXT @35
eglQuerySurfacePointerANGLE @36
eglPostSubBufferNV @37
eglQueryDisplayAttribEXT @48
eglQueryDeviceAttribEXT @49
eglQueryDeviceStringEXT @50
; 1.5 entry points
eglCreateSync @38
......
......@@ -62,6 +62,8 @@
'libANGLE/Context.h',
'libANGLE/Data.cpp',
'libANGLE/Data.h',
'libANGLE/Device.cpp',
'libANGLE/Device.h',
'libANGLE/Display.cpp',
'libANGLE/Display.h',
'libANGLE/Error.cpp',
......@@ -116,6 +118,8 @@
'libANGLE/queryconversions.h',
'libANGLE/renderer/BufferImpl.h',
'libANGLE/renderer/CompilerImpl.h',
'libANGLE/renderer/DeviceImpl.cpp',
'libANGLE/renderer/DeviceImpl.h',
'libANGLE/renderer/DisplayImpl.cpp',
'libANGLE/renderer/DisplayImpl.h',
'libANGLE/renderer/FenceNVImpl.h',
......@@ -158,6 +162,8 @@
'libANGLE/renderer/d3d/copyimage.cpp',
'libANGLE/renderer/d3d/copyimage.h',
'libANGLE/renderer/d3d/copyimage.inl',
'libANGLE/renderer/d3d/DeviceD3D.cpp',
'libANGLE/renderer/d3d/DeviceD3D.h',
'libANGLE/renderer/d3d/DisplayD3D.cpp',
'libANGLE/renderer/d3d/DisplayD3D.h',
'libANGLE/renderer/d3d/DynamicHLSL.cpp',
......
......@@ -1084,6 +1084,9 @@ __eglMustCastToProperFunctionPointerType EGLAPIENTRY GetProcAddress(const char *
static const Extension extensions[] =
{
{ "eglQueryDeviceAttribEXT", (__eglMustCastToProperFunctionPointerType)QueryDeviceAttribEXT },
{ "eglQueryDeviceStringEXT", (__eglMustCastToProperFunctionPointerType)QueryDeviceStringEXT },
{ "eglQueryDisplayAttribEXT", (__eglMustCastToProperFunctionPointerType)QueryDisplayAttribEXT },
{ "eglQuerySurfacePointerANGLE", (__eglMustCastToProperFunctionPointerType)QuerySurfacePointerANGLE },
{ "eglPostSubBufferNV", (__eglMustCastToProperFunctionPointerType)PostSubBufferNV },
{ "eglGetPlatformDisplayEXT", (__eglMustCastToProperFunctionPointerType)GetPlatformDisplayEXT },
......
......@@ -10,8 +10,10 @@
#include "libGLESv2/global_state.h"
#include "libANGLE/Display.h"
#include "libANGLE/Device.h"
#include "libANGLE/Surface.h"
#include "libANGLE/validationEGL.h"
#include "libANGLE/renderer/renderer.h"
#include "common/debug.h"
......@@ -268,4 +270,113 @@ EGLDisplay EGLAPIENTRY GetPlatformDisplayEXT(EGLenum platform, void *native_disp
return Display::getDisplay(displayId, AttributeMap(attrib_list));
}
// EGL_EXT_device_query
EGLBoolean EGLAPIENTRY QueryDeviceAttribEXT(EGLDeviceEXT device, EGLint attribute, EGLAttrib *value)
{
EVENT("(EGLDeviceEXT device = 0x%0.8p, EGLint attribute = %d, EGLAttrib *value = 0x%0.8p)",
device, attribute, value);
Device *dev = static_cast<Device*>(device);
if (dev == EGL_NO_DEVICE_EXT)
{
SetGlobalError(Error(EGL_BAD_ACCESS));
return EGL_FALSE;
}
Display *display = dev->getDisplay();
Error error(EGL_SUCCESS);
if (!display->getExtensions().deviceQuery)
{
SetGlobalError(Error(EGL_BAD_ACCESS));
return EGL_FALSE;
}
// validate the attribute parameter
switch (attribute)
{
case EGL_D3D11_DEVICE_ANGLE:
if (!dev->getExtensions().deviceD3D || dev->getType() != EGL_D3D11_DEVICE_ANGLE)
{
SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
return EGL_FALSE;
}
error = dev->getDevice(value);
break;
case EGL_D3D9_DEVICE_ANGLE:
if (!dev->getExtensions().deviceD3D || dev->getType() != EGL_D3D9_DEVICE_ANGLE)
{
SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
return EGL_FALSE;
}
error = dev->getDevice(value);
break;
default:
SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
return EGL_FALSE;
}
SetGlobalError(error);
return (error.isError() ? EGL_FALSE : EGL_TRUE);
}
// EGL_EXT_device_query
const char * EGLAPIENTRY QueryDeviceStringEXT(EGLDeviceEXT device, EGLint name)
{
EVENT("(EGLDeviceEXT device = 0x%0.8p, EGLint name = %d)",
device, name);
Device *dev = static_cast<Device*>(device);
if (dev == EGL_NO_DEVICE_EXT)
{
SetGlobalError(Error(EGL_BAD_DEVICE_EXT));
return nullptr;
}
const char *result;
switch (name)
{
case EGL_EXTENSIONS:
result = dev->getExtensionString().c_str();
break;
default:
SetGlobalError(Error(EGL_BAD_DEVICE_EXT));
return nullptr;
}
SetGlobalError(Error(EGL_SUCCESS));
return result;
}
// EGL_EXT_device_query
EGLBoolean EGLAPIENTRY QueryDisplayAttribEXT(EGLDisplay dpy, EGLint attribute, EGLAttrib *value)
{
EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint attribute = %d, EGLAttrib *value = 0x%0.8p)",
dpy, attribute, value);
Display *display = static_cast<Display*>(dpy);
Error error(EGL_SUCCESS);
if (!display->getExtensions().deviceQuery)
{
SetGlobalError(Error(EGL_BAD_ACCESS));
return EGL_FALSE;
}
// validate the attribute parameter
switch (attribute)
{
case EGL_DEVICE_EXT:
*value = reinterpret_cast<EGLAttrib>(display->getDevice());
break;
default:
SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
return EGL_FALSE;
}
SetGlobalError(error);
return (error.isError() ? EGL_FALSE : EGL_TRUE);
}
}
......@@ -25,6 +25,11 @@ ANGLE_EXPORT EGLBoolean EGLAPIENTRY PostSubBufferNV(EGLDisplay dpy, EGLSurface s
// EGL_EXT_platform_base
ANGLE_EXPORT EGLDisplay EGLAPIENTRY GetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list);
// EGL_EXT_device_query
ANGLE_EXPORT EGLBoolean EGLAPIENTRY QueryDisplayAttribEXT(EGLDisplay dpy, EGLint attribute, EGLAttrib *value);
ANGLE_EXPORT EGLBoolean EGLAPIENTRY QueryDeviceAttribEXT(EGLDeviceEXT device, EGLint attribute, EGLAttrib *value);
ANGLE_EXPORT const char * EGLAPIENTRY QueryDeviceStringEXT(EGLDeviceEXT device, EGLint name);
}
#endif // LIBGLESV2_ENTRYPOINTSEGLEXT_H_
......@@ -40,6 +40,7 @@
'<(angle_path)/src/tests/end2end_tests/PbufferTest.cpp',
'<(angle_path)/src/tests/end2end_tests/PointSpritesTest.cpp',
'<(angle_path)/src/tests/end2end_tests/ProgramBinaryTest.cpp',
'<(angle_path)/src/tests/end2end_tests/QueryDisplayAttribTest.cpp',
'<(angle_path)/src/tests/end2end_tests/ReadPixelsTest.cpp',
'<(angle_path)/src/tests/end2end_tests/RendererTest.cpp',
'<(angle_path)/src/tests/end2end_tests/SimpleOperationTest.cpp',
......
#define ANGLE_ENABLE_D3D9
#define ANGLE_ENABLE_D3D11
#include "ANGLETest.h"
#include "com_utils.h"
// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
ANGLE_TYPED_TEST_CASE(QueryDisplayAttributeTest, ES2_D3D9, ES2_D3D11);
template<typename T>
class QueryDisplayAttributeTest : public ANGLETest
{
protected:
QueryDisplayAttributeTest() : ANGLETest(T::GetGlesMajorVersion(), T::GetPlatform())
{
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.
TYPED_TEST(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.
TYPED_TEST(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));
}
}
//
// Copyright (c) 2014 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.
//
// com_utils.h: Utility functions for working with COM objects
#ifndef UTIL_COM_UTILS_H
#define UTIL_COM_UTILS_H
template <typename outType>
inline outType *DynamicCastComObject(IUnknown *object)
{
outType *outObject = nullptr;
HRESULT result = object->QueryInterface(__uuidof(outType), reinterpret_cast<void**>(&outObject));
if (SUCCEEDED(result))
{
return outObject;
}
else
{
SafeRelease(outObject);
return nullptr;
}
}
#endif // UTIL_COM_UTILS_H
......@@ -30,6 +30,7 @@
],
'sources':
[
'com_utils.h',
'keyboard.h',
'mouse.h',
'path_utils.h',
......
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