Add support for D3D11 texture backed EGLImages

Implement EGL_ANGLE_image_d3d11_texture extension.  Images created with
this extension might not be renderable based on bind flags and resource
usage of the client provided texture in which case attaching them to a
framebuffer won't succeed.

The intended use case is to bind the front and back buffers of a swap
chain to GL textures that can be used for rendering in the case of the
back buffer and as a shader input for the front buffer.

Bug: chromium:939655
Change-Id: Ic3328e831880292217b88be84740740df6031fa6
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1646732
Commit-Queue: Sunny Sachanandani <sunnyps@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
This commit is contained in:
Sunny Sachanandani 2019-06-04 17:49:43 -07:00 коммит произвёл Commit Bot
Родитель eee67c6ec2
Коммит f9686af021
18 изменённых файлов: 451 добавлений и 7 удалений

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

@ -227,6 +227,10 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribANGLE(EGLDisplay dpy, EGLint
#endif
#endif /* EGL_ANGLE_feature_control */
#ifndef EGL_ANGLE_image_d3d11_texture
#define EGL_D3D11_TEXTURE_ANGLE 0x3484
#endif /* EGL_ANGLE_image_d3d11_texture */
// clang-format on
#endif // INCLUDE_EGL_EGLEXT_ANGLE_

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

@ -954,6 +954,7 @@ bool IsExternalImageTarget(EGLenum target)
switch (target)
{
case EGL_NATIVE_BUFFER_ANDROID:
case EGL_D3D11_TEXTURE_ANGLE:
return true;
default:

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

@ -1422,7 +1422,8 @@ DisplayExtensions::DisplayExtensions()
imageNativeBuffer(false),
getFrameTimestamps(false),
recordable(false),
powerPreference(false)
powerPreference(false),
imageD3D11Texture(false)
{}
std::vector<std::string> DisplayExtensions::getStrings() const
@ -1477,6 +1478,7 @@ std::vector<std::string> DisplayExtensions::getStrings() const
InsertExtensionString("EGL_ANDROID_get_frame_timestamps", getFrameTimestamps, &extensionStrings);
InsertExtensionString("EGL_ANDROID_recordable", recordable, &extensionStrings);
InsertExtensionString("EGL_ANGLE_power_preference", powerPreference, &extensionStrings);
InsertExtensionString("EGL_ANGLE_image_d3d11_texture", imageD3D11Texture, &extensionStrings);
// TODO(jmadill): Enable this when complete.
//InsertExtensionString("KHR_create_context_no_error", createContextNoError, &extensionStrings);
// clang-format on

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

@ -887,6 +887,9 @@ struct DisplayExtensions
// EGL_ANGLE_power_preference
bool powerPreference;
// EGL_ANGLE_image_d3d11_texture
bool imageD3D11Texture;
};
struct DeviceExtensions

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

@ -215,6 +215,15 @@ StreamProducerImpl *DisplayD3D::createStreamProducerD3DTexture(
return mRenderer->createStreamProducerD3DTexture(consumerType, attribs);
}
ExternalImageSiblingImpl *DisplayD3D::createExternalImageSibling(const gl::Context *context,
EGLenum target,
EGLClientBuffer buffer,
const egl::AttributeMap &attribs)
{
ASSERT(mRenderer != nullptr);
return mRenderer->createExternalImageSibling(context, target, buffer, attribs);
}
egl::Error DisplayD3D::makeCurrent(egl::Surface *drawSurface,
egl::Surface *readSurface,
gl::Context *context)
@ -290,14 +299,33 @@ egl::Error DisplayD3D::validateClientBuffer(const egl::Config *configuration,
attribs);
case EGL_D3D_TEXTURE_ANGLE:
return mRenderer->getD3DTextureInfo(
configuration, static_cast<IUnknown *>(clientBuffer), nullptr, nullptr, nullptr);
return mRenderer->getD3DTextureInfo(configuration,
static_cast<IUnknown *>(clientBuffer), nullptr,
nullptr, nullptr, nullptr);
default:
return DisplayImpl::validateClientBuffer(configuration, buftype, clientBuffer, attribs);
}
}
egl::Error DisplayD3D::validateImageClientBuffer(const gl::Context *context,
EGLenum target,
EGLClientBuffer clientBuffer,
const egl::AttributeMap &attribs) const
{
switch (target)
{
case EGL_D3D11_TEXTURE_ANGLE:
{
return mRenderer->getD3DTextureInfo(nullptr, static_cast<IUnknown *>(clientBuffer),
nullptr, nullptr, nullptr, nullptr);
}
default:
return DisplayImpl::validateImageClientBuffer(context, target, clientBuffer, attribs);
}
}
void DisplayD3D::generateExtensions(egl::DisplayExtensions *outExtensions) const
{
mRenderer->generateDisplayExtensions(outExtensions);

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

@ -52,6 +52,11 @@ class DisplayD3D : public DisplayImpl, public d3d::Context
StreamProducerImpl *createStreamProducerD3DTexture(egl::Stream::ConsumerType consumerType,
const egl::AttributeMap &attribs) override;
ExternalImageSiblingImpl *createExternalImageSibling(const gl::Context *context,
EGLenum target,
EGLClientBuffer buffer,
const egl::AttributeMap &attribs) override;
egl::Error makeCurrent(egl::Surface *drawSurface,
egl::Surface *readSurface,
gl::Context *context) override;
@ -66,6 +71,10 @@ class DisplayD3D : public DisplayImpl, public d3d::Context
EGLenum buftype,
EGLClientBuffer clientBuffer,
const egl::AttributeMap &attribs) const override;
egl::Error validateImageClientBuffer(const gl::Context *context,
EGLenum target,
EGLClientBuffer clientBuffer,
const egl::AttributeMap &attribs) const override;
DeviceImpl *createDevice() override;

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

