Commit c1af9abf by Sunny Sachanandani Committed by Commit Bot

Add support for overriding internal format for D3D11 texture EGLImages

Add an optional EGL_D3D11_TEXTURE_FORMAT_ANGLE attribute that is the GL internal format to use for EGLImage being created. This will be used for RGB emulation of swap chain texture backed WebGL contexts in Chrome when they have alpha:false set. Without RGB emulation it is possible to observe side-effects of the underlying swap chain being RGBA such as reading/writing the alpha channel, BlitFramebuffer working/not working when expected, etc. Also document creating EGLImages from D3D11 textures in the existing EGL_ANGLE_d3d_texture_client_buffer extension along with RGB emulation. Bug: chromium:699566, chromium:939657 Change-Id: I4931cb7bdc46e9bc6debd56b79ecc10ea27bd78b Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1777099Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Sunny Sachanandani <sunnyps@chromium.org>
parent 263e08b6
...@@ -22,7 +22,7 @@ Status ...@@ -22,7 +22,7 @@ Status
Version Version
Version 3, Jan 23, 2018 Version 5, Sep 6, 2019
Number Number
...@@ -30,14 +30,15 @@ Number ...@@ -30,14 +30,15 @@ Number
Dependencies Dependencies
This extension is written against the wording of the EGL 1.5 This extension is written against the wording of the EGL 1.2
Specification. Specification.
References the EGL_ANGLE_device_d3d extension. References the EGL_ANGLE_device_d3d and EGL_KHR_image_base extensions.
Overview Overview
This extension allows creating EGL surfaces from D3D texture objects. This extension allows creating EGL surfaces and EGL images from D3D texture
objects.
New Types New Types
...@@ -49,11 +50,44 @@ New Procedures and Functions ...@@ -49,11 +50,44 @@ New Procedures and Functions
New Tokens New Tokens
Accepted in the <buftype> parameter of eglCreatePbufferFromClientBuffer: Accepted by the <target> parameter of eglCreateImageKHR and <buftype>
parameter of eglCreatePbufferFromClientBuffer:
EGL_D3D_TEXTURE_ANGLE 0x33A3 EGL_D3D_TEXTURE_ANGLE 0x33A3
Additions to Chapter 3 of the EGL 1.5 Specification (EGL Functions and Errors) Additions to Chapter 2 of the EGL 1.2 Specification (EGL Operation)
Add to section 2.5.1 "EGLImage Specification" (as defined by the
EGL_KHR_image_base specification), in the description of
eglCreateImageKHR:
"Values accepted for <target> are listed in Table aaa, below.
+----------------------------+-----------------------------------------+
| <target> | Notes |
+----------------------------+-----------------------------------------+
| EGL_D3D_TEXTURE_ANGLE | Used for Direct3D11 texture objects |
+----------------------------+-----------------------------------------+
Table aaa. Legal values for eglCreateImageKHR <target> parameter
...
If <target> is EGL_D3D_TEXTURE_ANGLE, <dpy> must be a valid display, <ctx>
must be EGL_NO_CONTEXT, <buffer> must be a pointer to a valid D3D11 texture
object (cast into the type EGLClientBuffer), and attributes other than
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE are ignored. The width and height of
the pbuffer are determined by the width and height of <buffer>."
If EGL_TEXTURE_INTERNAL_FORMAT_ANGLE is specified, it is used to interpret
<buffer> according to the provided internal format. See table
egl.restrictions for acceptable texture object types and formats.
If the EGL_ANGLE_device_d3d extension is present, the provided D3D11 texture
object must have been created by the same D3D11 device queried from the
display. If these requirements are not met, an EGL_BAD_PARAMETER error is
generated."
Additions to Chapter 3 of the EGL 1.2 Specification (EGL Functions and Errors)
Replace the last sentence of paragraph 1 of Section 3.5.3 with the Replace the last sentence of paragraph 1 of Section 3.5.3 with the
following text. following text.
...@@ -81,10 +115,16 @@ Additions to Chapter 3 of the EGL 1.5 Specification (EGL Functions and Errors) ...@@ -81,10 +115,16 @@ Additions to Chapter 3 of the EGL 1.5 Specification (EGL Functions and Errors)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Resource Type Resource Restrictions Resource Type Resource Restrictions
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
IDirect3DTexture9 Memory pool must be D3DPOOL_DEFAULT. Format must be IDirect3DTexture9 Memory pool must be D3DPOOL_DEFAULT.
D3DFMT_R8G8B8, D3DFMT_A8R8G8B8, D3DFMT_A16B16G16R16F or
D3DFMT_A32B32G32R32F. Format must be D3DFMT_R8G8B8, D3DFMT_A8R8G8B8,
ID3D11Texture2D Usage flags must be D3D11_USAGE_DEFAULT. Format must be D3DFMT_A16B16G16R16F or D3DFMT_A32B32G32R32F.
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE is not supported.
ID3D11Texture2D Usage flags must be D3D11_USAGE_DEFAULT.
Format must be
DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM,
...@@ -92,8 +132,17 @@ Additions to Chapter 3 of the EGL 1.5 Specification (EGL Functions and Errors) ...@@ -92,8 +132,17 @@ Additions to Chapter 3 of the EGL 1.5 Specification (EGL Functions and Errors)
DXGI_FORMAT_R8G8B8A8_TYPELESS (support is optional), DXGI_FORMAT_R8G8B8A8_TYPELESS (support is optional),
DXGI_FORMAT_B8G8R8A8_TYPELESS (support is optional), DXGI_FORMAT_B8G8R8A8_TYPELESS (support is optional),
DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT,
DXGI_FORMAT_R32G32B32A32_FLOAT or DXGI_FORMAT_R32G32B32A32_FLOAT, or
DXGI_FORMAT_R10G10B10A2_UNORM. DXGI_FORMAT_R10G10B10A2_UNORM.
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE (if supported) must be
GL_RGBA (supported for all formats),
GL_RGB (supported except for DXGI_FORMAT_R10G10B10A2_UNORM), or
GL_BGRA_EXT (supported only for
DXGI_FORMAT_B8G8R8A8_UNORM,
DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, or
DXGI_FORMAT_B8G8R8A8_TYPELESS).
-------------------------------------------------------------------------- --------------------------------------------------------------------------
Table egl.restrictions - Restrictions on D3D resources that can be used Table egl.restrictions - Restrictions on D3D resources that can be used
as a <buffer>. as a <buffer>.
...@@ -122,8 +171,8 @@ Issues ...@@ -122,8 +171,8 @@ Issues
1. What renderers allow the use of a multi-sampled texture? 1. What renderers allow the use of a multi-sampled texture?
PROPOSED: Mutli-sampled texture support is currently limited to D3D11. Additionally, PROPOSED: Mutli-sampled texture support is currently limited to D3D11.
the client is responsible for resolving the texture. Additionally, the client is responsible for resolving the texture.
2. How does this extension interact with EXT_sRGB_write_control? 2. How does this extension interact with EXT_sRGB_write_control?
...@@ -135,8 +184,17 @@ Issues ...@@ -135,8 +184,17 @@ Issues
PROPOSED: Support for typeless textures is currently limited to D3D11. PROPOSED: Support for typeless textures is currently limited to D3D11.
4. Can RGB formats be supported?
RESOLVED: RGB internal formats are supported for creating images from D3D11
textures in version 5 by setting EGL_TEXTURE_INTERNAL_FORMAT_ANGLE attribute
to GL_RGB. Images with an RGB format will ensure that the alpha channel of
the texture is reset to 1.0 when it is used.
Revision History Revision History
Version 5, 2019/09/06 - added support for creating EGLImage.
Version 4, 2019/04/15 - added support for DXGI_FORMAT_R10G10B10A2_UNORM. Version 4, 2019/04/15 - added support for DXGI_FORMAT_R10G10B10A2_UNORM.
Version 3, 2018/01/23 - added support for typeless textures. Version 3, 2018/01/23 - added support for typeless textures.
......
...@@ -229,6 +229,7 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribANGLE(EGLDisplay dpy, EGLint ...@@ -229,6 +229,7 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribANGLE(EGLDisplay dpy, EGLint
#ifndef EGL_ANGLE_image_d3d11_texture #ifndef EGL_ANGLE_image_d3d11_texture
#define EGL_D3D11_TEXTURE_ANGLE 0x3484 #define EGL_D3D11_TEXTURE_ANGLE 0x3484
#define EGL_TEXTURE_INTERNAL_FORMAT_ANGLE 0x345D
#endif /* EGL_ANGLE_image_d3d11_texture */ #endif /* EGL_ANGLE_image_d3d11_texture */
#ifndef EGL_ANGLE_create_context_backwards_compatible #ifndef EGL_ANGLE_create_context_backwards_compatible
......
...@@ -287,7 +287,7 @@ bool DisplayD3D::isValidNativeWindow(EGLNativeWindowType window) const ...@@ -287,7 +287,7 @@ bool DisplayD3D::isValidNativeWindow(EGLNativeWindowType window) const
return mRenderer->isValidNativeWindow(window); return mRenderer->isValidNativeWindow(window);
} }
egl::Error DisplayD3D::validateClientBuffer(const egl::Config *configuration, egl::Error DisplayD3D::validateClientBuffer(const egl::Config *config,
EGLenum buftype, EGLenum buftype,
EGLClientBuffer clientBuffer, EGLClientBuffer clientBuffer,
const egl::AttributeMap &attribs) const const egl::AttributeMap &attribs) const
...@@ -295,16 +295,16 @@ egl::Error DisplayD3D::validateClientBuffer(const egl::Config *configuration, ...@@ -295,16 +295,16 @@ egl::Error DisplayD3D::validateClientBuffer(const egl::Config *configuration,
switch (buftype) switch (buftype)
{ {
case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE: case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
return mRenderer->validateShareHandle(configuration, static_cast<HANDLE>(clientBuffer), return mRenderer->validateShareHandle(config, static_cast<HANDLE>(clientBuffer),
attribs); attribs);
case EGL_D3D_TEXTURE_ANGLE: case EGL_D3D_TEXTURE_ANGLE:
return mRenderer->getD3DTextureInfo(configuration, return mRenderer->getD3DTextureInfo(config, static_cast<IUnknown *>(clientBuffer),
static_cast<IUnknown *>(clientBuffer), nullptr, attribs, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr); nullptr);
default: default:
return DisplayImpl::validateClientBuffer(configuration, buftype, clientBuffer, attribs); return DisplayImpl::validateClientBuffer(config, buftype, clientBuffer, attribs);
} }
} }
...@@ -318,7 +318,8 @@ egl::Error DisplayD3D::validateImageClientBuffer(const gl::Context *context, ...@@ -318,7 +318,8 @@ egl::Error DisplayD3D::validateImageClientBuffer(const gl::Context *context,
case EGL_D3D11_TEXTURE_ANGLE: case EGL_D3D11_TEXTURE_ANGLE:
{ {
return mRenderer->getD3DTextureInfo(nullptr, static_cast<IUnknown *>(clientBuffer), return mRenderer->getD3DTextureInfo(nullptr, static_cast<IUnknown *>(clientBuffer),
nullptr, nullptr, nullptr, nullptr); attribs, nullptr, nullptr, nullptr, nullptr,
nullptr);
} }
default: default:
......
...@@ -180,9 +180,11 @@ class RendererD3D : public BufferFactoryD3D ...@@ -180,9 +180,11 @@ class RendererD3D : public BufferFactoryD3D
EGLint samples) = 0; EGLint samples) = 0;
virtual egl::Error getD3DTextureInfo(const egl::Config *configuration, virtual egl::Error getD3DTextureInfo(const egl::Config *configuration,
IUnknown *d3dTexture, IUnknown *d3dTexture,
const egl::AttributeMap &attribs,
EGLint *width, EGLint *width,
EGLint *height, EGLint *height,
EGLint *samples, GLsizei *samples,
gl::Format *glFormat,
const angle::Format **angleFormat) const = 0; const angle::Format **angleFormat) const = 0;
virtual egl::Error validateShareHandle(const egl::Config *config, virtual egl::Error validateShareHandle(const egl::Config *config,
HANDLE shareHandle, HANDLE shareHandle,
......
...@@ -105,8 +105,9 @@ egl::Error SurfaceD3D::initialize(const egl::Display *display) ...@@ -105,8 +105,9 @@ egl::Error SurfaceD3D::initialize(const egl::Display *display)
if (mBuftype == EGL_D3D_TEXTURE_ANGLE) if (mBuftype == EGL_D3D_TEXTURE_ANGLE)
{ {
ANGLE_TRY(mRenderer->getD3DTextureInfo(mState.config, mD3DTexture, &mFixedWidth, ANGLE_TRY(mRenderer->getD3DTextureInfo(mState.config, mD3DTexture, mState.attributes,
&mFixedHeight, nullptr, &mColorFormat)); &mFixedWidth, &mFixedHeight, nullptr, nullptr,
&mColorFormat));
if (mState.attributes.contains(EGL_GL_COLORSPACE)) if (mState.attributes.contains(EGL_GL_COLORSPACE))
{ {
if (mColorFormat->id != angle::FormatID::R8G8B8A8_TYPELESS && if (mColorFormat->id != angle::FormatID::R8G8B8A8_TYPELESS &&
......
...@@ -17,32 +17,24 @@ ...@@ -17,32 +17,24 @@
namespace rx namespace rx
{ {
ExternalImageSiblingImpl11::ExternalImageSiblingImpl11(Renderer11 *renderer, EGLClientBuffer buffer) ExternalImageSiblingImpl11::ExternalImageSiblingImpl11(Renderer11 *renderer,
: mRenderer(renderer), EGLClientBuffer buffer,
mBuffer(buffer), const egl::AttributeMap &attribs)
mFormat(GL_NONE), : mRenderer(renderer), mBuffer(buffer), mAttribs(attribs)
mIsRenderable(false),
mIsTexturable(false),
mSamples(0)
{} {}
ExternalImageSiblingImpl11::~ExternalImageSiblingImpl11() {} ExternalImageSiblingImpl11::~ExternalImageSiblingImpl11() {}
egl::Error ExternalImageSiblingImpl11::initialize(const egl::Display *display) egl::Error ExternalImageSiblingImpl11::initialize(const egl::Display *display)
{ {
EGLint width, height, samples = 0; const angle::Format *angleFormat = nullptr;
const angle::Format *format = nullptr; ANGLE_TRY(mRenderer->getD3DTextureInfo(nullptr, static_cast<IUnknown *>(mBuffer), mAttribs,
ANGLE_TRY(mRenderer->getD3DTextureInfo(nullptr, static_cast<IUnknown *>(mBuffer), &width, &mWidth, &mHeight, &mSamples, &mFormat, &angleFormat));
&height, &samples, &format));
mFormat = gl::Format(format->glInternalFormat);
mSize = gl::Extents(width, height, 1);
mSamples = static_cast<size_t>(samples);
ID3D11Texture2D *texture = ID3D11Texture2D *texture =
d3d11::DynamicCastComObject<ID3D11Texture2D>(static_cast<IUnknown *>(mBuffer)); d3d11::DynamicCastComObject<ID3D11Texture2D>(static_cast<IUnknown *>(mBuffer));
ASSERT(texture != nullptr); ASSERT(texture != nullptr);
// TextureHelper11 will release texture on destruction. // TextureHelper11 will release texture on destruction.
mTexture.set(texture, d3d11::Format::Get(format->glInternalFormat, mTexture.set(texture, d3d11::Format::Get(angleFormat->glInternalFormat,
mRenderer->getRenderer11DeviceCaps())); mRenderer->getRenderer11DeviceCaps()));
D3D11_TEXTURE2D_DESC textureDesc = {}; D3D11_TEXTURE2D_DESC textureDesc = {};
mTexture.getDesc(&textureDesc); mTexture.getDesc(&textureDesc);
...@@ -80,7 +72,7 @@ bool ExternalImageSiblingImpl11::isTexturable(const gl::Context *context) const ...@@ -80,7 +72,7 @@ bool ExternalImageSiblingImpl11::isTexturable(const gl::Context *context) const
gl::Extents ExternalImageSiblingImpl11::getSize() const gl::Extents ExternalImageSiblingImpl11::getSize() const
{ {
return mSize; return gl::Extents(mWidth, mHeight, 1);
} }
size_t ExternalImageSiblingImpl11::getSamples() const size_t ExternalImageSiblingImpl11::getSamples() const
...@@ -144,8 +136,8 @@ angle::Result ExternalImageSiblingImpl11::createRenderTarget(const gl::Context * ...@@ -144,8 +136,8 @@ angle::Result ExternalImageSiblingImpl11::createRenderTarget(const gl::Context *
d3d11::SharedSRV blitSrv = srv.makeCopy(); d3d11::SharedSRV blitSrv = srv.makeCopy();
mRenderTarget = std::make_unique<TextureRenderTarget11>( mRenderTarget = std::make_unique<TextureRenderTarget11>(
std::move(rtv), mTexture, std::move(srv), std::move(blitSrv), formatInfo.internalFormat, std::move(rtv), mTexture, std::move(srv), std::move(blitSrv), mFormat.info->internalFormat,
formatInfo, mSize.width, mSize.height, 1, 1); formatInfo, mWidth, mHeight, 1, mSamples);
return angle::Result::Continue; return angle::Result::Continue;
} }
......
...@@ -19,7 +19,9 @@ class RenderTargetD3D; ...@@ -19,7 +19,9 @@ class RenderTargetD3D;
class ExternalImageSiblingImpl11 : public ExternalImageSiblingImpl class ExternalImageSiblingImpl11 : public ExternalImageSiblingImpl
{ {
public: public:
ExternalImageSiblingImpl11(Renderer11 *renderer, EGLClientBuffer clientBuffer); ExternalImageSiblingImpl11(Renderer11 *renderer,
EGLClientBuffer clientBuffer,
const egl::AttributeMap &attribs);
~ExternalImageSiblingImpl11() override; ~ExternalImageSiblingImpl11() override;
// ExternalImageSiblingImpl interface // ExternalImageSiblingImpl interface
...@@ -44,13 +46,16 @@ class ExternalImageSiblingImpl11 : public ExternalImageSiblingImpl ...@@ -44,13 +46,16 @@ class ExternalImageSiblingImpl11 : public ExternalImageSiblingImpl
Renderer11 *mRenderer; Renderer11 *mRenderer;
EGLClientBuffer mBuffer; EGLClientBuffer mBuffer;
egl::AttributeMap mAttribs;
TextureHelper11 mTexture; TextureHelper11 mTexture;
gl::Format mFormat; gl::Format mFormat = gl::Format::Invalid();
bool mIsRenderable; bool mIsRenderable = false;
bool mIsTexturable; bool mIsTexturable = false;
gl::Extents mSize; EGLint mWidth = 0;
size_t mSamples; EGLint mHeight = 0;
GLsizei mSamples = 0;
std::unique_ptr<RenderTargetD3D> mRenderTarget; std::unique_ptr<RenderTargetD3D> mRenderTarget;
}; };
......
...@@ -1239,9 +1239,11 @@ NativeWindowD3D *Renderer11::createNativeWindow(EGLNativeWindowType window, ...@@ -1239,9 +1239,11 @@ NativeWindowD3D *Renderer11::createNativeWindow(EGLNativeWindowType window,
egl::Error Renderer11::getD3DTextureInfo(const egl::Config *configuration, egl::Error Renderer11::getD3DTextureInfo(const egl::Config *configuration,
IUnknown *texture, IUnknown *texture,
const egl::AttributeMap &attribs,
EGLint *width, EGLint *width,
EGLint *height, EGLint *height,
EGLint *samples, GLsizei *samples,
gl::Format *glFormat,
const angle::Format **angleFormat) const const angle::Format **angleFormat) const
{ {
angle::ComPtr<ID3D11Texture2D> d3dTexture = angle::ComPtr<ID3D11Texture2D> d3dTexture =
...@@ -1270,7 +1272,7 @@ egl::Error Renderer11::getD3DTextureInfo(const egl::Config *configuration, ...@@ -1270,7 +1272,7 @@ egl::Error Renderer11::getD3DTextureInfo(const egl::Config *configuration,
*height = static_cast<EGLint>(desc.Height); *height = static_cast<EGLint>(desc.Height);
} }
EGLint sampleCount = static_cast<EGLint>(desc.SampleDesc.Count); GLsizei sampleCount = static_cast<GLsizei>(desc.SampleDesc.Count);
if (configuration && (configuration->samples != sampleCount)) if (configuration && (configuration->samples != sampleCount))
{ {
// Both the texture and EGL config sample count may not be the same when multi-sampling // Both the texture and EGL config sample count may not be the same when multi-sampling
...@@ -1304,12 +1306,51 @@ egl::Error Renderer11::getD3DTextureInfo(const egl::Config *configuration, ...@@ -1304,12 +1306,51 @@ egl::Error Renderer11::getD3DTextureInfo(const egl::Config *configuration,
default: default:
return egl::EglBadParameter() return egl::EglBadParameter()
<< "Unknown client buffer texture format: " << desc.Format; << "Invalid client buffer texture format: " << desc.Format;
}
const angle::Format *textureAngleFormat = &d3d11_angle::GetFormat(desc.Format);
ASSERT(textureAngleFormat);
GLenum sizedInternalFormat = textureAngleFormat->glInternalFormat;
if (attribs.contains(EGL_TEXTURE_INTERNAL_FORMAT_ANGLE))
{
const GLenum internalFormat =
static_cast<GLenum>(attribs.get(EGL_TEXTURE_INTERNAL_FORMAT_ANGLE));
switch (internalFormat)
{
case GL_RGBA:
case GL_BGRA_EXT:
case GL_RGB:
break;
default:
return egl::EglBadParameter()
<< "Invalid client buffer texture internal format: " << std::hex
<< internalFormat;
}
const GLenum type = gl::GetSizedInternalFormatInfo(sizedInternalFormat).type;
const auto format = gl::Format(internalFormat, type);
if (!format.valid())
{
return egl::EglBadParameter()
<< "Invalid client buffer texture internal format: " << std::hex
<< internalFormat;
}
sizedInternalFormat = format.info->sizedInternalFormat;
}
if (glFormat)
{
*glFormat = gl::Format(sizedInternalFormat);
} }
if (angleFormat) if (angleFormat)
{ {
*angleFormat = &d3d11_angle::GetFormat(desc.Format); *angleFormat = textureAngleFormat;
} }
return egl::NoError(); return egl::NoError();
...@@ -2942,7 +2983,7 @@ ExternalImageSiblingImpl *Renderer11::createExternalImageSibling(const gl::Conte ...@@ -2942,7 +2983,7 @@ ExternalImageSiblingImpl *Renderer11::createExternalImageSibling(const gl::Conte
switch (target) switch (target)
{ {
case EGL_D3D11_TEXTURE_ANGLE: case EGL_D3D11_TEXTURE_ANGLE:
return new ExternalImageSiblingImpl11(this, buffer); return new ExternalImageSiblingImpl11(this, buffer, attribs);
default: default:
UNREACHABLE(); UNREACHABLE();
......
...@@ -141,9 +141,11 @@ class Renderer11 : public RendererD3D ...@@ -141,9 +141,11 @@ class Renderer11 : public RendererD3D
EGLint samples) override; EGLint samples) override;
egl::Error getD3DTextureInfo(const egl::Config *configuration, egl::Error getD3DTextureInfo(const egl::Config *configuration,
IUnknown *d3dTexture, IUnknown *d3dTexture,
const egl::AttributeMap &attribs,
EGLint *width, EGLint *width,
EGLint *height, EGLint *height,
EGLint *samples, GLsizei *samples,
gl::Format *glFormat,
const angle::Format **angleFormat) const override; const angle::Format **angleFormat) const override;
egl::Error validateShareHandle(const egl::Config *config, egl::Error validateShareHandle(const egl::Config *config,
HANDLE shareHandle, HANDLE shareHandle,
......
...@@ -715,9 +715,11 @@ SwapChainD3D *Renderer9::createSwapChain(NativeWindowD3D *nativeWindow, ...@@ -715,9 +715,11 @@ SwapChainD3D *Renderer9::createSwapChain(NativeWindowD3D *nativeWindow,
egl::Error Renderer9::getD3DTextureInfo(const egl::Config *configuration, egl::Error Renderer9::getD3DTextureInfo(const egl::Config *configuration,
IUnknown *d3dTexture, IUnknown *d3dTexture,
const egl::AttributeMap &attribs,
EGLint *width, EGLint *width,
EGLint *height, EGLint *height,
EGLint *samples, GLsizei *samples,
gl::Format *glFormat,
const angle::Format **angleFormat) const const angle::Format **angleFormat) const
{ {
IDirect3DTexture9 *texture = nullptr; IDirect3DTexture9 *texture = nullptr;
...@@ -773,10 +775,17 @@ egl::Error Renderer9::getD3DTextureInfo(const egl::Config *configuration, ...@@ -773,10 +775,17 @@ egl::Error Renderer9::getD3DTextureInfo(const egl::Config *configuration,
<< "Unknown client buffer texture format: " << desc.Format; << "Unknown client buffer texture format: " << desc.Format;
} }
const auto &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format);
ASSERT(d3dFormatInfo.info().id != angle::FormatID::NONE);
if (glFormat)
{
*glFormat = gl::Format(d3dFormatInfo.info().glInternalFormat);
}
if (angleFormat) if (angleFormat)
{ {
const auto &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format);
ASSERT(d3dFormatInfo.info().id != angle::FormatID::NONE);
*angleFormat = &d3dFormatInfo.info(); *angleFormat = &d3dFormatInfo.info();
} }
......
...@@ -96,9 +96,11 @@ class Renderer9 : public RendererD3D ...@@ -96,9 +96,11 @@ class Renderer9 : public RendererD3D
EGLint samples) override; EGLint samples) override;
egl::Error getD3DTextureInfo(const egl::Config *configuration, egl::Error getD3DTextureInfo(const egl::Config *configuration,
IUnknown *d3dTexture, IUnknown *d3dTexture,
const egl::AttributeMap &attribs,
EGLint *width, EGLint *width,
EGLint *height, EGLint *height,
EGLint *samples, GLsizei *samples,
gl::Format *glFormat,
const angle::Format **angleFormat) const override; const angle::Format **angleFormat) const override;
egl::Error validateShareHandle(const egl::Config *config, egl::Error validateShareHandle(const egl::Config *config,
HANDLE shareHandle, HANDLE shareHandle,
......
...@@ -1615,7 +1615,7 @@ Error ValidateCreatePbufferFromClientBuffer(Display *display, ...@@ -1615,7 +1615,7 @@ Error ValidateCreatePbufferFromClientBuffer(Display *display,
break; break;
case EGL_TEXTURE_INTERNAL_FORMAT_ANGLE: case EGL_TEXTURE_INTERNAL_FORMAT_ANGLE:
if (buftype != EGL_IOSURFACE_ANGLE) if (buftype != EGL_IOSURFACE_ANGLE && buftype != EGL_D3D_TEXTURE_ANGLE)
{ {
return EglBadAttribute() << "<buftype> doesn't support texture internal format"; return EglBadAttribute() << "<buftype> doesn't support texture internal format";
} }
...@@ -1904,6 +1904,15 @@ Error ValidateCreateImage(const Display *display, ...@@ -1904,6 +1904,15 @@ Error ValidateCreateImage(const Display *display,
} }
break; break;
case EGL_TEXTURE_INTERNAL_FORMAT_ANGLE:
if (!displayExtensions.imageD3D11Texture)
{
return EglBadParameter()
<< "EGL_TEXTURE_INTERNAL_FORMAT_ANGLE and EGL_TEXTURE_TYPE_ANGLE cannot "
"be used without EGL_ANGLE_image_d3d11_texture support.";
}
break;
default: default:
return EglBadParameter() return EglBadParameter()
<< "invalid attribute: 0x" << std::hex << std::uppercase << attribute; << "invalid attribute: 0x" << std::hex << std::uppercase << attribute;
......
...@@ -1302,6 +1302,140 @@ TEST_P(D3DTextureTest, NonRenderableTextureImage) ...@@ -1302,6 +1302,140 @@ TEST_P(D3DTextureTest, NonRenderableTextureImage)
d3d11_texture->Release(); d3d11_texture->Release();
} }
TEST_P(D3DTextureTest, RGBEmulationTextureImage)
{
ANGLE_SKIP_TEST_IF(!valid() || !IsD3D11());
EGLWindow *window = getEGLWindow();
EGLDisplay display = window->getDisplay();
window->makeCurrent();
const UINT bufferSize = 32;
EXPECT_TRUE(mD3D11Device != nullptr);
ID3D11Texture2D *d3d11_texture = nullptr;
CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_R8G8B8A8_UNORM, bufferSize, bufferSize, 1, 1,
D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET);
EXPECT_TRUE(SUCCEEDED(mD3D11Device->CreateTexture2D(&desc, nullptr, &d3d11_texture)));
const EGLint attribs[] = {EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, GL_RGB, EGL_NONE};
EGLImage image = eglCreateImageKHR(display, EGL_NO_CONTEXT, EGL_D3D11_TEXTURE_ANGLE,
static_cast<EGLClientBuffer>(d3d11_texture), attribs);
ASSERT_EGL_SUCCESS();
ASSERT_NE(image, EGL_NO_IMAGE_KHR);
GLuint texture;
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);
ASSERT_GL_NO_ERROR();
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
ASSERT_GL_NO_ERROR();
GLuint fbo;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
EXPECT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE));
ASSERT_GL_NO_ERROR();
// Although we are writing 0.5 to the alpha channel it should have the same
// side effects as if alpha were 1.0.
glViewport(0, 0, static_cast<GLsizei>(bufferSize), static_cast<GLsizei>(bufferSize));
glClearColor(1.0f, 0.0f, 1.0f, 0.5f);
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);
GLuint rgbaRbo;
glGenRenderbuffers(1, &rgbaRbo);
glBindRenderbuffer(GL_RENDERBUFFER, rgbaRbo);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, bufferSize, bufferSize);
GLuint rgbaFbo;
glGenFramebuffers(1, &rgbaFbo);
glBindFramebuffer(GL_FRAMEBUFFER, rgbaFbo);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rgbaRbo);
EXPECT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE));
ASSERT_GL_NO_ERROR();
// BlitFramebuffer from/to RGBA framebuffer fails.
glBindFramebuffer(GL_READ_FRAMEBUFFER, rgbaFbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
glBlitFramebufferANGLE(0, 0, bufferSize, bufferSize, 0, 0, bufferSize, bufferSize,
GL_COLOR_BUFFER_BIT, GL_NEAREST);
ASSERT_GL_ERROR(GL_INVALID_OPERATION);
ASSERT_GL_NO_ERROR();
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, rgbaFbo);
glBlitFramebufferANGLE(0, 0, bufferSize, bufferSize, 0, 0, bufferSize, bufferSize,
GL_COLOR_BUFFER_BIT, GL_NEAREST);
ASSERT_GL_ERROR(GL_INVALID_OPERATION);
ASSERT_GL_NO_ERROR();
GLuint rgbRbo;
glGenRenderbuffers(1, &rgbRbo);
glBindRenderbuffer(GL_RENDERBUFFER, rgbRbo);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB8_OES, bufferSize, bufferSize);
GLuint rgbFbo;
glGenFramebuffers(1, &rgbFbo);
glBindFramebuffer(GL_FRAMEBUFFER, rgbFbo);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rgbRbo);
EXPECT_EQ(glCheckFramebufferStatus(GL_FRAMEBUFFER),
static_cast<unsigned>(GL_FRAMEBUFFER_COMPLETE));
ASSERT_GL_NO_ERROR();
glClearColor(1.0f, 0.0f, 1.0f, 0.5f);
glClear(GL_COLOR_BUFFER_BIT);
ASSERT_GL_NO_ERROR();
// Clear texture framebuffer.
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2, 0, 0, 0,
255);
// BlitFramebuffer from/to RGB framebuffer succeeds.
glBindFramebuffer(GL_READ_FRAMEBUFFER, rgbFbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
glBlitFramebufferANGLE(0, 0, bufferSize, bufferSize, 0, 0, bufferSize, bufferSize,
GL_COLOR_BUFFER_BIT, GL_NEAREST);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2, 255, 0,
255, 255);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT);
glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, rgbFbo);
glBlitFramebufferANGLE(0, 0, bufferSize, bufferSize, 0, 0, bufferSize, bufferSize,
GL_COLOR_BUFFER_BIT, GL_NEAREST);
ASSERT_GL_NO_ERROR();
glBindFramebuffer(GL_FRAMEBUFFER, rgbFbo);
EXPECT_PIXEL_EQ(static_cast<GLint>(bufferSize) / 2, static_cast<GLint>(bufferSize) / 2, 0, 0, 0,
255);
glDeleteFramebuffers(1, &rgbFbo);
glDeleteRenderbuffers(1, &rgbRbo);
glDeleteFramebuffers(1, &rgbaFbo);
glDeleteRenderbuffers(1, &rgbaRbo);
glDeleteFramebuffers(1, &fbo);
glDeleteTextures(1, &texture);
d3d11_texture->Release();
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these // Use this to select which configurations (e.g. which renderer, which GLES major version) these
// tests should be run against. // tests should be run against.
ANGLE_INSTANTIATE_TEST(D3DTextureTest, ES2_D3D9(), ES2_D3D11(), ES2_OPENGL(), ES2_VULKAN()); ANGLE_INSTANTIATE_TEST(D3DTextureTest, ES2_D3D9(), ES2_D3D11(), ES2_OPENGL(), ES2_VULKAN());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment