Commit 4b225c70 by Sunny Sachanandani Committed by Commit Bot

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 Change-Id: I363f739f3f05c38720f385e34c91e98fc6a622a0 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>
parent fecd1afc
...@@ -22,7 +22,7 @@ Status ...@@ -22,7 +22,7 @@ Status
Version Version
Version 5, Sep 6, 2019 Version 6, May 12, 2020
Number Number
...@@ -75,13 +75,17 @@ Additions to Chapter 2 of the EGL 1.2 Specification (EGL Operation) ...@@ -75,13 +75,17 @@ 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> 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 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 object (cast into the type EGLClientBuffer), and attributes other than
EGL_TEXTURE_INTERNAL_FORMAT_ANGLE are ignored. The width and height of EGL_TEXTURE_INTERNAL_FORMAT_ANGLE, EGL_TEXTURE_OFFSET_X_ANGLE, or
the pbuffer are determined by the width and height of <buffer>." 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 If EGL_TEXTURE_INTERNAL_FORMAT_ANGLE is specified, it is used to interpret
<buffer> according to the provided internal format. See table <buffer> according to the provided internal format. See table
egl.restrictions for acceptable texture object types and formats. egl.restrictions for acceptable texture object types and formats.
If EGL_TEXTURE_OFFSET_X_ANGLE or EGL_TEXTURE_OFFSET_Y_ANGLE are specified,
they are used to offset all rendering into the surface.
If the EGL_ANGLE_device_d3d extension is present, the provided D3D11 texture 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 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 display. If these requirements are not met, an EGL_BAD_PARAMETER error is
...@@ -122,6 +126,9 @@ Additions to Chapter 3 of the EGL 1.2 Specification (EGL Functions and Errors) ...@@ -122,6 +126,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_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. ID3D11Texture2D Usage flags must be D3D11_USAGE_DEFAULT.
Format must be Format must be
...@@ -191,8 +198,18 @@ Issues ...@@ -191,8 +198,18 @@ Issues
to GL_RGB. Images with an RGB format will ensure that the alpha channel of 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. 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.
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 Revision History
Version 6, 2020/05/12 - added support for specifying texture offsets.
Version 5, 2019/09/06 - added support for creating EGLImage. Version 5, 2019/09/06 - added support for creating EGLImage.
Version 4, 2019/04/15 - added support for DXGI_FORMAT_R10G10B10A2_UNORM. Version 4, 2019/04/15 - added support for DXGI_FORMAT_R10G10B10A2_UNORM.
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
#ifndef EGL_ANGLE_d3d_texture_client_buffer #ifndef EGL_ANGLE_d3d_texture_client_buffer
#define EGL_ANGLE_d3d_texture_client_buffer 1 #define EGL_ANGLE_d3d_texture_client_buffer 1
#define EGL_D3D_TEXTURE_ANGLE 0x33A3 #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 */ #endif /* EGL_ANGLE_d3d_texture_client_buffer */
#ifndef EGL_ANGLE_software_display #ifndef EGL_ANGLE_software_display
......
...@@ -1727,6 +1727,15 @@ bool Framebuffer::hasValidDepthStencil() const ...@@ -1727,6 +1727,15 @@ bool Framebuffer::hasValidDepthStencil() const
return mState.getDepthStencilAttachment() != nullptr; return mState.getDepthStencilAttachment() != nullptr;
} }
gl::Offset Framebuffer::getTextureOffset() const
{
if (isDefault() && getFirstColorAttachment()->getSurface())
{
return getFirstColorAttachment()->getSurface()->getTextureOffset();
}
return gl::Offset();
}
void Framebuffer::setAttachment(const Context *context, void Framebuffer::setAttachment(const Context *context,
GLenum type, GLenum type,
GLenum binding, GLenum binding,
......
...@@ -314,6 +314,11 @@ class Framebuffer final : public angle::ObserverInterface, ...@@ -314,6 +314,11 @@ class Framebuffer final : public angle::ObserverInterface,
bool hasValidDepthStencil() const; bool hasValidDepthStencil() const;
// Returns the offset into the texture backing the default framebuffer's surface if any. Returns
// zero offset otherwise. Offset is applied to scissor and viewport rects so that it applies to
// all rendering.
gl::Offset getTextureOffset() const;
angle::Result discard(const Context *context, size_t count, const GLenum *attachments); 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 invalidate(const Context *context, size_t count, const GLenum *attachments);
angle::Result invalidateSub(const Context *context, angle::Result invalidateSub(const Context *context,
......
...@@ -119,6 +119,9 @@ Surface::Surface(EGLint surfaceType, ...@@ -119,6 +119,9 @@ Surface::Surface(EGLint surfaceType,
} }
mOrientation = static_cast<EGLint>(attributes.get(EGL_SURFACE_ORIENTATION_ANGLE, 0)); 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() {} Surface::~Surface() {}
......
...@@ -178,6 +178,11 @@ class Surface : public LabeledObject, public gl::FramebufferAttachmentObject ...@@ -178,6 +178,11 @@ class Surface : public LabeledObject, public gl::FramebufferAttachmentObject
const EGLint *timestamps, const EGLint *timestamps,
EGLnsecsANDROID *values) const; 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: protected:
Surface(EGLint surfaceType, Surface(EGLint surfaceType,
const egl::Config *config, const egl::Config *config,
...@@ -235,6 +240,8 @@ class Surface : public LabeledObject, public gl::FramebufferAttachmentObject ...@@ -235,6 +240,8 @@ class Surface : public LabeledObject, public gl::FramebufferAttachmentObject
gl::Format mColorFormat; gl::Format mColorFormat;
gl::Format mDSFormat; gl::Format mDSFormat;
gl::Offset mTextureOffset;
private: private:
Error destroyImpl(const Display *display); Error destroyImpl(const Display *display);
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "common/utilities.h" #include "common/utilities.h"
#include "libANGLE/Context.h" #include "libANGLE/Context.h"
#include "libANGLE/Query.h" #include "libANGLE/Query.h"
#include "libANGLE/Surface.h"
#include "libANGLE/VertexArray.h" #include "libANGLE/VertexArray.h"
#include "libANGLE/renderer/d3d/DisplayD3D.h" #include "libANGLE/renderer/d3d/DisplayD3D.h"
#include "libANGLE/renderer/d3d/TextureD3D.h" #include "libANGLE/renderer/d3d/TextureD3D.h"
...@@ -1404,19 +1405,28 @@ angle::Result StateManager11::syncRasterizerState(const gl::Context *context, ...@@ -1404,19 +1405,28 @@ angle::Result StateManager11::syncRasterizerState(const gl::Context *context,
return angle::Result::Continue; 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->getTextureOffset();
int scissorX = scissor.x + mCurScissorOffset.x;
int scissorY = scissor.y + mCurScissorOffset.y;
if (mCurPresentPathFastEnabled) if (mCurPresentPathFastEnabled)
{ {
modifiedScissorY = mCurPresentPathFastColorBufferHeight - scissor.height - scissor.y; scissorY = mCurPresentPathFastColorBufferHeight - scissor.height - scissor.y;
} }
if (enabled) if (enabled)
{ {
D3D11_RECT rect; D3D11_RECT rect;
int x = scissor.x; int x = scissorX;
int y = modifiedScissorY; int y = scissorY;
rect.left = std::max(0, x); rect.left = std::max(0, x);
rect.top = std::max(0, y); rect.top = std::max(0, y);
rect.right = x + std::max(0, scissor.width); rect.right = x + std::max(0, scissor.width);
...@@ -1459,10 +1469,14 @@ void StateManager11::syncViewport(const gl::Context *context) ...@@ -1459,10 +1469,14 @@ void StateManager11::syncViewport(const gl::Context *context)
int dxViewportWidth = 0; int dxViewportWidth = 0;
int dxViewportHeight = 0; int dxViewportHeight = 0;
dxViewportTopLeftX = gl::clamp(viewport.x, dxMinViewportBoundsX, dxMaxViewportBoundsX); mCurViewportOffset = framebuffer->getTextureOffset();
dxViewportTopLeftY = gl::clamp(viewport.y, dxMinViewportBoundsY, dxMaxViewportBoundsY);
dxViewportWidth = gl::clamp(viewport.width, 0, dxMaxViewportBoundsX - dxViewportTopLeftX); dxViewportTopLeftX =
dxViewportHeight = gl::clamp(viewport.height, 0, dxMaxViewportBoundsY - dxViewportTopLeftY); 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; D3D11_VIEWPORT dxViewport;
dxViewport.TopLeftX = static_cast<float>(dxViewportTopLeftX); dxViewport.TopLeftX = static_cast<float>(dxViewportTopLeftX);
...@@ -1540,6 +1554,16 @@ void StateManager11::processFramebufferInvalidation(const gl::Context *context) ...@@ -1540,6 +1554,16 @@ void StateManager11::processFramebufferInvalidation(const gl::Context *context)
gl::Framebuffer *fbo = context->getState().getDrawFramebuffer(); gl::Framebuffer *fbo = context->getState().getDrawFramebuffer();
ASSERT(fbo); ASSERT(fbo);
// Dirty scissor and viewport because surface texture offset might have changed.
if (mCurViewportOffset != fbo->getTextureOffset())
{
mInternalDirtyBits.set(DIRTY_BIT_VIEWPORT_STATE);
}
if (mCurScissorOffset != fbo->getTextureOffset())
{
mInternalDirtyBits.set(DIRTY_BIT_SCISSOR_STATE);
}
// Disable the depth test/depth write if we are using a stencil-only attachment. // 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 // 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. // nor write to the unused depth part of this emulated texture.
...@@ -2269,7 +2293,7 @@ angle::Result StateManager11::updateState(const gl::Context *context, ...@@ -2269,7 +2293,7 @@ angle::Result StateManager11::updateState(const gl::Context *context,
syncViewport(context); syncViewport(context);
break; break;
case DIRTY_BIT_SCISSOR_STATE: case DIRTY_BIT_SCISSOR_STATE:
syncScissorRectangle(glState.getScissor(), glState.isScissorTestEnabled()); syncScissorRectangle(context);
break; break;
case DIRTY_BIT_RASTERIZER_STATE: case DIRTY_BIT_RASTERIZER_STATE:
ANGLE_TRY(syncRasterizerState(context, mode)); ANGLE_TRY(syncRasterizerState(context, mode));
......
...@@ -323,7 +323,7 @@ class StateManager11 final : angle::NonCopyable ...@@ -323,7 +323,7 @@ class StateManager11 final : angle::NonCopyable
angle::Result syncRasterizerState(const gl::Context *context, gl::PrimitiveMode mode); 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); void syncViewport(const gl::Context *context);
...@@ -490,6 +490,10 @@ class StateManager11 final : angle::NonCopyable ...@@ -490,6 +490,10 @@ class StateManager11 final : angle::NonCopyable
float mCurNear; float mCurNear;
float mCurFar; float mCurFar;
// Currently applied offset to viewport and scissor
gl::Offset mCurViewportOffset;
gl::Offset mCurScissorOffset;
// Things needed in viewport state // Things needed in viewport state
ShaderConstants11 mShaderConstants; ShaderConstants11 mShaderConstants;
......
...@@ -1841,12 +1841,14 @@ Error ValidateCreatePbufferFromClientBuffer(Display *display, ...@@ -1841,12 +1841,14 @@ Error ValidateCreatePbufferFromClientBuffer(Display *display,
return EglBadAttribute() << "<buftype> doesn't support texture internal format"; return EglBadAttribute() << "<buftype> doesn't support texture internal format";
} }
break; break;
case EGL_GL_COLORSPACE: case EGL_GL_COLORSPACE:
if (buftype != EGL_D3D_TEXTURE_ANGLE) if (buftype != EGL_D3D_TEXTURE_ANGLE)
{ {
return EglBadAttribute() << "<buftype> doesn't support setting GL colorspace"; return EglBadAttribute() << "<buftype> doesn't support setting GL colorspace";
} }
break; break;
case EGL_IOSURFACE_USAGE_HINT_ANGLE: case EGL_IOSURFACE_USAGE_HINT_ANGLE:
if (value & ~(EGL_IOSURFACE_READ_HINT_ANGLE | EGL_IOSURFACE_WRITE_HINT_ANGLE)) if (value & ~(EGL_IOSURFACE_READ_HINT_ANGLE | EGL_IOSURFACE_WRITE_HINT_ANGLE))
{ {
...@@ -1854,6 +1856,15 @@ Error ValidateCreatePbufferFromClientBuffer(Display *display, ...@@ -1854,6 +1856,15 @@ Error ValidateCreatePbufferFromClientBuffer(Display *display,
<< "IOSurface usage hint must only contain READ or WRITE"; << "IOSurface usage hint must only contain READ or WRITE";
} }
break; 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";
}
break;
default: default:
return EglBadAttribute(); return EglBadAttribute();
} }
......
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