@ -182,6 +182,7 @@ class RendererD3D : public BufferFactoryD3D
IUnknown *d3dTexture,
EGLint *width,
EGLint *height,
EGLint *samples,
const angle::Format **angleFormat) const = 0;
virtual egl::Error validateShareHandle(const egl::Config *config,
HANDLE shareHandle,
@ -275,6 +276,11 @@ class RendererD3D : public BufferFactoryD3D
// Image operations
virtual ImageD3D *createImage() = 0;
virtual ExternalImageSiblingImpl *createExternalImageSibling(
const gl::Context *context,
EGLenum target,
EGLClientBuffer buffer,
const egl::AttributeMap &attribs) = 0;
virtual angle::Result generateMipmap(const gl::Context *context,
ImageD3D *dest,
ImageD3D *source) = 0;

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

@ -106,7 +106,7 @@ egl::Error SurfaceD3D::initialize(const egl::Display *display)
if (mBuftype == EGL_D3D_TEXTURE_ANGLE)
{
ANGLE_TRY(mRenderer->getD3DTextureInfo(mState.config, mD3DTexture, &mFixedWidth,
&mFixedHeight, &mColorFormat));
&mFixedHeight, nullptr, &mColorFormat));
if (mState.attributes.contains(EGL_GL_COLORSPACE))
{
if (mColorFormat->id != angle::FormatID::R8G8B8A8_TYPELESS &&

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

@ -0,0 +1,151 @@
//
// Copyright 2019 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.
//
#include "libANGLE/renderer/d3d/d3d11/ExternalImageSiblingImpl11.h"
#include "libANGLE/Context.h"
#include "libANGLE/Error.h"
#include "libANGLE/angletypes.h"
#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/d3d/d3d11/Context11.h"
#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
#include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
namespace rx
{
ExternalImageSiblingImpl11::ExternalImageSiblingImpl11(Renderer11 *renderer, EGLClientBuffer buffer)
: mRenderer(renderer),
mBuffer(buffer),
mFormat(GL_NONE),
mIsRenderable(false),
mIsTexturable(false),
mSamples(0)
{}
ExternalImageSiblingImpl11::~ExternalImageSiblingImpl11() {}
egl::Error ExternalImageSiblingImpl11::initialize(const egl::Display *display)
{
EGLint width, height, samples = 0;
const angle::Format *format = nullptr;
ANGLE_TRY(mRenderer->getD3DTextureInfo(nullptr, static_cast<IUnknown *>(mBuffer), &width,
&height, &samples, &format));
mFormat = gl::Format(format->glInternalFormat);
mSize = gl::Extents(width, height, 1);
mSamples = static_cast<size_t>(samples);
ID3D11Texture2D *texture =
d3d11::DynamicCastComObject<ID3D11Texture2D>(static_cast<IUnknown *>(mBuffer));
ASSERT(texture != nullptr);
// TextureHelper11 will release texture on destruction.
mTexture.set(texture, d3d11::Format::Get(format->glInternalFormat,
mRenderer->getRenderer11DeviceCaps()));
D3D11_TEXTURE2D_DESC textureDesc = {};
mTexture.getDesc(&textureDesc);
IDXGIResource *resource = d3d11::DynamicCastComObject<IDXGIResource>(mTexture.get());
ASSERT(resource != nullptr);
DXGI_USAGE resourceUsage = 0;
resource->GetUsage(&resourceUsage);
SafeRelease(resource);
mIsRenderable = (textureDesc.BindFlags & D3D11_BIND_RENDER_TARGET) &&
(resourceUsage & DXGI_USAGE_RENDER_TARGET_OUTPUT) &&
!(resourceUsage & DXGI_USAGE_READ_ONLY);
mIsTexturable = (textureDesc.BindFlags & D3D11_BIND_SHADER_RESOURCE) &&
(resourceUsage & DXGI_USAGE_SHADER_INPUT);
return egl::NoError();
}
gl::Format ExternalImageSiblingImpl11::getFormat() const
{
return mFormat;
}
bool ExternalImageSiblingImpl11::isRenderable(const gl::Context *context) const
{
return mIsRenderable;
}
bool ExternalImageSiblingImpl11::isTexturable(const gl::Context *context) const
{
return mIsTexturable;
}
gl::Extents ExternalImageSiblingImpl11::getSize() const
{
return mSize;
}
size_t ExternalImageSiblingImpl11::getSamples() const
{
return mSamples;
}
angle::Result ExternalImageSiblingImpl11::getAttachmentRenderTarget(
const gl::Context *context,
GLenum binding,
const gl::ImageIndex &imageIndex,
FramebufferAttachmentRenderTarget **rtOut)
{
ANGLE_TRY(createRenderTarget(context));
*rtOut = mRenderTarget.get();
return angle::Result::Continue;
}
angle::Result ExternalImageSiblingImpl11::initializeContents(const gl::Context *context,
const gl::ImageIndex &imageIndex)
{
UNREACHABLE();
return angle::Result::Stop;
}
angle::Result ExternalImageSiblingImpl11::createRenderTarget(const gl::Context *context)
{
if (mRenderTarget)
return angle::Result::Continue;
Context11 *context11 = GetImplAs<Context11>(context);
const d3d11::Format &formatInfo = mTexture.getFormatSet();
d3d11::RenderTargetView rtv;
if (mIsRenderable)
{
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
rtvDesc.Format = formatInfo.rtvFormat;
rtvDesc.ViewDimension =
mSamples == 0 ? D3D11_RTV_DIMENSION_TEXTURE2D : D3D11_RTV_DIMENSION_TEXTURE2DMS;
rtvDesc.Texture2D.MipSlice = 0;
ANGLE_TRY(mRenderer->allocateResource(context11, rtvDesc, mTexture.get(), &rtv));
rtv.setDebugName("getAttachmentRenderTarget.RTV");
}
d3d11::SharedSRV srv;
if (mIsTexturable)
{
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
srvDesc.Format = formatInfo.srvFormat;
srvDesc.ViewDimension =
mSamples == 0 ? D3D11_SRV_DIMENSION_TEXTURE2D : D3D11_SRV_DIMENSION_TEXTURE2DMS;
srvDesc.Texture2D.MostDetailedMip = 0;
srvDesc.Texture2D.MipLevels = 1;
ANGLE_TRY(mRenderer->allocateResource(context11, srvDesc, mTexture.get(), &srv));
srv.setDebugName("getAttachmentRenderTarget.SRV");
}
d3d11::SharedSRV blitSrv = srv.makeCopy();
mRenderTarget = std::make_unique<TextureRenderTarget11>(
std::move(rtv), mTexture, std::move(srv), std::move(blitSrv), formatInfo.internalFormat,
formatInfo, mSize.width, mSize.height, 1, 1);
return angle::Result::Continue;
}
} // namespace rx

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

@ -0,0 +1,59 @@
//
// Copyright 2019 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.
//
#ifndef LIBANGLE_RENDERER_D3D_D3D11_EXTERNALIMAGESIBLINGIMPL11_H_
#define LIBANGLE_RENDERER_D3D_D3D11_EXTERNALIMAGESIBLINGIMPL11_H_
#include "libANGLE/renderer/ImageImpl.h"
#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
namespace rx
{
class Renderer11;
class RenderTargetD3D;
class ExternalImageSiblingImpl11 : public ExternalImageSiblingImpl
{
public:
ExternalImageSiblingImpl11(Renderer11 *renderer, EGLClientBuffer clientBuffer);
~ExternalImageSiblingImpl11() override;
// ExternalImageSiblingImpl interface
egl::Error initialize(const egl::Display *display) override;
gl::Format getFormat() const override;
bool isRenderable(const gl::Context *context) const override;
bool isTexturable(const gl::Context *context) const override;
gl::Extents getSize() const override;
size_t getSamples() const override;
// FramebufferAttachmentObjectImpl interface
angle::Result getAttachmentRenderTarget(const gl::Context *context,
GLenum binding,
const gl::ImageIndex &imageIndex,
FramebufferAttachmentRenderTarget **rtOut) override;
angle::Result initializeContents(const gl::Context *context,
const gl::ImageIndex &imageIndex) override;
private:
angle::Result createRenderTarget(const gl::Context *context);
Renderer11 *mRenderer;
EGLClientBuffer mBuffer;
TextureHelper11 mTexture;
gl::Format mFormat;
bool mIsRenderable;
bool mIsTexturable;
gl::Extents mSize;
size_t mSamples;
std::unique_ptr<RenderTargetD3D> mRenderTarget;
};
} // namespace rx
#endif // LIBANGLE_RENDERER_D3D_D3D11_EXTERNALIMAGESIBLINGIMPL11_H_

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

@ -38,6 +38,7 @@
#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
#include "libANGLE/renderer/d3d/d3d11/Clear11.h"
#include "libANGLE/renderer/d3d/d3d11/Context11.h"
#include "libANGLE/renderer/d3d/d3d11/ExternalImageSiblingImpl11.h"
#include "libANGLE/renderer/d3d/d3d11/Fence11.h"
#include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h"
#include "libANGLE/renderer/d3d/d3d11/Image11.h"
@ -1102,6 +1103,7 @@ void Renderer11::generateDisplayExtensions(egl::DisplayExtensions *outExtensions
outExtensions->surfaceD3DTexture2DShareHandle = true;
}
outExtensions->d3dTextureClientBuffer = true;
outExtensions->imageD3D11Texture = true;
outExtensions->keyedMutex = true;
outExtensions->querySurfacePointer = true;
@ -1242,6 +1244,7 @@ egl::Error Renderer11::getD3DTextureInfo(const egl::Config *configuration,
IUnknown *d3dTexture,
EGLint *width,
EGLint *height,
EGLint *samples,
const angle::Format **angleFormat) const
{
ID3D11Texture2D *texture = d3d11::DynamicCastComObject<ID3D11Texture2D>(d3dTexture);
@ -1271,17 +1274,25 @@ egl::Error Renderer11::getD3DTextureInfo(const egl::Config *configuration,
{
*height = static_cast<EGLint>(desc.Height);
}
if (static_cast<EGLint>(desc.SampleDesc.Count) != configuration->samples)
EGLint sampleCount = static_cast<EGLint>(desc.SampleDesc.Count);
if (configuration && (configuration->samples != sampleCount))
{
// Both the texture and EGL config sample count may not be the same when multi-sampling
// is disabled. The EGL sample count can be 0 but a D3D texture is always 1. Therefore,
// we must only check for a invalid match when the EGL config is non-zero or the texture is
// not one.
if (configuration->samples != 0 || desc.SampleDesc.Count != 1)
if (configuration->samples != 0 || sampleCount != 1)
{
return egl::EglBadParameter() << "Texture's sample count does not match.";
}
}
if (samples)
{
// EGL samples 0 corresponds to D3D11 sample count 1.
*samples = sampleCount != 1 ? sampleCount : 0;
}
// From table egl.restrictions in EGL_ANGLE_d3d_texture_client_buffer.
switch (desc.Format)
{
@ -2923,6 +2934,22 @@ ImageD3D *Renderer11::createImage()
return new Image11(this);
}
ExternalImageSiblingImpl *Renderer11::createExternalImageSibling(const gl::Context *context,
EGLenum target,
EGLClientBuffer buffer,
const egl::AttributeMap &attribs)
{
switch (target)
{
case EGL_D3D11_TEXTURE_ANGLE:
return new ExternalImageSiblingImpl11(this, buffer);
default:
UNREACHABLE();
return nullptr;
}
}
angle::Result Renderer11::generateMipmap(const gl::Context *context, ImageD3D *dest, ImageD3D *src)
{
Image11 *dest11 = GetAs<Image11>(dest);

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

@ -143,6 +143,7 @@ class Renderer11 : public RendererD3D
IUnknown *d3dTexture,
EGLint *width,
EGLint *height,
EGLint *samples,
const angle::Format **angleFormat) const override;
egl::Error validateShareHandle(const egl::Config *config,
HANDLE shareHandle,
@ -249,6 +250,10 @@ class Renderer11 : public RendererD3D
// Image operations
ImageD3D *createImage() override;
ExternalImageSiblingImpl *createExternalImageSibling(const gl::Context *context,
EGLenum target,
EGLClientBuffer buffer,
const egl::AttributeMap &attribs) override;
angle::Result generateMipmap(const gl::Context *context,
ImageD3D *dest,
ImageD3D *source) override;

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

@ -392,6 +392,7 @@ class TextureHelper11 : public Resource11Base<ID3D11Resource, std::shared_ptr, G
void set(ResourceT *object, const d3d11::Format &format)
{
ASSERT(!valid());
mFormatSet = &format;
mData->object = object;
mData->manager = nullptr;

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

@ -713,10 +713,11 @@ SwapChainD3D *Renderer9::createSwapChain(NativeWindowD3D *nativeWindow,
backBufferFormat, depthBufferFormat, orientation);
}
egl::Error Renderer9::getD3DTextureInfo(const egl::Config *config,
egl::Error Renderer9::getD3DTextureInfo(const egl::Config *configuration,
IUnknown *d3dTexture,
EGLint *width,
EGLint *height,
EGLint *samples,
const angle::Format **angleFormat) const
{
IDirect3DTexture9 *texture = nullptr;
@ -747,6 +748,17 @@ egl::Error Renderer9::getD3DTextureInfo(const egl::Config *config,
*height = static_cast<EGLint>(desc.Height);
}
// GetSamplesCount() returns 0 when multisampling isn't used.
GLsizei sampleCount = d3d9_gl::GetSamplesCount(desc.MultiSampleType);
if ((configuration && configuration->samples > 1) || sampleCount != 0)
{
return egl::EglBadParameter() << "Multisampling not supported for client buffer texture";
}
if (samples)
{
*samples = static_cast<EGLint>(sampleCount);
}
// From table egl.restrictions in EGL_ANGLE_d3d_texture_client_buffer.
switch (desc.Format)
{
@ -2780,6 +2792,15 @@ ImageD3D *Renderer9::createImage()
return new Image9(this);
}
ExternalImageSiblingImpl *Renderer9::createExternalImageSibling(const gl::Context *context,
EGLenum target,
EGLClientBuffer buffer,
const egl::AttributeMap &attribs)
{
UNREACHABLE();
return nullptr;
}
angle::Result Renderer9::generateMipmap(const gl::Context *context, ImageD3D *dest, ImageD3D *src)
{
Image9 *src9 = GetAs<Image9>(src);

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

@ -98,6 +98,7 @@ class Renderer9 : public RendererD3D
IUnknown *d3dTexture,
EGLint *width,
EGLint *height,
EGLint *samples,
const angle::Format **angleFormat) const override;
egl::Error validateShareHandle(const egl::Config *config,
HANDLE shareHandle,
@ -274,6 +275,10 @@ class Renderer9 : public RendererD3D
// Image operations
ImageD3D *createImage() override;
ExternalImageSiblingImpl *createExternalImageSibling(const gl::Context *context,
EGLenum target,
EGLClientBuffer buffer,
const egl::AttributeMap &attribs) override;
angle::Result generateMipmap(const gl::Context *context,
ImageD3D *dest,
ImageD3D *source) override;

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

@ -2071,6 +2071,20 @@ Error ValidateCreateImage(const Display *display,
}
break;
case EGL_D3D11_TEXTURE_ANGLE:
if (!displayExtensions.imageD3D11Texture)
{
return EglBadParameter() << "EGL_ANGLE_image_d3d11_texture not supported.";
}
if (context != nullptr)
{
return EglBadContext() << "ctx must be EGL_NO_CONTEXT.";
}
ANGLE_TRY(display->validateImageClientBuffer(context, target, buffer, attributes));
break;
default:
return EglBadParameter()
<< "invalid target: 0x" << std::hex << std::uppercase << target;

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

@ -479,6 +479,8 @@ libangle_d3d11_sources = [
"src/libANGLE/renderer/d3d/d3d11/dxgi_format_map_autogen.cpp",
"src/libANGLE/renderer/d3d/d3d11/dxgi_support_table_autogen.cpp",
"src/libANGLE/renderer/d3d/d3d11/dxgi_support_table.h",
"src/libANGLE/renderer/d3d/d3d11/ExternalImageSiblingImpl11.cpp",
"src/libANGLE/renderer/d3d/d3d11/ExternalImageSiblingImpl11.h",
"src/libANGLE/renderer/d3d/d3d11/Fence11.cpp",
"src/libANGLE/renderer/d3d/d3d11/Fence11.h",
"src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp",

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

@ -755,6 +755,7 @@ TEST_P(D3DTextureTest, Clear)
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);
@ -1196,6 +1197,111 @@ TEST_P(D3DTextureTestMS, CopyTexSubImage2DTest)
eglDestroySurface(display, pbuffer);
}
TEST_P(D3DTextureTest, ClearTextureImage)
{
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_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();
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);
glDeleteFramebuffers(1, &fbo);
glDeleteTextures(1, &texture);
d3d11_texture->Release();
}
TEST_P(D3DTextureTest, NonRenderableTextureImage)
{
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);
EXPECT_TRUE(SUCCEEDED(mD3D11Device->CreateTexture2D(&desc, nullptr, &d3d11_texture)));
const EGLint attribs[] = {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_INCOMPLETE_ATTACHMENT));
ASSERT_GL_NO_ERROR();
glDeleteFramebuffers(1, &fbo);
glDeleteTextures(1, &texture);
d3d11_texture->Release();
}
// 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(), ES2_VULKAN());