Implement the egl and gl layers of EGL Image.
Add end2end tests and unittests.
BUG=angleproject:970
Change-Id: I13fc501b24c3f11bfedc810c1ff80fcf1318877c
Reviewed-on: https://chromium-review.googlesource.com/287343
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Tested-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/Texture.cpp b/src/libANGLE/Texture.cpp
index 8b18663..2668478 100644
--- a/src/libANGLE/Texture.cpp
+++ b/src/libANGLE/Texture.cpp
@@ -12,6 +12,7 @@
#include "common/utilities.h"
#include "libANGLE/Config.h"
#include "libANGLE/Data.h"
+#include "libANGLE/Image.h"
#include "libANGLE/Surface.h"
#include "libANGLE/formatutils.h"
@@ -46,7 +47,7 @@
}
Texture::Texture(rx::TextureImpl *impl, GLuint id, GLenum target)
- : FramebufferAttachmentObject(id),
+ : egl::ImageSibling(id),
mTexture(impl),
mUsage(GL_NONE),
mImmutableLevelCount(0),
@@ -127,6 +128,11 @@
return mCompletenessCache.samplerComplete;
}
+bool Texture::isMipmapComplete() const
+{
+ return computeMipmapCompleteness(mSamplerState);
+}
+
// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
bool Texture::isCubeComplete() const
{
@@ -152,6 +158,22 @@
return true;
}
+size_t Texture::getMipCompleteLevels() const
+{
+ const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), 0);
+ if (mTarget == GL_TEXTURE_3D)
+ {
+ const size_t maxDim =
+ std::max(std::max(baseImageDesc.size.width, baseImageDesc.size.height),
+ baseImageDesc.size.depth);
+ return log2(maxDim) + 1;
+ }
+ else
+ {
+ return log2(std::max(baseImageDesc.size.width, baseImageDesc.size.height)) + 1;
+ }
+}
+
bool Texture::isImmutable() const
{
return (mImmutableLevelCount > 0);
@@ -162,6 +184,11 @@
return mImmutableLevelCount;
}
+egl::Surface *Texture::getBoundSurface() const
+{
+ return mBoundSurface;
+}
+
Error Texture::setImage(GLenum target, size_t level, GLenum internalFormat, const Extents &size, GLenum format, GLenum type,
const PixelUnpackState &unpack, const uint8_t *pixels)
{
@@ -169,6 +196,7 @@
// Release from previous calls to eglBindTexImage, to avoid calling the Impl after
releaseTexImageInternal();
+ orphanImages();
Error error = mTexture->setImage(target, level, internalFormat, size, format, type, unpack, pixels);
if (error.isError())
@@ -196,6 +224,7 @@
// Release from previous calls to eglBindTexImage, to avoid calling the Impl after
releaseTexImageInternal();
+ orphanImages();
Error error = mTexture->setCompressedImage(target, level, internalFormat, size, unpack, imageSize, pixels);
if (error.isError())
@@ -223,6 +252,7 @@
// Release from previous calls to eglBindTexImage, to avoid calling the Impl after
releaseTexImageInternal();
+ orphanImages();
Error error = mTexture->copyImage(target, level, sourceArea, internalFormat, source);
if (error.isError())
@@ -250,6 +280,7 @@
// Release from previous calls to eglBindTexImage, to avoid calling the Impl after
releaseTexImageInternal();
+ orphanImages();
Error error = mTexture->setStorage(target, levels, internalFormat, size);
if (error.isError())
@@ -270,6 +301,13 @@
// Release from previous calls to eglBindTexImage, to avoid calling the Impl after
releaseTexImageInternal();
+ // EGL_KHR_gl_image states that images are only orphaned when generating mipmaps if the texture
+ // is not mip complete.
+ if (!isMipmapComplete())
+ {
+ orphanImages();
+ }
+
Error error = mTexture->generateMipmaps(getSamplerState());
if (error.isError())
{
@@ -388,24 +426,38 @@
}
}
+Error Texture::setEGLImageTarget(GLenum target, egl::Image *imageTarget)
+{
+ ASSERT(target == mTarget);
+ ASSERT(target == GL_TEXTURE_2D);
+
+ // Release from previous calls to eglBindTexImage, to avoid calling the Impl after
+ releaseTexImageInternal();
+ orphanImages();
+
+ Error error = mTexture->setEGLImageTarget(target, imageTarget);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ setTargetImage(imageTarget);
+
+ Extents size(imageTarget->getWidth(), imageTarget->getHeight(), 1);
+ GLenum internalFormat = imageTarget->getInternalFormat();
+ GLenum type = GetInternalFormatInfo(internalFormat).type;
+
+ clearImageDescs();
+ setImageDesc(target, 0, ImageDesc(size, GetSizedInternalFormat(internalFormat, type)));
+
+ return Error(GL_NO_ERROR);
+}
+
GLenum Texture::getBaseImageTarget() const
{
return mTarget == GL_TEXTURE_CUBE_MAP ? FirstCubeMapTextureTarget : mTarget;
}
-size_t Texture::getExpectedMipLevels() const
-{
- const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), 0);
- if (mTarget == GL_TEXTURE_3D)
- {
- return log2(std::max(std::max(baseImageDesc.size.width, baseImageDesc.size.height), baseImageDesc.size.depth)) + 1;
- }
- else
- {
- return log2(std::max(baseImageDesc.size.width, baseImageDesc.size.height)) + 1;
- }
-}
-
bool Texture::computeSamplerCompleteness(const SamplerState &samplerState, const Data &data) const
{
const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), samplerState.baseLevel);
@@ -481,7 +533,7 @@
bool Texture::computeMipmapCompleteness(const gl::SamplerState &samplerState) const
{
- size_t expectedMipLevels = getExpectedMipLevels();
+ size_t expectedMipLevels = getMipCompleteLevels();
size_t maxLevel = std::min<size_t>(expectedMipLevels, samplerState.maxLevel + 1);
@@ -525,13 +577,13 @@
return false;
}
- // The base image level is complete if the width and height are positive
- if (level == 0)
+ const ImageDesc &levelImageDesc = getImageDesc(target, level);
+ if (levelImageDesc.size.width == 0 || levelImageDesc.size.height == 0 ||
+ levelImageDesc.size.depth == 0)
{
- return true;
+ return false;
}
- const ImageDesc &levelImageDesc = getImageDesc(target, level);
if (levelImageDesc.internalFormat != baseImageDesc.internalFormat)
{
return false;