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: Geoff Lang <geofflang@chromium.org>
This commit is contained in:
LRN 2018-07-14 13:31:35 +00:00 коммит произвёл Commit Bot
Родитель 854429de7d
Коммит 03d132eb80
11 изменённых файлов: 181 добавлений и 20 удалений

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

@ -51,3 +51,4 @@ Nickolay Artamonov
Ihsan Akmal
Andrei Volykhin
Jérôme Duval
Руслан Ижбулатов

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

@ -10,6 +10,7 @@ Contributors
John Bauman
Shannon Woods
Geoff Lang
Contacts
@ -21,7 +22,7 @@ Status
Version
Version 4, February 24, 2014
Version 5, July 23, 2018
Number
@ -34,8 +35,8 @@ Dependencies
Overview
This extension allows creating a window surface with a fixed size that is
specified when it is created.
This extension allows creating a window surface that does not resize
automatically.
New Types
@ -54,7 +55,8 @@ New Tokens
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
the same structure as described for eglChooseConfig. Attributes that can
@ -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.
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,
and will not change throughout the lifetime of the surface. If its value
is EGL_FALSE, then the values of EGL_WIDTH and EGL_HEIGHT are ignored and
the window surface must be resized by the implementation subsequent to the
native window being resized, and prior to copying its contents to the
native window (e.g. in eglSwapBuffers, as described in section 3.9.1.1).
The default values for EGL_WIDTH and EGL_HEIGHT are zero. If the value
specified for either of EGL_WIDTH or EGL_HEIGHT is less than zero then an
EGL_BAD_PARAMETER error is generated."
size in pixels is specified by the EGL_WIDTH and EGL_HEIGHT attributes.
If its value is EGL_FALSE, then the values of EGL_WIDTH and EGL_HEIGHT
are ignored and the window surface must be resized by the implementation
subsequent to the native window being resized, and prior to copying its
contents to the native window (e.g. in eglSwapBuffers, as described in
section 3.9.1.1). The default values for EGL_WIDTH and EGL_HEIGHT are zero.
If the value specified for either of EGL_WIDTH or EGL_HEIGHT is less than
zero then an EGL_BAD_PARAMETER error is generated."
Add the following entry to Table 3.5
(Queryable surface attributes and types)
@ -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
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)
"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:
Alter the beginning of the first paragraph of Section 3.9.1.1 (Native
Window Resizing)
"If <surface> does not have EGL_FIXED_SIZE_ANGLE set and the native window
corresponding to <surface> has been resized prior to the swap, <surface>
must be resized to match."
"If the surface has EGL_FIXED_SIZE_ANGLE set and EGL_WIDTH or EGL_HEIGHT
have changed or the surface does not have EGL_FIXED_SIZE_ANGLE set and its
corresponding native window has been resized prior to the swap, surface
must be resized to match".
Issues
@ -123,8 +140,15 @@ Issues
RESOLVED: No. Surfaces that have their sizes specified initially must have
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
Version 5, 2018/07/23 - Allow reizing fixed size surfaces.
Version 4, 2014/02/24 - formatting changes.
Version 3, 2014/02/12 - ignore EGL_WIDTH and EGL_HEIGHT if

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

@ -289,6 +289,18 @@ void Surface::setSwapBehavior(EGLenum 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
{
return mState.config;

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

@ -84,6 +84,9 @@ class Surface : public LabeledObject, public gl::FramebufferAttachmentObject
void setMultisampleResolve(EGLenum resolve);
void setSwapBehavior(EGLenum behavior);
void setFixedWidth(EGLint width);
void setFixedHeight(EGLint height);
gl::Framebuffer *createDefaultFramebuffer(const gl::Context *context);
const Config *getConfig() const;

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

@ -2828,6 +2828,12 @@ void SetSurfaceAttrib(Surface *surface, EGLint attribute, EGLint value)
case EGL_SWAP_BEHAVIOR:
surface->setSwapBehavior(value);
break;
case EGL_WIDTH:
surface->setFixedWidth(value);
break;
case EGL_HEIGHT:
surface->setFixedHeight(value);
break;
default:
UNREACHABLE();
break;

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

@ -31,4 +31,14 @@ egl::Error SurfaceImpl::setPresentationTime(EGLnsecsANDROID time)
return egl::EglBadSurface() << "setPresentationTime implementation missing.";
}
void SurfaceImpl::setFixedWidth(EGLint width)
{
UNREACHABLE();
}
void SurfaceImpl::setFixedHeight(EGLint height)
{
UNREACHABLE();
}
} // namespace rx

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

