Commit ceffd20c by Olli Etuaho Committed by Commit Bot

Set colorspace of D3D pbuffers according to DXGI format

When a EGL pbuffer is created based on a D3D SRGB texture using EGL_ANGLE_d3d_texture_client_buffer, SRGB conversions are performed as if it was an SRGB surface. The value of EGL_GL_COLORSPACE now reflects that correctly. If the pbuffer is bound to a texture and used as a framebuffer attachment, querying GL_FRAMEBUFFER_COLOR_ATTACHMENT also reflects that correctly. The behavior is the same on both the D3D backend, where there is no native interop involved, and on the GL backend using WGL_NV_DX_interop(2). There are a few limitations on the GL backend that relies on native interop: 1. SRGB conversion for textures created this way can't be disabled using the GL_FRAMEBUFFER_SRGB_EXT toggle that's exposed in ANGLE through EXT_sRGB_write_control. This is now documented in the EGL_ANGLE_d3d_texture_client_buffer spec. On the D3D backend this is not a problem since EXT_sRGB_write_control is not supported either way. 2. Creating a pbuffer out of a D3D11 texture with the format DXGI_FORMAT_B8G8R8A8_UNORM_SRGB does not work, even though it was listed as one of the supported formats in the EGL_ANGLE_d3d_texture_client_buffer spec. It's now mentioned that support for this format is optional. BUG=angleproject:2300 TEST=angle_white_box_tests Change-Id: I70ee0646680805e4469291a5b2ce59e92fda009e Reviewed-on: https://chromium-review.googlesource.com/866743Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent cf180fcc
...@@ -9,6 +9,7 @@ Name Strings ...@@ -9,6 +9,7 @@ Name Strings
Contributors Contributors
Geoff Lang Geoff Lang
Olli Etuaho
Contacts Contacts
...@@ -86,7 +87,7 @@ Additions to Chapter 3 of the EGL 1.4 Specification (EGL Functions and Errors) ...@@ -86,7 +87,7 @@ Additions to Chapter 3 of the EGL 1.4 Specification (EGL Functions and Errors)
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,
DXGI_FORMAT_B8G8R8A8_UNORM_SRGB, DXGI_FORMAT_B8G8R8A8_UNORM_SRGB (support is optional),
DXGI_FORMAT_R16G16B16A16_FLOAT or DXGI_FORMAT_R16G16B16A16_FLOAT or
DXGI_FORMAT_R32G32B32A32_FLOAT. DXGI_FORMAT_R32G32B32A32_FLOAT.
-------------------------------------------------------------------------- --------------------------------------------------------------------------
...@@ -99,6 +100,13 @@ Additions to Chapter 3 of the EGL 1.4 Specification (EGL Functions and Errors) ...@@ -99,6 +100,13 @@ Additions to Chapter 3 of the EGL 1.4 Specification (EGL Functions and Errors)
of the associcated D3D texture object are undefined while the pbuffer is of the associcated D3D texture object are undefined while the pbuffer is
the current read surface, draw surface or bound to a client texture." the current read surface, draw surface or bound to a client texture."
Append to the end of Section 3.5.3.
"When a pbuffer is created with type EGL_D3D_TEXTURE_ANGLE, the
EGL_GL_COLORSPACE attribute of the surface is determined by the DXGI format
of the Direct3D texture. For *_SRGB DXGI formats, the value of
EGL_GL_COLORSPACE is EGL_GL_COLORSPACE_SRGB. For other formats, the value of
EGL_GL_COLORSPACE is EGL_GL_COLORSPACE_LINEAR."
Issues Issues
1. What renderers allow the use of a multi-sampled texture? 1. What renderers allow the use of a multi-sampled texture?
...@@ -106,6 +114,14 @@ Issues ...@@ -106,6 +114,14 @@ Issues
PROPOSED: Mutli-sampled texture support is currently limited to D3D11. Additionally, PROPOSED: Mutli-sampled texture support is currently limited to D3D11. Additionally,
the client is responsible for resolving the texture. the client is responsible for resolving the texture.
2. How does this extension interact with EXT_sRGB_write_control?
If GL_FRAMEBUFFER_SRGB_EXT is disabled and a pbuffer created from a D3D
texture with an *_SRGB format is being rendered to, it is undefined whether
SRGB conversion will be performed.
Revision History Revision History
Version 1, 2016/10/05 - first draft. Version 2, 2018/01/15 - clarified SRGB conversion handling.
Version 1, 2016/10/05 - first draft.
\ No newline at end of file
...@@ -29,13 +29,17 @@ SurfaceState::SurfaceState(const egl::Config *configIn, const AttributeMap &attr ...@@ -29,13 +29,17 @@ SurfaceState::SurfaceState(const egl::Config *configIn, const AttributeMap &attr
{ {
} }
Surface::Surface(EGLint surfaceType, const egl::Config *config, const AttributeMap &attributes) Surface::Surface(EGLint surfaceType,
const egl::Config *config,
const AttributeMap &attributes,
EGLenum buftype)
: FramebufferAttachmentObject(), : FramebufferAttachmentObject(),
mState(config, attributes), mState(config, attributes),
mImplementation(nullptr), mImplementation(nullptr),
mCurrentCount(0), mCurrentCount(0),
mDestroyed(false), mDestroyed(false),
mType(surfaceType), mType(surfaceType),
mBuftype(buftype),
mPostSubBufferRequested(false), mPostSubBufferRequested(false),
mLargestPbuffer(false), mLargestPbuffer(false),
mGLColorspace(EGL_GL_COLORSPACE_LINEAR), mGLColorspace(EGL_GL_COLORSPACE_LINEAR),
...@@ -154,6 +158,26 @@ Error Surface::initialize(const Display *display) ...@@ -154,6 +158,26 @@ Error Surface::initialize(const Display *display)
mState.defaultFramebuffer = createDefaultFramebuffer(display); mState.defaultFramebuffer = createDefaultFramebuffer(display);
ASSERT(mState.defaultFramebuffer != nullptr); ASSERT(mState.defaultFramebuffer != nullptr);
if (mBuftype == EGL_IOSURFACE_ANGLE)
{
GLenum internalFormat =
static_cast<GLenum>(mState.attributes.get(EGL_TEXTURE_INTERNAL_FORMAT_ANGLE));
GLenum type = static_cast<GLenum>(mState.attributes.get(EGL_TEXTURE_TYPE_ANGLE));
mColorFormat = gl::Format(internalFormat, type);
}
if (mBuftype == EGL_D3D_TEXTURE_ANGLE)
{
const angle::Format *colorFormat = mImplementation->getD3DTextureColorFormat();
ASSERT(colorFormat != nullptr);
GLenum internalFormat = colorFormat->fboImplementationInternalFormat;
mColorFormat = gl::Format(internalFormat, colorFormat->componentType);
mGLColorspace = EGL_GL_COLORSPACE_LINEAR;
if (mColorFormat.info->colorEncoding == GL_SRGB)
{
mGLColorspace = EGL_GL_COLORSPACE_SRGB;
}
}
return NoError(); return NoError();
} }
...@@ -441,17 +465,10 @@ PbufferSurface::PbufferSurface(rx::EGLImplFactory *implFactory, ...@@ -441,17 +465,10 @@ PbufferSurface::PbufferSurface(rx::EGLImplFactory *implFactory,
EGLenum buftype, EGLenum buftype,
EGLClientBuffer clientBuffer, EGLClientBuffer clientBuffer,
const AttributeMap &attribs) const AttributeMap &attribs)
: Surface(EGL_PBUFFER_BIT, config, attribs) : Surface(EGL_PBUFFER_BIT, config, attribs, buftype)
{ {
mImplementation = mImplementation =
implFactory->createPbufferFromClientBuffer(mState, buftype, clientBuffer, attribs); implFactory->createPbufferFromClientBuffer(mState, buftype, clientBuffer, attribs);
if (buftype == EGL_IOSURFACE_ANGLE)
{
GLenum internalFormat = static_cast<GLenum>(attribs.get(EGL_TEXTURE_INTERNAL_FORMAT_ANGLE));
GLenum type = static_cast<GLenum>(attribs.get(EGL_TEXTURE_TYPE_ANGLE));
mColorFormat = gl::Format(internalFormat, type);
}
} }
PbufferSurface::~PbufferSurface() PbufferSurface::~PbufferSurface()
......
...@@ -128,7 +128,10 @@ class Surface : public gl::FramebufferAttachmentObject ...@@ -128,7 +128,10 @@ class Surface : public gl::FramebufferAttachmentObject
const gl::Format &getBindTexImageFormat() const { return mColorFormat; } const gl::Format &getBindTexImageFormat() const { return mColorFormat; }
protected: protected:
Surface(EGLint surfaceType, const egl::Config *config, const AttributeMap &attributes); Surface(EGLint surfaceType,
const egl::Config *config,
const AttributeMap &attributes,
EGLenum buftype = EGL_NONE);
~Surface() override; ~Surface() override;
rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const override; rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const override;
...@@ -144,6 +147,7 @@ class Surface : public gl::FramebufferAttachmentObject ...@@ -144,6 +147,7 @@ class Surface : public gl::FramebufferAttachmentObject
bool mDestroyed; bool mDestroyed;
EGLint mType; EGLint mType;
EGLenum mBuftype;
bool mPostSubBufferRequested; bool mPostSubBufferRequested;
bool mFlexibleSurfaceCompatibilityRequested; bool mFlexibleSurfaceCompatibilityRequested;
......
...@@ -712,6 +712,12 @@ static InternalFormatInfoMap BuildInternalFormatInfoMap() ...@@ -712,6 +712,12 @@ static InternalFormatInfoMap BuildInternalFormatInfoMap()
AddRGBAFormat(&map, GL_BGRA4_ANGLEX, true, 4, 4, 4, 4, 0, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888>, RequireExt<&Extensions::textureFormatBGRA8888>, AlwaysSupported); AddRGBAFormat(&map, GL_BGRA4_ANGLEX, true, 4, 4, 4, 4, 0, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888>, RequireExt<&Extensions::textureFormatBGRA8888>, AlwaysSupported);
AddRGBAFormat(&map, GL_BGR5_A1_ANGLEX, true, 5, 5, 5, 1, 0, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888>, RequireExt<&Extensions::textureFormatBGRA8888>, AlwaysSupported); AddRGBAFormat(&map, GL_BGR5_A1_ANGLEX, true, 5, 5, 5, 1, 0, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888>, RequireExt<&Extensions::textureFormatBGRA8888>, AlwaysSupported);
// Special format that is used for D3D textures that are used within ANGLE via the
// EGL_ANGLE_d3d_texture_client_buffer extension. We don't allow uploading texture images with
// this format, but textures in this format can be created from D3D textures, and filtering them
// and rendering to them is allowed.
AddRGBAFormat(&map, GL_BGRA8_SRGB_ANGLEX, true, 8, 8, 8, 8, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, true, NeverSupported, AlwaysSupported, AlwaysSupported);
// Special format which is not really supported, so always false for all supports. // Special format which is not really supported, so always false for all supports.
AddRGBAFormat(&map, GL_BGR565_ANGLEX, true, 5, 6, 5, 1, 0, GL_BGRA_EXT, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_NORMALIZED, false, NeverSupported, NeverSupported, NeverSupported); AddRGBAFormat(&map, GL_BGR565_ANGLEX, true, 5, 6, 5, 1, 0, GL_BGRA_EXT, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_NORMALIZED, false, NeverSupported, NeverSupported, NeverSupported);
......
...@@ -17,6 +17,11 @@ ...@@ -17,6 +17,11 @@
#include "libANGLE/FramebufferAttachment.h" #include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/renderer/FramebufferAttachmentObjectImpl.h" #include "libANGLE/renderer/FramebufferAttachmentObjectImpl.h"
namespace angle
{
struct Format;
}
namespace gl namespace gl
{ {
class FramebufferState; class FramebufferState;
...@@ -63,6 +68,13 @@ class SurfaceImpl : public FramebufferAttachmentObjectImpl ...@@ -63,6 +68,13 @@ class SurfaceImpl : public FramebufferAttachmentObjectImpl
virtual EGLint isPostSubBufferSupported() const = 0; virtual EGLint isPostSubBufferSupported() const = 0;
virtual EGLint getSwapBehavior() const = 0; virtual EGLint getSwapBehavior() const = 0;
// Used to query color format from pbuffers created from D3D textures.
virtual const angle::Format *getD3DTextureColorFormat() const
{
UNREACHABLE();
return nullptr;
}
protected: protected:
const egl::SurfaceState &mState; const egl::SurfaceState &mState;
}; };
......
...@@ -135,7 +135,7 @@ class RendererD3D : public BufferFactoryD3D, public MultisampleTextureInitialize ...@@ -135,7 +135,7 @@ class RendererD3D : public BufferFactoryD3D, public MultisampleTextureInitialize
IUnknown *d3dTexture, IUnknown *d3dTexture,
EGLint *width, EGLint *width,
EGLint *height, EGLint *height,
GLenum *fboFormat) 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,
const egl::AttributeMap &attribs) const = 0; const egl::AttributeMap &attribs) const = 0;
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "libANGLE/Context.h" #include "libANGLE/Context.h"
#include "libANGLE/Display.h" #include "libANGLE/Display.h"
#include "libANGLE/Surface.h" #include "libANGLE/Surface.h"
#include "libANGLE/renderer/Format.h"
#include "libANGLE/renderer/d3d/RenderTargetD3D.h" #include "libANGLE/renderer/d3d/RenderTargetD3D.h"
#include "libANGLE/renderer/d3d/RendererD3D.h" #include "libANGLE/renderer/d3d/RendererD3D.h"
#include "libANGLE/renderer/d3d/SwapChainD3D.h" #include "libANGLE/renderer/d3d/SwapChainD3D.h"
...@@ -36,6 +37,7 @@ SurfaceD3D::SurfaceD3D(const egl::SurfaceState &state, ...@@ -36,6 +37,7 @@ SurfaceD3D::SurfaceD3D(const egl::SurfaceState &state,
mOrientation(static_cast<EGLint>(attribs.get(EGL_SURFACE_ORIENTATION_ANGLE, 0))), mOrientation(static_cast<EGLint>(attribs.get(EGL_SURFACE_ORIENTATION_ANGLE, 0))),
mRenderTargetFormat(state.config->renderTargetFormat), mRenderTargetFormat(state.config->renderTargetFormat),
mDepthStencilFormat(state.config->depthStencilFormat), mDepthStencilFormat(state.config->depthStencilFormat),
mColorFormat(nullptr),
mSwapChain(nullptr), mSwapChain(nullptr),
mSwapIntervalDirty(true), mSwapIntervalDirty(true),
mNativeWindow(renderer->createNativeWindow(window, state.config, attribs)), mNativeWindow(renderer->createNativeWindow(window, state.config, attribs)),
...@@ -62,7 +64,8 @@ SurfaceD3D::SurfaceD3D(const egl::SurfaceState &state, ...@@ -62,7 +64,8 @@ SurfaceD3D::SurfaceD3D(const egl::SurfaceState &state,
ASSERT(mD3DTexture != nullptr); ASSERT(mD3DTexture != nullptr);
mD3DTexture->AddRef(); mD3DTexture->AddRef();
ANGLE_SWALLOW_ERR(mRenderer->getD3DTextureInfo(state.config, mD3DTexture, &mWidth, ANGLE_SWALLOW_ERR(mRenderer->getD3DTextureInfo(state.config, mD3DTexture, &mWidth,
&mHeight, &mRenderTargetFormat)); &mHeight, &mColorFormat));
mRenderTargetFormat = mColorFormat->fboImplementationInternalFormat;
break; break;
default: default:
...@@ -356,6 +359,11 @@ egl::Error SurfaceD3D::querySurfacePointerANGLE(EGLint attribute, void **value) ...@@ -356,6 +359,11 @@ egl::Error SurfaceD3D::querySurfacePointerANGLE(EGLint attribute, void **value)
return egl::NoError(); return egl::NoError();
} }
const angle::Format *SurfaceD3D::getD3DTextureColorFormat() const
{
return mColorFormat;
}
gl::Error SurfaceD3D::getAttachmentRenderTarget(const gl::Context *context, gl::Error SurfaceD3D::getAttachmentRenderTarget(const gl::Context *context,
GLenum binding, GLenum binding,
const gl::ImageIndex &imageIndex, const gl::ImageIndex &imageIndex,
......
...@@ -61,6 +61,8 @@ class SurfaceD3D : public SurfaceImpl ...@@ -61,6 +61,8 @@ class SurfaceD3D : public SurfaceImpl
const gl::ImageIndex &imageIndex, const gl::ImageIndex &imageIndex,
FramebufferAttachmentRenderTarget **rtOut) override; FramebufferAttachmentRenderTarget **rtOut) override;
const angle::Format *getD3DTextureColorFormat() const override;
protected: protected:
SurfaceD3D(const egl::SurfaceState &state, SurfaceD3D(const egl::SurfaceState &state,
RendererD3D *renderer, RendererD3D *renderer,
...@@ -90,6 +92,7 @@ class SurfaceD3D : public SurfaceImpl ...@@ -90,6 +92,7 @@ class SurfaceD3D : public SurfaceImpl
GLenum mRenderTargetFormat; GLenum mRenderTargetFormat;
GLenum mDepthStencilFormat; GLenum mDepthStencilFormat;
const angle::Format *mColorFormat;
SwapChainD3D *mSwapChain; SwapChainD3D *mSwapChain;
bool mSwapIntervalDirty; bool mSwapIntervalDirty;
......
...@@ -1299,7 +1299,7 @@ egl::Error Renderer11::getD3DTextureInfo(const egl::Config *configuration, ...@@ -1299,7 +1299,7 @@ egl::Error Renderer11::getD3DTextureInfo(const egl::Config *configuration,
IUnknown *d3dTexture, IUnknown *d3dTexture,
EGLint *width, EGLint *width,
EGLint *height, EGLint *height,
GLenum *fboFormat) const const angle::Format **angleFormat) const
{ {
ID3D11Texture2D *texture = d3d11::DynamicCastComObject<ID3D11Texture2D>(d3dTexture); ID3D11Texture2D *texture = d3d11::DynamicCastComObject<ID3D11Texture2D>(d3dTexture);
if (texture == nullptr) if (texture == nullptr)
...@@ -1355,10 +1355,9 @@ egl::Error Renderer11::getD3DTextureInfo(const egl::Config *configuration, ...@@ -1355,10 +1355,9 @@ egl::Error Renderer11::getD3DTextureInfo(const egl::Config *configuration,
<< "Unknown client buffer texture format: " << desc.Format; << "Unknown client buffer texture format: " << desc.Format;
} }
if (fboFormat) if (angleFormat)
{ {
const angle::Format &angleFormat = d3d11_angle::GetFormat(desc.Format); *angleFormat = &d3d11_angle::GetFormat(desc.Format);
*fboFormat = angleFormat.fboImplementationInternalFormat;
} }
return egl::NoError(); return egl::NoError();
......
...@@ -143,7 +143,7 @@ class Renderer11 : public RendererD3D ...@@ -143,7 +143,7 @@ class Renderer11 : public RendererD3D
IUnknown *d3dTexture, IUnknown *d3dTexture,
EGLint *width, EGLint *width,
EGLint *height, EGLint *height,
GLenum *fboFormat) 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,
const egl::AttributeMap &attribs) const override; const egl::AttributeMap &attribs) const override;
......
...@@ -99,7 +99,7 @@ const DXGISupport &GetDXGISupport_9_3(DXGI_FORMAT dxgiFormat) ...@@ -99,7 +99,7 @@ const DXGISupport &GetDXGISupport_9_3(DXGI_FORMAT dxgiFormat)
} }
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
{ {
static const DXGISupport info(0, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS); static const DXGISupport info(F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_2D | F_3D | F_CUBE | F_MS);
return info; return info;
} }
case DXGI_FORMAT_B8G8R8X8_TYPELESS: case DXGI_FORMAT_B8G8R8X8_TYPELESS:
...@@ -692,7 +692,7 @@ const DXGISupport &GetDXGISupport_10_0(DXGI_FORMAT dxgiFormat) ...@@ -692,7 +692,7 @@ const DXGISupport &GetDXGISupport_10_0(DXGI_FORMAT dxgiFormat)
} }
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
{ {
static const DXGISupport info(0, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE); static const DXGISupport info(F_MIPGEN, F_DS, F_2D | F_3D | F_CUBE | F_MS | F_RT | F_SAMPLE);
return info; return info;
} }
case DXGI_FORMAT_B8G8R8X8_TYPELESS: case DXGI_FORMAT_B8G8R8X8_TYPELESS:
...@@ -1285,7 +1285,7 @@ const DXGISupport &GetDXGISupport_10_1(DXGI_FORMAT dxgiFormat) ...@@ -1285,7 +1285,7 @@ const DXGISupport &GetDXGISupport_10_1(DXGI_FORMAT dxgiFormat)
} }
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
{ {
static const DXGISupport info(0, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS | F_SAMPLE); static const DXGISupport info(F_MIPGEN, F_DS, F_2D | F_3D | F_CUBE | F_MS | F_RT | F_SAMPLE);
return info; return info;
} }
case DXGI_FORMAT_B8G8R8X8_TYPELESS: case DXGI_FORMAT_B8G8R8X8_TYPELESS:
...@@ -1878,7 +1878,7 @@ const DXGISupport &GetDXGISupport_11_0(DXGI_FORMAT dxgiFormat) ...@@ -1878,7 +1878,7 @@ const DXGISupport &GetDXGISupport_11_0(DXGI_FORMAT dxgiFormat)
} }
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
{ {
static const DXGISupport info(F_RT | F_SAMPLE, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS); static const DXGISupport info(F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_2D | F_3D | F_CUBE | F_MS);
return info; return info;
} }
case DXGI_FORMAT_B8G8R8X8_TYPELESS: case DXGI_FORMAT_B8G8R8X8_TYPELESS:
...@@ -2471,7 +2471,7 @@ const DXGISupport &GetDXGISupport_11_1(DXGI_FORMAT dxgiFormat) ...@@ -2471,7 +2471,7 @@ const DXGISupport &GetDXGISupport_11_1(DXGI_FORMAT dxgiFormat)
} }
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
{ {
static const DXGISupport info(F_RT | F_SAMPLE, F_DS | F_MIPGEN, F_2D | F_3D | F_CUBE | F_MS); static const DXGISupport info(F_MIPGEN | F_RT | F_SAMPLE, F_DS, F_2D | F_3D | F_CUBE | F_MS);
return info; return info;
} }
case DXGI_FORMAT_B8G8R8X8_TYPELESS: case DXGI_FORMAT_B8G8R8X8_TYPELESS:
......
...@@ -725,7 +725,7 @@ egl::Error Renderer9::getD3DTextureInfo(const egl::Config *config, ...@@ -725,7 +725,7 @@ egl::Error Renderer9::getD3DTextureInfo(const egl::Config *config,
IUnknown *d3dTexture, IUnknown *d3dTexture,
EGLint *width, EGLint *width,
EGLint *height, EGLint *height,
GLenum *fboFormat) const const angle::Format **angleFormat) const
{ {
IDirect3DTexture9 *texture = nullptr; IDirect3DTexture9 *texture = nullptr;
if (FAILED(d3dTexture->QueryInterface(&texture))) if (FAILED(d3dTexture->QueryInterface(&texture)))
...@@ -769,11 +769,11 @@ egl::Error Renderer9::getD3DTextureInfo(const egl::Config *config, ...@@ -769,11 +769,11 @@ egl::Error Renderer9::getD3DTextureInfo(const egl::Config *config,
<< "Unknown client buffer texture format: " << desc.Format; << "Unknown client buffer texture format: " << desc.Format;
} }
if (fboFormat) if (angleFormat)
{ {
const auto &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format); const auto &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format);
ASSERT(d3dFormatInfo.info().id != angle::Format::ID::NONE); ASSERT(d3dFormatInfo.info().id != angle::Format::ID::NONE);
*fboFormat = d3dFormatInfo.info().fboImplementationInternalFormat; *angleFormat = &d3dFormatInfo.info();
} }
return egl::NoError(); return egl::NoError();
......
...@@ -97,7 +97,7 @@ class Renderer9 : public RendererD3D ...@@ -97,7 +97,7 @@ class Renderer9 : public RendererD3D
IUnknown *d3dTexture, IUnknown *d3dTexture,
EGLint *width, EGLint *width,
EGLint *height, EGLint *height,
GLenum *fboFormat) 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,
const egl::AttributeMap &attribs) const override; const egl::AttributeMap &attribs) const override;
......
...@@ -9,10 +9,12 @@ ...@@ -9,10 +9,12 @@
#include "libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.h" #include "libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.h"
#include "libANGLE/Surface.h" #include "libANGLE/Surface.h"
#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
#include "libANGLE/renderer/gl/FramebufferGL.h" #include "libANGLE/renderer/gl/FramebufferGL.h"
#include "libANGLE/renderer/gl/TextureGL.h"
#include "libANGLE/renderer/gl/RendererGL.h" #include "libANGLE/renderer/gl/RendererGL.h"
#include "libANGLE/renderer/gl/StateManagerGL.h" #include "libANGLE/renderer/gl/StateManagerGL.h"
#include "libANGLE/renderer/gl/TextureGL.h"
#include "libANGLE/renderer/gl/wgl/DisplayWGL.h" #include "libANGLE/renderer/gl/wgl/DisplayWGL.h"
#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h" #include "libANGLE/renderer/gl/wgl/FunctionsWGL.h"
...@@ -26,6 +28,7 @@ egl::Error GetD3D11TextureInfo(EGLenum buftype, ...@@ -26,6 +28,7 @@ egl::Error GetD3D11TextureInfo(EGLenum buftype,
ID3D11Texture2D *texture11, ID3D11Texture2D *texture11,
size_t *width, size_t *width,
size_t *height, size_t *height,
const angle::Format **angleFormat,
IUnknown **object, IUnknown **object,
IUnknown **device) IUnknown **device)
{ {
...@@ -60,6 +63,11 @@ egl::Error GetD3D11TextureInfo(EGLenum buftype, ...@@ -60,6 +63,11 @@ egl::Error GetD3D11TextureInfo(EGLenum buftype,
return egl::EglBadParameter() << "Could not query the D3D11 device from the client buffer."; return egl::EglBadParameter() << "Could not query the D3D11 device from the client buffer.";
} }
if (angleFormat)
{
*angleFormat = &d3d11_angle::GetFormat(textureDesc.Format);
}
if (width) if (width)
{ {
*width = textureDesc.Width; *width = textureDesc.Width;
...@@ -94,6 +102,7 @@ egl::Error GetD3D9TextureInfo(EGLenum buftype, ...@@ -94,6 +102,7 @@ egl::Error GetD3D9TextureInfo(EGLenum buftype,
IDirect3DTexture9 *texture9, IDirect3DTexture9 *texture9,
size_t *width, size_t *width,
size_t *height, size_t *height,
const angle::Format **angleFormat,
IUnknown **object, IUnknown **object,
IUnknown **device) IUnknown **device)
{ {
...@@ -122,6 +131,13 @@ egl::Error GetD3D9TextureInfo(EGLenum buftype, ...@@ -122,6 +131,13 @@ egl::Error GetD3D9TextureInfo(EGLenum buftype,
} }
} }
if (angleFormat)
{
const auto &d3dFormatInfo = d3d9::GetD3DFormatInfo(surfaceDesc.Format);
ASSERT(d3dFormatInfo.info().id != angle::Format::ID::NONE);
*angleFormat = &d3dFormatInfo.info();
}
if (width) if (width)
{ {
*width = surfaceDesc.Width; *width = surfaceDesc.Width;
...@@ -165,6 +181,7 @@ egl::Error GetD3DTextureInfo(EGLenum buftype, ...@@ -165,6 +181,7 @@ egl::Error GetD3DTextureInfo(EGLenum buftype,
ID3D11Device *d3d11Device, ID3D11Device *d3d11Device,
size_t *width, size_t *width,
size_t *height, size_t *height,
const angle::Format **angleFormat,
IUnknown **object, IUnknown **object,
IUnknown **device) IUnknown **device)
{ {
...@@ -175,11 +192,13 @@ egl::Error GetD3DTextureInfo(EGLenum buftype, ...@@ -175,11 +192,13 @@ egl::Error GetD3DTextureInfo(EGLenum buftype,
IDirect3DTexture9 *texture9 = nullptr; IDirect3DTexture9 *texture9 = nullptr;
if (SUCCEEDED(buffer->QueryInterface<ID3D11Texture2D>(&texture11))) if (SUCCEEDED(buffer->QueryInterface<ID3D11Texture2D>(&texture11)))
{ {
return GetD3D11TextureInfo(buftype, texture11, width, height, object, device); return GetD3D11TextureInfo(buftype, texture11, width, height, angleFormat, object,
device);
} }
else if (SUCCEEDED(buffer->QueryInterface<IDirect3DTexture9>(&texture9))) else if (SUCCEEDED(buffer->QueryInterface<IDirect3DTexture9>(&texture9)))
{ {
return GetD3D9TextureInfo(buftype, texture9, width, height, object, device); return GetD3D9TextureInfo(buftype, texture9, width, height, angleFormat, object,
device);
} }
else else
{ {
...@@ -199,7 +218,7 @@ egl::Error GetD3DTextureInfo(EGLenum buftype, ...@@ -199,7 +218,7 @@ egl::Error GetD3DTextureInfo(EGLenum buftype,
return egl::EglBadParameter() << "Failed to open share handle, " << gl::FmtHR(result); return egl::EglBadParameter() << "Failed to open share handle, " << gl::FmtHR(result);
} }
return GetD3D11TextureInfo(buftype, texture11, width, height, object, device); return GetD3D11TextureInfo(buftype, texture11, width, height, angleFormat, object, device);
} }
else else
{ {
...@@ -232,6 +251,7 @@ D3DTextureSurfaceWGL::D3DTextureSurfaceWGL(const egl::SurfaceState &state, ...@@ -232,6 +251,7 @@ D3DTextureSurfaceWGL::D3DTextureSurfaceWGL(const egl::SurfaceState &state,
mDeviceContext(deviceContext), mDeviceContext(deviceContext),
mWidth(0), mWidth(0),
mHeight(0), mHeight(0),
mColorFormat(nullptr),
mDeviceHandle(nullptr), mDeviceHandle(nullptr),
mObject(nullptr), mObject(nullptr),
mKeyedMutex(nullptr), mKeyedMutex(nullptr),
...@@ -278,7 +298,7 @@ egl::Error D3DTextureSurfaceWGL::ValidateD3DTextureClientBuffer(EGLenum buftype, ...@@ -278,7 +298,7 @@ egl::Error D3DTextureSurfaceWGL::ValidateD3DTextureClientBuffer(EGLenum buftype,
EGLClientBuffer clientBuffer, EGLClientBuffer clientBuffer,
ID3D11Device *d3d11Device) ID3D11Device *d3d11Device)
{ {
return GetD3DTextureInfo(buftype, clientBuffer, d3d11Device, nullptr, nullptr, nullptr, return GetD3DTextureInfo(buftype, clientBuffer, d3d11Device, nullptr, nullptr, nullptr, nullptr,
nullptr); nullptr);
} }
...@@ -286,7 +306,7 @@ egl::Error D3DTextureSurfaceWGL::initialize(const egl::Display *display) ...@@ -286,7 +306,7 @@ egl::Error D3DTextureSurfaceWGL::initialize(const egl::Display *display)
{ {
IUnknown *device = nullptr; IUnknown *device = nullptr;
ANGLE_TRY(GetD3DTextureInfo(mBuftype, mClientBuffer, mDisplayD3D11Device, &mWidth, &mHeight, ANGLE_TRY(GetD3DTextureInfo(mBuftype, mClientBuffer, mDisplayD3D11Device, &mWidth, &mHeight,
&mObject, &device)); &mColorFormat, &mObject, &device));
// Grab the keyed mutex, if one exists // Grab the keyed mutex, if one exists
mObject->QueryInterface(&mKeyedMutex); mObject->QueryInterface(&mKeyedMutex);
...@@ -475,4 +495,9 @@ HDC D3DTextureSurfaceWGL::getDC() const ...@@ -475,4 +495,9 @@ HDC D3DTextureSurfaceWGL::getDC() const
return mDeviceContext; return mDeviceContext;
} }
const angle::Format *D3DTextureSurfaceWGL::getD3DTextureColorFormat() const
{
return mColorFormat;
}
} // namespace rx } // namespace rx
...@@ -65,6 +65,8 @@ class D3DTextureSurfaceWGL : public SurfaceWGL ...@@ -65,6 +65,8 @@ class D3DTextureSurfaceWGL : public SurfaceWGL
HDC getDC() const override; HDC getDC() const override;
const angle::Format *getD3DTextureColorFormat() const override;
private: private:
EGLenum mBuftype; EGLenum mBuftype;
EGLClientBuffer mClientBuffer; EGLClientBuffer mClientBuffer;
...@@ -84,6 +86,8 @@ class D3DTextureSurfaceWGL : public SurfaceWGL ...@@ -84,6 +86,8 @@ class D3DTextureSurfaceWGL : public SurfaceWGL
size_t mWidth; size_t mWidth;
size_t mHeight; size_t mHeight;
const angle::Format *mColorFormat;
HANDLE mDeviceHandle; HANDLE mDeviceHandle;
IUnknown *mObject; IUnknown *mObject;
IDXGIKeyedMutex *mKeyedMutex; IDXGIKeyedMutex *mKeyedMutex;
......
...@@ -266,16 +266,27 @@ class D3DTextureTest : public ANGLETest ...@@ -266,16 +266,27 @@ class D3DTextureTest : public ANGLETest
IDirect3DDevice9 *mD3D9Device = nullptr; IDirect3DDevice9 *mD3D9Device = nullptr;
}; };
// Test creating pbuffer from textures with several // Test creating pbuffer from textures with several different DXGI formats.
// different DXGI formats. TEST_P(D3DTextureTest, TestD3D11SupportedFormatsSurface)
TEST_P(D3DTextureTest, TestD3D11SupportedFormats)
{ {
ANGLE_SKIP_TEST_IF(!valid() || !IsD3D11()); bool srgbSupported = extensionEnabled("GL_EXT_sRGB") || getClientMajorVersion() == 3;
ANGLE_SKIP_TEST_IF(!valid() || !mD3D11Device || !srgbSupported);
const DXGI_FORMAT formats[] = {DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, const DXGI_FORMAT formats[] = {DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM_SRGB}; DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM_SRGB};
for (size_t i = 0; i < 4; ++i) for (size_t i = 0; i < 4; ++i)
{ {
if (formats[i] == DXGI_FORMAT_B8G8R8A8_UNORM_SRGB)
{
if (IsOpenGL())
{
// This generates an invalid format error when calling wglDXRegisterObjectNV().
// Reproducible at least on NVIDIA driver 390.65 on Windows 10.
std::cout << "DXGI_FORMAT_B8G8R8A8_UNORM_SRGB subtest skipped: IsOpenGL().\n";
continue;
}
}
EGLSurface pbuffer = createD3D11PBuffer(32, 32, EGL_TEXTURE_RGBA, EGL_TEXTURE_2D, 1, 0, EGLSurface pbuffer = createD3D11PBuffer(32, 32, EGL_TEXTURE_RGBA, EGL_TEXTURE_2D, 1, 0,
D3D11_BIND_RENDER_TARGET, formats[i]); D3D11_BIND_RENDER_TARGET, formats[i]);
ASSERT_EGL_SUCCESS(); ASSERT_EGL_SUCCESS();
...@@ -283,14 +294,150 @@ TEST_P(D3DTextureTest, TestD3D11SupportedFormats) ...@@ -283,14 +294,150 @@ TEST_P(D3DTextureTest, TestD3D11SupportedFormats)
EGLWindow *window = getEGLWindow(); EGLWindow *window = getEGLWindow();
EGLDisplay display = window->getDisplay(); EGLDisplay display = window->getDisplay();
EGLint colorspace;
eglQuerySurface(display, pbuffer, EGL_GL_COLORSPACE, &colorspace);
if (formats[i] == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB ||
formats[i] == DXGI_FORMAT_B8G8R8A8_UNORM_SRGB)
{
EXPECT_EQ(EGL_GL_COLORSPACE_SRGB, colorspace);
}
else
{
EXPECT_EQ(EGL_GL_COLORSPACE_LINEAR, colorspace);
}
eglMakeCurrent(display, pbuffer, pbuffer, window->getContext()); eglMakeCurrent(display, pbuffer, pbuffer, window->getContext());
ASSERT_EGL_SUCCESS(); ASSERT_EGL_SUCCESS();
window->makeCurrent(); window->makeCurrent();
eglDestroySurface(display, pbuffer); eglDestroySurface(display, pbuffer);
} }
} }
// Test binding a pbuffer created from a D3D texture as a texture image with several different DXGI
// formats. The test renders to and samples from the pbuffer.
TEST_P(D3DTextureTest, TestD3D11SupportedFormatsTexture)
{
bool srgbSupported = extensionEnabled("GL_EXT_sRGB") || getClientMajorVersion() == 3;
ANGLE_SKIP_TEST_IF(!valid() || !mD3D11Device || !srgbSupported);
bool srgbWriteControlSupported = extensionEnabled("GL_EXT_sRGB_write_control") && !IsOpenGL();
const DXGI_FORMAT formats[] = {DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
DXGI_FORMAT_B8G8R8A8_UNORM_SRGB};
for (size_t i = 0; i < 4; ++i)
{
if (formats[i] == DXGI_FORMAT_B8G8R8A8_UNORM_SRGB)
{
if (IsOpenGL())
{
// This generates an invalid format error when calling wglDXRegisterObjectNV().
// Reproducible at least on NVIDIA driver 390.65 on Windows 10.
std::cout << "DXGI_FORMAT_B8G8R8A8_UNORM_SRGB subtest skipped: IsOpenGL().\n";
continue;
}
}
SCOPED_TRACE(std::string("Test case:") + std::to_string(i));
EGLWindow *window = getEGLWindow();
EGLDisplay display = window->getDisplay();
EGLSurface pbuffer =
createD3D11PBuffer(32, 32, EGL_TEXTURE_RGBA, EGL_TEXTURE_2D, 1, 0,
D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE, formats[i]);
ASSERT_EGL_SUCCESS();
ASSERT_NE(pbuffer, EGL_NO_SURFACE);
EGLint colorspace;
eglQuerySurface(display, pbuffer, EGL_GL_COLORSPACE, &colorspace);
GLuint texture = 0u;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
EGLBoolean result = eglBindTexImage(display, pbuffer, EGL_BACK_BUFFER);
ASSERT_EGL_SUCCESS();
ASSERT(result == EGL_TRUE);
GLuint fbo = 0u;
glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
glViewport(0, 0, 32, 32);
// Clear the texture with 50% green and check that the color value written is correct.
glClearColor(0.0f, 0.5f, 0.0f, 1.0f);
GLint colorEncoding = 0;
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT,
&colorEncoding);
if (formats[i] == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB ||
formats[i] == DXGI_FORMAT_B8G8R8A8_UNORM_SRGB)
{
EXPECT_EQ(EGL_GL_COLORSPACE_SRGB, colorspace);
EXPECT_EQ(GL_SRGB_EXT, colorEncoding);
}
else
{
EXPECT_EQ(EGL_GL_COLORSPACE_LINEAR, colorspace);
EXPECT_EQ(GL_LINEAR, colorEncoding);
}
if (colorEncoding == GL_SRGB_EXT)
{
glClear(GL_COLOR_BUFFER_BIT);
EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0u, 188u, 0u, 255u), 2);
// Disable SRGB and run the non-sRGB test case.
if (srgbWriteControlSupported)
glDisable(GL_FRAMEBUFFER_SRGB_EXT);
}
if (colorEncoding == GL_LINEAR || srgbWriteControlSupported)
{
glClearColor(0.0f, 0.5f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0u, 127u, 0u, 255u), 2);
}
// Draw with the texture to a linear framebuffer and check that the color value written is
// correct.
GLFramebuffer scratchFbo;
glBindFramebuffer(GL_FRAMEBUFFER, scratchFbo);
GLTexture scratchTexture;
glBindTexture(GL_TEXTURE_2D, scratchTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 32, 32, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, scratchTexture,
0);
glClearColor(1.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(mTextureProgram);
glUniform1i(mTextureUniformLocation, 0);
glActiveTexture(GL_TEXTURE0);
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);
drawQuad(mTextureProgram, "position", 0.5f);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0u, 127u, 0u, 255u), 2);
glBindFramebuffer(GL_FRAMEBUFFER, 0u);
glBindTexture(GL_TEXTURE_2D, 0u);
glDeleteTextures(1, &texture);
glDeleteFramebuffers(1, &fbo);
eglDestroySurface(display, pbuffer);
}
}
// Test creating a pbuffer with unnecessary EGL_WIDTH and EGL_HEIGHT attributes because that's what // Test creating a pbuffer with unnecessary EGL_WIDTH and EGL_HEIGHT attributes because that's what
// Chromium does. This is a regression test for crbug.com/794086 // Chromium does. This is a regression test for crbug.com/794086
TEST_P(D3DTextureTest, UnnecessaryWidthHeightAttributes) TEST_P(D3DTextureTest, UnnecessaryWidthHeightAttributes)
......
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