Commit 03d132eb by LRN Committed by Commit Bot

Support EGL_(WIDTH|HEIGHT) in eglSurfaceAttrib(), fixed resize

Setting EGL_WIDTH or EGL_HEIGHT results in mFixedWidth and mFixedHeight changing their values. Whenever the swap chain is tested for needing a resize, surfaces with mFixedSize are treated as if they should be resized to mFixedWidth and mFixedHeight from their current size. This way fixed-size surfaces can be resized - it's enough to do a couple of eglSurfaceAttrib() calls and then either let ANGLE check surface for needing a resize in due course, or force that by calling eglWaitNative(). BUG=angleproject:2725 Change-Id: I2932d8ecd5a2f10500e4aa8583a169aa09bf01bb Reviewed-on: https://chromium-review.googlesource.com/1139055 Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 854429de
...@@ -51,3 +51,4 @@ Nickolay Artamonov ...@@ -51,3 +51,4 @@ Nickolay Artamonov
Ihsan Akmal Ihsan Akmal
Andrei Volykhin Andrei Volykhin
Jérôme Duval Jérôme Duval
Руслан Ижбулатов
...@@ -10,6 +10,7 @@ Contributors ...@@ -10,6 +10,7 @@ Contributors
John Bauman John Bauman
Shannon Woods Shannon Woods
Geoff Lang
Contacts Contacts
...@@ -21,7 +22,7 @@ Status ...@@ -21,7 +22,7 @@ Status
Version Version
Version 4, February 24, 2014 Version 5, July 23, 2018
Number Number
...@@ -34,8 +35,8 @@ Dependencies ...@@ -34,8 +35,8 @@ Dependencies
Overview Overview
This extension allows creating a window surface with a fixed size that is This extension allows creating a window surface that does not resize
specified when it is created. automatically.
New Types New Types
...@@ -54,7 +55,8 @@ New Tokens ...@@ -54,7 +55,8 @@ New Tokens
Additions to Chapter 3 of the EGL 1.4 Specification: Additions to Chapter 3 of the EGL 1.4 Specification:
Modify the third paragraph of Section 3.5.1 (Creating On-Screen Rendering Surfaces) Modify the third paragraph of Section 3.5.1 (Creating On-Screen Rendering
Surfaces)
"<attrib_list> specifies a list of attributes for the window. The list has "<attrib_list> specifies a list of attributes for the window. The list has
the same structure as described for eglChooseConfig. Attributes that can the same structure as described for eglChooseConfig. Attributes that can
...@@ -71,15 +73,14 @@ Additions to Chapter 3 of the EGL 1.4 Specification: ...@@ -71,15 +73,14 @@ Additions to Chapter 3 of the EGL 1.4 Specification:
is taken from the native window. Its default value is EGL_FALSE. is taken from the native window. Its default value is EGL_FALSE.
If the value of EGL_FIXED_SIZE_ANGLE is EGL_TRUE, the window surface's If the value of EGL_FIXED_SIZE_ANGLE is EGL_TRUE, the window surface's
size in pixels is specified by the EGL_WIDTH and EGL_HEIGHT attributes, size in pixels is specified by the EGL_WIDTH and EGL_HEIGHT attributes.
and will not change throughout the lifetime of the surface. If its value If its value is EGL_FALSE, then the values of EGL_WIDTH and EGL_HEIGHT
is EGL_FALSE, then the values of EGL_WIDTH and EGL_HEIGHT are ignored and are ignored and the window surface must be resized by the implementation
the window surface must be resized by the implementation subsequent to the subsequent to the native window being resized, and prior to copying its
native window being resized, and prior to copying its contents to the contents to the native window (e.g. in eglSwapBuffers, as described in
native window (e.g. in eglSwapBuffers, as described in section 3.9.1.1). section 3.9.1.1). The default values for EGL_WIDTH and EGL_HEIGHT are zero.
The default values for EGL_WIDTH and EGL_HEIGHT are zero. If the value If the value specified for either of EGL_WIDTH or EGL_HEIGHT is less than
specified for either of EGL_WIDTH or EGL_HEIGHT is less than zero then an zero then an EGL_BAD_PARAMETER error is generated."
EGL_BAD_PARAMETER error is generated."
Add the following entry to Table 3.5 Add the following entry to Table 3.5
(Queryable surface attributes and types) (Queryable surface attributes and types)
...@@ -102,6 +103,21 @@ Additions to Chapter 3 of the EGL 1.4 Specification: ...@@ -102,6 +103,21 @@ Additions to Chapter 3 of the EGL 1.4 Specification:
yet resized the window surface, the size returned by eglQuerySurface will yet resized the window surface, the size returned by eglQuerySurface will
always be that of the EGL surface, not the corresponding native window." always be that of the EGL surface, not the corresponding native window."
Alter the beginning of the first paragraph of Section 3.5.6 (Surface
Attributes)
"The specified attribute of surface is set to value. Attributes that can
be specified are EGL_MIPMAP_LEVEL, EGL_MULTISAMPLE_RESOLVE,
EGL_SWAP_BEHAVIOR, EGL_WIDTH, and EGL_HEIGHT."
Add the following paragraph to Section 3.5.6 (Surface Attributes)
"If attribute is EGL_WIDTH or EGL_HEIGHT then the value specifies the new
surface width or height respectively. The new width and height are not
guarenteed to be applied until the next call to eglSwapBuffers or
eglWaitNative. If the surface does not have EGL_FIXED_SIZE_ANGLE set then
an EGL_BAD_MATCH error is generated."
Add the following paragraph to Section 3.5.6 (Surface Attributes) Add the following paragraph to Section 3.5.6 (Surface Attributes)
"Querying EGL_FIXED_SIZE_ANGLE returns EGL_FALSE if the surface will be "Querying EGL_FIXED_SIZE_ANGLE returns EGL_FALSE if the surface will be
...@@ -111,9 +127,10 @@ Additions to Chapter 3 of the EGL 1.4 Specification: ...@@ -111,9 +127,10 @@ Additions to Chapter 3 of the EGL 1.4 Specification:
Alter the beginning of the first paragraph of Section 3.9.1.1 (Native Alter the beginning of the first paragraph of Section 3.9.1.1 (Native
Window Resizing) Window Resizing)
"If <surface> does not have EGL_FIXED_SIZE_ANGLE set and the native window "If the surface has EGL_FIXED_SIZE_ANGLE set and EGL_WIDTH or EGL_HEIGHT
corresponding to <surface> has been resized prior to the swap, <surface> have changed or the surface does not have EGL_FIXED_SIZE_ANGLE set and its
must be resized to match." corresponding native window has been resized prior to the swap, surface
must be resized to match".
Issues Issues
...@@ -123,8 +140,15 @@ Issues ...@@ -123,8 +140,15 @@ Issues
RESOLVED: No. Surfaces that have their sizes specified initially must have RESOLVED: No. Surfaces that have their sizes specified initially must have
EGL_FIXED_SIZE_ANGLE set and can never be resized. EGL_FIXED_SIZE_ANGLE set and can never be resized.
RESOLVED(rev 5): Fixed size surfaces can now be resized by setting
EGL_WIDTH and EGL_HEIGHT surface attributes. This is the best way to give
users explicit control of the size of window surfaces without re-creating
them on each resize.
Revision History Revision History
Version 5, 2018/07/23 - Allow reizing fixed size surfaces.
Version 4, 2014/02/24 - formatting changes. Version 4, 2014/02/24 - formatting changes.
Version 3, 2014/02/12 - ignore EGL_WIDTH and EGL_HEIGHT if Version 3, 2014/02/12 - ignore EGL_WIDTH and EGL_HEIGHT if
......
...@@ -289,6 +289,18 @@ void Surface::setSwapBehavior(EGLenum behavior) ...@@ -289,6 +289,18 @@ void Surface::setSwapBehavior(EGLenum behavior)
mSwapBehavior = behavior; mSwapBehavior = behavior;
} }
void Surface::setFixedWidth(EGLint width)
{
mFixedWidth = width;
mImplementation->setFixedWidth(width);
}
void Surface::setFixedHeight(EGLint height)
{
mFixedHeight = height;
mImplementation->setFixedHeight(height);
}
const Config *Surface::getConfig() const const Config *Surface::getConfig() const
{ {
return mState.config; return mState.config;
......
...@@ -84,6 +84,9 @@ class Surface : public LabeledObject, public gl::FramebufferAttachmentObject ...@@ -84,6 +84,9 @@ class Surface : public LabeledObject, public gl::FramebufferAttachmentObject
void setMultisampleResolve(EGLenum resolve); void setMultisampleResolve(EGLenum resolve);
void setSwapBehavior(EGLenum behavior); void setSwapBehavior(EGLenum behavior);
void setFixedWidth(EGLint width);
void setFixedHeight(EGLint height);
gl::Framebuffer *createDefaultFramebuffer(const gl::Context *context); gl::Framebuffer *createDefaultFramebuffer(const gl::Context *context);
const Config *getConfig() const; const Config *getConfig() const;
......
...@@ -2828,6 +2828,12 @@ void SetSurfaceAttrib(Surface *surface, EGLint attribute, EGLint value) ...@@ -2828,6 +2828,12 @@ void SetSurfaceAttrib(Surface *surface, EGLint attribute, EGLint value)
case EGL_SWAP_BEHAVIOR: case EGL_SWAP_BEHAVIOR:
surface->setSwapBehavior(value); surface->setSwapBehavior(value);
break; break;
case EGL_WIDTH:
surface->setFixedWidth(value);
break;
case EGL_HEIGHT:
surface->setFixedHeight(value);
break;
default: default:
UNREACHABLE(); UNREACHABLE();
break; break;
......
...@@ -31,4 +31,14 @@ egl::Error SurfaceImpl::setPresentationTime(EGLnsecsANDROID time) ...@@ -31,4 +31,14 @@ egl::Error SurfaceImpl::setPresentationTime(EGLnsecsANDROID time)
return egl::EglBadSurface() << "setPresentationTime implementation missing."; return egl::EglBadSurface() << "setPresentationTime implementation missing.";
} }
void SurfaceImpl::setFixedWidth(EGLint width)
{
UNREACHABLE();
}
void SurfaceImpl::setFixedHeight(EGLint height)
{
UNREACHABLE();
}
} // namespace rx } // namespace rx
...@@ -65,6 +65,8 @@ class SurfaceImpl : public FramebufferAttachmentObjectImpl ...@@ -65,6 +65,8 @@ class SurfaceImpl : public FramebufferAttachmentObjectImpl
virtual egl::Error releaseTexImage(const gl::Context *context, EGLint buffer) = 0; virtual egl::Error releaseTexImage(const gl::Context *context, EGLint buffer) = 0;
virtual egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) = 0; virtual egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) = 0;
virtual void setSwapInterval(EGLint interval) = 0; virtual void setSwapInterval(EGLint interval) = 0;
virtual void setFixedWidth(EGLint width);
virtual void setFixedHeight(EGLint height);
// width and height can change with client window resizing // width and height can change with client window resizing
virtual EGLint getWidth() const = 0; virtual EGLint getWidth() const = 0;
......
...@@ -36,6 +36,8 @@ SurfaceD3D::SurfaceD3D(const egl::SurfaceState &state, ...@@ -36,6 +36,8 @@ SurfaceD3D::SurfaceD3D(const egl::SurfaceState &state,
mRenderer(renderer), mRenderer(renderer),
mDisplay(display), mDisplay(display),
mFixedSize(window == nullptr || attribs.get(EGL_FIXED_SIZE_ANGLE, EGL_FALSE) == EGL_TRUE), mFixedSize(window == nullptr || attribs.get(EGL_FIXED_SIZE_ANGLE, EGL_FALSE) == EGL_TRUE),
mFixedWidth(0),
mFixedHeight(0),
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),
...@@ -56,6 +58,12 @@ SurfaceD3D::SurfaceD3D(const egl::SurfaceState &state, ...@@ -56,6 +58,12 @@ SurfaceD3D::SurfaceD3D(const egl::SurfaceState &state,
mHeight = -1; mHeight = -1;
} }
if (mFixedSize)
{
mFixedWidth = mWidth;
mFixedHeight = mHeight;
}
switch (buftype) switch (buftype)
{ {
case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE: case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
...@@ -97,8 +105,8 @@ egl::Error SurfaceD3D::initialize(const egl::Display *display) ...@@ -97,8 +105,8 @@ egl::Error SurfaceD3D::initialize(const egl::Display *display)
if (mBuftype == EGL_D3D_TEXTURE_ANGLE) if (mBuftype == EGL_D3D_TEXTURE_ANGLE)
{ {
ANGLE_TRY(mRenderer->getD3DTextureInfo(mState.config, mD3DTexture, &mWidth, &mHeight, ANGLE_TRY(mRenderer->getD3DTextureInfo(mState.config, mD3DTexture, &mFixedWidth,
&mColorFormat)); &mFixedHeight, &mColorFormat));
if (mState.attributes.contains(EGL_GL_COLORSPACE)) if (mState.attributes.contains(EGL_GL_COLORSPACE))
{ {
if (mColorFormat->id != angle::FormatID::R8G8B8A8_TYPELESS && if (mColorFormat->id != angle::FormatID::R8G8B8A8_TYPELESS &&
...@@ -177,8 +185,8 @@ egl::Error SurfaceD3D::resetSwapChain(const egl::Display *display) ...@@ -177,8 +185,8 @@ egl::Error SurfaceD3D::resetSwapChain(const egl::Display *display)
else else
{ {
// non-window surface - size is determined at creation // non-window surface - size is determined at creation
width = mWidth; width = mFixedWidth;
height = mHeight; height = mFixedHeight;
} }
mSwapChain = mSwapChain =
...@@ -317,6 +325,12 @@ egl::Error SurfaceD3D::checkForOutOfDateSwapChain(DisplayD3D *displayD3D) ...@@ -317,6 +325,12 @@ egl::Error SurfaceD3D::checkForOutOfDateSwapChain(DisplayD3D *displayD3D)
clientHeight = client.bottom - client.top; clientHeight = client.bottom - client.top;
sizeDirty = clientWidth != getWidth() || clientHeight != getHeight(); sizeDirty = clientWidth != getWidth() || clientHeight != getHeight();
} }
else if (mFixedSize)
{
clientWidth = mFixedWidth;
clientHeight = mFixedHeight;
sizeDirty = mFixedWidth != getWidth() || mFixedHeight != getHeight();
}
if (mSwapIntervalDirty) if (mSwapIntervalDirty)
{ {
...@@ -362,6 +376,16 @@ void SurfaceD3D::setSwapInterval(EGLint interval) ...@@ -362,6 +376,16 @@ void SurfaceD3D::setSwapInterval(EGLint interval)
mSwapIntervalDirty = true; mSwapIntervalDirty = true;
} }
void SurfaceD3D::setFixedWidth(EGLint width)
{
mFixedWidth = width;
}
void SurfaceD3D::setFixedHeight(EGLint height)
{
mFixedHeight = height;
}
EGLint SurfaceD3D::getWidth() const EGLint SurfaceD3D::getWidth() const
{ {
return mWidth; return mWidth;
......
...@@ -46,6 +46,8 @@ class SurfaceD3D : public SurfaceImpl ...@@ -46,6 +46,8 @@ class SurfaceD3D : public SurfaceImpl
egl::Error releaseTexImage(const gl::Context *context, EGLint buffer) override; egl::Error releaseTexImage(const gl::Context *context, EGLint buffer) override;
egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) override; egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) override;
void setSwapInterval(EGLint interval) override; void setSwapInterval(EGLint interval) override;
void setFixedWidth(EGLint width) override;
void setFixedHeight(EGLint height) override;
EGLint getWidth() const override; EGLint getWidth() const override;
EGLint getHeight() const override; EGLint getHeight() const override;
...@@ -86,6 +88,8 @@ class SurfaceD3D : public SurfaceImpl ...@@ -86,6 +88,8 @@ class SurfaceD3D : public SurfaceImpl
egl::Display *mDisplay; egl::Display *mDisplay;
bool mFixedSize; bool mFixedSize;
GLint mFixedWidth;
GLint mFixedHeight;
GLint mOrientation; GLint mOrientation;
GLenum mRenderTargetFormat; GLenum mRenderTargetFormat;
......
...@@ -2782,6 +2782,20 @@ Error ValidateSurfaceAttrib(const Display *display, ...@@ -2782,6 +2782,20 @@ Error ValidateSurfaceAttrib(const Display *display,
} }
break; break;
case EGL_WIDTH:
case EGL_HEIGHT:
if (!display->getExtensions().windowFixedSize)
{
return EglBadAttribute() << "EGL_WIDTH or EGL_HEIGHT cannot be set without "
"EGL_ANGLE_window_fixed_size support.";
}
if (!surface->isFixedSize())
{
return EglBadMatch() << "EGL_WIDTH or EGL_HEIGHT cannot be set without "
"EGL_FIXED_SIZE_ANGLE being enabled on the surface.";
}
break;
default: default:
return EglBadAttribute() << "Invalid surface attribute."; return EglBadAttribute() << "Invalid surface attribute.";
} }
......
...@@ -521,6 +521,67 @@ TEST_F(EGLSurfaceTest, CreateWithEGLConfig8880Support) ...@@ -521,6 +521,67 @@ TEST_F(EGLSurfaceTest, CreateWithEGLConfig8880Support)
glDeleteProgram(program); glDeleteProgram(program);
} }
TEST_F(EGLSurfaceTest, FixedSizeWindow)
{
ANGLE_SKIP_TEST_IF(
!ANGLETest::eglDisplayExtensionEnabled(EGL_NO_DISPLAY, "EGL_ANGLE_platform_angle_d3d"));
const EGLint configAttributes[] = {
EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 0,
EGL_DEPTH_SIZE, 0, EGL_STENCIL_SIZE, 0, EGL_SAMPLE_BUFFERS, 0, EGL_NONE};
initializeDisplay(EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE);
ANGLE_SKIP_TEST_IF(EGLWindow::FindEGLConfig(mDisplay, configAttributes, &mConfig) == EGL_FALSE);
ANGLE_SKIP_TEST_IF(
!ANGLETest::eglDisplayExtensionEnabled(mDisplay, "EGL_ANGLE_window_fixed_size"));
constexpr EGLint kInitialSize = 64;
constexpr EGLint kUpdateSize = 32;
EGLint surfaceAttributes[] = {
EGL_FIXED_SIZE_ANGLE, EGL_TRUE, EGL_WIDTH, kInitialSize, EGL_HEIGHT, kInitialSize, EGL_NONE,
};
// Create first window surface
mWindowSurface =
eglCreateWindowSurface(mDisplay, mConfig, mOSWindow->getNativeWindow(), surfaceAttributes);
ASSERT_EGL_SUCCESS();
ASSERT_NE(EGL_NO_SURFACE, mWindowSurface);
initializeContext();
EXPECT_EGL_TRUE(eglMakeCurrent(mDisplay, mWindowSurface, mWindowSurface, mContext));
ASSERT_EGL_SUCCESS();
EGLint queryIsFixedSize = 0;
EXPECT_EGL_TRUE(
eglQuerySurface(mDisplay, mWindowSurface, EGL_FIXED_SIZE_ANGLE, &queryIsFixedSize));
ASSERT_EGL_SUCCESS();
EXPECT_EGL_TRUE(queryIsFixedSize);
EGLint queryWidth = 0;
EXPECT_EGL_TRUE(eglQuerySurface(mDisplay, mWindowSurface, EGL_WIDTH, &queryWidth));
ASSERT_EGL_SUCCESS();
EXPECT_EQ(kInitialSize, queryWidth);
EGLint queryHeight = 0;
EXPECT_EGL_TRUE(eglQuerySurface(mDisplay, mWindowSurface, EGL_HEIGHT, &queryHeight));
ASSERT_EGL_SUCCESS();
EXPECT_EQ(kInitialSize, queryHeight);
// Update the size
EXPECT_EGL_TRUE(eglSurfaceAttrib(mDisplay, mWindowSurface, EGL_WIDTH, kUpdateSize));
ASSERT_EGL_SUCCESS();
EXPECT_EGL_TRUE(eglWaitNative(EGL_CORE_NATIVE_ENGINE));
ASSERT_EGL_SUCCESS();
EGLint queryUpdatedWidth = 0;
EXPECT_EGL_TRUE(eglQuerySurface(mDisplay, mWindowSurface, EGL_WIDTH, &queryUpdatedWidth));
ASSERT_EGL_SUCCESS();
EXPECT_EQ(kUpdateSize, queryUpdatedWidth);
}
#if defined(ANGLE_ENABLE_D3D11) #if defined(ANGLE_ENABLE_D3D11)
// Test that rendering to an IDCompositionSurface using a pbuffer works. // Test that rendering to an IDCompositionSurface using a pbuffer works.
TEST_F(EGLSurfaceTest, CreateDirectCompositionSurface) TEST_F(EGLSurfaceTest, CreateDirectCompositionSurface)
......
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