Commit d188231d by Sunny Sachanandani Committed by Commit Bot

Merge surface texture offset changes to M84

This includes two CLs, cherry picked and squashed together: Add texture offset attributess for D3D texture pbuffer surfaces Add EGL_TEXTURE_OFFSET_X_ANGLE and EGL_TEXTURE_OFFSET_Y_ANGLE attributes to EGL_ANGLE_d3d_texture_client_buffer which are used to specify offsets used for rendering into the pbuffer surface backed by a D3D11 texture. Rendering with the correct offset is needed when Chrome gets a texture and offset from an external source e.g. when calling BeginDraw() on IDCompositionSurface. Bug: angleproject:2997 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2186176Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarJonah Ryan-Davis <jonahr@google.com> Commit-Queue: Sunny Sachanandani <sunnyps@chromium.org> (cherry picked from commit 4b225c70) Use surface texture offset for clears and blits https://chromium-review.googlesource.com/c/angle/angle/+/2186176 added surface texture offset attributes for D3D11 pbuffer surfaces, but the implementation didn't apply the offset to blits or clears. This CL fixes that and includes a unit test for blit, clear, and draw. Also renames textureOffset to surfaceTextureOffset throughout since it's clearer, and fixes the dcomp surface test to specify the update offset returned by dcomp BeginDraw(). Bug: angleproject:2997 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2210967 Commit-Queue: Sunny Sachanandani <sunnyps@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> (cherry picked from commit 3d5f0c82) Change-Id: If850aadedf1edaacea63113c8b6b474c156e9fa6 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2237352Reviewed-by: 's avatarSunny Sachanandani <sunnyps@chromium.org>
parent 660e3d47
......@@ -22,7 +22,7 @@ Status
Version
Version 5, Sep 6, 2019
Version 6, May 12, 2020
Number
......@@ -75,13 +75,18 @@ Additions to Chapter 2 of the EGL 1.2 Specification (EGL Operation)
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>."
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, EGL_TEXTURE_OFFSET_X_ANGLE, or
EGL_TEXTURE_OFFSET_Y_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 EGL_TEXTURE_OFFSET_X_ANGLE or EGL_TEXTURE_OFFSET_Y_ANGLE are specified,
they must be non-negative and are used to offset all rendering into the
surface including blits, clears and draws.
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
......@@ -122,6 +127,9 @@ Additions to Chapter 3 of the EGL 1.2 Specification (EGL Functions and Errors)
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE is not supported.
EGL_TEXTURE_OFFSET_X_ANGLE and EGL_TEXTURE_OFFSET_Y_ANGLE
are not supported.
ID3D11Texture2D Usage flags must be D3D11_USAGE_DEFAULT.
Format must be
......@@ -191,8 +199,19 @@ Issues
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.
5. What operations do the texture offsets affect?
RESOLVED: The texture offsets specified by EGL_TEXTURE_OFFSET_X_ANGLE and
EGL_TEXTURE_OFFSET_Y_ANGLE affect only rendering into the surface.
Specifically these affect the internal D3D viewport and scissor rect states
for draws, clears, and blits. This is needed to apply the update offset
returned by calling BeginDraw() on IDCompositionSurface, and is needed for
correct rendering in that case.
Revision History
Version 6, 2020/05/12 - added support for specifying texture offsets.
Version 5, 2019/09/06 - added support for creating EGLImage.
Version 4, 2019/04/15 - added support for DXGI_FORMAT_R10G10B10A2_UNORM.
......
......@@ -25,6 +25,8 @@
#ifndef EGL_ANGLE_d3d_texture_client_buffer
#define EGL_ANGLE_d3d_texture_client_buffer 1
#define EGL_D3D_TEXTURE_ANGLE 0x33A3
#define EGL_TEXTURE_OFFSET_X_ANGLE 0x3490
#define EGL_TEXTURE_OFFSET_Y_ANGLE 0x3491
#endif /* EGL_ANGLE_d3d_texture_client_buffer */
#ifndef EGL_ANGLE_software_display
......
......@@ -805,6 +805,8 @@ Framebuffer::Framebuffer(const Context *context, egl::Surface *surface, egl::Sur
}
SetComponentTypeMask(getDrawbufferWriteType(0), 0, &mState.mDrawBufferTypeMask);
mState.mSurfaceTextureOffset = surface->getTextureOffset();
// Ensure the backend has a chance to synchronize its content for a new backbuffer.
mDirtyBits.set(DIRTY_BIT_COLOR_BUFFER_CONTENTS_0);
}
......@@ -1727,6 +1729,11 @@ bool Framebuffer::hasValidDepthStencil() const
return mState.getDepthStencilAttachment() != nullptr;
}
const gl::Offset &Framebuffer::getSurfaceTextureOffset() const
{
return mState.getSurfaceTextureOffset();
}
void Framebuffer::setAttachment(const Context *context,
GLenum type,
GLenum binding,
......
......@@ -129,6 +129,8 @@ class FramebufferState final : angle::NonCopyable
return mDepthBufferFeedbackLoop || mStencilBufferFeedbackLoop;
}
const gl::Offset &getSurfaceTextureOffset() const { return mSurfaceTextureOffset; }
private:
const FramebufferAttachment *getWebGLDepthStencilAttachment() const;
const FramebufferAttachment *getWebGLDepthAttachment() const;
......@@ -177,6 +179,8 @@ class FramebufferState final : angle::NonCopyable
bool mDefaultFramebufferReadAttachmentInitialized;
FramebufferAttachment mDefaultFramebufferReadAttachment;
gl::Offset mSurfaceTextureOffset;
};
class Framebuffer final : public angle::ObserverInterface,
......@@ -314,6 +318,11 @@ class Framebuffer final : public angle::ObserverInterface,
bool hasValidDepthStencil() const;
// Returns the offset into the texture backing the default framebuffer's surface if any. Returns
// zero offset otherwise. The renderer will apply the offset to scissor and viewport rects used
// for draws, clears, and blits.
const gl::Offset &getSurfaceTextureOffset() const;
angle::Result discard(const Context *context, size_t count, const GLenum *attachments);
angle::Result invalidate(const Context *context, size_t count, const GLenum *attachments);
angle::Result invalidateSub(const Context *context,
......
......@@ -119,6 +119,9 @@ Surface::Surface(EGLint surfaceType,
}
mOrientation = static_cast<EGLint>(attributes.get(EGL_SURFACE_ORIENTATION_ANGLE, 0));
mTextureOffset.x = static_cast<int>(mState.attributes.get(EGL_TEXTURE_OFFSET_X_ANGLE, 0));
mTextureOffset.y = static_cast<int>(mState.attributes.get(EGL_TEXTURE_OFFSET_Y_ANGLE, 0));
}
Surface::~Surface() {}
......
......@@ -178,6 +178,11 @@ class Surface : public LabeledObject, public gl::FramebufferAttachmentObject
const EGLint *timestamps,
EGLnsecsANDROID *values) const;
// Returns the offset into the texture backing the surface if specified via texture offset
// attributes (see EGL_ANGLE_d3d_texture_client_buffer extension). Returns zero offset
// otherwise.
const gl::Offset &getTextureOffset() const { return mTextureOffset; }
protected:
Surface(EGLint surfaceType,
const egl::Config *config,
......@@ -235,6 +240,8 @@ class Surface : public LabeledObject, public gl::FramebufferAttachmentObject
gl::Format mColorFormat;
gl::Format mDSFormat;
gl::Offset mTextureOffset;
private:
Error destroyImpl(const Display *display);
......
......@@ -43,10 +43,24 @@ ClearParameters GetClearParameters(const gl::State &state, GLbitfield mask)
clearParams.clearStencil = false;
clearParams.stencilValue = state.getStencilClearValue();
clearParams.stencilWriteMask = state.getDepthStencilState().stencilWritemask;
clearParams.scissorEnabled = state.isScissorTestEnabled();
clearParams.scissor = state.getScissor();
const gl::Framebuffer *framebufferObject = state.getDrawFramebuffer();
const auto *framebufferObject = state.getDrawFramebuffer();
const gl::Extents &framebufferSize = framebufferObject->getFirstNonNullAttachment()->getSize();
const gl::Offset &surfaceTextureOffset = framebufferObject->getSurfaceTextureOffset();
if (state.isScissorTestEnabled())
{
clearParams.scissorEnabled = true;
clearParams.scissor = state.getScissor();
clearParams.scissor.x = clearParams.scissor.x + surfaceTextureOffset.x;
clearParams.scissor.y = clearParams.scissor.y + surfaceTextureOffset.y;
}
else if (surfaceTextureOffset != gl::kOffsetZero)
{
clearParams.scissorEnabled = true;
clearParams.scissor = gl::Rectangle(surfaceTextureOffset.x, surfaceTextureOffset.y,
framebufferSize.width, framebufferSize.height);
}
const bool clearColor =
(mask & GL_COLOR_BUFFER_BIT) && framebufferObject->hasEnabledDrawBuffer();
ASSERT(blendStateArray.size() == gl::IMPLEMENTATION_MAX_DRAW_BUFFERS);
......
......@@ -318,6 +318,11 @@ angle::Result Framebuffer11::blitImpl(const gl::Context *context,
const bool invertColorDest = UsePresentPathFast(mRenderer, &drawBuffer);
gl::Rectangle actualDestArea = destArea;
const auto &surfaceTextureOffset = mState.getSurfaceTextureOffset();
actualDestArea.x = actualDestArea.x + surfaceTextureOffset.x;
actualDestArea.y = actualDestArea.y + surfaceTextureOffset.y;
if (invertColorDest)
{
RenderTarget11 *drawRenderTarget11 = GetAs<RenderTarget11>(drawRenderTarget);
......
......@@ -14,6 +14,7 @@
#include "common/utilities.h"
#include "libANGLE/Context.h"
#include "libANGLE/Query.h"
#include "libANGLE/Surface.h"
#include "libANGLE/VertexArray.h"
#include "libANGLE/renderer/d3d/DisplayD3D.h"
#include "libANGLE/renderer/d3d/TextureD3D.h"
......@@ -1404,19 +1405,28 @@ angle::Result StateManager11::syncRasterizerState(const gl::Context *context,
return angle::Result::Continue;
}
void StateManager11::syncScissorRectangle(const gl::Rectangle &scissor, bool enabled)
void StateManager11::syncScissorRectangle(const gl::Context *context)
{
int modifiedScissorY = scissor.y;
const auto &glState = context->getState();
gl::Framebuffer *framebuffer = glState.getDrawFramebuffer();
const gl::Rectangle &scissor = glState.getScissor();
const bool enabled = glState.isScissorTestEnabled();
mCurScissorOffset = framebuffer->getSurfaceTextureOffset();
int scissorX = scissor.x + mCurScissorOffset.x;
int scissorY = scissor.y + mCurScissorOffset.y;
if (mCurPresentPathFastEnabled)
{
modifiedScissorY = mCurPresentPathFastColorBufferHeight - scissor.height - scissor.y;
scissorY = mCurPresentPathFastColorBufferHeight - scissor.height - scissor.y;
}
if (enabled)
{
D3D11_RECT rect;
int x = scissor.x;
int y = modifiedScissorY;
int x = scissorX;
int y = scissorY;
rect.left = std::max(0, x);
rect.top = std::max(0, y);
rect.right = x + std::max(0, scissor.width);
......@@ -1459,10 +1469,14 @@ void StateManager11::syncViewport(const gl::Context *context)
int dxViewportWidth = 0;
int dxViewportHeight = 0;
dxViewportTopLeftX = gl::clamp(viewport.x, dxMinViewportBoundsX, dxMaxViewportBoundsX);
dxViewportTopLeftY = gl::clamp(viewport.y, dxMinViewportBoundsY, dxMaxViewportBoundsY);
dxViewportWidth = gl::clamp(viewport.width, 0, dxMaxViewportBoundsX - dxViewportTopLeftX);
dxViewportHeight = gl::clamp(viewport.height, 0, dxMaxViewportBoundsY - dxViewportTopLeftY);
mCurViewportOffset = framebuffer->getSurfaceTextureOffset();
dxViewportTopLeftX =
gl::clamp(viewport.x + mCurViewportOffset.x, dxMinViewportBoundsX, dxMaxViewportBoundsX);
dxViewportTopLeftY =
gl::clamp(viewport.y + mCurViewportOffset.y, dxMinViewportBoundsY, dxMaxViewportBoundsY);
dxViewportWidth = gl::clamp(viewport.width, 0, dxMaxViewportBoundsX - dxViewportTopLeftX);
dxViewportHeight = gl::clamp(viewport.height, 0, dxMaxViewportBoundsY - dxViewportTopLeftY);
D3D11_VIEWPORT dxViewport;
dxViewport.TopLeftX = static_cast<float>(dxViewportTopLeftX);
......@@ -1540,6 +1554,16 @@ void StateManager11::processFramebufferInvalidation(const gl::Context *context)
gl::Framebuffer *fbo = context->getState().getDrawFramebuffer();
ASSERT(fbo);
// Dirty scissor and viewport because surface texture offset might have changed.
if (mCurViewportOffset != fbo->getSurfaceTextureOffset())
{
mInternalDirtyBits.set(DIRTY_BIT_VIEWPORT_STATE);
}
if (mCurScissorOffset != fbo->getSurfaceTextureOffset())
{
mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE);
}
// Disable the depth test/depth write if we are using a stencil-only attachment.
// This is because ANGLE emulates stencil-only with D24S8 on D3D11 - we should neither read
// nor write to the unused depth part of this emulated texture.
......@@ -2269,7 +2293,7 @@ angle::Result StateManager11::updateState(const gl::Context *context,
syncViewport(context);
break;
case DIRTY_BIT_SCISSOR_STATE:
syncScissorRectangle(glState.getScissor(), glState.isScissorTestEnabled());
syncScissorRectangle(context);
break;
case DIRTY_BIT_RASTERIZER_STATE:
ANGLE_TRY(syncRasterizerState(context, mode));
......
......@@ -323,7 +323,7 @@ class StateManager11 final : angle::NonCopyable
angle::Result syncRasterizerState(const gl::Context *context, gl::PrimitiveMode mode);
void syncScissorRectangle(const gl::Rectangle &scissor, bool enabled);
void syncScissorRectangle(const gl::Context *context);
void syncViewport(const gl::Context *context);
......@@ -490,6 +490,10 @@ class StateManager11 final : angle::NonCopyable
float mCurNear;
float mCurFar;
// Currently applied offset to viewport and scissor
gl::Offset mCurViewportOffset;
gl::Offset mCurScissorOffset;
// Things needed in viewport state
ShaderConstants11 mShaderConstants;
......
......@@ -1841,12 +1841,14 @@ Error ValidateCreatePbufferFromClientBuffer(Display *display,
return EglBadAttribute() << "<buftype> doesn't support texture internal format";
}
break;
case EGL_GL_COLORSPACE:
if (buftype != EGL_D3D_TEXTURE_ANGLE)
{
return EglBadAttribute() << "<buftype> doesn't support setting GL colorspace";
}
break;
case EGL_IOSURFACE_USAGE_HINT_ANGLE:
if (value & ~(EGL_IOSURFACE_READ_HINT_ANGLE | EGL_IOSURFACE_WRITE_HINT_ANGLE))
{
......@@ -1854,6 +1856,19 @@ Error ValidateCreatePbufferFromClientBuffer(Display *display,
<< "IOSurface usage hint must only contain READ or WRITE";
}
break;
case EGL_TEXTURE_OFFSET_X_ANGLE:
case EGL_TEXTURE_OFFSET_Y_ANGLE:
if (buftype != EGL_D3D_TEXTURE_ANGLE)
{
return EglBadAttribute() << "<buftype> doesn't support setting texture offset";
}
if (value < 0)
{
return EglBadAttribute() << "Texture offset cannot be negative";
}
break;
default:
return EglBadAttribute();
}
......
......@@ -11,6 +11,7 @@
#include <vector>
#include "common/Color.h"
#include "common/platform.h"
#include "test_utils/ANGLETest.h"
#include "util/EGLWindow.h"
......@@ -852,7 +853,17 @@ TEST_P(EGLSurfaceTestD3D11, CreateDirectCompositionSurface)
EGLConfig config;
ASSERT_EGL_TRUE(EGLWindow::FindEGLConfig(mDisplay, configAttributes, &config));
const EGLint surfaceAttributes[] = {EGL_WIDTH, 64, EGL_HEIGHT, 64, EGL_NONE};
const EGLint surfaceAttributes[] = {EGL_WIDTH,
100,
EGL_HEIGHT,
100,
EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE,
EGL_TRUE,
EGL_TEXTURE_OFFSET_X_ANGLE,
updateOffset.x,
EGL_TEXTURE_OFFSET_Y_ANGLE,
updateOffset.y,
EGL_NONE};
EGLClientBuffer buffer = reinterpret_cast<EGLClientBuffer>(texture.Get());
mPbufferSurface = eglCreatePbufferFromClientBuffer(mDisplay, EGL_D3D_TEXTURE_ANGLE, buffer,
......@@ -872,6 +883,136 @@ TEST_P(EGLSurfaceTestD3D11, CreateDirectCompositionSurface)
glDeleteProgram(program);
}
TEST_P(EGLSurfaceTestD3D11, CreateSurfaceWithTextureOffset)
{
ANGLE_SKIP_TEST_IF(!IsEGLClientExtensionEnabled("EGL_ANGLE_platform_angle_d3d"));
initializeDisplay();
const EGLint configAttributes[] = {
EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 8,
EGL_DEPTH_SIZE, 0, EGL_STENCIL_SIZE, 0, EGL_SAMPLE_BUFFERS, 0, EGL_NONE};
EGLConfig config;
ASSERT_EGL_TRUE(EGLWindow::FindEGLConfig(mDisplay, configAttributes, &config));
mConfig = config;
initializeContext();
EGLAttrib device = 0;
EGLAttrib newEglDevice = 0;
ASSERT_EGL_TRUE(eglQueryDisplayAttribEXT(mDisplay, EGL_DEVICE_EXT, &newEglDevice));
ASSERT_EGL_TRUE(eglQueryDeviceAttribEXT(reinterpret_cast<EGLDeviceEXT>(newEglDevice),
EGL_D3D11_DEVICE_ANGLE, &device));
angle::ComPtr<ID3D11Device> d3d11Device(reinterpret_cast<ID3D11Device *>(device));
ASSERT_TRUE(!!d3d11Device);
constexpr UINT kTextureWidth = 100;
constexpr UINT kTextureHeight = 100;
constexpr Color<uint8_t> kOpaqueBlack(0, 0, 0, 255);
std::vector<Color<uint8_t>> textureData(kTextureWidth * kTextureHeight, kOpaqueBlack);
D3D11_SUBRESOURCE_DATA initialData = {};
initialData.pSysMem = textureData.data();
initialData.SysMemPitch = kTextureWidth * sizeof(kOpaqueBlack);
D3D11_TEXTURE2D_DESC desc = {};
desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
desc.Width = kTextureWidth;
desc.Height = kTextureHeight;
desc.ArraySize = 1;
desc.MipLevels = 1;
desc.SampleDesc.Count = 1;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_RENDER_TARGET;
angle::ComPtr<ID3D11Texture2D> texture;
HRESULT hr = d3d11Device->CreateTexture2D(&desc, &initialData, &texture);
ASSERT_TRUE(SUCCEEDED(hr));
angle::ComPtr<ID3D11DeviceContext> d3d11Context;
d3d11Device->GetImmediateContext(&d3d11Context);
// Specify a texture offset of (50, 50) when rendering to the pbuffer surface.
const EGLint surfaceAttributes[] = {EGL_WIDTH,
kTextureWidth,
EGL_HEIGHT,
kTextureHeight,
EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE,
EGL_TRUE,
EGL_TEXTURE_OFFSET_X_ANGLE,
50,
EGL_TEXTURE_OFFSET_Y_ANGLE,
50,
EGL_NONE};
EGLClientBuffer buffer = reinterpret_cast<EGLClientBuffer>(texture.Get());
mPbufferSurface = eglCreatePbufferFromClientBuffer(mDisplay, EGL_D3D_TEXTURE_ANGLE, buffer,
config, surfaceAttributes);
ASSERT_EGL_SUCCESS();
eglMakeCurrent(mDisplay, mPbufferSurface, mPbufferSurface, mContext);
ASSERT_EGL_SUCCESS();
// glClear should only clear subrect at offset (50, 50) without explicit scissor.
glClearColor(0, 0, 1, 1); // Blue
glClear(GL_COLOR_BUFFER_BIT);
EXPECT_PIXEL_EQ(25, 25, 0, 0, 0, 255);
EXPECT_PIXEL_EQ(75, 75, 0, 0, 255, 255);
EXPECT_GL_NO_ERROR();
// Drawing with a shader should also update the same subrect only without explicit viewport.
GLuint program = createProgram(); // Red
ASSERT_NE(0u, program);
GLint positionLocation = glGetAttribLocation(program, angle::essl1_shaders::PositionAttrib());
glUseProgram(program);
const GLfloat vertices[] = {
-1.0f, 1.0f, 0.5f, -1.0f, -1.0f, 0.5f, 1.0f, -1.0f, 0.5f,
-1.0f, 1.0f, 0.5f, 1.0f, -1.0f, 0.5f, 1.0f, 1.0f, 0.5f,
};
glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, vertices);
glEnableVertexAttribArray(positionLocation);
glDrawArrays(GL_TRIANGLES, 0, 6);
glDisableVertexAttribArray(positionLocation);
glVertexAttribPointer(positionLocation, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
EXPECT_PIXEL_EQ(25, 25, 0, 0, 0, 255);
EXPECT_PIXEL_EQ(75, 75, 255, 0, 0, 255);
EXPECT_GL_NO_ERROR();
glDeleteProgram(program);
EXPECT_GL_NO_ERROR();
// Blit framebuffer should also blit to the same subrect despite the dstX/Y arguments.
GLuint renderBuffer = 0;
glGenRenderbuffers(1u, &renderBuffer);
glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 50, 50);
EXPECT_GL_NO_ERROR();
GLuint framebuffer = 0;
glGenFramebuffers(1u, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderBuffer);
EXPECT_GL_NO_ERROR();
glClearColor(0, 1, 0, 1); // Green
glClear(GL_COLOR_BUFFER_BIT);
EXPECT_PIXEL_EQ(25, 25, 0, 255, 0, 255);
EXPECT_GL_NO_ERROR();
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0u);
glBindFramebuffer(GL_READ_FRAMEBUFFER, framebuffer);
glBlitFramebuffer(0, 0, 50, 50, 0, 0, 50, 50, GL_COLOR_BUFFER_BIT, GL_NEAREST);
EXPECT_GL_NO_ERROR();
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0u);
EXPECT_PIXEL_EQ(25, 25, 0, 0, 0, 255);
EXPECT_PIXEL_EQ(75, 75, 0, 255, 0, 255);
EXPECT_GL_NO_ERROR();
glDeleteFramebuffers(1u, &framebuffer);
glDeleteRenderbuffers(1u, &renderBuffer);
EXPECT_GL_NO_ERROR();
}
TEST_P(EGLSurfaceTestD3D11, CreateSurfaceWithMSAA)
{
ANGLE_SKIP_TEST_IF(!IsEGLClientExtensionEnabled("EGL_ANGLE_platform_angle_d3d"));
......
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