EGL: EGL_KHR_lock_surface3 frontend

Add queries to get locked buffer attributes
Add validation for LockSurface, QuerySurface

Bug: angleproject:6062
Change-Id: I4919bef2a17d3505cccad08f7c4f8a3ca5d7e4e6
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3174322
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
This commit is contained in:
Jeff Vigil 2021-09-21 15:17:04 -07:00 коммит произвёл Angle LUCI CQ
Родитель d3e6771671
Коммит 5eb86d4ab7
11 изменённых файлов: 339 добавлений и 1 удалений

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

@ -372,6 +372,16 @@ std::vector<const Config *> ConfigSet::filter(const AttributeMap &attributeMap)
case EGL_Y_INVERTED_NOK:
match = config.yInverted == static_cast<EGLBoolean>(attributeValue);
break;
case EGL_MATCH_FORMAT_KHR:
if (attributeValue == EGL_NONE)
{
match = (config.surfaceType & EGL_LOCK_SURFACE_BIT_KHR) == 0;
}
else
{
match = config.matchFormat == attributeValue;
}
break;
default:
UNREACHABLE();
}

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

@ -77,6 +77,7 @@ struct Config
EGLBoolean yInverted; // True if the drawable's framebuffer is y-inverted. This can be used to
// determine if y-inverted texture coordinates need to be used when
// texturing from this drawable when it is bound to a texture target.
EGLint matchFormat; // LockSurface match format.
};
class ConfigSet

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

