зеркало из https://github.com/AvaloniaUI/angle.git
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:
Родитель
d3e6771671
Коммит
5eb86d4ab7
|
@ -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;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче