Commit 2eb54074 by Yuly Novikov Committed by Commit Bot

Fix EGLImage pixel format validation

This fixes the scenario when EGLImage source and target have different types. For example, a texture is created with unsigned format using glTexImage2D, it is used as a source of EGLImage with eglCreateImageKHR, and then the EGLImage is used to create a renderbuffer target with glEGLImageTargetRenderbufferStorageOES. OES_EGL_image doesn't specify what should happen in this case, but GL implementations (Nexus 5X) seem to allow using this renderbuffer in glFramebufferRenderbuffer and the resulting framebuffer is complete. Thus, in this case, instead of checking whether the renderbuffer format can be used in glFramebufferRenderbuffer, we need to check whether the original texture can be used in glFramebufferTexture2D. Similarly in reverse direction. Also, for the case of source renderbuffer and target texture, presume that glEGLImageTargetTexture2DOES will succeed regardless of renderbuffer format. 1. Add isRenderable and isTexturable checks to egl::Image class, and perform different checks depending on source type. 2. Add isRenderable check to FramebufferAttachment and delegate EGLImage attachments check to egl::Image. 3. Use these checks in validation of EGLImageTargetTexture2D, EGLImageTargetRenderbufferStorage and when checking attachment completeness Bug: angleproject:2567 Change-Id: I8e9f4a2930a4075a4d8464f62582c6825270187e Reviewed-on: https://chromium-review.googlesource.com/1192585 Commit-Queue: Yuly Novikov <ynovikov@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent abcb2b3b
......@@ -71,14 +71,7 @@ bool CheckAttachmentCompleteness(const Context *context, const FramebufferAttach
return false;
}
const InternalFormat &format = *attachment.getFormat().info;
if (attachment.type() == GL_RENDERBUFFER &&
!format.renderbufferSupport(context->getClientVersion(), context->getExtensions()))
{
return false;
}
if (attachment.type() == GL_TEXTURE &&
!format.textureAttachmentSupport(context->getClientVersion(), context->getExtensions()))
if (!attachment.isRenderable(context))
{
return false;
}
......
......@@ -126,6 +126,7 @@ class FramebufferAttachment final
GLsizei getSamples() const;
GLenum type() const { return mType; }
bool isAttached() const { return mType != GL_NONE; }
bool isRenderable(const Context *context) const;
Renderbuffer *getRenderbuffer() const;
Texture *getTexture() const;
......@@ -199,6 +200,9 @@ class FramebufferAttachmentObject
virtual Extents getAttachmentSize(const ImageIndex &imageIndex) const = 0;
virtual Format getAttachmentFormat(GLenum binding, const ImageIndex &imageIndex) const = 0;
virtual GLsizei getAttachmentSamples(const ImageIndex &imageIndex) const = 0;
virtual bool isRenderable(const Context *context,
GLenum binding,
const ImageIndex &imageIndex) const = 0;
virtual void onAttach(const Context *context) = 0;
virtual void onDetach(const Context *context) = 0;
......@@ -249,6 +253,12 @@ inline gl::Error FramebufferAttachment::getRenderTargetImpl(
rtOut);
}
inline bool FramebufferAttachment::isRenderable(const Context *context) const
{
ASSERT(mResource);
return mResource->isRenderable(context, mTarget.binding(), mTarget.textureIndex());
}
} // namespace gl
#endif // LIBANGLE_FRAMEBUFFERATTACHMENT_H_
......@@ -123,6 +123,14 @@ void ImageSibling::setSourceEGLImageInitState(gl::InitState initState) const
mTargetOf->setInitState(initState);
}
bool ImageSibling::isRenderable(const gl::Context *context,
GLenum binding,
const gl::ImageIndex &imageIndex) const
{
ASSERT(isEGLImageTarget());
return mTargetOf->isRenderable(context);
}
ImageState::ImageState(EGLenum target, ImageSibling *buffer, const AttributeMap &attribs)
: label(nullptr),
imageIndex(GetImageIndex(target, attribs)),
......@@ -130,7 +138,8 @@ ImageState::ImageState(EGLenum target, ImageSibling *buffer, const AttributeMap
targets(),
format(buffer->getAttachmentFormat(GL_NONE, imageIndex)),
size(buffer->getAttachmentSize(imageIndex)),
samples(buffer->getAttachmentSamples(imageIndex))
samples(buffer->getAttachmentSamples(imageIndex)),
sourceType(target)
{
}
......@@ -217,6 +226,39 @@ const gl::Format &Image::getFormat() const
return mState.format;
}
bool Image::isRenderable(const gl::Context *context) const
{
if (IsTextureTarget(mState.sourceType))
{
return mState.format.info->textureAttachmentSupport(context->getClientVersion(),
context->getExtensions());
}
if (IsRenderbufferTarget(mState.sourceType))
{
return mState.format.info->renderbufferSupport(context->getClientVersion(),
context->getExtensions());
}
UNREACHABLE();
return false;
}
bool Image::isTexturable(const gl::Context *context) const
{
if (IsTextureTarget(mState.sourceType))
{
return mState.format.info->textureSupport(context->getClientVersion(),
context->getExtensions());
}
if (IsRenderbufferTarget(mState.sourceType))
{
return true;
}
UNREACHABLE();
return false;
}
size_t Image::getWidth() const
{
return mState.size.width;
......
......@@ -43,6 +43,10 @@ class ImageSibling : public gl::FramebufferAttachmentObject
gl::InitState sourceEGLImageInitState() const;
void setSourceEGLImageInitState(gl::InitState initState) const;
bool isRenderable(const gl::Context *context,
GLenum binding,
const gl::ImageIndex &imageIndex) const override;
protected:
// Set the image target of this sibling
void setTargetImage(const gl::Context *context, egl::Image *imageTarget);
......@@ -76,6 +80,7 @@ struct ImageState : private angle::NonCopyable
gl::Format format;
gl::Extents size;
size_t samples;
EGLenum sourceType;
};
class Image final : public RefCountObject, public LabeledObject
......@@ -94,6 +99,8 @@ class Image final : public RefCountObject, public LabeledObject
EGLLabelKHR getLabel() const override;
const gl::Format &getFormat() const;
bool isRenderable(const gl::Context *context) const;
bool isTexturable(const gl::Context *context) const;
size_t getWidth() const;
size_t getHeight() const;
size_t getSamples() const;
......
......@@ -11,6 +11,7 @@
#include "libANGLE/Renderbuffer.h"
#include "common/utilities.h"
#include "libANGLE/Context.h"
#include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/Image.h"
#include "libANGLE/Renderbuffer.h"
......@@ -231,6 +232,18 @@ GLsizei Renderbuffer::getAttachmentSamples(const ImageIndex & /*imageIndex*/) co
return getSamples();
}
bool Renderbuffer::isRenderable(const Context *context,
GLenum binding,
const ImageIndex &imageIndex) const
{
if (isEGLImageTarget())
{
return ImageSibling::isRenderable(context, binding, imageIndex);
}
return getFormat().info->renderbufferSupport(context->getClientVersion(),
context->getExtensions());
}
InitState Renderbuffer::initState(const gl::ImageIndex & /*imageIndex*/) const
{
if (isEGLImageTarget())
......
......@@ -97,6 +97,9 @@ class Renderbuffer final : public RefCountObject, public egl::ImageSibling, publ
Extents getAttachmentSize(const ImageIndex &imageIndex) const override;
Format getAttachmentFormat(GLenum binding, const ImageIndex &imageIndex) const override;
GLsizei getAttachmentSamples(const ImageIndex &imageIndex) const override;
bool isRenderable(const Context *context,
GLenum binding,
const ImageIndex &imageIndex) const override;
void onAttach(const Context *context) override;
void onDetach(const Context *context) override;
......
......@@ -450,6 +450,13 @@ GLsizei Surface::getAttachmentSamples(const gl::ImageIndex &target) const
return getConfig()->samples;
}
bool Surface::isRenderable(const gl::Context *context,
GLenum binding,
const gl::ImageIndex &imageIndex) const
{
return true;
}
GLuint Surface::getId() const
{
UNREACHABLE();
......
......@@ -117,6 +117,9 @@ class Surface : public LabeledObject, public gl::FramebufferAttachmentObject
gl::Extents getAttachmentSize(const gl::ImageIndex &imageIndex) const override;
gl::Format getAttachmentFormat(GLenum binding, const gl::ImageIndex &imageIndex) const override;
GLsizei getAttachmentSamples(const gl::ImageIndex &imageIndex) const override;
bool isRenderable(const gl::Context *context,
GLenum binding,
const gl::ImageIndex &imageIndex) const override;
void onAttach(const gl::Context *context) override {}
void onDetach(const gl::Context *context) override {}
......
......@@ -1454,6 +1454,18 @@ GLsizei Texture::getAttachmentSamples(const ImageIndex &imageIndex) const
return getSamples(imageIndex.getTarget(), imageIndex.getLevelIndex());
}
bool Texture::isRenderable(const Context *context,
GLenum binding,
const ImageIndex &imageIndex) const
{
if (isEGLImageTarget())
{
return ImageSibling::isRenderable(context, binding, imageIndex);
}
return getAttachmentFormat(binding, imageIndex)
.info->textureAttachmentSupport(context->getClientVersion(), context->getExtensions());
}
bool Texture::getAttachmentFixedSampleLocations(const ImageIndex &imageIndex) const
{
// We do not allow querying TextureTarget by an ImageIndex that represents an entire level of a
......
......@@ -377,6 +377,9 @@ class Texture final : public RefCountObject, public egl::ImageSibling, public La
Extents getAttachmentSize(const ImageIndex &imageIndex) const override;
Format getAttachmentFormat(GLenum binding, const ImageIndex &imageIndex) const override;
GLsizei getAttachmentSamples(const ImageIndex &imageIndex) const override;
bool isRenderable(const Context *context,
GLenum binding,
const ImageIndex &imageIndex) const override;
bool getAttachmentFixedSampleLocations(const ImageIndex &imageIndex) const;
......
......@@ -3536,9 +3536,7 @@ bool ValidateEGLImageTargetTexture2DOES(Context *context, TextureType type, GLeg
return false;
}
const TextureCaps &textureCaps =
context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
if (!textureCaps.texturable)
if (!imageObject->isTexturable(context))
{
context->handleError(InvalidOperation()
<< "EGL image internal format is not supported as a texture.");
......@@ -3577,9 +3575,7 @@ bool ValidateEGLImageTargetRenderbufferStorageOES(Context *context,
return false;
}
const TextureCaps &textureCaps =
context->getTextureCaps().get(imageObject->getFormat().info->sizedInternalFormat);
if (!textureCaps.renderbuffer)
if (!imageObject->isRenderable(context))
{
context->handleError(InvalidOperation()
<< "EGL image internal format is not supported as a renderbuffer.");
......
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