@ -93,6 +93,9 @@ Surface::Surface(EGLint surfaceType,
mTexture(nullptr),
mColorFormat(config->renderTargetFormat),
mDSFormat(config->depthStencilFormat),
mIsCurrentOnAnyContext(false),
mLockBufferPtr(nullptr),
mLockBufferPitch(0),
mInitState(gl::InitState::Initialized),
mImplObserverBinding(this, kSurfaceImplSubjectIndex)
{
@ -244,8 +247,12 @@ Error Surface::initialize(const Display *display)
Error Surface::makeCurrent(const gl::Context *context)
{
if (isLocked())
{
return EglBadAccess();
}
ANGLE_TRY(mImplementation->makeCurrent(context));
mIsCurrentOnAnyContext = true;
mRefCount++;
return NoError();
}
@ -253,6 +260,7 @@ Error Surface::makeCurrent(const gl::Context *context)
Error Surface::unMakeCurrent(const gl::Context *context)
{
ANGLE_TRY(mImplementation->unMakeCurrent(context));
mIsCurrentOnAnyContext = false;
return releaseRef(context->getDisplay());
}
@ -694,6 +702,107 @@ void Surface::setRenderBuffer(EGLint value)
mRenderBuffer = value;
}
bool Surface::isLocked() const
{
return (mLockBufferPtr != nullptr);
}
EGLint Surface::getBitmapPitch() const
{
return mLockBufferPitch;
}
EGLint Surface::getBitmapOrigin() const
{
return mImplementation->origin();
}
EGLint Surface::getRedOffset() const
{
const gl::InternalFormat &format = *mColorFormat.info;
if (gl::IsBGRAFormat(format.internalFormat))
{
return format.blueBits + format.greenBits;
}
else
{
return 0;
}
}
EGLint Surface::getGreenOffset() const
{
const gl::InternalFormat &format = *mColorFormat.info;
if (gl::IsBGRAFormat(format.internalFormat))
{
return format.blueBits;
}
else
{
return format.redBits;
}
}
EGLint Surface::getBlueOffset() const
{
const gl::InternalFormat &format = *mColorFormat.info;
if (gl::IsBGRAFormat(format.internalFormat))
{
return 0;
}
else
{
return format.redBits + format.greenBits;
}
}
EGLint Surface::getAlphaOffset() const
{
const gl::InternalFormat &format = *mColorFormat.info;
if (format.isLUMA())
{
return format.luminanceBits; // Luma always first, alpha optional
}
// For RGBA/BGRA alpha is last
return format.blueBits + format.greenBits + format.redBits;
}
EGLint Surface::getLuminanceOffset() const
{
return 0;
}
EGLint Surface::getBitmapPixelSize() const
{
constexpr EGLint kBitsPerByte = 8;
const gl::InternalFormat &format = *mColorFormat.info;
return (format.pixelBytes * kBitsPerByte);
}
EGLAttribKHR Surface::getBitmapPointer() const
{
return static_cast<EGLAttribKHR>((intptr_t)mLockBufferPtr);
}
egl::Error Surface::lockSurfaceKHR(const egl::Display *display, const AttributeMap &attributes)
{
EGLint lockBufferUsageHint = attributes.getAsInt(
EGL_LOCK_USAGE_HINT_KHR, (EGL_READ_SURFACE_BIT_KHR | EGL_WRITE_SURFACE_BIT_KHR));
bool preservePixels = ((attributes.getAsInt(EGL_MAP_PRESERVE_PIXELS_KHR, false) == EGL_TRUE) ||
(mSwapBehavior == EGL_BUFFER_PRESERVED));
return mImplementation->lockSurface(display, lockBufferUsageHint, preservePixels,
&mLockBufferPtr, &mLockBufferPitch);
}
egl::Error Surface::unlockSurfaceKHR(const egl::Display *display)
{
mLockBufferPtr = nullptr;
mLockBufferPitch = 0;
return mImplementation->unlockSurface(display, true);
}
WindowSurface::WindowSurface(rx::EGLImplFactory *implFactory,
const egl::Config *config,
EGLNativeWindowType window,

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

@ -136,6 +136,22 @@ class Surface : public LabeledObject, public gl::FramebufferAttachmentObject
EGLenum getMultisampleResolve() const;
bool hasProtectedContent() const override;
// For lock surface buffer
EGLint getBitmapPitch() const;
EGLint getBitmapOrigin() const;
EGLint getRedOffset() const;
EGLint getGreenOffset() const;
EGLint getBlueOffset() const;
EGLint getAlphaOffset() const;
EGLint getLuminanceOffset() const;
EGLint getBitmapPixelSize() const;
EGLAttribKHR getBitmapPointer() const;
egl::Error lockSurfaceKHR(const egl::Display *display, const AttributeMap &attributes);
egl::Error unlockSurfaceKHR(const egl::Display *display);
bool isLocked() const;
bool isCurrentOnAnyContext() const { return mIsCurrentOnAnyContext; }
gl::Texture *getBoundTexture() const { return mTexture; }
EGLint isFixedSize() const;
@ -248,6 +264,10 @@ class Surface : public LabeledObject, public gl::FramebufferAttachmentObject
gl::Offset mTextureOffset;
bool mIsCurrentOnAnyContext; // The surface is current to a context/client API
uint8_t *mLockBufferPtr; // Memory owned by backend.
EGLint mLockBufferPitch;
private:
Error destroyImpl(const Display *display);

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

@ -476,6 +476,25 @@ ANGLE_INLINE bool IsPVRTC1Format(const GLenum format)
}
}
ANGLE_INLINE bool IsBGRAFormat(const GLenum internalFormat)
{
switch (internalFormat)
{
case GL_BGRA8_EXT:
case GL_BGRA4_ANGLEX:
case GL_BGR5_A1_ANGLEX:
case GL_BGRA8_SRGB_ANGLEX:
case GL_BGRX8_ANGLEX:
case GL_RGBX8_ANGLEX:
case GL_BGR565_ANGLEX:
case GL_BGR10_A2_ANGLEX:
return true;
default:
return false;
}
}
// Check if an internal format is ever valid in ES3. Makes no checks about support for a specific
// context.
bool ValidES3InternalFormat(GLenum internalFormat);

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

@ -4149,6 +4149,9 @@ void QueryConfigAttrib(const Config *config, EGLint attribute, EGLint *value)
case EGL_FRAMEBUFFER_TARGET_ANDROID:
*value = config->framebufferTarget;
break;
case EGL_MATCH_FORMAT_KHR:
*value = config->matchFormat;
break;
default:
UNREACHABLE();
break;
@ -4290,6 +4293,72 @@ egl::Error QuerySurfaceAttrib(const Display *display,
case EGL_BUFFER_AGE_EXT:
ANGLE_TRY(surface->getBufferAge(context, value));
break;
case EGL_BITMAP_PITCH_KHR:
*value = surface->getBitmapPitch();
break;
case EGL_BITMAP_ORIGIN_KHR:
*value = surface->getBitmapOrigin();
break;
case EGL_BITMAP_PIXEL_RED_OFFSET_KHR:
*value = surface->getRedOffset();
break;
case EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR:
*value = surface->getGreenOffset();
break;
case EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR:
*value = surface->getBlueOffset();
break;
case EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR:
*value = surface->getAlphaOffset();
break;
case EGL_BITMAP_PIXEL_LUMINANCE_OFFSET_KHR:
*value = surface->getLuminanceOffset();
break;
case EGL_BITMAP_PIXEL_SIZE_KHR:
*value = surface->getBitmapPixelSize();
break;
default:
UNREACHABLE();
break;
}
return NoError();
}
egl::Error QuerySurfaceAttrib64KHR(const Display *display,
const gl::Context *context,
const Surface *surface,
EGLint attribute,
EGLAttribKHR *value)
{
switch (attribute)
{
case EGL_BITMAP_PITCH_KHR:
*value = static_cast<EGLAttribKHR>(surface->getBitmapPitch());
break;
case EGL_BITMAP_ORIGIN_KHR:
*value = static_cast<EGLAttribKHR>(surface->getBitmapOrigin());
break;
case EGL_BITMAP_PIXEL_RED_OFFSET_KHR:
*value = static_cast<EGLAttribKHR>(surface->getRedOffset());
break;
case EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR:
*value = static_cast<EGLAttribKHR>(surface->getGreenOffset());
break;
case EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR:
*value = static_cast<EGLAttribKHR>(surface->getBlueOffset());
break;
case EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR:
*value = static_cast<EGLAttribKHR>(surface->getAlphaOffset());
break;
case EGL_BITMAP_PIXEL_LUMINANCE_OFFSET_KHR:
*value = static_cast<EGLAttribKHR>(surface->getLuminanceOffset());
break;
case EGL_BITMAP_PIXEL_SIZE_KHR:
*value = static_cast<EGLAttribKHR>(surface->getBitmapPixelSize());
break;
case EGL_BITMAP_POINTER_KHR:
*value = surface->getBitmapPointer();
break;
default:
UNREACHABLE();
break;

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

@ -281,6 +281,11 @@ egl::Error QuerySurfaceAttrib(const Display *display,
EGLint *value);
void SetSurfaceAttrib(Surface *surface, EGLint attribute, EGLint value);
Error GetSyncAttrib(Display *display, Sync *sync, EGLint attribute, EGLint *value);
egl::Error QuerySurfaceAttrib64KHR(const Display *display,
const gl::Context *context,
const Surface *surface,
EGLint attribute,
EGLAttribKHR *value);
} // namespace egl

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

@ -120,4 +120,25 @@ egl::Error SurfaceImpl::getBufferAge(const gl::Context *context, EGLint *age)
return egl::EglBadMatch();
}
egl::Error SurfaceImpl::lockSurface(const egl::Display *display,
EGLint usageHint,
bool preservePixels,
uint8_t **bufferPtrOut,
EGLint *bufferPitchOut)
{
UNREACHABLE();
return egl::EglBadMatch();
}
egl::Error SurfaceImpl::unlockSurface(const egl::Display *display, bool preservePixels)
{
UNREACHABLE();
return egl::EglBadMatch();
}
EGLint SurfaceImpl::origin() const
{
return EGL_LOWER_LEFT_KHR;
}
} // namespace rx

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

@ -110,6 +110,14 @@ class SurfaceImpl : public FramebufferAttachmentObjectImpl
const EGLint *timestamps,
EGLnsecsANDROID *values) const;
virtual egl::Error getBufferAge(const gl::Context *context, EGLint *age);
// EGL_KHR_lock_surface3
virtual egl::Error lockSurface(const egl::Display *display,
EGLint usageHint,
bool preservePixels,
uint8_t **bufferPtrOut,
EGLint *bufferPitchOut);
virtual egl::Error unlockSurface(const egl::Display *display, bool preservePixels);
virtual EGLint origin() const;
protected:
const egl::SurfaceState &mState;

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

