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:
Geoff Lang 2015-12-08 11:48:51 -05:00 коммит произвёл Commit Bot
Родитель 9f4583dd8a
Коммит 2018c0bac4
55 изменённых файлов: 1466 добавлений и 106 удалений

Просмотреть файл

@ -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);