Implement EGL_ANDROID_image_native_buffer.
BUG=angleproject:2508
Change-Id: I8ef2ce8320edeb336727905055f47bb299dec2ea
Reviewed-on: https://chromium-review.googlesource.com/c/1238886
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
Reviewed-by: Yuly Novikov <ynovikov@chromium.org>
Commit-Queue: Geoff Lang <geofflang@chromium.org>
diff --git a/src/common/utilities.cpp b/src/common/utilities.cpp
index 2f632cf..a94946e 100644
--- a/src/common/utilities.cpp
+++ b/src/common/utilities.cpp
@@ -929,6 +929,18 @@
return target == EGL_GL_RENDERBUFFER_KHR;
}
+bool IsExternalImageTarget(EGLenum target)
+{
+ switch (target)
+ {
+ case EGL_NATIVE_BUFFER_ANDROID:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
const char *GetGenericErrorMessage(EGLint error)
{
switch (error)
diff --git a/src/common/utilities.h b/src/common/utilities.h
index 648fe2f..673e0c4 100644
--- a/src/common/utilities.h
+++ b/src/common/utilities.h
@@ -150,6 +150,7 @@
EGLenum LayerIndexToCubeMapTextureTarget(size_t index);
bool IsTextureTarget(EGLenum target);
bool IsRenderbufferTarget(EGLenum target);
+bool IsExternalImageTarget(EGLenum target);
const char *GetGenericErrorMessage(EGLint error);
} // namespace egl
diff --git a/src/libANGLE/Caps.cpp b/src/libANGLE/Caps.cpp
index 1b495bc..6f3e5b7 100644
--- a/src/libANGLE/Caps.cpp
+++ b/src/libANGLE/Caps.cpp
@@ -1356,7 +1356,8 @@
iosurfaceClientBuffer(false),
createContextExtensionsEnabled(false),
presentationTime(false),
- blobCache(false)
+ blobCache(false),
+ imageNativeBuffer(false)
{
}
@@ -1405,6 +1406,7 @@
InsertExtensionString("EGL_ANGLE_create_context_extensions_enabled", createContextExtensionsEnabled, &extensionStrings);
InsertExtensionString("EGL_ANDROID_presentation_time", presentationTime, &extensionStrings);
InsertExtensionString("EGL_ANDROID_blob_cache", blobCache, &extensionStrings);
+ InsertExtensionString("EGL_ANDROID_image_native_buffer", imageNativeBuffer, &extensionStrings);
// TODO(jmadill): Enable this when complete.
//InsertExtensionString("KHR_create_context_no_error", createContextNoError, &extensionStrings);
// clang-format on
diff --git a/src/libANGLE/Caps.h b/src/libANGLE/Caps.h
index e9f5c33..e427009 100644
--- a/src/libANGLE/Caps.h
+++ b/src/libANGLE/Caps.h
@@ -801,6 +801,9 @@
// EGL_ANDROID_blob_cache
bool blobCache;
+
+ // EGL_ANDROID_image_native_buffer
+ bool imageNativeBuffer;
};
struct DeviceExtensions
diff --git a/src/libANGLE/Display.cpp b/src/libANGLE/Display.cpp
index df640fe..ffb1066 100644
--- a/src/libANGLE/Display.cpp
+++ b/src/libANGLE/Display.cpp
@@ -719,6 +719,10 @@
{
sibling = context->getRenderbuffer(egl_gl::EGLClientBufferToGLObjectHandle(buffer));
}
+ else if (IsExternalImageTarget(target))
+ {
+ sibling = new ExternalImageSibling(mImplementation, context, target, buffer, attribs);
+ }
else
{
UNREACHABLE();
@@ -1120,11 +1124,19 @@
Error Display::validateClientBuffer(const Config *configuration,
EGLenum buftype,
EGLClientBuffer clientBuffer,
- const AttributeMap &attribs)
+ const AttributeMap &attribs) const
{
return mImplementation->validateClientBuffer(configuration, buftype, clientBuffer, attribs);
}
+Error Display::validateImageClientBuffer(const gl::Context *context,
+ EGLenum target,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) const
+{
+ return mImplementation->validateImageClientBuffer(context, target, clientBuffer, attribs);
+}
+
bool Display::isValidDisplay(const egl::Display *display)
{
const ANGLEPlatformDisplayMap *anglePlatformDisplayMap = GetANGLEPlatformDisplayMap();
diff --git a/src/libANGLE/Display.h b/src/libANGLE/Display.h
index 86f98e0..4dc8196 100644
--- a/src/libANGLE/Display.h
+++ b/src/libANGLE/Display.h
@@ -125,7 +125,11 @@
Error validateClientBuffer(const Config *configuration,
EGLenum buftype,
EGLClientBuffer clientBuffer,
- const AttributeMap &attribs);
+ const AttributeMap &attribs) const;
+ Error validateImageClientBuffer(const gl::Context *context,
+ EGLenum target,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) const;
static bool isValidDisplay(const Display *display);
static bool isValidNativeDisplay(EGLNativeDisplayType display);
diff --git a/src/libANGLE/Image.cpp b/src/libANGLE/Image.cpp
index 2753f2f..5cbdf5a 100644
--- a/src/libANGLE/Image.cpp
+++ b/src/libANGLE/Image.cpp
@@ -25,7 +25,7 @@
{
gl::ImageIndex GetImageIndex(EGLenum eglTarget, const egl::AttributeMap &attribs)
{
- if (eglTarget == EGL_GL_RENDERBUFFER)
+ if (!IsTextureTarget(eglTarget))
{
return gl::ImageIndex();
}
@@ -131,6 +131,76 @@
return mTargetOf->isRenderable(context);
}
+ExternalImageSibling::ExternalImageSibling(rx::EGLImplFactory *factory,
+ const gl::Context *context,
+ EGLenum target,
+ EGLClientBuffer buffer,
+ const AttributeMap &attribs)
+ : mImplementation(factory->createExternalImageSibling(context, target, buffer, attribs))
+{
+}
+
+gl::Extents ExternalImageSibling::getAttachmentSize(const gl::ImageIndex &imageIndex) const
+{
+ return mImplementation->getSize();
+}
+
+gl::Format ExternalImageSibling::getAttachmentFormat(GLenum binding,
+ const gl::ImageIndex &imageIndex) const
+{
+ return mImplementation->getFormat();
+}
+
+GLsizei ExternalImageSibling::getAttachmentSamples(const gl::ImageIndex &imageIndex) const
+{
+ return mImplementation->getSamples();
+}
+
+bool ExternalImageSibling::isRenderable(const gl::Context *context,
+ GLenum binding,
+ const gl::ImageIndex &imageIndex) const
+{
+ return mImplementation->isRenderable(context);
+}
+
+bool ExternalImageSibling::isTextureable(const gl::Context *context) const
+{
+ return mImplementation->isTexturable(context);
+}
+
+void ExternalImageSibling::onAttach(const gl::Context *context)
+{
+}
+
+void ExternalImageSibling::onDetach(const gl::Context *context)
+{
+}
+
+GLuint ExternalImageSibling::getId() const
+{
+ UNREACHABLE();
+ return 0;
+}
+
+gl::InitState ExternalImageSibling::initState(const gl::ImageIndex &imageIndex) const
+{
+ return gl::InitState::Initialized;
+}
+
+void ExternalImageSibling::setInitState(const gl::ImageIndex &imageIndex, gl::InitState initState)
+{
+}
+
+rx::ExternalImageSiblingImpl *ExternalImageSibling::getImplementation() const
+{
+ return mImplementation.get();
+}
+
+rx::FramebufferAttachmentObjectImpl *ExternalImageSibling::getAttachmentImpl() const
+{
+ return mImplementation.get();
+}
+
ImageState::ImageState(EGLenum target, ImageSibling *buffer, const AttributeMap &attribs)
: label(nullptr),
imageIndex(GetImageIndex(target, attribs)),
@@ -172,6 +242,13 @@
if (mState.source != nullptr)
{
mState.source->removeImageSource(this);
+
+ // If the source is an external object, delete it
+ if (IsExternalImageTarget(mState.sourceType))
+ {
+ delete mState.source;
+ }
+
mState.source = nullptr;
}
}
@@ -205,6 +282,9 @@
if (mState.source == sibling)
{
+ // The external source of an image cannot be redefined so it cannot be orpahend.
+ ASSERT(!IsExternalImageTarget(mState.sourceType));
+
// If the sibling is the source, it cannot be a target.
ASSERT(mState.targets.find(sibling) == mState.targets.end());
mState.source = nullptr;
@@ -231,11 +311,16 @@
return mState.format.info->textureAttachmentSupport(context->getClientVersion(),
context->getExtensions());
}
- if (IsRenderbufferTarget(mState.sourceType))
+ else if (IsRenderbufferTarget(mState.sourceType))
{
return mState.format.info->renderbufferSupport(context->getClientVersion(),
context->getExtensions());
}
+ else if (IsExternalImageTarget(mState.sourceType))
+ {
+ ASSERT(mState.source != nullptr);
+ return mState.source->isRenderable(context, GL_NONE, gl::ImageIndex());
+ }
UNREACHABLE();
return false;
@@ -248,10 +333,15 @@
return mState.format.info->textureSupport(context->getClientVersion(),
context->getExtensions());
}
- if (IsRenderbufferTarget(mState.sourceType))
+ else if (IsRenderbufferTarget(mState.sourceType))
{
return true;
}
+ else if (IsExternalImageTarget(mState.sourceType))
+ {
+ ASSERT(mState.source != nullptr);
+ return rx::GetAs<ExternalImageSibling>(mState.source)->isTextureable(context);
+ }
UNREACHABLE();
return false;
diff --git a/src/libANGLE/Image.h b/src/libANGLE/Image.h
index f1b52c7..0034ac5 100644
--- a/src/libANGLE/Image.h
+++ b/src/libANGLE/Image.h
@@ -23,6 +23,7 @@
{
class EGLImplFactory;
class ImageImpl;
+class ExternalImageSiblingImpl;
}
namespace egl
@@ -67,6 +68,41 @@
BindingPointer<Image> mTargetOf;
};
+// Wrapper for EGLImage sources that are not owned by ANGLE, these often have to do
+// platform-specific queries for format and size information.
+class ExternalImageSibling : public ImageSibling
+{
+ public:
+ ExternalImageSibling(rx::EGLImplFactory *factory,
+ const gl::Context *context,
+ EGLenum target,
+ EGLClientBuffer buffer,
+ const AttributeMap &attribs);
+
+ 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;
+ bool isTextureable(const gl::Context *context) const;
+
+ void onAttach(const gl::Context *context) override;
+ void onDetach(const gl::Context *context) override;
+ GLuint getId() const override;
+
+ gl::InitState initState(const gl::ImageIndex &imageIndex) const override;
+ void setInitState(const gl::ImageIndex &imageIndex, gl::InitState initState) override;
+
+ rx::ExternalImageSiblingImpl *getImplementation() const;
+
+ protected:
+ rx::FramebufferAttachmentObjectImpl *getAttachmentImpl() const override;
+
+ private:
+ std::unique_ptr<rx::ExternalImageSiblingImpl> mImplementation;
+};
+
struct ImageState : private angle::NonCopyable
{
ImageState(EGLenum target, ImageSibling *buffer, const AttributeMap &attribs);
diff --git a/src/libANGLE/renderer/DisplayImpl.cpp b/src/libANGLE/renderer/DisplayImpl.cpp
index 80c044a..cbfc1a8 100644
--- a/src/libANGLE/renderer/DisplayImpl.cpp
+++ b/src/libANGLE/renderer/DisplayImpl.cpp
@@ -44,6 +44,15 @@
return egl::EglBadDisplay() << "DisplayImpl::validateClientBuffer unimplemented.";
}
+egl::Error DisplayImpl::validateImageClientBuffer(const gl::Context *context,
+ EGLenum target,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) const
+{
+ UNREACHABLE();
+ return egl::EglBadDisplay() << "DisplayImpl::validateImageClientBuffer unimplemented.";
+}
+
const egl::Caps &DisplayImpl::getCaps() const
{
if (!mCapsInitialized)
diff --git a/src/libANGLE/renderer/DisplayImpl.h b/src/libANGLE/renderer/DisplayImpl.h
index cb3515d..45bedd9 100644
--- a/src/libANGLE/renderer/DisplayImpl.h
+++ b/src/libANGLE/renderer/DisplayImpl.h
@@ -66,6 +66,10 @@
EGLenum buftype,
EGLClientBuffer clientBuffer,
const egl::AttributeMap &attribs) const;
+ virtual egl::Error validateImageClientBuffer(const gl::Context *context,
+ EGLenum target,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) const;
virtual std::string getVendorString() const = 0;
diff --git a/src/libANGLE/renderer/EGLImplFactory.h b/src/libANGLE/renderer/EGLImplFactory.h
index 72530f0..181cc01 100644
--- a/src/libANGLE/renderer/EGLImplFactory.h
+++ b/src/libANGLE/renderer/EGLImplFactory.h
@@ -31,6 +31,7 @@
{
class ContextImpl;
class ImageImpl;
+class ExternalImageSiblingImpl;
class SurfaceImpl;
class EGLImplFactory : angle::NonCopyable
@@ -41,16 +42,16 @@
virtual SurfaceImpl *createWindowSurface(const egl::SurfaceState &state,
EGLNativeWindowType window,
- const egl::AttributeMap &attribs) = 0;
+ const egl::AttributeMap &attribs) = 0;
virtual SurfaceImpl *createPbufferSurface(const egl::SurfaceState &state,
- const egl::AttributeMap &attribs) = 0;
+ const egl::AttributeMap &attribs) = 0;
virtual SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
EGLenum buftype,
EGLClientBuffer clientBuffer,
const egl::AttributeMap &attribs) = 0;
virtual SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
NativePixmapType nativePixmap,
- const egl::AttributeMap &attribs) = 0;
+ const egl::AttributeMap &attribs) = 0;
virtual ImageImpl *createImage(const egl::ImageState &state,
const gl::Context *context,
@@ -65,6 +66,15 @@
virtual StreamProducerImpl *createStreamProducerD3DTexture(
egl::Stream::ConsumerType consumerType,
const egl::AttributeMap &attribs) = 0;
+
+ virtual ExternalImageSiblingImpl *createExternalImageSibling(const gl::Context *context,
+ EGLenum target,
+ EGLClientBuffer buffer,
+ const egl::AttributeMap &attribs)
+ {
+ UNREACHABLE();
+ return nullptr;
+ }
};
} // namespace rx
diff --git a/src/libANGLE/renderer/ImageImpl.h b/src/libANGLE/renderer/ImageImpl.h
index d044639..8f5d720 100644
--- a/src/libANGLE/renderer/ImageImpl.h
+++ b/src/libANGLE/renderer/ImageImpl.h
@@ -11,6 +11,8 @@
#include "common/angleutils.h"
#include "libANGLE/Error.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/FramebufferAttachmentObjectImpl.h"
namespace gl
{
@@ -26,6 +28,18 @@
namespace rx
{
+class ExternalImageSiblingImpl : public FramebufferAttachmentObjectImpl
+{
+ public:
+ virtual ~ExternalImageSiblingImpl() {}
+
+ virtual gl::Format getFormat() const = 0;
+ virtual bool isRenderable(const gl::Context *context) const = 0;
+ virtual bool isTexturable(const gl::Context *context) const = 0;
+ virtual gl::Extents getSize() const = 0;
+ virtual size_t getSamples() const = 0;
+};
+
class ImageImpl : angle::NonCopyable
{
public:
diff --git a/src/libANGLE/renderer/gl/egl/DisplayEGL.cpp b/src/libANGLE/renderer/gl/egl/DisplayEGL.cpp
index 54c8056..e19fa47 100644
--- a/src/libANGLE/renderer/gl/egl/DisplayEGL.cpp
+++ b/src/libANGLE/renderer/gl/egl/DisplayEGL.cpp
@@ -131,6 +131,8 @@
outExtensions->glTexture3DImage = mEGL->hasExtension("EGL_KHR_gl_texture_3D_image");
outExtensions->glRenderbufferImage = mEGL->hasExtension("EGL_KHR_gl_renderbuffer_image");
+ outExtensions->imageNativeBuffer = mEGL->hasExtension("EGL_ANDROID_image_native_buffer");
+
DisplayGL::generateExtensions(outExtensions);
}
diff --git a/src/libANGLE/renderer/gl/egl/ExternalImageSiblingEGL.h b/src/libANGLE/renderer/gl/egl/ExternalImageSiblingEGL.h
new file mode 100644
index 0000000..17c8631
--- /dev/null
+++ b/src/libANGLE/renderer/gl/egl/ExternalImageSiblingEGL.h
@@ -0,0 +1,29 @@
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ExternalImageSiblingEGL.h: Defines the ExternalImageSiblingEGL interface to abstract all external
+// image siblings in the EGL backend
+
+#ifndef LIBANGLE_RENDERER_GL_EGL_EXTERNALIMAGESIBLINGEGL_H_
+#define LIBANGLE_RENDERER_GL_EGL_EXTERNALIMAGESIBLINGEGL_H_
+
+#include "libANGLE/renderer/ImageImpl.h"
+
+namespace rx
+{
+
+class ExternalImageSiblingEGL : public ExternalImageSiblingImpl
+{
+ public:
+ ExternalImageSiblingEGL() {}
+ virtual ~ExternalImageSiblingEGL() {}
+
+ virtual EGLClientBuffer getBuffer() const = 0;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_GL_EGL_EXTERNALIMAGESIBLINGEGL_H_
diff --git a/src/libANGLE/renderer/gl/egl/ImageEGL.cpp b/src/libANGLE/renderer/gl/egl/ImageEGL.cpp
index 12b5ceb..6a903fa 100644
--- a/src/libANGLE/renderer/gl/egl/ImageEGL.cpp
+++ b/src/libANGLE/renderer/gl/egl/ImageEGL.cpp
@@ -15,6 +15,7 @@
#include "libANGLE/renderer/gl/StateManagerGL.h"
#include "libANGLE/renderer/gl/TextureGL.h"
#include "libANGLE/renderer/gl/egl/ContextEGL.h"
+#include "libANGLE/renderer/gl/egl/ExternalImageSiblingEGL.h"
#include "libANGLE/renderer/gl/egl/FunctionsEGL.h"
namespace rx
@@ -71,6 +72,13 @@
buffer = gl_egl::GLObjectHandleToEGLClientBuffer(renderbufferGL->getRenderbufferID());
mNativeInternalFormat = renderbufferGL->getNativeInternalFormat();
}
+ else if (egl::IsExternalImageTarget(mTarget))
+ {
+ const ExternalImageSiblingEGL *externalImageSibling =
+ GetImplAs<ExternalImageSiblingEGL>(GetAs<egl::ExternalImageSibling>(mState.source));
+ buffer = externalImageSibling->getBuffer();
+ mNativeInternalFormat = externalImageSibling->getFormat().info->sizedInternalFormat;
+ }
else
{
UNREACHABLE();
diff --git a/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.cpp b/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.cpp
index 3b9459b..f1ddecf 100644
--- a/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.cpp
+++ b/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.cpp
@@ -22,6 +22,7 @@
#include "libANGLE/renderer/gl/egl/PbufferSurfaceEGL.h"
#include "libANGLE/renderer/gl/egl/RendererEGL.h"
#include "libANGLE/renderer/gl/egl/WindowSurfaceEGL.h"
+#include "libANGLE/renderer/gl/egl/android/NativeBufferImageSiblingAndroid.h"
#include "libANGLE/renderer/gl/renderergl_utils.h"
namespace
@@ -453,6 +454,37 @@
return ANativeWindow_getFormat(window) >= 0;
}
+egl::Error DisplayAndroid::validateImageClientBuffer(const gl::Context *context,
+ EGLenum target,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) const
+{
+ switch (target)
+ {
+ case EGL_NATIVE_BUFFER_ANDROID:
+ return egl::NoError();
+
+ default:
+ return DisplayEGL::validateImageClientBuffer(context, target, clientBuffer, attribs);
+ }
+}
+
+ExternalImageSiblingImpl *DisplayAndroid::createExternalImageSibling(
+ const gl::Context *context,
+ EGLenum target,
+ EGLClientBuffer buffer,
+ const egl::AttributeMap &attribs)
+{
+ switch (target)
+ {
+ case EGL_NATIVE_BUFFER_ANDROID:
+ return new NativeBufferImageSiblingAndroid(buffer);
+
+ default:
+ return DisplayEGL::createExternalImageSibling(context, target, buffer, attribs);
+ }
+}
+
DeviceImpl *DisplayAndroid::createDevice()
{
UNIMPLEMENTED();
diff --git a/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.h b/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.h
index cf75d36..e80f507 100644
--- a/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.h
+++ b/src/libANGLE/renderer/gl/egl/android/DisplayAndroid.h
@@ -54,6 +54,15 @@
egl::Error restoreLostDevice(const egl::Display *display) override;
bool isValidNativeWindow(EGLNativeWindowType window) const override;
+ egl::Error validateImageClientBuffer(const gl::Context *context,
+ EGLenum target,
+ EGLClientBuffer clientBuffer,
+ const egl::AttributeMap &attribs) const override;
+
+ ExternalImageSiblingImpl *createExternalImageSibling(const gl::Context *context,
+ EGLenum target,
+ EGLClientBuffer buffer,
+ const egl::AttributeMap &attribs) override;
DeviceImpl *createDevice() override;
diff --git a/src/libANGLE/renderer/gl/egl/android/NativeBufferImageSiblingAndroid.cpp b/src/libANGLE/renderer/gl/egl/android/NativeBufferImageSiblingAndroid.cpp
new file mode 100644
index 0000000..f3125b9
--- /dev/null
+++ b/src/libANGLE/renderer/gl/egl/android/NativeBufferImageSiblingAndroid.cpp
@@ -0,0 +1,98 @@
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// NativeBufferImageSiblingAndroid.cpp: Implements the NativeBufferImageSiblingAndroid class
+
+#include "libANGLE/renderer/gl/egl/android/NativeBufferImageSiblingAndroid.h"
+
+#include "libANGLE/renderer/gl/egl/android/android_util.h"
+
+// Taken from cutils/native_handle.h:
+// https://android.googlesource.com/platform/system/core/+/master/libcutils/include/cutils/native_handle.h
+typedef struct native_handle
+{
+ int version; /* sizeof(native_handle_t) */
+ int numFds; /* number of file-descriptors at &data[0] */
+ int numInts; /* number of ints at &data[numFds] */
+ int data[0]; /* numFds + numInts ints */
+} native_handle_t;
+
+// Taken from nativebase/nativebase.h
+// https://android.googlesource.com/platform/frameworks/native/+/master/libs/nativebase/include/nativebase/nativebase.h
+typedef const native_handle_t *buffer_handle_t;
+
+typedef struct android_native_base_t
+{
+ /* a magic value defined by the actual EGL native type */
+ int magic;
+ /* the sizeof() of the actual EGL native type */
+ int version;
+ void *reserved[4];
+ /* reference-counting interface */
+ void (*incRef)(struct android_native_base_t *base);
+ void (*decRef)(struct android_native_base_t *base);
+} android_native_base_t;
+
+typedef struct ANativeWindowBuffer
+{
+ struct android_native_base_t common;
+ int width;
+ int height;
+ int stride;
+ int format;
+ int usage_deprecated;
+ uintptr_t layerCount;
+ void *reserved[1];
+ const native_handle_t *handle;
+ uint64_t usage;
+ // we needed extra space for storing the 64-bits usage flags
+ // the number of slots to use from reserved_proc depends on the
+ // architecture.
+ void *reserved_proc[8 - (sizeof(uint64_t) / sizeof(void *))];
+} ANativeWindowBuffer_t;
+
+namespace rx
+{
+NativeBufferImageSiblingAndroid::NativeBufferImageSiblingAndroid(EGLClientBuffer buffer)
+ : mBuffer(static_cast<struct ANativeWindowBuffer *>(buffer))
+{
+}
+
+NativeBufferImageSiblingAndroid::~NativeBufferImageSiblingAndroid()
+{
+}
+
+gl::Format NativeBufferImageSiblingAndroid::getFormat() const
+{
+ return gl::Format(android::NativePixelFormatToGLInternalFormat(mBuffer->format));
+}
+
+bool NativeBufferImageSiblingAndroid::isRenderable(const gl::Context *context) const
+{
+ return true;
+}
+
+bool NativeBufferImageSiblingAndroid::isTexturable(const gl::Context *context) const
+{
+ return true;
+}
+
+gl::Extents NativeBufferImageSiblingAndroid::getSize() const
+{
+ return gl::Extents(mBuffer->width, mBuffer->height, 1);
+}
+
+size_t NativeBufferImageSiblingAndroid::getSamples() const
+{
+ return 0;
+}
+
+EGLClientBuffer NativeBufferImageSiblingAndroid::getBuffer() const
+{
+ return static_cast<EGLClientBuffer>(mBuffer);
+}
+
+} // namespace rx
diff --git a/src/libANGLE/renderer/gl/egl/android/NativeBufferImageSiblingAndroid.h b/src/libANGLE/renderer/gl/egl/android/NativeBufferImageSiblingAndroid.h
new file mode 100644
index 0000000..20c8960
--- /dev/null
+++ b/src/libANGLE/renderer/gl/egl/android/NativeBufferImageSiblingAndroid.h
@@ -0,0 +1,42 @@
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// NativeBufferImageSiblingAndroid.h: Defines the NativeBufferImageSiblingAndroid to wrap EGL images
+// created from ANativeWindowBuffer objects
+
+#ifndef LIBANGLE_RENDERER_GL_EGL_ANDROID_NATIVEBUFFERIMAGESIBLINGANDROID_H_
+#define LIBANGLE_RENDERER_GL_EGL_ANDROID_NATIVEBUFFERIMAGESIBLINGANDROID_H_
+
+#include "libANGLE/renderer/gl/egl/ExternalImageSiblingEGL.h"
+
+struct ANativeWindowBuffer;
+
+namespace rx
+{
+
+class NativeBufferImageSiblingAndroid : public ExternalImageSiblingEGL
+{
+ public:
+ NativeBufferImageSiblingAndroid(EGLClientBuffer buffer);
+ virtual ~NativeBufferImageSiblingAndroid();
+
+ // ExternalImageSiblingImpl interface
+ gl::Format getFormat() const override;
+ bool isRenderable(const gl::Context *context) const override;
+ bool isTexturable(const gl::Context *context) const override;
+ gl::Extents getSize() const override;
+ size_t getSamples() const override;
+
+ // ExternalImageSiblingEGL interface
+ EGLClientBuffer getBuffer() const override;
+
+ private:
+ struct ANativeWindowBuffer *mBuffer;
+};
+
+} // namespace rx
+
+#endif // LIBANGLE_RENDERER_GL_EGL_ANDROID_NATIVEBUFFERIMAGESIBLINGANDROID_H_
diff --git a/src/libANGLE/renderer/gl/egl/android/android_util.cpp b/src/libANGLE/renderer/gl/egl/android/android_util.cpp
new file mode 100644
index 0000000..8ead15d
--- /dev/null
+++ b/src/libANGLE/renderer/gl/egl/android/android_util.cpp
@@ -0,0 +1,158 @@
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// android_util.cpp: Utilities for the using the Android platform
+
+#include "libANGLE/renderer/gl/egl/android/android_util.h"
+
+namespace rx
+{
+
+namespace
+{
+
+// Taken from android/hardware_buffer.h
+// https://android.googlesource.com/platform/frameworks/native/+/master/libs/nativewindow/include/android/hardware_buffer.h
+
+// AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM AHARDWAREBUFFER_FORMAT_B4G4R4A4_UNORM,
+// AHARDWAREBUFFER_FORMAT_B5G5R5A1_UNORM formats were deprecated and re-added explicitly.
+
+// clang-format off
+/**
+ * Buffer pixel formats.
+ */
+enum {
+ /**
+ * Corresponding formats:
+ * Vulkan: VK_FORMAT_R8G8B8A8_UNORM
+ * OpenGL ES: GL_RGBA8
+ */
+ AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM = 1,
+ /**
+ * 32 bits per pixel, 8 bits per channel format where alpha values are
+ * ignored (always opaque).
+ * Corresponding formats:
+ * Vulkan: VK_FORMAT_R8G8B8A8_UNORM
+ * OpenGL ES: GL_RGB8
+ */
+ AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM = 2,
+ /**
+ * Corresponding formats:
+ * Vulkan: VK_FORMAT_R8G8B8_UNORM
+ * OpenGL ES: GL_RGB8
+ */
+ AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM = 3,
+ /**
+ * Corresponding formats:
+ * Vulkan: VK_FORMAT_R5G6B5_UNORM_PACK16
+ * OpenGL ES: GL_RGB565
+ */
+ AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM = 4,
+ AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM = 5,
+ AHARDWAREBUFFER_FORMAT_B4G4R4A4_UNORM = 6,
+ AHARDWAREBUFFER_FORMAT_B5G5R5A1_UNORM = 7,
+ /**
+ * Corresponding formats:
+ * Vulkan: VK_FORMAT_R16G16B16A16_SFLOAT
+ * OpenGL ES: GL_RGBA16F
+ */
+ AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT = 0x16,
+ /**
+ * Corresponding formats:
+ * Vulkan: VK_FORMAT_A2B10G10R10_UNORM_PACK32
+ * OpenGL ES: GL_RGB10_A2
+ */
+ AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM = 0x2b,
+ /**
+ * An opaque binary blob format that must have height 1, with width equal to
+ * the buffer size in bytes.
+ */
+ AHARDWAREBUFFER_FORMAT_BLOB = 0x21,
+ /**
+ * Corresponding formats:
+ * Vulkan: VK_FORMAT_D16_UNORM
+ * OpenGL ES: GL_DEPTH_COMPONENT16
+ */
+ AHARDWAREBUFFER_FORMAT_D16_UNORM = 0x30,
+ /**
+ * Corresponding formats:
+ * Vulkan: VK_FORMAT_X8_D24_UNORM_PACK32
+ * OpenGL ES: GL_DEPTH_COMPONENT24
+ */
+ AHARDWAREBUFFER_FORMAT_D24_UNORM = 0x31,
+ /**
+ * Corresponding formats:
+ * Vulkan: VK_FORMAT_D24_UNORM_S8_UINT
+ * OpenGL ES: GL_DEPTH24_STENCIL8
+ */
+ AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT = 0x32,
+ /**
+ * Corresponding formats:
+ * Vulkan: VK_FORMAT_D32_SFLOAT
+ * OpenGL ES: GL_DEPTH_COMPONENT32F
+ */
+ AHARDWAREBUFFER_FORMAT_D32_FLOAT = 0x33,
+ /**
+ * Corresponding formats:
+ * Vulkan: VK_FORMAT_D32_SFLOAT_S8_UINT
+ * OpenGL ES: GL_DEPTH32F_STENCIL8
+ */
+ AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT = 0x34,
+ /**
+ * Corresponding formats:
+ * Vulkan: VK_FORMAT_S8_UINT
+ * OpenGL ES: GL_STENCIL_INDEX8
+ */
+ AHARDWAREBUFFER_FORMAT_S8_UINT = 0x35,
+};
+// clang-format on
+
+} // anonymous namespace
+
+namespace android
+{
+GLenum NativePixelFormatToGLInternalFormat(int pixelFormat)
+{
+ switch (pixelFormat)
+ {
+ case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
+ return GL_RGBA8;
+ case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM:
+ return GL_RGB8;
+ case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
+ return GL_RGB8;
+ case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
+ return GL_RGB565;
+ case AHARDWAREBUFFER_FORMAT_B8G8R8A8_UNORM:
+ return GL_BGRA8_EXT;
+ case AHARDWAREBUFFER_FORMAT_B4G4R4A4_UNORM:
+ return GL_RGBA4;
+ case AHARDWAREBUFFER_FORMAT_B5G5R5A1_UNORM:
+ return GL_RGB5_A1;
+ case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
+ return GL_RGBA16F;
+ case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
+ return GL_RGB10_A2;
+ case AHARDWAREBUFFER_FORMAT_BLOB:
+ return GL_NONE;
+ case AHARDWAREBUFFER_FORMAT_D16_UNORM:
+ return GL_DEPTH_COMPONENT16;
+ case AHARDWAREBUFFER_FORMAT_D24_UNORM:
+ return GL_DEPTH_COMPONENT24;
+ case AHARDWAREBUFFER_FORMAT_D24_UNORM_S8_UINT:
+ return GL_DEPTH24_STENCIL8;
+ case AHARDWAREBUFFER_FORMAT_D32_FLOAT:
+ return GL_DEPTH_COMPONENT32F;
+ case AHARDWAREBUFFER_FORMAT_D32_FLOAT_S8_UINT:
+ return GL_DEPTH32F_STENCIL8;
+ case AHARDWAREBUFFER_FORMAT_S8_UINT:
+ return GL_STENCIL_INDEX8;
+ default:
+ return GL_NONE;
+ }
+}
+}
+}
diff --git a/src/libANGLE/renderer/gl/egl/android/android_util.h b/src/libANGLE/renderer/gl/egl/android/android_util.h
new file mode 100644
index 0000000..aaad466
--- /dev/null
+++ b/src/libANGLE/renderer/gl/egl/android/android_util.h
@@ -0,0 +1,23 @@
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// android_util.h: Utilities for the using the Android platform
+
+#ifndef LIBANGLE_RENDERER_GL_EGL_ANDROID_ANDROID_UTIL_H_
+#define LIBANGLE_RENDERER_GL_EGL_ANDROID_ANDROID_UTIL_H_
+
+#include "angle_gl.h"
+
+namespace rx
+{
+
+namespace android
+{
+GLenum NativePixelFormatToGLInternalFormat(int pixelFormat);
+}
+}
+
+#endif // LIBANGLE_RENDERER_GL_EGL_ANDROID_ANDROID_UTIL_H_
\ No newline at end of file
diff --git a/src/libANGLE/validationEGL.cpp b/src/libANGLE/validationEGL.cpp
index ba3c5d4..0a944ad 100644
--- a/src/libANGLE/validationEGL.cpp
+++ b/src/libANGLE/validationEGL.cpp
@@ -1649,7 +1649,8 @@
EGLClientBuffer buffer,
const AttributeMap &attributes)
{
- ANGLE_TRY(ValidateContext(display, context));
+
+ ANGLE_TRY(ValidateDisplay(display));
const DisplayExtensions &displayExtensions = display->getExtensions();
@@ -1728,6 +1729,7 @@
return EglBadParameter() << "buffer cannot reference a 2D texture with the name 0.";
}
+ ANGLE_TRY(ValidateContext(display, context));
const gl::Texture *texture =
context->getTexture(egl_gl::EGLClientBufferToGLObjectHandle(buffer));
if (texture == nullptr || texture->getType() != gl::TextureType::_2D)
@@ -1770,6 +1772,7 @@
<< "buffer cannot reference a cubemap texture with the name 0.";
}
+ ANGLE_TRY(ValidateContext(display, context));
const gl::Texture *texture =
context->getTexture(egl_gl::EGLClientBufferToGLObjectHandle(buffer));
if (texture == nullptr || texture->getType() != gl::TextureType::CubeMap)
@@ -1815,6 +1818,7 @@
return EglBadParameter() << "buffer cannot reference a 3D texture with the name 0.";
}
+ ANGLE_TRY(ValidateContext(display, context));
const gl::Texture *texture =
context->getTexture(egl_gl::EGLClientBufferToGLObjectHandle(buffer));
if (texture == nullptr || texture->getType() != gl::TextureType::_3D)
@@ -1868,6 +1872,7 @@
<< "buffer cannot reference a renderbuffer with the name 0.";
}
+ ANGLE_TRY(ValidateContext(display, context));
const gl::Renderbuffer *renderbuffer =
context->getRenderbuffer(egl_gl::EGLClientBufferToGLObjectHandle(buffer));
if (renderbuffer == nullptr)
@@ -1882,6 +1887,22 @@
}
break;
+ case EGL_NATIVE_BUFFER_ANDROID:
+ {
+ if (!displayExtensions.imageNativeBuffer)
+ {
+ return EglBadParameter() << "EGL_ANDROID_image_native_buffer not supported.";
+ }
+
+ if (context != nullptr)
+ {
+ return EglBadContext() << "ctx must be EGL_NO_CONTEXT.";
+ }
+
+ ANGLE_TRY(display->validateImageClientBuffer(context, target, buffer, attributes));
+ }
+ break;
+
default:
return EglBadParameter()
<< "invalid target: 0x" << std::hex << std::uppercase << target;
diff --git a/src/libGLESv2.gni b/src/libGLESv2.gni
index 2a98dd6..fff5b6e 100644
--- a/src/libGLESv2.gni
+++ b/src/libGLESv2.gni
@@ -690,6 +690,7 @@
"src/libANGLE/renderer/gl/egl/ContextEGL.h",
"src/libANGLE/renderer/gl/egl/DisplayEGL.cpp",
"src/libANGLE/renderer/gl/egl/DisplayEGL.h",
+ "src/libANGLE/renderer/gl/egl/ExternalImageSiblingEGL.h",
"src/libANGLE/renderer/gl/egl/egl_utils.cpp",
"src/libANGLE/renderer/gl/egl/egl_utils.h",
"src/libANGLE/renderer/gl/egl/FunctionsEGL.cpp",
@@ -717,8 +718,12 @@
"src/libANGLE/renderer/gl/egl/ozone/SurfaceOzone.h",
]
libangle_gl_egl_android_sources = [
+ "src/libANGLE/renderer/gl/egl/android/android_util.cpp",
+ "src/libANGLE/renderer/gl/egl/android/android_util.h",
"src/libANGLE/renderer/gl/egl/android/DisplayAndroid.cpp",
"src/libANGLE/renderer/gl/egl/android/DisplayAndroid.h",
+ "src/libANGLE/renderer/gl/egl/android/NativeBufferImageSiblingAndroid.cpp",
+ "src/libANGLE/renderer/gl/egl/android/NativeBufferImageSiblingAndroid.h",
]
libangle_gl_cgl_sources = [
"src/libANGLE/renderer/gl/cgl/DisplayCGL.mm",