зеркало из https://github.com/AvaloniaUI/angle.git
Add a EGL_ANGLE_d3d_texture_client_buffer extension.
Allows creation of pbuffers from D3D texture objects. BUG=540829 BUG=angleproject:1144 Change-Id: If8ea717ef011608cd01357c217837133d726d3ea Reviewed-on: https://chromium-review.googlesource.com/316804 Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: Jamie Madill <jmadill@chromium.org>
This commit is contained in:
Родитель
9f4583dd8a
Коммит
2018c0bac4
|
@ -0,0 +1,106 @@
|
|||
Name
|
||||
|
||||
ANGLE_d3d_texture_client_buffer
|
||||
|
||||
Name Strings
|
||||
|
||||
EGL_ANGLE_d3d_texture_client_buffer
|
||||
|
||||
Contributors
|
||||
|
||||
Geoff Lang
|
||||
|
||||
Contacts
|
||||
|
||||
Geoff Lang, Google Inc. (geofflang 'at' google.com)
|
||||
|
||||
Status
|
||||
|
||||
Draft
|
||||
|
||||
Version
|
||||
|
||||
Version 1, Oct 5, 2016
|
||||
|
||||
Number
|
||||
|
||||
EGL Extension #??
|
||||
|
||||
Dependencies
|
||||
|
||||
This extension is written against the wording of the EGL 1.4
|
||||
Specification.
|
||||
|
||||
References the EGL_ANGLE_device_d3d extension.
|
||||
|
||||
Overview
|
||||
|
||||
This extension allows creating EGL surfaces from D3D texture objects.
|
||||
|
||||
New Types
|
||||
|
||||
None
|
||||
|
||||
New Procedures and Functions
|
||||
|
||||
None
|
||||
|
||||
New Tokens
|
||||
|
||||
Accepted in the <buftype> parameter of eglCreatePbufferFromClientBuffer:
|
||||
|
||||
EGL_D3D_TEXTURE_ANGLE 0x33A3
|
||||
|
||||
Additions to Chapter 3 of the EGL 1.4 Specification (EGL Functions and Errors)
|
||||
|
||||
Replace the last sentence of paragraph 1 of Section 3.5.3 with the
|
||||
following text.
|
||||
"Currently, the only client API resources which may be bound in this
|
||||
fashion are OpenVG VGImage objects and Direct3D texture objects."
|
||||
|
||||
Replace the last sentence of paragraph 2 ("To bind a client API...") of
|
||||
Section 3.5.3 with the following text.
|
||||
"When <buftype> is EGL_OPENVG_IMAGE or EGL_D3D_TEXTURE_ANGLE, the width and
|
||||
height of the pbuffer are determined by the width and height of <buffer>."
|
||||
|
||||
Replace the third paragraph of Section 3.5.3 with the following text.
|
||||
"<buftype> specifies the type of buffer to be bound. The only allowed values
|
||||
of <buftype> are EGL_OPENVG_IMAGE and EGL_D3D_TEXTURE_ANGLE".
|
||||
|
||||
Append the following text to the fourth paragraph of Section 3.5.3.
|
||||
"When <buftype> is EGL_D3D_TEXTURE_ANGLE, <buffer> must be
|
||||
a valid D3D texture object, cast into the type EGLClientBuffer. See table
|
||||
egl.restrictions for acceptable texture object types and formats. If the
|
||||
EGL_ANGLE_device_d3d extension is present, the provided D3D texture object
|
||||
must have been created by the same D3D device queried from the display.
|
||||
If these requirements are not met, an EGL_BAD_PARAMETER error is
|
||||
generated."
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
Resource Type Resource Restrictions
|
||||
---------------------------------------------------------------------------
|
||||
IDirect3DTexture9 Memory pool must be D3DPOOL_DEFAULT. Format must be
|
||||
D3DFMT_R8G8B8, D3DFMT_A8R8G8B8, D3DFMT_A16B16G16R16F or
|
||||
D3DFMT_A32B32G32R32F.
|
||||
ID3D11Texture2D Usage flags must be D3D11_USAGE_DEFAULT. Format must be
|
||||
DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
|
||||
DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
DXGI_FORMAT_B8G8R8A8_UNORM_SRGB,
|
||||
DXGI_FORMAT_R16G16B16A16_FLOAT or
|
||||
DXGI_FORMAT_R32G32B32A32_FLOAT.
|
||||
--------------------------------------------------------------------------
|
||||
Table egl.restrictions - Restrictions on D3D resources that can be used
|
||||
as a <buffer>.
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
Append to the end of Section 3.5.3.
|
||||
"When a pbuffer is created with type EGL_D3D_TEXTURE_ANGLE, the contents
|
||||
of the associcated D3D texture object are undefined while the pbuffer is
|
||||
the current read surface, draw surface or bound to a client texture."
|
||||
|
||||
Issues
|
||||
|
||||
Revision History
|
||||
|
||||
Version 1, 2016/10/05 - first draft.
|
|
@ -472,6 +472,11 @@ EGLAPI EGLint EGLAPIENTRY eglDupNativeFenceFDANDROID (EGLDisplay dpy, EGLSyncKHR
|
|||
#define EGL_DXGI_KEYED_MUTEX_ANGLE 0x33A2
|
||||
#endif /* EGL_ANGLE_keyed_mutex */
|
||||
|
||||
#ifndef EGL_ANGLE_d3d_texture_client_buffer
|
||||
#define EGL_ANGLE_d3d_texture_client_buffer 1
|
||||
#define EGL_D3D_TEXTURE_ANGLE 0x33A3
|
||||
#endif /* EGL_ANGLE_d3d_texture_client_buffer */
|
||||
|
||||
#ifndef EGL_ANGLE_query_surface_pointer
|
||||
#define EGL_ANGLE_query_surface_pointer 1
|
||||
typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACEPOINTERANGLEPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value);
|
||||
|
|
|
@ -762,6 +762,7 @@ Caps::Caps()
|
|||
DisplayExtensions::DisplayExtensions()
|
||||
: createContextRobustness(false),
|
||||
d3dShareHandleClientBuffer(false),
|
||||
d3dTextureClientBuffer(false),
|
||||
surfaceD3DTexture2DShareHandle(false),
|
||||
querySurfacePointer(false),
|
||||
windowFixedSize(false),
|
||||
|
@ -800,6 +801,7 @@ std::vector<std::string> DisplayExtensions::getStrings() const
|
|||
// | Extension name | Supported flag | Output vector |
|
||||
InsertExtensionString("EGL_EXT_create_context_robustness", createContextRobustness, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_d3d_share_handle_client_buffer", d3dShareHandleClientBuffer, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_d3d_texture_client_buffer", d3dTextureClientBuffer, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_surface_d3d_texture_2d_share_handle", surfaceD3DTexture2DShareHandle, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_query_surface_pointer", querySurfacePointer, &extensionStrings);
|
||||
InsertExtensionString("EGL_ANGLE_window_fixed_size", windowFixedSize, &extensionStrings);
|
||||
|
|
|
@ -533,6 +533,9 @@ struct DisplayExtensions
|
|||
// EGL_ANGLE_d3d_share_handle_client_buffer
|
||||
bool d3dShareHandleClientBuffer;
|
||||
|
||||
// EGL_ANGLE_d3d_texture_client_buffer
|
||||
bool d3dTextureClientBuffer;
|
||||
|
||||
// EGL_ANGLE_surface_d3d_texture_2d_share_handle
|
||||
bool surfaceD3DTexture2DShareHandle;
|
||||
|
||||
|
|
|
@ -587,8 +587,11 @@ Error Display::createPbufferSurface(const Config *configuration, const Attribute
|
|||
return egl::Error(EGL_SUCCESS);
|
||||
}
|
||||
|
||||
Error Display::createPbufferFromClientBuffer(const Config *configuration, EGLClientBuffer shareHandle,
|
||||
const AttributeMap &attribs, Surface **outSurface)
|
||||
Error Display::createPbufferFromClientBuffer(const Config *configuration,
|
||||
EGLenum buftype,
|
||||
EGLClientBuffer clientBuffer,
|
||||
const AttributeMap &attribs,
|
||||
Surface **outSurface)
|
||||
{
|
||||
ASSERT(isInitialized());
|
||||
|
||||
|
@ -598,7 +601,7 @@ Error Display::createPbufferFromClientBuffer(const Config *configuration, EGLCli
|
|||
}
|
||||
|
||||
std::unique_ptr<Surface> surface(
|
||||
new PbufferSurface(mImplementation, configuration, shareHandle, attribs));
|
||||
new PbufferSurface(mImplementation, configuration, buftype, clientBuffer, attribs));
|
||||
ANGLE_TRY(surface->initialize());
|
||||
|
||||
ASSERT(outSurface != nullptr);
|
||||
|
@ -947,6 +950,14 @@ bool Display::isValidNativeWindow(EGLNativeWindowType window) const
|
|||
return mImplementation->isValidNativeWindow(window);
|
||||
}
|
||||
|
||||
Error Display::validateClientBuffer(const Config *configuration,
|
||||
EGLenum buftype,
|
||||
EGLClientBuffer clientBuffer,
|
||||
const AttributeMap &attribs)
|
||||
{
|
||||
return mImplementation->validateClientBuffer(configuration, buftype, clientBuffer, attribs);
|
||||
}
|
||||
|
||||
bool Display::isValidDisplay(const egl::Display *display)
|
||||
{
|
||||
const ANGLEPlatformDisplayMap *anglePlatformDisplayMap = GetANGLEPlatformDisplayMap();
|
||||
|
|
|
@ -57,7 +57,10 @@ class Display final : angle::NonCopyable
|
|||
Error createWindowSurface(const Config *configuration, EGLNativeWindowType window, const AttributeMap &attribs,
|
||||
Surface **outSurface);
|
||||
Error createPbufferSurface(const Config *configuration, const AttributeMap &attribs, Surface **outSurface);
|
||||
Error createPbufferFromClientBuffer(const Config *configuration, EGLClientBuffer shareHandle, const AttributeMap &attribs,
|
||||
Error createPbufferFromClientBuffer(const Config *configuration,
|
||||
EGLenum buftype,
|
||||
EGLClientBuffer clientBuffer,
|
||||
const AttributeMap &attribs,
|
||||
Surface **outSurface);
|
||||
Error createPixmapSurface(const Config *configuration, NativePixmapType nativePixmap, const AttributeMap &attribs,
|
||||
Surface **outSurface);
|
||||
|
@ -88,6 +91,11 @@ class Display final : angle::NonCopyable
|
|||
bool isValidStream(const Stream *stream) const;
|
||||
bool isValidNativeWindow(EGLNativeWindowType window) const;
|
||||
|
||||
Error validateClientBuffer(const Config *configuration,
|
||||
EGLenum buftype,
|
||||
EGLClientBuffer clientBuffer,
|
||||
const AttributeMap &attribs);
|
||||
|
||||
static bool isValidDisplay(const egl::Display *display);
|
||||
static bool isValidNativeDisplay(EGLNativeDisplayType display);
|
||||
static bool hasExistingWindowSurface(EGLNativeWindowType window);
|
||||
|
|
|
@ -211,19 +211,23 @@ EGLint Surface::getHeight() const
|
|||
Error Surface::bindTexImage(gl::Texture *texture, EGLint buffer)
|
||||
{
|
||||
ASSERT(!mTexture.get());
|
||||
ANGLE_TRY(mImplementation->bindTexImage(texture, buffer));
|
||||
|
||||
texture->bindTexImageFromSurface(this);
|
||||
mTexture.set(texture);
|
||||
return mImplementation->bindTexImage(texture, buffer);
|
||||
|
||||
return Error(EGL_SUCCESS);
|
||||
}
|
||||
|
||||
Error Surface::releaseTexImage(EGLint buffer)
|
||||
{
|
||||
ANGLE_TRY(mImplementation->releaseTexImage(buffer));
|
||||
|
||||
ASSERT(mTexture.get());
|
||||
mTexture->releaseTexImageFromSurface();
|
||||
mTexture.set(nullptr);
|
||||
|
||||
return mImplementation->releaseTexImage(buffer);
|
||||
return Error(EGL_SUCCESS);
|
||||
}
|
||||
|
||||
Error Surface::getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc)
|
||||
|
@ -308,12 +312,13 @@ PbufferSurface::PbufferSurface(rx::EGLImplFactory *implFactory,
|
|||
|
||||
PbufferSurface::PbufferSurface(rx::EGLImplFactory *implFactory,
|
||||
const Config *config,
|
||||
EGLClientBuffer shareHandle,
|
||||
EGLenum buftype,
|
||||
EGLClientBuffer clientBuffer,
|
||||
const AttributeMap &attribs)
|
||||
: Surface(EGL_PBUFFER_BIT, config, attribs)
|
||||
{
|
||||
mImplementation =
|
||||
implFactory->createPbufferFromClientBuffer(mState, config, shareHandle, attribs);
|
||||
implFactory->createPbufferFromClientBuffer(mState, config, buftype, clientBuffer, attribs);
|
||||
}
|
||||
|
||||
PbufferSurface::~PbufferSurface()
|
||||
|
|
|
@ -164,7 +164,8 @@ class PbufferSurface final : public Surface
|
|||
const AttributeMap &attribs);
|
||||
PbufferSurface(rx::EGLImplFactory *implFactory,
|
||||
const Config *config,
|
||||
EGLClientBuffer shareHandle,
|
||||
EGLenum buftype,
|
||||
EGLClientBuffer clientBuffer,
|
||||
const AttributeMap &attribs);
|
||||
~PbufferSurface() override;
|
||||
};
|
||||
|
|
|
@ -41,6 +41,15 @@ const egl::DisplayExtensions &DisplayImpl::getExtensions() const
|
|||
return mExtensions;
|
||||
}
|
||||
|
||||
egl::Error DisplayImpl::validateClientBuffer(const egl::Config *configuration,
|
||||
EGLenum buftype,
|
||||
EGLClientBuffer clientBuffer,
|
||||
const egl::AttributeMap &attribs) const
|
||||
{
|
||||
UNREACHABLE();
|
||||
return egl::Error(EGL_BAD_DISPLAY, "DisplayImpl::validateClientBuffer unimplemented.");
|
||||
}
|
||||
|
||||
const egl::Caps &DisplayImpl::getCaps() const
|
||||
{
|
||||
if (!mCapsInitialized)
|
||||
|
|
|
@ -59,6 +59,10 @@ class DisplayImpl : public EGLImplFactory
|
|||
virtual egl::Error restoreLostDevice() = 0;
|
||||
|
||||
virtual bool isValidNativeWindow(EGLNativeWindowType window) const = 0;
|
||||
virtual egl::Error validateClientBuffer(const egl::Config *configuration,
|
||||
EGLenum buftype,
|
||||
EGLClientBuffer clientBuffer,
|
||||
const egl::AttributeMap &attribs) const;
|
||||
|
||||
virtual std::string getVendorString() const = 0;
|
||||
|
||||
|
|
|
@ -47,7 +47,8 @@ class EGLImplFactory : angle::NonCopyable
|
|||
const egl::AttributeMap &attribs) = 0;
|
||||
virtual SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
|
||||
const egl::Config *configuration,
|
||||
EGLClientBuffer shareHandle,
|
||||
EGLenum buftype,
|
||||
EGLClientBuffer clientBuffer,
|
||||
const egl::AttributeMap &attribs) = 0;
|
||||
virtual SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
|
||||
const egl::Config *configuration,
|
||||
|
|
|
@ -176,16 +176,18 @@ SurfaceImpl *DisplayD3D::createPbufferSurface(const egl::SurfaceState &state,
|
|||
const egl::AttributeMap &attribs)
|
||||
{
|
||||
ASSERT(mRenderer != nullptr);
|
||||
return new PbufferSurfaceD3D(state, mRenderer, mDisplay, configuration, nullptr, attribs);
|
||||
return new PbufferSurfaceD3D(state, mRenderer, mDisplay, configuration, 0, nullptr, attribs);
|
||||
}
|
||||
|
||||
SurfaceImpl *DisplayD3D::createPbufferFromClientBuffer(const egl::SurfaceState &state,
|
||||
const egl::Config *configuration,
|
||||
EGLClientBuffer shareHandle,
|
||||
EGLenum buftype,
|
||||
EGLClientBuffer clientBuffer,
|
||||
const egl::AttributeMap &attribs)
|
||||
{
|
||||
ASSERT(mRenderer != nullptr);
|
||||
return new PbufferSurfaceD3D(state, mRenderer, mDisplay, configuration, shareHandle, attribs);
|
||||
return new PbufferSurfaceD3D(state, mRenderer, mDisplay, configuration, buftype, clientBuffer,
|
||||
attribs);
|
||||
}
|
||||
|
||||
SurfaceImpl *DisplayD3D::createPixmapSurface(const egl::SurfaceState &state,
|
||||
|
@ -291,6 +293,26 @@ bool DisplayD3D::isValidNativeWindow(EGLNativeWindowType window) const
|
|||
return mRenderer->isValidNativeWindow(window);
|
||||
}
|
||||
|
||||
egl::Error DisplayD3D::validateClientBuffer(const egl::Config *configuration,
|
||||
EGLenum buftype,
|
||||
EGLClientBuffer clientBuffer,
|
||||
const egl::AttributeMap &attribs) const
|
||||
{
|
||||
switch (buftype)
|
||||
{
|
||||
case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
|
||||
return mRenderer->validateShareHandle(configuration, static_cast<HANDLE>(clientBuffer),
|
||||
attribs);
|
||||
|
||||
case EGL_D3D_TEXTURE_ANGLE:
|
||||
return mRenderer->getD3DTextureInfo(static_cast<IUnknown *>(clientBuffer), nullptr,
|
||||
nullptr, nullptr);
|
||||
|
||||
default:
|
||||
return DisplayImpl::validateClientBuffer(configuration, buftype, clientBuffer, attribs);
|
||||
}
|
||||
}
|
||||
|
||||
void DisplayD3D::generateExtensions(egl::DisplayExtensions *outExtensions) const
|
||||
{
|
||||
mRenderer->generateDisplayExtensions(outExtensions);
|
||||
|
|
|
@ -34,7 +34,8 @@ class DisplayD3D : public DisplayImpl
|
|||
const egl::AttributeMap &attribs) override;
|
||||
SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
|
||||
const egl::Config *configuration,
|
||||
EGLClientBuffer shareHandle,
|
||||
EGLenum buftype,
|
||||
EGLClientBuffer clientBuffer,
|
||||
const egl::AttributeMap &attribs) override;
|
||||
SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
|
||||
const egl::Config *configuration,
|
||||
|
@ -59,6 +60,10 @@ class DisplayD3D : public DisplayImpl
|
|||
egl::Error restoreLostDevice() override;
|
||||
|
||||
bool isValidNativeWindow(EGLNativeWindowType window) const override;
|
||||
egl::Error validateClientBuffer(const egl::Config *configuration,
|
||||
EGLenum buftype,
|
||||
EGLClientBuffer clientBuffer,
|
||||
const egl::AttributeMap &attribs) const override;
|
||||
|
||||
egl::Error getDevice(DeviceImpl **device) override;
|
||||
|
||||
|
|
|
@ -127,9 +127,17 @@ class RendererD3D : public BufferFactoryD3D
|
|||
|
||||
virtual SwapChainD3D *createSwapChain(NativeWindowD3D *nativeWindow,
|
||||
HANDLE shareHandle,
|
||||
IUnknown *d3dTexture,
|
||||
GLenum backBufferFormat,
|
||||
GLenum depthBufferFormat,
|
||||
EGLint orientation) = 0;
|
||||
virtual egl::Error getD3DTextureInfo(IUnknown *d3dTexture,
|
||||
EGLint *width,
|
||||
EGLint *height,
|
||||
GLenum *fboFormat) const = 0;
|
||||
virtual egl::Error validateShareHandle(const egl::Config *config,
|
||||
HANDLE shareHandle,
|
||||
const egl::AttributeMap &attribs) const = 0;
|
||||
|
||||
virtual gl::Error setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &sampler) = 0;
|
||||
virtual gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture) = 0;
|
||||
|
|
|
@ -26,7 +26,8 @@ SurfaceD3D::SurfaceD3D(const egl::SurfaceState &state,
|
|||
egl::Display *display,
|
||||
const egl::Config *config,
|
||||
EGLNativeWindowType window,
|
||||
EGLClientBuffer shareHandle,
|
||||
EGLenum buftype,
|
||||
EGLClientBuffer clientBuffer,
|
||||
const egl::AttributeMap &attribs)
|
||||
: SurfaceImpl(state),
|
||||
mRenderer(renderer),
|
||||
|
@ -41,19 +42,39 @@ SurfaceD3D::SurfaceD3D(const egl::SurfaceState &state,
|
|||
mWidth(static_cast<EGLint>(attribs.get(EGL_WIDTH, 0))),
|
||||
mHeight(static_cast<EGLint>(attribs.get(EGL_HEIGHT, 0))),
|
||||
mSwapInterval(1),
|
||||
mShareHandle(reinterpret_cast<HANDLE *>(shareHandle))
|
||||
mShareHandle(0),
|
||||
mD3DTexture(nullptr)
|
||||
{
|
||||
if (window != nullptr && !mFixedSize)
|
||||
{
|
||||
mWidth = -1;
|
||||
mHeight = -1;
|
||||
}
|
||||
|
||||
switch (buftype)
|
||||
{
|
||||
case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
|
||||
mShareHandle = static_cast<HANDLE>(clientBuffer);
|
||||
break;
|
||||
|
||||
case EGL_D3D_TEXTURE_ANGLE:
|
||||
mD3DTexture = static_cast<IUnknown *>(clientBuffer);
|
||||
ASSERT(mD3DTexture != nullptr);
|
||||
mD3DTexture->AddRef();
|
||||
mRenderer->getD3DTextureInfo(mD3DTexture, &mWidth, &mHeight, &mRenderTargetFormat);
|
||||
mDepthStencilFormat = GL_NONE;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SurfaceD3D::~SurfaceD3D()
|
||||
{
|
||||
releaseSwapChain();
|
||||
SafeDelete(mNativeWindow);
|
||||
SafeRelease(mD3DTexture);
|
||||
}
|
||||
|
||||
void SurfaceD3D::releaseSwapChain()
|
||||
|
@ -127,8 +148,8 @@ egl::Error SurfaceD3D::resetSwapChain()
|
|||
height = mHeight;
|
||||
}
|
||||
|
||||
mSwapChain = mRenderer->createSwapChain(mNativeWindow, mShareHandle, mRenderTargetFormat,
|
||||
mDepthStencilFormat, mOrientation);
|
||||
mSwapChain = mRenderer->createSwapChain(mNativeWindow, mShareHandle, mD3DTexture,
|
||||
mRenderTargetFormat, mDepthStencilFormat, mOrientation);
|
||||
if (!mSwapChain)
|
||||
{
|
||||
return egl::Error(EGL_BAD_ALLOC);
|
||||
|
@ -346,7 +367,14 @@ WindowSurfaceD3D::WindowSurfaceD3D(const egl::SurfaceState &state,
|
|||
const egl::Config *config,
|
||||
EGLNativeWindowType window,
|
||||
const egl::AttributeMap &attribs)
|
||||
: SurfaceD3D(state, renderer, display, config, window, static_cast<EGLClientBuffer>(0), attribs)
|
||||
: SurfaceD3D(state,
|
||||
renderer,
|
||||
display,
|
||||
config,
|
||||
window,
|
||||
0,
|
||||
static_cast<EGLClientBuffer>(0),
|
||||
attribs)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -358,14 +386,16 @@ PbufferSurfaceD3D::PbufferSurfaceD3D(const egl::SurfaceState &state,
|
|||
RendererD3D *renderer,
|
||||
egl::Display *display,
|
||||
const egl::Config *config,
|
||||
EGLClientBuffer shareHandle,
|
||||
EGLenum buftype,
|
||||
EGLClientBuffer clientBuffer,
|
||||
const egl::AttributeMap &attribs)
|
||||
: SurfaceD3D(state,
|
||||
renderer,
|
||||
display,
|
||||
config,
|
||||
static_cast<EGLNativeWindowType>(0),
|
||||
shareHandle,
|
||||
buftype,
|
||||
clientBuffer,
|
||||
attribs)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -62,7 +62,8 @@ class SurfaceD3D : public SurfaceImpl
|
|||
egl::Display *display,
|
||||
const egl::Config *config,
|
||||
EGLNativeWindowType window,
|
||||
EGLClientBuffer shareHandle,
|
||||
EGLenum buftype,
|
||||
EGLClientBuffer clientBuffer,
|
||||
const egl::AttributeMap &attribs);
|
||||
|
||||
egl::Error swapRect(EGLint x, EGLint y, EGLint width, EGLint height);
|
||||
|
@ -88,6 +89,7 @@ class SurfaceD3D : public SurfaceImpl
|
|||
EGLint mSwapInterval;
|
||||
|
||||
HANDLE mShareHandle;
|
||||
IUnknown *mD3DTexture;
|
||||
};
|
||||
|
||||
class WindowSurfaceD3D : public SurfaceD3D
|
||||
|
@ -109,7 +111,8 @@ class PbufferSurfaceD3D : public SurfaceD3D
|
|||
RendererD3D *renderer,
|
||||
egl::Display *display,
|
||||
const egl::Config *config,
|
||||
EGLClientBuffer shareHandle,
|
||||
EGLenum buftype,
|
||||
EGLClientBuffer clientBuffer,
|
||||
const egl::AttributeMap &attribs);
|
||||
~PbufferSurfaceD3D() override;
|
||||
};
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
//
|
||||
// Copyright (c) 2016 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.
|
||||
//
|
||||
|
||||
// SwapChainD3D.cpp: Defines a back-end specific class that hides the details of the
|
||||
// implementation-specific swapchain.
|
||||
|
||||
#include "libANGLE/renderer/d3d/SwapChainD3D.h"
|
||||
|
||||
namespace rx
|
||||
{
|
||||
|
||||
SwapChainD3D::SwapChainD3D(HANDLE shareHandle,
|
||||
IUnknown *d3dTexture,
|
||||
GLenum backBufferFormat,
|
||||
GLenum depthBufferFormat)
|
||||
: mOffscreenRenderTargetFormat(backBufferFormat),
|
||||
mDepthBufferFormat(depthBufferFormat),
|
||||
mShareHandle(shareHandle),
|
||||
mD3DTexture(d3dTexture)
|
||||
{
|
||||
if (mD3DTexture)
|
||||
{
|
||||
mD3DTexture->AddRef();
|
||||
}
|
||||
}
|
||||
|
||||
SwapChainD3D::~SwapChainD3D()
|
||||
{
|
||||
SafeRelease(mD3DTexture);
|
||||
}
|
||||
} // namespace rx
|
|
@ -29,14 +29,11 @@ class RenderTargetD3D;
|
|||
class SwapChainD3D : angle::NonCopyable
|
||||
{
|
||||
public:
|
||||
SwapChainD3D(HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
|
||||
: mOffscreenRenderTargetFormat(backBufferFormat),
|
||||
mDepthBufferFormat(depthBufferFormat),
|
||||
mShareHandle(shareHandle)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~SwapChainD3D() {};
|
||||
SwapChainD3D(HANDLE shareHandle,
|
||||
IUnknown *d3dTexture,
|
||||
GLenum backBufferFormat,
|
||||
GLenum depthBufferFormat);
|
||||
virtual ~SwapChainD3D();
|
||||
|
||||
virtual EGLint resize(EGLint backbufferWidth, EGLint backbufferSize) = 0;
|
||||
virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval) = 0;
|
||||
|
@ -59,7 +56,8 @@ class SwapChainD3D : angle::NonCopyable
|
|||
const GLenum mDepthBufferFormat;
|
||||
|
||||
HANDLE mShareHandle;
|
||||
IUnknown *mD3DTexture;
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace rx
|
||||
#endif // LIBANGLE_RENDERER_D3D_SWAPCHAIND3D_H_
|
||||
|
|
|
@ -1081,6 +1081,7 @@ void Renderer11::generateDisplayExtensions(egl::DisplayExtensions *outExtensions
|
|||
outExtensions->d3dShareHandleClientBuffer = true;
|
||||
outExtensions->surfaceD3DTexture2DShareHandle = true;
|
||||
}
|
||||
outExtensions->d3dTextureClientBuffer = true;
|
||||
|
||||
outExtensions->keyedMutex = true;
|
||||
outExtensions->querySurfacePointer = true;
|
||||
|
@ -1193,14 +1194,119 @@ NativeWindowD3D *Renderer11::createNativeWindow(EGLNativeWindowType window,
|
|||
#endif
|
||||
}
|
||||
|
||||
egl::Error Renderer11::getD3DTextureInfo(IUnknown *d3dTexture,
|
||||
EGLint *width,
|
||||
EGLint *height,
|
||||
GLenum *fboFormat) const
|
||||
{
|
||||
ID3D11Texture2D *texture = d3d11::DynamicCastComObject<ID3D11Texture2D>(d3dTexture);
|
||||
if (texture == nullptr)
|
||||
{
|
||||
return egl::Error(EGL_BAD_PARAMETER, "client buffer is not a ID3D11Texture2D");
|
||||
}
|
||||
|
||||
ID3D11Device *textureDevice = nullptr;
|
||||
texture->GetDevice(&textureDevice);
|
||||
if (textureDevice != mDevice)
|
||||
{
|
||||
SafeRelease(texture);
|
||||
return egl::Error(EGL_BAD_PARAMETER, "Texture's device does not match.");
|
||||
}
|
||||
SafeRelease(textureDevice);
|
||||
|
||||
D3D11_TEXTURE2D_DESC desc = {0};
|
||||
texture->GetDesc(&desc);
|
||||
SafeRelease(texture);
|
||||
|
||||
if (width)
|
||||
{
|
||||
*width = static_cast<EGLint>(desc.Width);
|
||||
}
|
||||
if (height)
|
||||
{
|
||||
*height = static_cast<EGLint>(desc.Height);
|
||||
}
|
||||
|
||||
// From table egl.restrictions in EGL_ANGLE_d3d_texture_client_buffer.
|
||||
switch (desc.Format)
|
||||
{
|
||||
case DXGI_FORMAT_R8G8B8A8_UNORM:
|
||||
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
|
||||
case DXGI_FORMAT_B8G8R8A8_UNORM:
|
||||
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
|
||||
case DXGI_FORMAT_R16G16B16A16_FLOAT:
|
||||
case DXGI_FORMAT_R32G32B32A32_FLOAT:
|
||||
break;
|
||||
|
||||
default:
|
||||
return egl::Error(EGL_BAD_PARAMETER, "Unknown client buffer texture format: %u.",
|
||||
desc.Format);
|
||||
}
|
||||
|
||||
if (fboFormat)
|
||||
{
|
||||
const angle::Format &angleFormat = d3d11_angle::GetFormat(desc.Format);
|
||||
*fboFormat = angleFormat.fboImplementationInternalFormat;
|
||||
}
|
||||
|
||||
return egl::Error(EGL_SUCCESS);
|
||||
}
|
||||
|
||||
egl::Error Renderer11::validateShareHandle(const egl::Config *config,
|
||||
HANDLE shareHandle,
|
||||
const egl::AttributeMap &attribs) const
|
||||
{
|
||||
if (shareHandle == nullptr)
|
||||
{
|
||||
return egl::Error(EGL_BAD_PARAMETER, "NULL share handle.");
|
||||
}
|
||||
|
||||
ID3D11Resource *tempResource11 = nullptr;
|
||||
HRESULT result = mDevice->OpenSharedResource(shareHandle, __uuidof(ID3D11Resource),
|
||||
(void **)&tempResource11);
|
||||
if (FAILED(result))
|
||||
{
|
||||
return egl::Error(EGL_BAD_PARAMETER, "Failed to open share handle, result: 0x%X.", result);
|
||||
}
|
||||
|
||||
ID3D11Texture2D *texture2D = d3d11::DynamicCastComObject<ID3D11Texture2D>(tempResource11);
|
||||
SafeRelease(tempResource11);
|
||||
|
||||
if (texture2D == nullptr)
|
||||
{
|
||||
return egl::Error(EGL_BAD_PARAMETER,
|
||||
"Failed to query ID3D11Texture2D object from share handle.");
|
||||
}
|
||||
|
||||
D3D11_TEXTURE2D_DESC desc = {0};
|
||||
texture2D->GetDesc(&desc);
|
||||
SafeRelease(texture2D);
|
||||
|
||||
EGLint width = attribs.getAsInt(EGL_WIDTH, 0);
|
||||
EGLint height = attribs.getAsInt(EGL_HEIGHT, 0);
|
||||
ASSERT(width != 0 && height != 0);
|
||||
|
||||
const d3d11::Format &backbufferFormatInfo =
|
||||
d3d11::Format::Get(config->renderTargetFormat, getRenderer11DeviceCaps());
|
||||
|
||||
if (desc.Width != static_cast<UINT>(width) || desc.Height != static_cast<UINT>(height) ||
|
||||
desc.Format != backbufferFormatInfo.texFormat || desc.MipLevels != 1 || desc.ArraySize != 1)
|
||||
{
|
||||
return egl::Error(EGL_BAD_PARAMETER, "Invalid texture parameters in share handle texture.");
|
||||
}
|
||||
|
||||
return egl::Error(EGL_SUCCESS);
|
||||
}
|
||||
|
||||
SwapChainD3D *Renderer11::createSwapChain(NativeWindowD3D *nativeWindow,
|
||||
HANDLE shareHandle,
|
||||
IUnknown *d3dTexture,
|
||||
GLenum backBufferFormat,
|
||||
GLenum depthBufferFormat,
|
||||
EGLint orientation)
|
||||
{
|
||||
return new SwapChain11(this, GetAs<NativeWindow11>(nativeWindow), shareHandle, backBufferFormat,
|
||||
depthBufferFormat, orientation);
|
||||
return new SwapChain11(this, GetAs<NativeWindow11>(nativeWindow), shareHandle, d3dTexture,
|
||||
backBufferFormat, depthBufferFormat, orientation);
|
||||
}
|
||||
|
||||
void *Renderer11::getD3DDevice()
|
||||
|
|
|
@ -123,9 +123,17 @@ class Renderer11 : public RendererD3D
|
|||
|
||||
SwapChainD3D *createSwapChain(NativeWindowD3D *nativeWindow,
|
||||
HANDLE shareHandle,
|
||||
IUnknown *d3dTexture,
|
||||
GLenum backBufferFormat,
|
||||
GLenum depthBufferFormat,
|
||||
EGLint orientation) override;
|
||||
egl::Error getD3DTextureInfo(IUnknown *d3dTexture,
|
||||
EGLint *width,
|
||||
EGLint *height,
|
||||
GLenum *fboFormat) const override;
|
||||
egl::Error validateShareHandle(const egl::Config *config,
|
||||
HANDLE shareHandle,
|
||||
const egl::AttributeMap &attribs) const override;
|
||||
|
||||
gl::Error setSamplerState(gl::SamplerType type,
|
||||
int index,
|
||||
|
@ -334,7 +342,7 @@ class Renderer11 : public RendererD3D
|
|||
bool colorBlit, bool depthBlit, bool stencilBlit);
|
||||
|
||||
bool isES3Capable() const;
|
||||
const Renderer11DeviceCaps &getRenderer11DeviceCaps() { return mRenderer11DeviceCaps; };
|
||||
const Renderer11DeviceCaps &getRenderer11DeviceCaps() const { return mRenderer11DeviceCaps; };
|
||||
|
||||
RendererClass getRendererClass() const override { return RENDERER_D3D11; }
|
||||
InputLayoutCache *getInputLayoutCache() { return &mInputLayoutCache; }
|
||||
|
|
|
@ -51,10 +51,11 @@ bool NeedsOffscreenTexture(Renderer11 *renderer, NativeWindow11 *nativeWindow, E
|
|||
SwapChain11::SwapChain11(Renderer11 *renderer,
|
||||
NativeWindow11 *nativeWindow,
|
||||
HANDLE shareHandle,
|
||||
IUnknown *d3dTexture,
|
||||
GLenum backBufferFormat,
|
||||
GLenum depthBufferFormat,
|
||||
EGLint orientation)
|
||||
: SwapChainD3D(shareHandle, backBufferFormat, depthBufferFormat),
|
||||
: SwapChainD3D(shareHandle, d3dTexture, backBufferFormat, depthBufferFormat),
|
||||
mRenderer(renderer),
|
||||
mWidth(-1),
|
||||
mHeight(-1),
|
||||
|
@ -194,42 +195,29 @@ EGLint SwapChain11::resetOffscreenColorBuffer(int backbufferWidth, int backbuffe
|
|||
const d3d11::Format &backbufferFormatInfo =
|
||||
d3d11::Format::Get(mOffscreenRenderTargetFormat, mRenderer->getRenderer11DeviceCaps());
|
||||
|
||||
// If the app passed in a share handle, open the resource
|
||||
// See EGL_ANGLE_d3d_share_handle_client_buffer
|
||||
if (mAppCreatedShareHandle)
|
||||
// If the app passed in a share handle or D3D texture, open the resource
|
||||
// See EGL_ANGLE_d3d_share_handle_client_buffer and EGL_ANGLE_d3d_texture_client_buffer
|
||||
if (mAppCreatedShareHandle || mD3DTexture != nullptr)
|
||||
{
|
||||
ID3D11Resource *tempResource11;
|
||||
HRESULT result = device->OpenSharedResource(mShareHandle, __uuidof(ID3D11Resource), (void**)&tempResource11);
|
||||
|
||||
if (FAILED(result))
|
||||
if (mAppCreatedShareHandle)
|
||||
{
|
||||
ERR("Failed to open the swap chain pbuffer share handle: %08lX", result);
|
||||
release();
|
||||
return EGL_BAD_PARAMETER;
|
||||
ID3D11Resource *tempResource11;
|
||||
HRESULT result = device->OpenSharedResource(mShareHandle, __uuidof(ID3D11Resource),
|
||||
(void **)&tempResource11);
|
||||
ASSERT(SUCCEEDED(result));
|
||||
|
||||
mOffscreenTexture = d3d11::DynamicCastComObject<ID3D11Texture2D>(tempResource11);
|
||||
SafeRelease(tempResource11);
|
||||
ASSERT(SUCCEEDED(mOffscreenTexture != nullptr));
|
||||
}
|
||||
|
||||
result = tempResource11->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&mOffscreenTexture);
|
||||
SafeRelease(tempResource11);
|
||||
|
||||
if (FAILED(result))
|
||||
else if (mD3DTexture != nullptr)
|
||||
{
|
||||
ERR("Failed to query texture2d interface in pbuffer share handle: %08lX", result);
|
||||
release();
|
||||
return EGL_BAD_PARAMETER;
|
||||
mOffscreenTexture = d3d11::DynamicCastComObject<ID3D11Texture2D>(mD3DTexture);
|
||||
ASSERT(mOffscreenTexture != nullptr);
|
||||
}
|
||||
|
||||
// Validate offscreen texture parameters
|
||||
D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
|
||||
mOffscreenTexture->GetDesc(&offscreenTextureDesc);
|
||||
|
||||
if (offscreenTextureDesc.Width != (UINT)backbufferWidth ||
|
||||
offscreenTextureDesc.Height != (UINT)backbufferHeight ||
|
||||
offscreenTextureDesc.Format != backbufferFormatInfo.texFormat ||
|
||||
offscreenTextureDesc.MipLevels != 1 || offscreenTextureDesc.ArraySize != 1)
|
||||
else
|
||||
{
|
||||
ERR("Invalid texture parameters in the shared offscreen texture pbuffer");
|
||||
release();
|
||||
return EGL_BAD_PARAMETER;
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -24,6 +24,7 @@ class SwapChain11 final : public SwapChainD3D
|
|||
SwapChain11(Renderer11 *renderer,
|
||||
NativeWindow11 *nativeWindow,
|
||||
HANDLE shareHandle,
|
||||
IUnknown *d3dTexture,
|
||||
GLenum backBufferFormat,
|
||||
GLenum depthBufferFormat,
|
||||
EGLint orientation);
|
||||
|
|
|
@ -60,6 +60,11 @@ GLenum GetComponentType(DXGI_FORMAT dxgiFormat);
|
|||
|
||||
} // namespace d3d11
|
||||
|
||||
namespace d3d11_angle
|
||||
{
|
||||
const angle::Format &GetFormat(DXGI_FORMAT dxgiFormat);
|
||||
}
|
||||
|
||||
} // namespace rx
|
||||
|
||||
#endif // LIBANGLE_RENDERER_D3D_D3D11_FORMATUTILS11_H_
|
||||
|
|
|
@ -525,6 +525,7 @@ void Renderer9::generateDisplayExtensions(egl::DisplayExtensions *outExtensions)
|
|||
outExtensions->d3dShareHandleClientBuffer = true;
|
||||
outExtensions->surfaceD3DTexture2DShareHandle = true;
|
||||
}
|
||||
outExtensions->d3dTextureClientBuffer = true;
|
||||
|
||||
outExtensions->querySurfacePointer = true;
|
||||
outExtensions->windowFixedSize = true;
|
||||
|
@ -672,12 +673,111 @@ NativeWindowD3D *Renderer9::createNativeWindow(EGLNativeWindowType window,
|
|||
|
||||
SwapChainD3D *Renderer9::createSwapChain(NativeWindowD3D *nativeWindow,
|
||||
HANDLE shareHandle,
|
||||
IUnknown *d3dTexture,
|
||||
GLenum backBufferFormat,
|
||||
GLenum depthBufferFormat,
|
||||
EGLint orientation)
|
||||
{
|
||||
return new SwapChain9(this, GetAs<NativeWindow9>(nativeWindow), shareHandle, backBufferFormat,
|
||||
depthBufferFormat, orientation);
|
||||
return new SwapChain9(this, GetAs<NativeWindow9>(nativeWindow), shareHandle, d3dTexture,
|
||||
backBufferFormat, depthBufferFormat, orientation);
|
||||
}
|
||||
|
||||
egl::Error Renderer9::getD3DTextureInfo(IUnknown *d3dTexture,
|
||||
EGLint *width,
|
||||
EGLint *height,
|
||||
GLenum *fboFormat) const
|
||||
{
|
||||
IDirect3DTexture9 *texture = nullptr;
|
||||
if (FAILED(d3dTexture->QueryInterface(&texture)))
|
||||
{
|
||||
return egl::Error(EGL_BAD_PARAMETER, "client buffer is not a IDirect3DTexture9");
|
||||
}
|
||||
|
||||
IDirect3DDevice9 *textureDevice = nullptr;
|
||||
texture->GetDevice(&textureDevice);
|
||||
if (textureDevice != mDevice)
|
||||
{
|
||||
SafeRelease(texture);
|
||||
return egl::Error(EGL_BAD_PARAMETER, "Texture's device does not match.");
|
||||
}
|
||||
SafeRelease(textureDevice);
|
||||
|
||||
D3DSURFACE_DESC desc;
|
||||
texture->GetLevelDesc(0, &desc);
|
||||
SafeRelease(texture);
|
||||
|
||||
if (width)
|
||||
{
|
||||
*width = static_cast<EGLint>(desc.Width);
|
||||
}
|
||||
if (height)
|
||||
{
|
||||
*height = static_cast<EGLint>(desc.Height);
|
||||
}
|
||||
|
||||
// From table egl.restrictions in EGL_ANGLE_d3d_texture_client_buffer.
|
||||
switch (desc.Format)
|
||||
{
|
||||
case D3DFMT_R8G8B8:
|
||||
case D3DFMT_A8R8G8B8:
|
||||
case D3DFMT_A16B16G16R16F:
|
||||
case D3DFMT_A32B32G32R32F:
|
||||
break;
|
||||
|
||||
default:
|
||||
return egl::Error(EGL_BAD_PARAMETER, "Unknown client buffer texture format: %u.",
|
||||
desc.Format);
|
||||
}
|
||||
|
||||
if (fboFormat)
|
||||
{
|
||||
const auto &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format);
|
||||
ASSERT(d3dFormatInfo.info != nullptr);
|
||||
*fboFormat = d3dFormatInfo.info->fboImplementationInternalFormat;
|
||||
}
|
||||
|
||||
return egl::Error(EGL_SUCCESS);
|
||||
}
|
||||
|
||||
egl::Error Renderer9::validateShareHandle(const egl::Config *config,
|
||||
HANDLE shareHandle,
|
||||
const egl::AttributeMap &attribs) const
|
||||
{
|
||||
if (shareHandle == nullptr)
|
||||
{
|
||||
return egl::Error(EGL_BAD_PARAMETER, "NULL share handle.");
|
||||
}
|
||||
|
||||
EGLint width = attribs.getAsInt(EGL_WIDTH, 0);
|
||||
EGLint height = attribs.getAsInt(EGL_HEIGHT, 0);
|
||||
ASSERT(width != 0 && height != 0);
|
||||
|
||||
const d3d9::TextureFormat &backBufferd3dFormatInfo =
|
||||
d3d9::GetTextureFormatInfo(config->renderTargetFormat);
|
||||
|
||||
IDirect3DTexture9 *texture = nullptr;
|
||||
HRESULT result = mDevice->CreateTexture(width, height, 1, D3DUSAGE_RENDERTARGET,
|
||||
backBufferd3dFormatInfo.texFormat, D3DPOOL_DEFAULT,
|
||||
&texture, &shareHandle);
|
||||
if (FAILED(result))
|
||||
{
|
||||
return egl::Error(EGL_BAD_PARAMETER, "Failed to open share handle, result: 0x%X.", result);
|
||||
}
|
||||
|
||||
DWORD levelCount = texture->GetLevelCount();
|
||||
|
||||
D3DSURFACE_DESC desc;
|
||||
texture->GetLevelDesc(0, &desc);
|
||||
SafeRelease(texture);
|
||||
|
||||
if (levelCount != 1 || desc.Width != static_cast<UINT>(width) ||
|
||||
desc.Height != static_cast<UINT>(height) ||
|
||||
desc.Format != backBufferd3dFormatInfo.texFormat)
|
||||
{
|
||||
return egl::Error(EGL_BAD_PARAMETER, "Invalid texture parameters in share handle texture.");
|
||||
}
|
||||
|
||||
return egl::Error(EGL_SUCCESS);
|
||||
}
|
||||
|
||||
ContextImpl *Renderer9::createContext(const gl::ContextState &state)
|
||||
|
|
|
@ -88,9 +88,17 @@ class Renderer9 : public RendererD3D
|
|||
|
||||
SwapChainD3D *createSwapChain(NativeWindowD3D *nativeWindow,
|
||||
HANDLE shareHandle,
|
||||
IUnknown *d3dTexture,
|
||||
GLenum backBufferFormat,
|
||||
GLenum depthBufferFormat,
|
||||
EGLint orientation) override;
|
||||
egl::Error getD3DTextureInfo(IUnknown *d3dTexture,
|
||||
EGLint *width,
|
||||
EGLint *height,
|
||||
GLenum *fboFormat) const override;
|
||||
egl::Error validateShareHandle(const egl::Config *config,
|
||||
HANDLE shareHandle,
|
||||
const egl::AttributeMap &attribs) const override;
|
||||
|
||||
ContextImpl *createContext(const gl::ContextState &state) override;
|
||||
|
||||
|
|
|
@ -19,10 +19,11 @@ namespace rx
|
|||
SwapChain9::SwapChain9(Renderer9 *renderer,
|
||||
NativeWindow9 *nativeWindow,
|
||||
HANDLE shareHandle,
|
||||
IUnknown *d3dTexture,
|
||||
GLenum backBufferFormat,
|
||||
GLenum depthBufferFormat,
|
||||
EGLint orientation)
|
||||
: SwapChainD3D(shareHandle, backBufferFormat, depthBufferFormat),
|
||||
: SwapChainD3D(shareHandle, d3dTexture, backBufferFormat, depthBufferFormat),
|
||||
mRenderer(renderer),
|
||||
mWidth(-1),
|
||||
mHeight(-1),
|
||||
|
@ -105,28 +106,37 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI
|
|||
SafeRelease(mOffscreenTexture);
|
||||
SafeRelease(mDepthStencil);
|
||||
|
||||
HANDLE *pShareHandle = NULL;
|
||||
if (!mNativeWindow->getNativeWindow() && mRenderer->getShareHandleSupport())
|
||||
const d3d9::TextureFormat &backBufferd3dFormatInfo =
|
||||
d3d9::GetTextureFormatInfo(mOffscreenRenderTargetFormat);
|
||||
if (mD3DTexture != nullptr)
|
||||
{
|
||||
pShareHandle = &mShareHandle;
|
||||
result = mD3DTexture->QueryInterface(&mOffscreenTexture);
|
||||
ASSERT(SUCCEEDED(result));
|
||||
}
|
||||
|
||||
const d3d9::TextureFormat &backBufferd3dFormatInfo = d3d9::GetTextureFormatInfo(mOffscreenRenderTargetFormat);
|
||||
result = device->CreateTexture(backbufferWidth, backbufferHeight, 1, D3DUSAGE_RENDERTARGET,
|
||||
backBufferd3dFormatInfo.texFormat, D3DPOOL_DEFAULT, &mOffscreenTexture,
|
||||
pShareHandle);
|
||||
if (FAILED(result))
|
||||
else
|
||||
{
|
||||
ERR("Could not create offscreen texture: %08lX", result);
|
||||
release();
|
||||
|
||||
if (d3d9::isDeviceLostError(result))
|
||||
HANDLE *pShareHandle = NULL;
|
||||
if (!mNativeWindow->getNativeWindow() && mRenderer->getShareHandleSupport())
|
||||
{
|
||||
return EGL_CONTEXT_LOST;
|
||||
pShareHandle = &mShareHandle;
|
||||
}
|
||||
else
|
||||
|
||||
result = device->CreateTexture(backbufferWidth, backbufferHeight, 1, D3DUSAGE_RENDERTARGET,
|
||||
backBufferd3dFormatInfo.texFormat, D3DPOOL_DEFAULT,
|
||||
&mOffscreenTexture, pShareHandle);
|
||||
if (FAILED(result))
|
||||
{
|
||||
return EGL_BAD_ALLOC;
|
||||
ERR("Could not create offscreen texture: %08lX", result);
|
||||
release();
|
||||
|
||||
if (d3d9::isDeviceLostError(result))
|
||||
{
|
||||
return EGL_CONTEXT_LOST;
|
||||
}
|
||||
else
|
||||
{
|
||||
return EGL_BAD_ALLOC;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ class SwapChain9 : public SwapChainD3D
|
|||
SwapChain9(Renderer9 *renderer,
|
||||
NativeWindow9 *nativeWindow,
|
||||
HANDLE shareHandle,
|
||||
IUnknown *d3dTexture,
|
||||
GLenum backBufferFormat,
|
||||
GLenum depthBufferFormat,
|
||||
EGLint orientation);
|
||||
|
|
|
@ -22,8 +22,7 @@
|
|||
namespace rx
|
||||
{
|
||||
|
||||
DisplayGL::DisplayGL()
|
||||
: mRenderer(nullptr)
|
||||
DisplayGL::DisplayGL() : mRenderer(nullptr), mCurrentDrawSurface(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -73,6 +72,13 @@ StreamProducerImpl *DisplayGL::createStreamProducerD3DTextureNV12(
|
|||
|
||||
egl::Error DisplayGL::makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context)
|
||||
{
|
||||
// Notify the previous surface (if it still exists) that it is no longer current
|
||||
if (mCurrentDrawSurface && mSurfaceSet.find(mCurrentDrawSurface) != mSurfaceSet.end())
|
||||
{
|
||||
ANGLE_TRY(GetImplAs<SurfaceGL>(mCurrentDrawSurface)->unMakeCurrent());
|
||||
}
|
||||
mCurrentDrawSurface = nullptr;
|
||||
|
||||
if (!drawSurface)
|
||||
{
|
||||
return egl::Error(EGL_SUCCESS);
|
||||
|
@ -83,7 +89,10 @@ egl::Error DisplayGL::makeCurrent(egl::Surface *drawSurface, egl::Surface *readS
|
|||
glContext->getStateManager()->pauseTransformFeedback(context->getContextState());
|
||||
|
||||
SurfaceGL *glDrawSurface = GetImplAs<SurfaceGL>(drawSurface);
|
||||
return glDrawSurface->makeCurrent();
|
||||
ANGLE_TRY(glDrawSurface->makeCurrent());
|
||||
mCurrentDrawSurface = drawSurface;
|
||||
|
||||
return egl::Error(EGL_SUCCESS);
|
||||
}
|
||||
|
||||
gl::Version DisplayGL::getMaxSupportedESVersion() const
|
||||
|
|
|
@ -12,6 +12,11 @@
|
|||
#include "libANGLE/renderer/DisplayImpl.h"
|
||||
#include "libANGLE/renderer/gl/FunctionsGL.h"
|
||||
|
||||
namespace egl
|
||||
{
|
||||
class Surface;
|
||||
}
|
||||
|
||||
namespace rx
|
||||
{
|
||||
|
||||
|
@ -48,6 +53,8 @@ class DisplayGL : public DisplayImpl
|
|||
virtual const FunctionsGL *getFunctionsGL() const = 0;
|
||||
|
||||
RendererGL *mRenderer;
|
||||
|
||||
egl::Surface *mCurrentDrawSurface;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -34,4 +34,9 @@ egl::Error SurfaceGL::getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuin
|
|||
UNREACHABLE();
|
||||
return egl::Error(EGL_BAD_SURFACE);
|
||||
}
|
||||
|
||||
egl::Error SurfaceGL::unMakeCurrent()
|
||||
{
|
||||
return egl::Error(EGL_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ class SurfaceGL : public SurfaceImpl
|
|||
egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) override;
|
||||
|
||||
virtual egl::Error makeCurrent() = 0;
|
||||
virtual egl::Error unMakeCurrent();
|
||||
|
||||
private:
|
||||
RendererGL *mRenderer;
|
||||
|
|
|
@ -35,7 +35,8 @@ class DisplayCGL : public DisplayGL
|
|||
const egl::AttributeMap &attribs) override;
|
||||
SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
|
||||
const egl::Config *configuration,
|
||||
EGLClientBuffer shareHandle,
|
||||
EGLenum buftype,
|
||||
EGLClientBuffer clientBuffer,
|
||||
const egl::AttributeMap &attribs) override;
|
||||
SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
|
||||
const egl::Config *configuration,
|
||||
|
|
|
@ -128,7 +128,8 @@ SurfaceImpl *DisplayCGL::createPbufferSurface(const egl::SurfaceState &state,
|
|||
|
||||
SurfaceImpl *DisplayCGL::createPbufferFromClientBuffer(const egl::SurfaceState &state,
|
||||
const egl::Config *configuration,
|
||||
EGLClientBuffer shareHandle,
|
||||
EGLenum buftype,
|
||||
EGLClientBuffer clientBuffer,
|
||||
const egl::AttributeMap &attribs)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
|
|
|
@ -185,7 +185,8 @@ SurfaceImpl *DisplayAndroid::createPbufferSurface(const egl::SurfaceState &state
|
|||
|
||||
SurfaceImpl *DisplayAndroid::createPbufferFromClientBuffer(const egl::SurfaceState &state,
|
||||
const egl::Config *configuration,
|
||||
EGLClientBuffer shareHandle,
|
||||
EGLenum buftype,
|
||||
EGLClientBuffer clientBuffer,
|
||||
const egl::AttributeMap &attribs)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
|
|
|
@ -36,7 +36,8 @@ class DisplayAndroid : public DisplayEGL
|
|||
const egl::AttributeMap &attribs) override;
|
||||
SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
|
||||
const egl::Config *configuration,
|
||||
EGLClientBuffer shareHandle,
|
||||
EGLenum buftype,
|
||||
EGLClientBuffer clientBuffer,
|
||||
const egl::AttributeMap &attribs) override;
|
||||
SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
|
||||
const egl::Config *configuration,
|
||||
|
|
|
@ -859,7 +859,8 @@ SurfaceImpl *DisplayOzone::createPbufferSurface(const egl::SurfaceState &state,
|
|||
|
||||
SurfaceImpl *DisplayOzone::createPbufferFromClientBuffer(const egl::SurfaceState &state,
|
||||
const egl::Config *configuration,
|
||||
EGLClientBuffer shareHandle,
|
||||
EGLenum buftype,
|
||||
EGLClientBuffer clientBuffer,
|
||||
const egl::AttributeMap &attribs)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
|
|
|
@ -122,7 +122,8 @@ class DisplayOzone final : public DisplayEGL
|
|||
const egl::AttributeMap &attribs) override;
|
||||
SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
|
||||
const egl::Config *configuration,
|
||||
EGLClientBuffer shareHandle,
|
||||
EGLenum buftype,
|
||||
EGLClientBuffer clientBuffer,
|
||||
const egl::AttributeMap &attribs) override;
|
||||
SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
|
||||
const egl::Config *configuration,
|
||||
|
|
|
@ -410,7 +410,8 @@ SurfaceImpl *DisplayGLX::createPbufferSurface(const egl::SurfaceState &state,
|
|||
|
||||
SurfaceImpl *DisplayGLX::createPbufferFromClientBuffer(const egl::SurfaceState &state,
|
||||
const egl::Config *configuration,
|
||||
EGLClientBuffer shareHandle,
|
||||
EGLenum buftype,
|
||||
EGLClientBuffer clientBuffer,
|
||||
const egl::AttributeMap &attribs)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
|
|
|
@ -53,7 +53,8 @@ class DisplayGLX : public DisplayGL
|
|||
const egl::AttributeMap &attribs) override;
|
||||
SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
|
||||
const egl::Config *configuration,
|
||||
EGLClientBuffer shareHandle,
|
||||
EGLenum buftype,
|
||||
EGLClientBuffer clientBuffer,
|
||||
const egl::AttributeMap &attribs) override;
|
||||
SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
|
||||
const egl::Config *configuration,
|
||||
|
|
|
@ -0,0 +1,384 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
|
||||
// D3DTextureSurfaceWGL.cpp: WGL implementation of egl::Surface for D3D texture interop.
|
||||
|
||||
#include "libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.h"
|
||||
|
||||
#include "libANGLE/renderer/gl/FramebufferGL.h"
|
||||
#include "libANGLE/renderer/gl/TextureGL.h"
|
||||
#include "libANGLE/renderer/gl/RendererGL.h"
|
||||
#include "libANGLE/renderer/gl/StateManagerGL.h"
|
||||
#include "libANGLE/renderer/gl/wgl/DisplayWGL.h"
|
||||
#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h"
|
||||
|
||||
namespace rx
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
egl::Error GetD3DTextureInfo(EGLClientBuffer clientBuffer,
|
||||
size_t *width,
|
||||
size_t *height,
|
||||
IUnknown **object,
|
||||
IUnknown **device)
|
||||
{
|
||||
IUnknown *buffer = static_cast<IUnknown *>(clientBuffer);
|
||||
|
||||
IDirect3DTexture9 *texture9 = nullptr;
|
||||
ID3D11Texture2D *texture11 = nullptr;
|
||||
if (SUCCEEDED(buffer->QueryInterface<ID3D11Texture2D>(&texture11)))
|
||||
{
|
||||
D3D11_TEXTURE2D_DESC textureDesc;
|
||||
texture11->GetDesc(&textureDesc);
|
||||
|
||||
// From table egl.restrictions in EGL_ANGLE_d3d_texture_client_buffer.
|
||||
switch (textureDesc.Format)
|
||||
{
|
||||
case DXGI_FORMAT_R8G8B8A8_UNORM:
|
||||
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
|
||||
case DXGI_FORMAT_B8G8R8A8_UNORM:
|
||||
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
|
||||
case DXGI_FORMAT_R16G16B16A16_FLOAT:
|
||||
case DXGI_FORMAT_R32G32B32A32_FLOAT:
|
||||
break;
|
||||
|
||||
default:
|
||||
SafeRelease(texture11);
|
||||
return egl::Error(EGL_BAD_PARAMETER, "Unknown client buffer texture format: %u.",
|
||||
textureDesc.Format);
|
||||
}
|
||||
|
||||
ID3D11Device *d3d11Device = nullptr;
|
||||
texture11->GetDevice(&d3d11Device);
|
||||
if (d3d11Device == nullptr)
|
||||
{
|
||||
SafeRelease(texture11);
|
||||
return egl::Error(EGL_BAD_PARAMETER,
|
||||
"Could not query the D3D11 device from the client buffer.");
|
||||
}
|
||||
|
||||
if (width)
|
||||
{
|
||||
*width = textureDesc.Width;
|
||||
}
|
||||
if (height)
|
||||
{
|
||||
*height = textureDesc.Height;
|
||||
}
|
||||
|
||||
if (device)
|
||||
{
|
||||
*device = d3d11Device;
|
||||
}
|
||||
else
|
||||
{
|
||||
SafeRelease(d3d11Device);
|
||||
}
|
||||
|
||||
if (object)
|
||||
{
|
||||
*object = texture11;
|
||||
}
|
||||
else
|
||||
{
|
||||
SafeRelease(texture11);
|
||||
}
|
||||
|
||||
return egl::Error(EGL_SUCCESS);
|
||||
}
|
||||
else if (SUCCEEDED(buffer->QueryInterface<IDirect3DTexture9>(&texture9)))
|
||||
{
|
||||
D3DSURFACE_DESC surfaceDesc;
|
||||
if (FAILED(texture9->GetLevelDesc(0, &surfaceDesc)))
|
||||
{
|
||||
SafeRelease(texture9);
|
||||
return egl::Error(EGL_BAD_PARAMETER,
|
||||
"Could not query description of the D3D9 surface.");
|
||||
}
|
||||
|
||||
// From table egl.restrictions in EGL_ANGLE_d3d_texture_client_buffer.
|
||||
switch (surfaceDesc.Format)
|
||||
{
|
||||
case D3DFMT_R8G8B8:
|
||||
case D3DFMT_A8R8G8B8:
|
||||
case D3DFMT_A16B16G16R16F:
|
||||
case D3DFMT_A32B32G32R32F:
|
||||
break;
|
||||
|
||||
default:
|
||||
SafeRelease(texture9);
|
||||
return egl::Error(EGL_BAD_PARAMETER, "Unknown client buffer texture format: %u.",
|
||||
surfaceDesc.Format);
|
||||
}
|
||||
|
||||
if (width)
|
||||
{
|
||||
*width = surfaceDesc.Width;
|
||||
}
|
||||
if (height)
|
||||
{
|
||||
*height = surfaceDesc.Height;
|
||||
}
|
||||
|
||||
IDirect3DDevice9 *d3d9Device = nullptr;
|
||||
HRESULT result = texture9->GetDevice(&d3d9Device);
|
||||
if (FAILED(result))
|
||||
{
|
||||
SafeRelease(texture9);
|
||||
return egl::Error(EGL_BAD_PARAMETER,
|
||||
"Could not query the D3D9 device from the client buffer.");
|
||||
}
|
||||
|
||||
if (device)
|
||||
{
|
||||
*device = d3d9Device;
|
||||
}
|
||||
else
|
||||
{
|
||||
SafeRelease(d3d9Device);
|
||||
}
|
||||
|
||||
if (object)
|
||||
{
|
||||
*object = texture9;
|
||||
}
|
||||
else
|
||||
{
|
||||
SafeRelease(texture9);
|
||||
}
|
||||
|
||||
return egl::Error(EGL_SUCCESS);
|
||||
}
|
||||
else
|
||||
{
|
||||
return egl::Error(EGL_BAD_PARAMETER,
|
||||
"Provided buffer is not a IDirect3DTexture9 or ID3D11Texture2D.");
|
||||
}
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
D3DTextureSurfaceWGL::D3DTextureSurfaceWGL(const egl::SurfaceState &state,
|
||||
RendererGL *renderer,
|
||||
EGLClientBuffer clientBuffer,
|
||||
DisplayWGL *display,
|
||||
HGLRC wglContext,
|
||||
HDC deviceContext,
|
||||
const FunctionsGL *functionsGL,
|
||||
const FunctionsWGL *functionsWGL)
|
||||
: SurfaceGL(state, renderer),
|
||||
mClientBuffer(clientBuffer),
|
||||
mRenderer(renderer),
|
||||
mDisplay(display),
|
||||
mStateManager(renderer->getStateManager()),
|
||||
mWorkarounds(renderer->getWorkarounds()),
|
||||
mFunctionsGL(functionsGL),
|
||||
mFunctionsWGL(functionsWGL),
|
||||
mWGLContext(wglContext),
|
||||
mDeviceContext(deviceContext),
|
||||
mWidth(0),
|
||||
mHeight(0),
|
||||
mDeviceHandle(nullptr),
|
||||
mObject(nullptr),
|
||||
mBoundObjectTextureHandle(nullptr),
|
||||
mBoundObjectRenderbufferHandle(nullptr),
|
||||
mRenderbufferID(0),
|
||||
mFramebufferID(0)
|
||||
{
|
||||
}
|
||||
|
||||
D3DTextureSurfaceWGL::~D3DTextureSurfaceWGL()
|
||||
{
|
||||
ASSERT(mBoundObjectTextureHandle == nullptr);
|
||||
|
||||
SafeRelease(mObject);
|
||||
|
||||
if (mDeviceHandle)
|
||||
{
|
||||
if (mBoundObjectRenderbufferHandle)
|
||||
{
|
||||
mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mBoundObjectRenderbufferHandle);
|
||||
mBoundObjectRenderbufferHandle = nullptr;
|
||||
}
|
||||
mStateManager->deleteRenderbuffer(mRenderbufferID);
|
||||
|
||||
if (mBoundObjectTextureHandle)
|
||||
{
|
||||
mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mBoundObjectTextureHandle);
|
||||
mBoundObjectTextureHandle = nullptr;
|
||||
}
|
||||
|
||||
// GL framebuffer is deleted by the default framebuffer object
|
||||
mFramebufferID = 0;
|
||||
|
||||
mDisplay->releaseD3DDevice(mDeviceHandle);
|
||||
mDeviceHandle = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
egl::Error D3DTextureSurfaceWGL::ValidateD3DTextureClientBuffer(EGLClientBuffer clientBuffer)
|
||||
{
|
||||
return GetD3DTextureInfo(clientBuffer, nullptr, nullptr, nullptr, nullptr);
|
||||
}
|
||||
|
||||
egl::Error D3DTextureSurfaceWGL::initialize()
|
||||
{
|
||||
IUnknown *device = nullptr;
|
||||
ANGLE_TRY(GetD3DTextureInfo(mClientBuffer, &mWidth, &mHeight, &mObject, &device));
|
||||
|
||||
ASSERT(device != nullptr);
|
||||
egl::Error error = mDisplay->registerD3DDevice(device, &mDeviceHandle);
|
||||
SafeRelease(device);
|
||||
if (error.isError())
|
||||
{
|
||||
return error;
|
||||
}
|
||||
|
||||
mFunctionsGL->genRenderbuffers(1, &mRenderbufferID);
|
||||
mStateManager->bindRenderbuffer(GL_RENDERBUFFER, mRenderbufferID);
|
||||
mBoundObjectRenderbufferHandle = mFunctionsWGL->dxRegisterObjectNV(
|
||||
mDeviceHandle, mObject, mRenderbufferID, GL_RENDERBUFFER, WGL_ACCESS_READ_WRITE_NV);
|
||||
if (mBoundObjectRenderbufferHandle == nullptr)
|
||||
{
|
||||
return egl::Error(EGL_BAD_ALLOC, "Failed to register D3D object, error: 0x%08x.",
|
||||
HRESULT_CODE(GetLastError()));
|
||||
}
|
||||
|
||||
mFunctionsGL->genFramebuffers(1, &mFramebufferID);
|
||||
mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
|
||||
mFunctionsGL->framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
|
||||
mRenderbufferID);
|
||||
|
||||
return egl::Error(EGL_SUCCESS);
|
||||
}
|
||||
|
||||
egl::Error D3DTextureSurfaceWGL::makeCurrent()
|
||||
{
|
||||
if (!mFunctionsWGL->makeCurrent(mDeviceContext, mWGLContext))
|
||||
{
|
||||
// TODO(geofflang): What error type here?
|
||||
return egl::Error(EGL_CONTEXT_LOST, "Failed to make the WGL context current.");
|
||||
}
|
||||
|
||||
if (!mFunctionsWGL->dxLockObjectsNV(mDeviceHandle, 1, &mBoundObjectRenderbufferHandle))
|
||||
{
|
||||
DWORD error = GetLastError();
|
||||
return egl::Error(EGL_BAD_ALLOC, "Failed to lock object, error: 0x%08x.",
|
||||
HRESULT_CODE(error));
|
||||
}
|
||||
|
||||
return egl::Error(EGL_SUCCESS);
|
||||
}
|
||||
|
||||
egl::Error D3DTextureSurfaceWGL::unMakeCurrent()
|
||||
{
|
||||
if (!mFunctionsWGL->dxUnlockObjectsNV(mDeviceHandle, 1, &mBoundObjectRenderbufferHandle))
|
||||
{
|
||||
DWORD error = GetLastError();
|
||||
return egl::Error(EGL_BAD_ALLOC, "Failed to unlock object, error: 0x%08x.",
|
||||
HRESULT_CODE(error));
|
||||
}
|
||||
|
||||
return egl::Error(EGL_SUCCESS);
|
||||
}
|
||||
|
||||
egl::Error D3DTextureSurfaceWGL::swap()
|
||||
{
|
||||
return egl::Error(EGL_SUCCESS);
|
||||
}
|
||||
|
||||
egl::Error D3DTextureSurfaceWGL::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
return egl::Error(EGL_SUCCESS);
|
||||
}
|
||||
|
||||
egl::Error D3DTextureSurfaceWGL::querySurfacePointerANGLE(EGLint attribute, void **value)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
return egl::Error(EGL_SUCCESS);
|
||||
}
|
||||
|
||||
egl::Error D3DTextureSurfaceWGL::bindTexImage(gl::Texture *texture, EGLint buffer)
|
||||
{
|
||||
ASSERT(mBoundObjectTextureHandle == nullptr);
|
||||
|
||||
const TextureGL *textureGL = GetImplAs<TextureGL>(texture);
|
||||
GLuint textureID = textureGL->getTextureID();
|
||||
|
||||
mBoundObjectTextureHandle = mFunctionsWGL->dxRegisterObjectNV(
|
||||
mDeviceHandle, mObject, textureID, GL_TEXTURE_2D, WGL_ACCESS_READ_WRITE_NV);
|
||||
if (mBoundObjectTextureHandle == nullptr)
|
||||
{
|
||||
DWORD error = GetLastError();
|
||||
return egl::Error(EGL_BAD_ALLOC, "Failed to register D3D object, error: 0x%08x.",
|
||||
HRESULT_CODE(error));
|
||||
}
|
||||
|
||||
if (!mFunctionsWGL->dxLockObjectsNV(mDeviceHandle, 1, &mBoundObjectTextureHandle))
|
||||
{
|
||||
DWORD error = GetLastError();
|
||||
return egl::Error(EGL_BAD_ALLOC, "Failed to lock object, error: 0x%08x.",
|
||||
HRESULT_CODE(error));
|
||||
}
|
||||
|
||||
return egl::Error(EGL_SUCCESS);
|
||||
}
|
||||
|
||||
egl::Error D3DTextureSurfaceWGL::releaseTexImage(EGLint buffer)
|
||||
{
|
||||
ASSERT(mBoundObjectTextureHandle != nullptr);
|
||||
if (!mFunctionsWGL->dxUnlockObjectsNV(mDeviceHandle, 1, &mBoundObjectTextureHandle))
|
||||
{
|
||||
DWORD error = GetLastError();
|
||||
return egl::Error(EGL_BAD_ALLOC, "Failed to unlock object, error: 0x%08x.",
|
||||
HRESULT_CODE(error));
|
||||
}
|
||||
|
||||
if (!mFunctionsWGL->dxUnregisterObjectNV(mDeviceHandle, mBoundObjectTextureHandle))
|
||||
{
|
||||
DWORD error = GetLastError();
|
||||
return egl::Error(EGL_BAD_ALLOC, "Failed to unregister D3D object, error: 0x%08x.",
|
||||
HRESULT_CODE(error));
|
||||
}
|
||||
mBoundObjectTextureHandle = nullptr;
|
||||
|
||||
return egl::Error(EGL_SUCCESS);
|
||||
}
|
||||
|
||||
void D3DTextureSurfaceWGL::setSwapInterval(EGLint interval)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
EGLint D3DTextureSurfaceWGL::getWidth() const
|
||||
{
|
||||
return static_cast<EGLint>(mWidth);
|
||||
}
|
||||
|
||||
EGLint D3DTextureSurfaceWGL::getHeight() const
|
||||
{
|
||||
return static_cast<EGLint>(mHeight);
|
||||
}
|
||||
|
||||
EGLint D3DTextureSurfaceWGL::isPostSubBufferSupported() const
|
||||
{
|
||||
return EGL_FALSE;
|
||||
}
|
||||
|
||||
EGLint D3DTextureSurfaceWGL::getSwapBehavior() const
|
||||
{
|
||||
return EGL_BUFFER_PRESERVED;
|
||||
}
|
||||
|
||||
FramebufferImpl *D3DTextureSurfaceWGL::createDefaultFramebuffer(const gl::FramebufferState &data)
|
||||
{
|
||||
return new FramebufferGL(mFramebufferID, data, mFunctionsGL, mWorkarounds,
|
||||
mRenderer->getBlitter(), mStateManager);
|
||||
}
|
||||
} // namespace rx
|
|
@ -0,0 +1,86 @@
|
|||
|
||||
// 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.
|
||||
//
|
||||
|
||||
// D3DTextureSurfaceWGL.h: WGL implementation of egl::Surface for D3D texture interop.
|
||||
|
||||
#ifndef LIBANGLE_RENDERER_GL_WGL_D3DTEXTIRESURFACEWGL_H_
|
||||
#define LIBANGLE_RENDERER_GL_WGL_D3DTEXTIRESURFACEWGL_H_
|
||||
|
||||
#include "libANGLE/renderer/gl/SurfaceGL.h"
|
||||
|
||||
#include <GL/wglext.h>
|
||||
|
||||
namespace rx
|
||||
{
|
||||
|
||||
class FunctionsGL;
|
||||
class FunctionsWGL;
|
||||
class DisplayWGL;
|
||||
class StateManagerGL;
|
||||
struct WorkaroundsGL;
|
||||
|
||||
class D3DTextureSurfaceWGL : public SurfaceGL
|
||||
{
|
||||
public:
|
||||
D3DTextureSurfaceWGL(const egl::SurfaceState &state,
|
||||
RendererGL *renderer,
|
||||
EGLClientBuffer clientBuffer,
|
||||
DisplayWGL *display,
|
||||
HGLRC wglContext,
|
||||
HDC deviceContext,
|
||||
const FunctionsGL *functionsGL,
|
||||
const FunctionsWGL *functionsWGL);
|
||||
~D3DTextureSurfaceWGL() override;
|
||||
|
||||
static egl::Error ValidateD3DTextureClientBuffer(EGLClientBuffer clientBuffer);
|
||||
|
||||
egl::Error initialize() override;
|
||||
egl::Error makeCurrent() override;
|
||||
egl::Error unMakeCurrent() override;
|
||||
|
||||
egl::Error swap() override;
|
||||
egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
|
||||
egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
|
||||
egl::Error bindTexImage(gl::Texture *texture, EGLint buffer) override;
|
||||
egl::Error releaseTexImage(EGLint buffer) override;
|
||||
void setSwapInterval(EGLint interval) override;
|
||||
|
||||
EGLint getWidth() const override;
|
||||
EGLint getHeight() const override;
|
||||
|
||||
EGLint isPostSubBufferSupported() const override;
|
||||
EGLint getSwapBehavior() const override;
|
||||
|
||||
FramebufferImpl *createDefaultFramebuffer(const gl::FramebufferState &data) override;
|
||||
|
||||
private:
|
||||
EGLClientBuffer mClientBuffer;
|
||||
|
||||
RendererGL *mRenderer;
|
||||
|
||||
DisplayWGL *mDisplay;
|
||||
StateManagerGL *mStateManager;
|
||||
const WorkaroundsGL &mWorkarounds;
|
||||
const FunctionsGL *mFunctionsGL;
|
||||
const FunctionsWGL *mFunctionsWGL;
|
||||
|
||||
HGLRC mWGLContext;
|
||||
HDC mDeviceContext;
|
||||
|
||||
size_t mWidth;
|
||||
size_t mHeight;
|
||||
|
||||
HANDLE mDeviceHandle;
|
||||
IUnknown *mObject;
|
||||
HANDLE mBoundObjectTextureHandle;
|
||||
HANDLE mBoundObjectRenderbufferHandle;
|
||||
|
||||
GLuint mRenderbufferID;
|
||||
GLuint mFramebufferID;
|
||||
};
|
||||
} // namespace rx
|
||||
|
||||
#endif // LIBANGLE_RENDERER_GL_WGL_D3DTEXTIRESURFACEWGL_H_
|
|
@ -14,6 +14,7 @@
|
|||
#include "libANGLE/Surface.h"
|
||||
#include "libANGLE/renderer/gl/RendererGL.h"
|
||||
#include "libANGLE/renderer/gl/renderergl_utils.h"
|
||||
#include "libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.h"
|
||||
#include "libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.h"
|
||||
#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h"
|
||||
#include "libANGLE/renderer/gl/wgl/PbufferSurfaceWGL.h"
|
||||
|
@ -464,11 +465,13 @@ SurfaceImpl *DisplayWGL::createPbufferSurface(const egl::SurfaceState &state,
|
|||
|
||||
SurfaceImpl *DisplayWGL::createPbufferFromClientBuffer(const egl::SurfaceState &state,
|
||||
const egl::Config *configuration,
|
||||
EGLClientBuffer shareHandle,
|
||||
EGLenum buftype,
|
||||
EGLClientBuffer clientBuffer,
|
||||
const egl::AttributeMap &attribs)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
return nullptr;
|
||||
ASSERT(buftype == EGL_D3D_TEXTURE_ANGLE);
|
||||
return new D3DTextureSurfaceWGL(state, getRenderer(), clientBuffer, this, mWGLContext,
|
||||
mDeviceContext, mFunctionsGL, mFunctionsWGL);
|
||||
}
|
||||
|
||||
SurfaceImpl *DisplayWGL::createPixmapSurface(const egl::SurfaceState &state,
|
||||
|
@ -581,6 +584,21 @@ bool DisplayWGL::isValidNativeWindow(EGLNativeWindowType window) const
|
|||
return (IsWindow(window) == TRUE);
|
||||
}
|
||||
|
||||
egl::Error DisplayWGL::validateClientBuffer(const egl::Config *configuration,
|
||||
EGLenum buftype,
|
||||
EGLClientBuffer clientBuffer,
|
||||
const egl::AttributeMap &attribs) const
|
||||
{
|
||||
switch (buftype)
|
||||
{
|
||||
case EGL_D3D_TEXTURE_ANGLE:
|
||||
return D3DTextureSurfaceWGL::ValidateD3DTextureClientBuffer(clientBuffer);
|
||||
|
||||
default:
|
||||
return DisplayGL::validateClientBuffer(configuration, buftype, clientBuffer, attribs);
|
||||
}
|
||||
}
|
||||
|
||||
std::string DisplayWGL::getVendorString() const
|
||||
{
|
||||
//UNIMPLEMENTED();
|
||||
|
@ -644,6 +662,8 @@ void DisplayWGL::generateExtensions(egl::DisplayExtensions *outExtensions) const
|
|||
outExtensions->surfaceOrientation = mUseDXGISwapChains;
|
||||
|
||||
outExtensions->createContextRobustness = mHasRobustness;
|
||||
|
||||
outExtensions->d3dTextureClientBuffer = mFunctionsWGL->hasExtension("WGL_NV_DX_interop2");
|
||||
}
|
||||
|
||||
void DisplayWGL::generateCaps(egl::Caps *outCaps) const
|
||||
|
|
|
@ -37,7 +37,8 @@ class DisplayWGL : public DisplayGL
|
|||
const egl::AttributeMap &attribs) override;
|
||||
SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
|
||||
const egl::Config *configuration,
|
||||
EGLClientBuffer shareHandle,
|
||||
EGLenum buftype,
|
||||
EGLClientBuffer clientBuffer,
|
||||
const egl::AttributeMap &attribs) override;
|
||||
SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
|
||||
const egl::Config *configuration,
|
||||
|
@ -50,6 +51,10 @@ class DisplayWGL : public DisplayGL
|
|||
egl::Error restoreLostDevice() override;
|
||||
|
||||
bool isValidNativeWindow(EGLNativeWindowType window) const override;
|
||||
egl::Error validateClientBuffer(const egl::Config *configuration,
|
||||
EGLenum buftype,
|
||||
EGLClientBuffer clientBuffer,
|
||||
const egl::AttributeMap &attribs) const override;
|
||||
|
||||
egl::Error getDevice(DeviceImpl **device) override;
|
||||
|
||||
|
|
|
@ -116,7 +116,8 @@ SurfaceImpl *DisplayNULL::createPbufferSurface(const egl::SurfaceState &state,
|
|||
|
||||
SurfaceImpl *DisplayNULL::createPbufferFromClientBuffer(const egl::SurfaceState &state,
|
||||
const egl::Config *configuration,
|
||||
EGLClientBuffer shareHandle,
|
||||
EGLenum buftype,
|
||||
EGLClientBuffer buffer,
|
||||
const egl::AttributeMap &attribs)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
|
|
|
@ -54,7 +54,8 @@ class DisplayNULL : public DisplayImpl
|
|||
const egl::AttributeMap &attribs) override;
|
||||
SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
|
||||
const egl::Config *configuration,
|
||||
EGLClientBuffer shareHandle,
|
||||
EGLenum buftype,
|
||||
EGLClientBuffer buffer,
|
||||
const egl::AttributeMap &attribs) override;
|
||||
SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
|
||||
const egl::Config *configuration,
|
||||
|
|
|
@ -111,7 +111,8 @@ SurfaceImpl *DisplayVk::createPbufferSurface(const egl::SurfaceState &state,
|
|||
|
||||
SurfaceImpl *DisplayVk::createPbufferFromClientBuffer(const egl::SurfaceState &state,
|
||||
const egl::Config *configuration,
|
||||
EGLClientBuffer shareHandle,
|
||||
EGLenum buftype,
|
||||
EGLClientBuffer clientBuffer,
|
||||
const egl::AttributeMap &attribs)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
|
|
|
@ -54,7 +54,8 @@ class DisplayVk : public DisplayImpl
|
|||
const egl::AttributeMap &attribs) override;
|
||||
SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
|
||||
const egl::Config *configuration,
|
||||
EGLClientBuffer shareHandle,
|
||||
EGLenum buftype,
|
||||
EGLClientBuffer clientBuffer,
|
||||
const egl::AttributeMap &attribs) override;
|
||||
SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
|
||||
const egl::Config *configuration,
|
||||
|
|
|
@ -653,6 +653,17 @@ Error ValidateCreatePbufferFromClientBuffer(Display *display, EGLenum buftype, E
|
|||
}
|
||||
break;
|
||||
|
||||
case EGL_D3D_TEXTURE_ANGLE:
|
||||
if (!displayExtensions.d3dTextureClientBuffer)
|
||||
{
|
||||
return Error(EGL_BAD_PARAMETER);
|
||||
}
|
||||
if (buffer == nullptr)
|
||||
{
|
||||
return Error(EGL_BAD_PARAMETER);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return Error(EGL_BAD_PARAMETER);
|
||||
}
|
||||
|
@ -753,6 +764,8 @@ Error ValidateCreatePbufferFromClientBuffer(Display *display, EGLenum buftype, E
|
|||
}
|
||||
}
|
||||
|
||||
ANGLE_TRY(display->validateClientBuffer(config, buftype, buffer, attributes));
|
||||
|
||||
return Error(EGL_SUCCESS);
|
||||
}
|
||||
|
||||
|
|
|
@ -255,6 +255,7 @@
|
|||
'libANGLE/renderer/d3d/ShaderExecutableD3D.h',
|
||||
'libANGLE/renderer/d3d/SurfaceD3D.cpp',
|
||||
'libANGLE/renderer/d3d/SurfaceD3D.h',
|
||||
'libANGLE/renderer/d3d/SwapChainD3D.cpp',
|
||||
'libANGLE/renderer/d3d/SwapChainD3D.h',
|
||||
'libANGLE/renderer/d3d/TextureD3D.cpp',
|
||||
'libANGLE/renderer/d3d/TextureD3D.h',
|
||||
|
@ -511,6 +512,8 @@
|
|||
],
|
||||
'libangle_gl_wgl_sources':
|
||||
[
|
||||
'libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.cpp',
|
||||
'libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.h',
|
||||
'libANGLE/renderer/gl/wgl/DisplayWGL.cpp',
|
||||
'libANGLE/renderer/gl/wgl/DisplayWGL.h',
|
||||
'libANGLE/renderer/gl/wgl/DXGISwapChainWindowSurfaceWGL.cpp',
|
||||
|
|
|
@ -1068,7 +1068,8 @@ EGLSurface EGLAPIENTRY CreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buf
|
|||
}
|
||||
|
||||
egl::Surface *surface = nullptr;
|
||||
error = display->createPbufferFromClientBuffer(configuration, buffer, attributes, &surface);
|
||||
error = display->createPbufferFromClientBuffer(configuration, buftype, buffer, attributes,
|
||||
&surface);
|
||||
if (error.isError())
|
||||
{
|
||||
SetGlobalError(error);
|
||||
|
|
|
@ -96,6 +96,7 @@
|
|||
'angle_end2end_tests_win_sources':
|
||||
[
|
||||
'<(angle_path)/src/tests/gl_tests/D3DImageFormatConversionTest.cpp',
|
||||
'<(angle_path)/src/tests/gl_tests/D3DTextureTest.cpp',
|
||||
'<(angle_path)/src/tests/gl_tests/D3D11EmulatedIndexedBufferTest.cpp',
|
||||
'<(angle_path)/src/tests/gl_tests/D3D11FormatTablesTest.cpp',
|
||||
'<(angle_path)/src/tests/gl_tests/D3D11InputLayoutCacheTest.cpp',
|
||||
|
|
|
@ -103,9 +103,10 @@ class MockEGLFactory : public EGLImplFactory
|
|||
SurfaceImpl *(const egl::SurfaceState &,
|
||||
const egl::Config *,
|
||||
const egl::AttributeMap &));
|
||||
MOCK_METHOD4(createPbufferFromClientBuffer,
|
||||
MOCK_METHOD5(createPbufferFromClientBuffer,
|
||||
SurfaceImpl *(const egl::SurfaceState &,
|
||||
const egl::Config *,
|
||||
EGLenum,
|
||||
EGLClientBuffer,
|
||||
const egl::AttributeMap &));
|
||||
MOCK_METHOD4(createPixmapSurface,
|
||||
|
|
|
@ -0,0 +1,321 @@
|
|||
//
|
||||
// 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.
|
||||
//
|
||||
// D3DTextureTest:
|
||||
// Tests of the EGL_ANGLE_d3d_texture_client_buffer extension
|
||||
|
||||
#include "test_utils/ANGLETest.h"
|
||||
|
||||
#include <d3d11.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "com_utils.h"
|
||||
|
||||
namespace angle
|
||||
{
|
||||
|
||||
class D3DTextureTest : public ANGLETest
|
||||
{
|
||||
protected:
|
||||
D3DTextureTest()
|
||||
{
|
||||
setWindowWidth(128);
|
||||
setWindowHeight(128);
|
||||
setConfigRedBits(8);
|
||||
setConfigGreenBits(8);
|
||||
setConfigBlueBits(8);
|
||||
setConfigAlphaBits(8);
|
||||
}
|
||||
|
||||
void SetUp() override
|
||||
{
|
||||
ANGLETest::SetUp();
|
||||
|
||||
// clang-format off
|
||||
const std::string vsSource = SHADER_SOURCE
|
||||
(
|
||||
precision highp float;
|
||||
attribute vec4 position;
|
||||
varying vec2 texcoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = position;
|
||||
texcoord = (position.xy * 0.5) + 0.5;
|
||||
texcoord.y = 1.0 - texcoord.y;
|
||||
}
|
||||
);
|
||||
|
||||
const std::string textureFSSource = SHADER_SOURCE
|
||||
(
|
||||
precision highp float;
|
||||
uniform sampler2D tex;
|
||||
varying vec2 texcoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = texture2D(tex, texcoord);
|
||||
}
|
||||
);
|
||||
// clang-format on
|
||||
|
||||
mTextureProgram = CompileProgram(vsSource, textureFSSource);
|
||||
ASSERT_NE(0u, mTextureProgram) << "shader compilation failed.";
|
||||
|
||||
mTextureUniformLocation = glGetUniformLocation(mTextureProgram, "tex");
|
||||
ASSERT_NE(-1, mTextureUniformLocation);
|
||||
|
||||
mD3D11Module = LoadLibrary(TEXT("d3d11.dll"));
|
||||
ASSERT_NE(nullptr, mD3D11Module);
|
||||
|
||||
PFN_D3D11_CREATE_DEVICE createDeviceFunc = reinterpret_cast<PFN_D3D11_CREATE_DEVICE>(
|
||||
GetProcAddress(mD3D11Module, "D3D11CreateDevice"));
|
||||
|
||||
EGLWindow *window = getEGLWindow();
|
||||
EGLDisplay display = window->getDisplay();
|
||||
if (eglDisplayExtensionEnabled(display, "EGL_EXT_device_query"))
|
||||
{
|
||||
PFNEGLQUERYDISPLAYATTRIBEXTPROC eglQueryDisplayAttribEXT =
|
||||
reinterpret_cast<PFNEGLQUERYDISPLAYATTRIBEXTPROC>(
|
||||
eglGetProcAddress("eglQueryDisplayAttribEXT"));
|
||||
PFNEGLQUERYDEVICEATTRIBEXTPROC eglQueryDeviceAttribEXT =
|
||||
reinterpret_cast<PFNEGLQUERYDEVICEATTRIBEXTPROC>(
|
||||
eglGetProcAddress("eglQueryDeviceAttribEXT"));
|
||||
|
||||
EGLDeviceEXT device = 0;
|
||||
{
|
||||
EGLAttrib result = 0;
|
||||
EXPECT_EGL_TRUE(eglQueryDisplayAttribEXT(display, EGL_DEVICE_EXT, &result));
|
||||
device = reinterpret_cast<EGLDeviceEXT>(result);
|
||||
}
|
||||
|
||||
if (eglDeviceExtensionEnabled(device, "EGL_ANGLE_device_d3d"))
|
||||
{
|
||||
EGLAttrib result = 0;
|
||||
if (eglQueryDeviceAttribEXT(device, EGL_D3D11_DEVICE_ANGLE, &result))
|
||||
{
|
||||
mD3D11Device = reinterpret_cast<ID3D11Device *>(result);
|
||||
mD3D11Device->AddRef();
|
||||
}
|
||||
else if (eglQueryDeviceAttribEXT(device, EGL_D3D9_DEVICE_ANGLE, &result))
|
||||
{
|
||||
mD3D9Device = reinterpret_cast<IDirect3DDevice9 *>(result);
|
||||
mD3D9Device->AddRef();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT_TRUE(
|
||||
SUCCEEDED(createDeviceFunc(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, 0, nullptr,
|
||||
0, D3D11_SDK_VERSION, &mD3D11Device, nullptr, nullptr)));
|
||||
}
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
glDeleteProgram(mTextureProgram);
|
||||
|
||||
if (mD3D11Device)
|
||||
{
|
||||
mD3D11Device->Release();
|
||||
mD3D11Device = nullptr;
|
||||
}
|
||||
|
||||
FreeLibrary(mD3D11Module);
|
||||
mD3D11Module = nullptr;
|
||||
|
||||
if (mD3D9Device)
|
||||
{
|
||||
mD3D9Device->Release();
|
||||
mD3D9Device = nullptr;
|
||||
}
|
||||
|
||||
ANGLETest::TearDown();
|
||||
}
|
||||
|
||||
EGLSurface createPBuffer(size_t width,
|
||||
size_t height,
|
||||
EGLint eglTextureFormat,
|
||||
EGLint eglTextureTarget)
|
||||
{
|
||||
EGLWindow *window = getEGLWindow();
|
||||
EGLDisplay display = window->getDisplay();
|
||||
EGLConfig config = window->getConfig();
|
||||
|
||||
EGLint attribs[] = {
|
||||
EGL_TEXTURE_FORMAT, eglTextureFormat, EGL_TEXTURE_TARGET,
|
||||
eglTextureTarget, EGL_NONE, EGL_NONE,
|
||||
};
|
||||
|
||||
if (mD3D11Device)
|
||||
{
|
||||
ID3D11Texture2D *texture = nullptr;
|
||||
CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_R8G8B8A8_UNORM, static_cast<UINT>(width),
|
||||
static_cast<UINT>(height), 1, 1,
|
||||
D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET);
|
||||
EXPECT_TRUE(SUCCEEDED(mD3D11Device->CreateTexture2D(&desc, nullptr, &texture)));
|
||||
|
||||
EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(display, EGL_D3D_TEXTURE_ANGLE,
|
||||
texture, config, attribs);
|
||||
|
||||
texture->Release();
|
||||
|
||||
return pbuffer;
|
||||
}
|
||||
else if (mD3D9Device)
|
||||
{
|
||||
IDirect3DTexture9 *texture = nullptr;
|
||||
EXPECT_TRUE(SUCCEEDED(mD3D9Device->CreateTexture(
|
||||
static_cast<UINT>(width), static_cast<UINT>(height), 1, D3DUSAGE_RENDERTARGET,
|
||||
D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &texture, nullptr)));
|
||||
|
||||
EGLSurface pbuffer = eglCreatePbufferFromClientBuffer(display, EGL_D3D_TEXTURE_ANGLE,
|
||||
texture, config, attribs);
|
||||
|
||||
texture->Release();
|
||||
|
||||
return pbuffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
return EGL_NO_SURFACE;
|
||||
}
|
||||
}
|
||||
|
||||
bool valid() const
|
||||
{
|
||||
EGLWindow *window = getEGLWindow();
|
||||
EGLDisplay display = window->getDisplay();
|
||||
if (!eglDisplayExtensionEnabled(display, "EGL_ANGLE_d3d_texture_client_buffer"))
|
||||
{
|
||||
std::cout << "Test skipped due to missing EGL_ANGLE_d3d_texture_client_buffer"
|
||||
<< std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mD3D11Device && !mD3D9Device)
|
||||
{
|
||||
std::cout << "Test skipped due to no D3D devices being available." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsWindows() && IsAMD() && IsOpenGL())
|
||||
{
|
||||
std::cout << "Test skipped on Windows AMD OpenGL." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
GLuint mTextureProgram;
|
||||
GLint mTextureUniformLocation;
|
||||
|
||||
HMODULE mD3D11Module = nullptr;
|
||||
ID3D11Device *mD3D11Device = nullptr;
|
||||
|
||||
IDirect3DDevice9 *mD3D9Device = nullptr;
|
||||
};
|
||||
|
||||
// Test creating a pbuffer from a d3d surface and clearing it
|
||||
TEST_P(D3DTextureTest, Clear)
|
||||
{
|
||||
if (!valid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
EGLWindow *window = getEGLWindow();
|
||||
EGLDisplay display = window->getDisplay();
|
||||
|
||||
const size_t bufferSize = 32;
|
||||
|
||||
EGLSurface pbuffer = createPBuffer(bufferSize, bufferSize, EGL_NO_TEXTURE, EGL_NO_TEXTURE);
|
||||
ASSERT_EGL_SUCCESS();
|
||||
ASSERT_NE(pbuffer, EGL_NO_SURFACE);
|
||||
|
||||
// Apply the Pbuffer and clear it to purple and verify
|
||||
eglMakeCurrent(display, pbuffer, pbuffer, window->getContext());
|
||||
ASSERT_EGL_SUCCESS();
|
||||
|
||||
glViewport(0, 0, static_cast<GLsizei>(bufferSize), static_cast<GLsizei>(bufferSize));
|
||||
glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
EXPECT_PIXEL_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2, 255, 0,
|
||||
255, 255);
|
||||
|
||||
eglDestroySurface(display, pbuffer);
|
||||
}
|
||||
|
||||
// Test creating a pbuffer from a d3d surface and binding it to a texture
|
||||
TEST_P(D3DTextureTest, BindTexImage)
|
||||
{
|
||||
if (!valid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
EGLWindow *window = getEGLWindow();
|
||||
|
||||
const size_t bufferSize = 32;
|
||||
|
||||
EGLSurface pbuffer = createPBuffer(bufferSize, bufferSize, EGL_TEXTURE_RGBA, EGL_TEXTURE_2D);
|
||||
ASSERT_EGL_SUCCESS();
|
||||
ASSERT_NE(pbuffer, EGL_NO_SURFACE);
|
||||
|
||||
// Apply the Pbuffer and clear it to purple
|
||||
eglMakeCurrent(window->getDisplay(), pbuffer, pbuffer, window->getContext());
|
||||
ASSERT_EGL_SUCCESS();
|
||||
|
||||
glViewport(0, 0, static_cast<GLsizei>(bufferSize), static_cast<GLsizei>(bufferSize));
|
||||
glClearColor(1.0f, 0.0f, 1.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
|
||||
EXPECT_PIXEL_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2, 255, 0,
|
||||
255, 255);
|
||||
|
||||
// Apply the window surface
|
||||
eglMakeCurrent(window->getDisplay(), window->getSurface(), window->getSurface(),
|
||||
window->getContext());
|
||||
|
||||
// Create a texture and bind the Pbuffer to it
|
||||
GLuint texture = 0;
|
||||
glGenTextures(1, &texture);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
EXPECT_GL_NO_ERROR();
|
||||
|
||||
eglBindTexImage(window->getDisplay(), pbuffer, EGL_BACK_BUFFER);
|
||||
glViewport(0, 0, getWindowWidth(), getWindowHeight());
|
||||
ASSERT_EGL_SUCCESS();
|
||||
|
||||
// Draw a quad and verify that it is purple
|
||||
glUseProgram(mTextureProgram);
|
||||
glUniform1i(mTextureUniformLocation, 0);
|
||||
|
||||
drawQuad(mTextureProgram, "position", 0.5f);
|
||||
EXPECT_GL_NO_ERROR();
|
||||
|
||||
// Unbind the texture
|
||||
eglReleaseTexImage(window->getDisplay(), pbuffer, EGL_BACK_BUFFER);
|
||||
ASSERT_EGL_SUCCESS();
|
||||
|
||||
// Verify that purple was drawn
|
||||
EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, 255, 0, 255, 255);
|
||||
|
||||
glDeleteTextures(1, &texture);
|
||||
}
|
||||
|
||||
// Use this to select which configurations (e.g. which renderer, which GLES major version) these
|
||||
// tests should be run against.
|
||||
ANGLE_INSTANTIATE_TEST(D3DTextureTest, ES2_D3D9(), ES2_D3D11(), ES2_OPENGL());
|
||||
|
||||
} // namespace
|
|
@ -549,6 +549,14 @@ bool ANGLETest::eglClientExtensionEnabled(const std::string &extName)
|
|||
return checkExtensionExists(eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS), extName);
|
||||
}
|
||||
|
||||
bool ANGLETest::eglDeviceExtensionEnabled(EGLDeviceEXT device, const std::string &extName)
|
||||
{
|
||||
PFNEGLQUERYDEVICESTRINGEXTPROC eglQueryDeviceStringEXT =
|
||||
reinterpret_cast<PFNEGLQUERYDEVICESTRINGEXTPROC>(
|
||||
eglGetProcAddress("eglQueryDeviceStringEXT"));
|
||||
return checkExtensionExists(eglQueryDeviceStringEXT(device, EGL_EXTENSIONS), extName);
|
||||
}
|
||||
|
||||
void ANGLETest::setWindowWidth(int width)
|
||||
{
|
||||
mWidth = width;
|
||||
|
|
|
@ -172,6 +172,7 @@ class ANGLETest : public ::testing::TestWithParam<angle::PlatformParameters>
|
|||
static GLuint compileShader(GLenum type, const std::string &source);
|
||||
static bool extensionEnabled(const std::string &extName);
|
||||
static bool eglClientExtensionEnabled(const std::string &extName);
|
||||
static bool eglDeviceExtensionEnabled(EGLDeviceEXT device, const std::string &extName);
|
||||
|
||||
void setWindowWidth(int width);
|
||||
void setWindowHeight(int height);
|
||||
|
|
Загрузка…
Ссылка в новой задаче