зеркало из https://github.com/AvaloniaUI/angle.git
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:
Родитель
854429de7d
Коммит
03d132eb80
1
AUTHORS
1
AUTHORS
|
@ -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)
|
||||
|
|
Загрузка…
Ссылка в новой задаче