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
Contributors
Geoff Lang
Olli Etuaho
Contacts
......@@ -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_SRGB,
DXGI_FORMAT_B8G8R8A8_UNORM,
DXGI_FORMAT_B8G8R8A8_UNORM_SRGB,
DXGI_FORMAT_B8G8R8A8_UNORM_SRGB (support is optional),
DXGI_FORMAT_R16G16B16A16_FLOAT or
DXGI_FORMAT_R32G32B32A32_FLOAT.
--------------------------------------------------------------------------
......@@ -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
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
1. What renderers allow the use of a multi-sampled texture?
......@@ -106,6 +114,14 @@ Issues
PROPOSED: Mutli-sampled texture support is currently limited to D3D11. Additionally,
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
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
{
}
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(),
mState(config, attributes),
mImplementation(nullptr),
mCurrentCount(0),
mDestroyed(false),
mType(surfaceType),
mBuftype(buftype),
mPostSubBufferRequested(false),
mLargestPbuffer(false),
mGLColorspace(EGL_GL_COLORSPACE_LINEAR),
......@@ -154,6 +158,26 @@ Error Surface::initialize(const Display *display)
mState.defaultFramebuffer = createDefaultFramebuffer(display);
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();
}
......@@ -441,17 +465,10 @@ PbufferSurface::PbufferSurface(rx::EGLImplFactory *implFactory,
EGLenum buftype,
EGLClientBuffer clientBuffer,
const AttributeMap &attribs)
: Surface(EGL_PBUFFER_BIT, config, attribs)
: Surface(EGL_PBUFFER_BIT, config, attribs, buftype)
{
mImplementation =
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()
......
......@@ -128,7 +128,10 @@ class Surface : public gl::FramebufferAttachmentObject
const gl::Format &getBindTexImageFormat() const { return mColorFormat; }
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;
rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const override;
......@@ -144,6 +147,7 @@ class Surface : public gl::FramebufferAttachmentObject
bool mDestroyed;
EGLint mType;
EGLenum mBuftype;
bool mPostSubBufferRequested;
bool mFlexibleSurfaceCompatibilityRequested;
......
......@@ -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_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.
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 @@
#include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/renderer/FramebufferAttachmentObjectImpl.h"
namespace angle
{
struct Format;
}
namespace gl
{
class FramebufferState;
......@@ -63,6 +68,13 @@ class SurfaceImpl : public FramebufferAttachmentObjectImpl
virtual EGLint isPostSubBufferSupported() 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:
const egl::SurfaceState &mState;
};
......
......@@ -135,7 +135,7 @@ class RendererD3D : public BufferFactoryD3D, public MultisampleTextureInitialize
IUnknown *d3dTexture,
EGLint *width,
EGLint *height,
GLenum *fboFormat) const = 0;
const angle::Format **angleFormat) const = 0;
virtual egl::Error validateShareHandle(const egl::Config *config,
HANDLE shareHandle,
const egl::AttributeMap &attribs) const = 0;
......
......@@ -11,6 +11,7 @@
#include "libANGLE/Context.h"
#include "libANGLE/Display.h"
#include "libANGLE/Surface.h"
#include "libANGLE/renderer/Format.h"
#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
#include "libANGLE/renderer/d3d/RendererD3D.h"
#include "libANGLE/renderer/d3d/SwapChainD3D.h"
......@@ -36,6 +37,7 @@ SurfaceD3D::SurfaceD3D(const egl::SurfaceState &state,
mOrientation(static_cast<EGLint>(attribs.get(EGL_SURFACE_ORIENTATION_ANGLE, 0))),
mRenderTargetFormat(state.config->renderTargetFormat),
mDepthStencilFormat(state.config->depthStencilFormat),
mColorFormat(nullptr),
mSwapChain(nullptr),
mSwapIntervalDirty(true),
mNativeWindow(renderer->createNativeWindow(window, state.config, attribs)),
......@@ -62,7 +64,8 @@ SurfaceD3D::SurfaceD3D(const egl::SurfaceState &state,
ASSERT(mD3DTexture != nullptr);
mD3DTexture->AddRef();
ANGLE_SWALLOW_ERR(mRenderer->getD3DTextureInfo(state.config, mD3DTexture, &mWidth,
&mHeight, &mRenderTargetFormat));
&mHeight, &mColorFormat));
mRenderTargetFormat = mColorFormat->fboImplementationInternalFormat;
break;
default:
......@@ -356,6 +359,11 @@ egl::Error SurfaceD3D::querySurfacePointerANGLE(EGLint attribute, void **value)
return egl::NoError();
}
const angle::Format *SurfaceD3D::getD3DTextureColorFormat() const
{
return mColorFormat;
}
gl::Error SurfaceD3D::getAttachmentRenderTarget(const gl::Context *context,
GLenum binding,
const gl::ImageIndex &imageIndex,
......
......@@ -61,6 +61,8 @@ class SurfaceD3D : public SurfaceImpl
const gl::ImageIndex &imageIndex,
FramebufferAttachmentRenderTarget **rtOut) override;
const angle::Format *getD3DTextureColorFormat() const override;
protected:
SurfaceD3D(const egl::SurfaceState &state,
RendererD3D *renderer,
......@@ -90,6 +92,7 @@ class SurfaceD3D : public SurfaceImpl
GLenum mRenderTargetFormat;
GLenum mDepthStencilFormat;
const angle::Format *mColorFormat;
SwapChainD3D *mSwapChain;
bool mSwapIntervalDirty;
......
......@@ -1299,7 +1299,7 @@ egl::Error Renderer11::getD3DTextureInfo(const egl::Config *configuration,
IUnknown *d3dTexture,
EGLint *width,
EGLint *height,
GLenum *fboFormat) const
const angle::Format **angleFormat) const
{
ID3D11Texture2D *texture = d3d11::DynamicCastComObject<ID3D11Texture2D>(d3dTexture);
if (texture == nullptr)
......@@ -1355,10 +1355,9 @@ egl::Error Renderer11::getD3DTextureInfo(const egl::Config *configuration,
<< "Unknown client buffer texture format: " << desc.Format;
}
if (fboFormat)
if (angleFormat)
{
const angle::Format &angleFormat = d3d11_angle::GetFormat(desc.Format);
*fboFormat = angleFormat.fboImplementationInternalFormat;
*angleFormat = &d3d11_angle::GetFormat(desc.Format);
}
return egl::NoError();
......
......@@ -143,7 +143,7 @@ class Renderer11 : public RendererD3D
IUnknown *d3dTexture,
EGLint *width,
EGLint *height,
GLenum *fboFormat) const override;
const angle::Format **angleFormat) const override;
egl::Error validateShareHandle(const egl::Config *config,
HANDLE shareHandle,
const egl::AttributeMap &attribs) const override;
......
......@@ -99,7 +99,7 @@ const DXGISupport &GetDXGISupport_9_3(DXGI_FORMAT dxgiFormat)
}
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;
}
case DXGI_FORMAT_B8G8R8X8_TYPELESS:
......@@ -692,7 +692,7 @@ const DXGISupport &GetDXGISupport_10_0(DXGI_FORMAT dxgiFormat)
}
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;
}
case DXGI_FORMAT_B8G8R8X8_TYPELESS:
......@@ -1285,7 +1285,7 @@ const DXGISupport &GetDXGISupport_10_1(DXGI_FORMAT dxgiFormat)
}
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;
}
case DXGI_FORMAT_B8G8R8X8_TYPELESS:
......@@ -1878,7 +1878,7 @@ const DXGISupport &GetDXGISupport_11_0(DXGI_FORMAT dxgiFormat)
}
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;
}
case DXGI_FORMAT_B8G8R8X8_TYPELESS:
......@@ -2471,7 +2471,7 @@ const DXGISupport &GetDXGISupport_11_1(DXGI_FORMAT dxgiFormat)
}
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;
}
case DXGI_FORMAT_B8G8R8X8_TYPELESS:
......
......@@ -725,7 +725,7 @@ egl::Error Renderer9::getD3DTextureInfo(const egl::Config *config,
IUnknown *d3dTexture,
EGLint *width,
EGLint *height,
GLenum *fboFormat) const
const angle::Format **angleFormat) const
{
IDirect3DTexture9 *texture = nullptr;
if (FAILED(d3dTexture->QueryInterface(&texture)))
......@@ -769,11 +769,11 @@ egl::Error Renderer9::getD3DTextureInfo(const egl::Config *config,
<< "Unknown client buffer texture format: " << desc.Format;
}
if (fboFormat)
if (angleFormat)
{
const auto &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format);
ASSERT(d3dFormatInfo.info().id != angle::Format::ID::NONE);
*fboFormat = d3dFormatInfo.info().fboImplementationInternalFormat;
*angleFormat = &d3dFormatInfo.info();
}
return egl::NoError();
......
......@@ -97,7 +97,7 @@ class Renderer9 : public RendererD3D
IUnknown *d3dTexture,
EGLint *width,
EGLint *height,
GLenum *fboFormat) const override;
const angle::Format **angleFormat) const override;
egl::Error validateShareHandle(const egl::Config *config,
HANDLE shareHandle,
const egl::AttributeMap &attribs) const override;
......
......@@ -9,10 +9,12 @@
#include "libANGLE/renderer/gl/wgl/D3DTextureSurfaceWGL.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/TextureGL.h"
#include "libANGLE/renderer/gl/RendererGL.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/FunctionsWGL.h"
......@@ -26,6 +28,7 @@ egl::Error GetD3D11TextureInfo(EGLenum buftype,
ID3D11Texture2D *texture11,
size_t *width,
size_t *height,
const angle::Format **angleFormat,
IUnknown **object,
IUnknown **device)
{
......@@ -60,6 +63,11 @@ egl::Error GetD3D11TextureInfo(EGLenum buftype,
return egl::EglBadParameter() << "Could not query the D3D11 device from the client buffer.";
}
if (angleFormat)
{
*angleFormat = &d3d11_angle::GetFormat(textureDesc.Format);
}
if (width)
{
*width = textureDesc.Width;
......@@ -94,6 +102,7 @@ egl::Error GetD3D9TextureInfo(EGLenum buftype,
IDirect3DTexture9 *texture9,
size_t *width,
size_t *height,
const angle::Format **angleFormat,
IUnknown **object,
IUnknown **device)
{
......@@ -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)
{
*width = surfaceDesc.Width;
......@@ -165,6 +181,7 @@ egl::Error GetD3DTextureInfo(EGLenum buftype,
ID3D11Device *d3d11Device,
size_t *width,
size_t *height,
const angle::Format **angleFormat,
IUnknown **object,
IUnknown **device)
{
......@@ -175,11 +192,13 @@ egl::Error GetD3DTextureInfo(EGLenum buftype,
IDirect3DTexture9 *texture9 = nullptr;
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)))
{
return GetD3D9TextureInfo(buftype, texture9, width, height, object, device);
return GetD3D9TextureInfo(buftype, texture9, width, height, angleFormat, object,
device);
}
else
{
......@@ -199,7 +218,7 @@ egl::Error GetD3DTextureInfo(EGLenum buftype,
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
{
......@@ -232,6 +251,7 @@ D3DTextureSurfaceWGL::D3DTextureSurfaceWGL(const egl::SurfaceState &state,
mDeviceContext(deviceContext),
mWidth(0),
mHeight(0),
mColorFormat(nullptr),
mDeviceHandle(nullptr),
mObject(nullptr),
mKeyedMutex(nullptr),
......@@ -278,7 +298,7 @@ egl::Error D3DTextureSurfaceWGL::ValidateD3DTextureClientBuffer(EGLenum buftype,
EGLClientBuffer clientBuffer,
ID3D11Device *d3d11Device)
{
return GetD3DTextureInfo(buftype, clientBuffer, d3d11Device, nullptr, nullptr, nullptr,
return GetD3DTextureInfo(buftype, clientBuffer, d3d11Device, nullptr, nullptr, nullptr, nullptr,
nullptr);
}
......@@ -286,7 +306,7 @@ egl::Error D3DTextureSurfaceWGL::initialize(const egl::Display *display)
{
IUnknown *device = nullptr;
ANGLE_TRY(GetD3DTextureInfo(mBuftype, mClientBuffer, mDisplayD3D11Device, &mWidth, &mHeight,
&mObject, &device));
&mColorFormat, &mObject, &device));
// Grab the keyed mutex, if one exists
mObject->QueryInterface(&mKeyedMutex);
......@@ -475,4 +495,9 @@ HDC D3DTextureSurfaceWGL::getDC() const
return mDeviceContext;
}
const angle::Format *D3DTextureSurfaceWGL::getD3DTextureColorFormat() const
{
return mColorFormat;
}
} // namespace rx
......@@ -65,6 +65,8 @@ class D3DTextureSurfaceWGL : public SurfaceWGL
HDC getDC() const override;
const angle::Format *getD3DTextureColorFormat() const override;
private:
EGLenum mBuftype;
EGLClientBuffer mClientBuffer;
......@@ -84,6 +86,8 @@ class D3DTextureSurfaceWGL : public SurfaceWGL
size_t mWidth;
size_t mHeight;
const angle::Format *mColorFormat;
HANDLE mDeviceHandle;
IUnknown *mObject;
IDXGIKeyedMutex *mKeyedMutex;
......
......@@ -266,16 +266,27 @@ class D3DTextureTest : public ANGLETest
IDirect3DDevice9 *mD3D9Device = nullptr;
};
// Test creating pbuffer from textures with several
// different DXGI formats.
TEST_P(D3DTextureTest, TestD3D11SupportedFormats)
// Test creating pbuffer from textures with several different DXGI formats.
TEST_P(D3DTextureTest, TestD3D11SupportedFormatsSurface)
{
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,
DXGI_FORMAT_B8G8R8A8_UNORM, 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;
}
}
EGLSurface pbuffer = createD3D11PBuffer(32, 32, EGL_TEXTURE_RGBA, EGL_TEXTURE_2D, 1, 0,
D3D11_BIND_RENDER_TARGET, formats[i]);
ASSERT_EGL_SUCCESS();
......@@ -283,14 +294,150 @@ TEST_P(D3DTextureTest, TestD3D11SupportedFormats)
EGLWindow *window = getEGLWindow();
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());
ASSERT_EGL_SUCCESS();
window->makeCurrent();
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
// Chromium does. This is a regression test for crbug.com/794086
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