@ -65,6 +65,8 @@ class SurfaceImpl : public FramebufferAttachmentObjectImpl
virtual egl::Error releaseTexImage(const gl::Context *context, EGLint buffer) = 0;
virtual egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) = 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
virtual EGLint getWidth() const = 0;

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

@ -36,6 +36,8 @@ SurfaceD3D::SurfaceD3D(const egl::SurfaceState &state,
mRenderer(renderer),
mDisplay(display),
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))),
mRenderTargetFormat(state.config->renderTargetFormat),
mDepthStencilFormat(state.config->depthStencilFormat),
@ -56,6 +58,12 @@ SurfaceD3D::SurfaceD3D(const egl::SurfaceState &state,
mHeight = -1;
}
if (mFixedSize)
{
mFixedWidth = mWidth;
mFixedHeight = mHeight;
}
switch (buftype)
{
case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
@ -97,8 +105,8 @@ egl::Error SurfaceD3D::initialize(const egl::Display *display)
if (mBuftype == EGL_D3D_TEXTURE_ANGLE)
{
ANGLE_TRY(mRenderer->getD3DTextureInfo(mState.config, mD3DTexture, &mWidth, &mHeight,
&mColorFormat));
ANGLE_TRY(mRenderer->getD3DTextureInfo(mState.config, mD3DTexture, &mFixedWidth,
&mFixedHeight, &mColorFormat));
if (mState.attributes.contains(EGL_GL_COLORSPACE))
{
if (mColorFormat->id != angle::FormatID::R8G8B8A8_TYPELESS &&
@ -177,8 +185,8 @@ egl::Error SurfaceD3D::resetSwapChain(const egl::Display *display)
else
{
// non-window surface - size is determined at creation
width = mWidth;
height = mHeight;
width = mFixedWidth;
height = mFixedHeight;
}
mSwapChain =
@ -317,6 +325,12 @@ egl::Error SurfaceD3D::checkForOutOfDateSwapChain(DisplayD3D *displayD3D)
clientHeight = client.bottom - client.top;
sizeDirty = clientWidth != getWidth() || clientHeight != getHeight();
}
else if (mFixedSize)
{
clientWidth = mFixedWidth;
clientHeight = mFixedHeight;
sizeDirty = mFixedWidth != getWidth() || mFixedHeight != getHeight();
}
if (mSwapIntervalDirty)
{
@ -362,6 +376,16 @@ void SurfaceD3D::setSwapInterval(EGLint interval)
mSwapIntervalDirty = true;
}
void SurfaceD3D::setFixedWidth(EGLint width)
{
mFixedWidth = width;
}
void SurfaceD3D::setFixedHeight(EGLint height)
{
mFixedHeight = height;
}
EGLint SurfaceD3D::getWidth() const
{
return mWidth;

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

@ -46,6 +46,8 @@ class SurfaceD3D : public SurfaceImpl
egl::Error releaseTexImage(const gl::Context *context, EGLint buffer) override;
egl::Error getSyncValues(EGLuint64KHR *ust, EGLuint64KHR *msc, EGLuint64KHR *sbc) override;
void setSwapInterval(EGLint interval) override;
void setFixedWidth(EGLint width) override;
void setFixedHeight(EGLint height) override;
EGLint getWidth() const override;
EGLint getHeight() const override;
@ -86,6 +88,8 @@ class SurfaceD3D : public SurfaceImpl
egl::Display *mDisplay;
bool mFixedSize;
GLint mFixedWidth;
GLint mFixedHeight;
GLint mOrientation;
GLenum mRenderTargetFormat;

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

@ -2782,6 +2782,20 @@ Error ValidateSurfaceAttrib(const Display *display,
}
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:
return EglBadAttribute() << "Invalid surface attribute.";
}

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

@ -521,6 +521,67 @@ TEST_F(EGLSurfaceTest, CreateWithEGLConfig8880Support)
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)
// Test that rendering to an IDCompositionSurface using a pbuffer works.
TEST_F(EGLSurfaceTest, CreateDirectCompositionSurface)