@ -4463,6 +4463,12 @@ bool ValidateSwapBuffers(const ValidationContext *val,
return false;
}
if (eglSurface->isLocked())
{
val->setError(EGL_BAD_ACCESS);
return false;
}
if (eglSurface == EGL_NO_SURFACE || !val->eglThread->getContext() ||
val->eglThread->getCurrentDrawSurface() != eglSurface)
{
@ -4507,6 +4513,12 @@ bool ValidateSwapBuffersWithDamageKHR(const ValidationContext *val,
return false;
}
if (surface->isLocked())
{
val->setError(EGL_BAD_ACCESS);
return false;
}
// TODO(jmadill): Validate Surface is bound to the thread.
return true;
@ -4579,6 +4591,12 @@ bool ValidateBindTexImage(const ValidationContext *val,
return false;
}
if (surface->isLocked())
{
val->setError(EGL_BAD_ACCESS);
return false;
}
gl::Context *context = val->eglThread->getContext();
if (context)
{
@ -6036,6 +6054,31 @@ bool ValidateLockSurfaceKHR(const ValidationContext *val,
return false;
}
if (surface->isLocked())
{
val->setError(EGL_BAD_ACCESS);
return false;
}
if ((surface->getConfig()->surfaceType & EGL_LOCK_SURFACE_BIT_KHR) == false)
{
val->setError(EGL_BAD_ACCESS, "Config does not support EGL_LOCK_SURFACE_BIT");
return false;
}
if (surface->isCurrentOnAnyContext())
{
val->setError(EGL_BAD_ACCESS,
"Surface cannot be current to a context for eglLockSurface()");
return false;
}
if (surface->hasProtectedContent())
{
val->setError(EGL_BAD_ACCESS, "Surface cannot be protected content for eglLockSurface()");
return false;
}
while (attrib_list != nullptr && attrib_list[0] != EGL_NONE)
{
EGLint attribute = *attrib_list++;
@ -6103,6 +6146,12 @@ bool ValidateQuerySurface64KHR(const ValidationContext *val,
return false;
}
if (!surface->isLocked())
{
val->setError(EGL_BAD_ACCESS, "Surface is not locked");
return false;
}
return true;
}
@ -6119,6 +6168,12 @@ bool ValidateUnlockSurfaceKHR(const ValidationContext *val,
return false;
}
if (!surface->isLocked())
{
val->setError(EGL_BAD_PARAMETER, "Surface is not locked.");
return false;
}
return true;
}

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

@ -799,12 +799,26 @@ EGLBoolean LockSurfaceKHR(Thread *thread,
Surface *surface,
const EGLint *attrib_list)
{
ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglLockSurfaceKHR",
GetDisplayIfValid(display), EGL_FALSE);
const AttributeMap &attributes = PackParam<const AttributeMap &>(attrib_list);
ANGLE_EGL_TRY_RETURN(thread, surface->lockSurfaceKHR(display, attributes), "eglLockSurfaceKHR",
GetSurfaceIfValid(display, surface), EGL_FALSE);
thread->setSuccess();
return EGL_TRUE;
}
EGLBoolean UnlockSurfaceKHR(Thread *thread, egl::Display *display, Surface *surface)
{
ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglUnlockSurfaceKHR",
GetDisplayIfValid(display), EGL_FALSE);
ANGLE_EGL_TRY_RETURN(thread, surface->unlockSurfaceKHR(display), "eglQuerySurface64KHR",
GetSurfaceIfValid(display, surface), EGL_FALSE);
thread->setSuccess();
return EGL_TRUE;
}
@ -815,6 +829,13 @@ EGLBoolean QuerySurface64KHR(Thread *thread,
EGLint attribute,
EGLAttribKHR *value)
{
ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglQuerySurface64KHR",
GetDisplayIfValid(display), EGL_FALSE);
ANGLE_EGL_TRY_RETURN(
thread, QuerySurfaceAttrib64KHR(display, thread->getContext(), surface, attribute, value),
"eglQuerySurface64KHR", GetSurfaceIfValid(display, surface), EGL_FALSE);
thread->setSuccess();
return EGL_TRUE;
}