Commit c3ee7ec0 by Geoff Lang Committed by Commit Bot

Implement EGL_ANDROID_image_native_buffer.

BUG=angleproject:2508 Change-Id: I8ef2ce8320edeb336727905055f47bb299dec2ea Reviewed-on: https://chromium-review.googlesource.com/c/1238886Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarYuly Novikov <ynovikov@chromium.org> Commit-Queue: Geoff Lang <geofflang@chromium.org>
parent 19603b9e
...@@ -929,6 +929,18 @@ bool IsRenderbufferTarget(EGLenum target) ...@@ -929,6 +929,18 @@ bool IsRenderbufferTarget(EGLenum target)
return target == EGL_GL_RENDERBUFFER_KHR; 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) const char *GetGenericErrorMessage(EGLint error)
{ {
switch (error) switch (error)
......
...@@ -150,6 +150,7 @@ size_t CubeMapTextureTargetToLayerIndex(EGLenum target); ...@@ -150,6 +150,7 @@ size_t CubeMapTextureTargetToLayerIndex(EGLenum target);
EGLenum LayerIndexToCubeMapTextureTarget(size_t index); EGLenum LayerIndexToCubeMapTextureTarget(size_t index);
bool IsTextureTarget(EGLenum target); bool IsTextureTarget(EGLenum target);
bool IsRenderbufferTarget(EGLenum target); bool IsRenderbufferTarget(EGLenum target);
bool IsExternalImageTarget(EGLenum target);
const char *GetGenericErrorMessage(EGLint error); const char *GetGenericErrorMessage(EGLint error);
} // namespace egl } // namespace egl
......
...@@ -1356,7 +1356,8 @@ DisplayExtensions::DisplayExtensions() ...@@ -1356,7 +1356,8 @@ DisplayExtensions::DisplayExtensions()
iosurfaceClientBuffer(false), iosurfaceClientBuffer(false),
createContextExtensionsEnabled(false), createContextExtensionsEnabled(false),
presentationTime(false), presentationTime(false),
blobCache(false) blobCache(false),
imageNativeBuffer(false)
{ {
} }
...@@ -1405,6 +1406,7 @@ std::vector<std::string> DisplayExtensions::getStrings() const ...@@ -1405,6 +1406,7 @@ std::vector<std::string> DisplayExtensions::getStrings() const
InsertExtensionString("EGL_ANGLE_create_context_extensions_enabled", createContextExtensionsEnabled, &extensionStrings); InsertExtensionString("EGL_ANGLE_create_context_extensions_enabled", createContextExtensionsEnabled, &extensionStrings);
InsertExtensionString("EGL_ANDROID_presentation_time", presentationTime, &extensionStrings); InsertExtensionString("EGL_ANDROID_presentation_time", presentationTime, &extensionStrings);
InsertExtensionString("EGL_ANDROID_blob_cache", blobCache, &extensionStrings); InsertExtensionString("EGL_ANDROID_blob_cache", blobCache, &extensionStrings);
InsertExtensionString("EGL_ANDROID_image_native_buffer", imageNativeBuffer, &extensionStrings);
// TODO(jmadill): Enable this when complete. // TODO(jmadill): Enable this when complete.
//InsertExtensionString("KHR_create_context_no_error", createContextNoError, &extensionStrings); //InsertExtensionString("KHR_create_context_no_error", createContextNoError, &extensionStrings);
// clang-format on // clang-format on
......
...@@ -801,6 +801,9 @@ struct DisplayExtensions ...@@ -801,6 +801,9 @@ struct DisplayExtensions
// EGL_ANDROID_blob_cache // EGL_ANDROID_blob_cache
bool blobCache; bool blobCache;
// EGL_ANDROID_image_native_buffer
bool imageNativeBuffer;
}; };
struct DeviceExtensions struct DeviceExtensions
......
...@@ -719,6 +719,10 @@ Error Display::createImage(const gl::Context *context, ...@@ -719,6 +719,10 @@ Error Display::createImage(const gl::Context *context,
{ {
sibling = context->getRenderbuffer(egl_gl::EGLClientBufferToGLObjectHandle(buffer)); sibling = context->getRenderbuffer(egl_gl::EGLClientBufferToGLObjectHandle(buffer));
} }
else if (IsExternalImageTarget(target))
{
sibling = new ExternalImageSibling(mImplementation, context, target, buffer, attribs);
}
else else
{ {
UNREACHABLE(); UNREACHABLE();
...@@ -1120,11 +1124,19 @@ bool Display::isValidNativeWindow(EGLNativeWindowType window) const ...@@ -1120,11 +1124,19 @@ bool Display::isValidNativeWindow(EGLNativeWindowType window) const
Error Display::validateClientBuffer(const Config *configuration, Error Display::validateClientBuffer(const Config *configuration,
EGLenum buftype, EGLenum buftype,
EGLClientBuffer clientBuffer, EGLClientBuffer clientBuffer,
const AttributeMap &attribs) const AttributeMap &attribs) const
{ {
return mImplementation->validateClientBuffer(configuration, buftype, clientBuffer, attribs); 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) bool Display::isValidDisplay(const egl::Display *display)
{ {
const ANGLEPlatformDisplayMap *anglePlatformDisplayMap = GetANGLEPlatformDisplayMap(); const ANGLEPlatformDisplayMap *anglePlatformDisplayMap = GetANGLEPlatformDisplayMap();
......
...@@ -125,7 +125,11 @@ class Display final : public LabeledObject, angle::NonCopyable ...@@ -125,7 +125,11 @@ class Display final : public LabeledObject, angle::NonCopyable
Error validateClientBuffer(const Config *configuration, Error validateClientBuffer(const Config *configuration,
EGLenum buftype, EGLenum buftype,
EGLClientBuffer clientBuffer, 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 isValidDisplay(const Display *display);
static bool isValidNativeDisplay(EGLNativeDisplayType display); static bool isValidNativeDisplay(EGLNativeDisplayType display);
......
...@@ -25,7 +25,7 @@ namespace ...@@ -25,7 +25,7 @@ namespace
{ {
gl::ImageIndex GetImageIndex(EGLenum eglTarget, const egl::AttributeMap &attribs) gl::ImageIndex GetImageIndex(EGLenum eglTarget, const egl::AttributeMap &attribs)
{ {
if (eglTarget == EGL_GL_RENDERBUFFER) if (!IsTextureTarget(eglTarget))
{ {
return gl::ImageIndex(); return gl::ImageIndex();
} }
...@@ -131,6 +131,76 @@ bool ImageSibling::isRenderable(const gl::Context *context, ...@@ -131,6 +131,76 @@ bool ImageSibling::isRenderable(const gl::Context *context,
return mTargetOf->isRenderable(context); 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) ImageState::ImageState(EGLenum target, ImageSibling *buffer, const AttributeMap &attribs)
: label(nullptr), : label(nullptr),
imageIndex(GetImageIndex(target, attribs)), imageIndex(GetImageIndex(target, attribs)),
...@@ -172,6 +242,13 @@ void Image::onDestroy(const Display *display) ...@@ -172,6 +242,13 @@ void Image::onDestroy(const Display *display)
if (mState.source != nullptr) if (mState.source != nullptr)
{ {
mState.source->removeImageSource(this); mState.source->removeImageSource(this);
// If the source is an external object, delete it
if (IsExternalImageTarget(mState.sourceType))
{
delete mState.source;
}
mState.source = nullptr; mState.source = nullptr;
} }
} }
...@@ -205,6 +282,9 @@ gl::Error Image::orphanSibling(const gl::Context *context, ImageSibling *sibling ...@@ -205,6 +282,9 @@ gl::Error Image::orphanSibling(const gl::Context *context, ImageSibling *sibling
if (mState.source == sibling) 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. // If the sibling is the source, it cannot be a target.
ASSERT(mState.targets.find(sibling) == mState.targets.end()); ASSERT(mState.targets.find(sibling) == mState.targets.end());
mState.source = nullptr; mState.source = nullptr;
...@@ -231,11 +311,16 @@ bool Image::isRenderable(const gl::Context *context) const ...@@ -231,11 +311,16 @@ bool Image::isRenderable(const gl::Context *context) const
return mState.format.info->textureAttachmentSupport(context->getClientVersion(), return mState.format.info->textureAttachmentSupport(context->getClientVersion(),
context->getExtensions()); context->getExtensions());
} }
if (IsRenderbufferTarget(mState.sourceType)) else if (IsRenderbufferTarget(mState.sourceType))
{ {
return mState.format.info->renderbufferSupport(context->getClientVersion(), return mState.format.info->renderbufferSupport(context->getClientVersion(),
context->getExtensions()); context->getExtensions());
} }
else if (IsExternalImageTarget(mState.sourceType))
{
ASSERT(mState.source != nullptr);
return mState.source->isRenderable(context, GL_NONE, gl::ImageIndex());
}
UNREACHABLE(); UNREACHABLE();
return false; return false;
...@@ -248,10 +333,15 @@ bool Image::isTexturable(const gl::Context *context) const ...@@ -248,10 +333,15 @@ bool Image::isTexturable(const gl::Context *context) const
return mState.format.info->textureSupport(context->getClientVersion(), return mState.format.info->textureSupport(context->getClientVersion(),
context->getExtensions()); context->getExtensions());
} }
if (IsRenderbufferTarget(mState.sourceType)) else if (IsRenderbufferTarget(mState.sourceType))
{ {
return true; return true;
} }
else if (IsExternalImageTarget(mState.sourceType))
{
ASSERT(mState.source != nullptr);
return rx::GetAs<ExternalImageSibling>(mState.source)->isTextureable(context);
}
UNREACHABLE(); UNREACHABLE();
return false; return false;
......
...@@ -23,6 +23,7 @@ namespace rx ...@@ -23,6 +23,7 @@ namespace rx
{ {
class EGLImplFactory; class EGLImplFactory;
class ImageImpl; class ImageImpl;
class ExternalImageSiblingImpl;
} }
namespace egl namespace egl
...@@ -67,6 +68,41 @@ class ImageSibling : public gl::FramebufferAttachmentObject ...@@ -67,6 +68,41 @@ class ImageSibling : public gl::FramebufferAttachmentObject
BindingPointer<Image> mTargetOf; 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 struct ImageState : private angle::NonCopyable
{ {
ImageState(EGLenum target, ImageSibling *buffer, const AttributeMap &attribs); ImageState(EGLenum target, ImageSibling *buffer, const AttributeMap &attribs);
......
...@@ -44,6 +44,15 @@ egl::Error DisplayImpl::validateClientBuffer(const egl::Config *configuration, ...@@ -44,6 +44,15 @@ egl::Error DisplayImpl::validateClientBuffer(const egl::Config *configuration,
return egl::EglBadDisplay() << "DisplayImpl::validateClientBuffer unimplemented."; 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 const egl::Caps &DisplayImpl::getCaps() const
{ {
if (!mCapsInitialized) if (!mCapsInitialized)
......
...@@ -66,6 +66,10 @@ class DisplayImpl : public EGLImplFactory ...@@ -66,6 +66,10 @@ class DisplayImpl : public EGLImplFactory
EGLenum buftype, EGLenum buftype,
EGLClientBuffer clientBuffer, EGLClientBuffer clientBuffer,
const egl::AttributeMap &attribs) const; 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; virtual std::string getVendorString() const = 0;
......
...@@ -31,6 +31,7 @@ namespace rx ...@@ -31,6 +31,7 @@ namespace rx
{ {
class ContextImpl; class ContextImpl;
class ImageImpl; class ImageImpl;
class ExternalImageSiblingImpl;
class SurfaceImpl; class SurfaceImpl;
class EGLImplFactory : angle::NonCopyable class EGLImplFactory : angle::NonCopyable
...@@ -41,16 +42,16 @@ class EGLImplFactory : angle::NonCopyable ...@@ -41,16 +42,16 @@ class EGLImplFactory : angle::NonCopyable
virtual SurfaceImpl *createWindowSurface(const egl::SurfaceState &state, virtual SurfaceImpl *createWindowSurface(const egl::SurfaceState &state,
EGLNativeWindowType window, EGLNativeWindowType window,
const egl::AttributeMap &attribs) = 0; const egl::AttributeMap &attribs) = 0;
virtual SurfaceImpl *createPbufferSurface(const egl::SurfaceState &state, virtual SurfaceImpl *createPbufferSurface(const egl::SurfaceState &state,
const egl::AttributeMap &attribs) = 0; const egl::AttributeMap &attribs) = 0;
virtual SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state, virtual SurfaceImpl *createPbufferFromClientBuffer(const egl::SurfaceState &state,
EGLenum buftype, EGLenum buftype,
EGLClientBuffer clientBuffer, EGLClientBuffer clientBuffer,
const egl::AttributeMap &attribs) = 0; const egl::AttributeMap &attribs) = 0;
virtual SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state, virtual SurfaceImpl *createPixmapSurface(const egl::SurfaceState &state,
NativePixmapType nativePixmap, NativePixmapType nativePixmap,
const egl::AttributeMap &attribs) = 0; const egl::AttributeMap &attribs) = 0;
virtual ImageImpl *createImage(const egl::ImageState &state, virtual ImageImpl *createImage(const egl::ImageState &state,
const gl::Context *context, const gl::Context *context,
...@@ -65,6 +66,15 @@ class EGLImplFactory : angle::NonCopyable ...@@ -65,6 +66,15 @@ class EGLImplFactory : angle::NonCopyable
virtual StreamProducerImpl *createStreamProducerD3DTexture( virtual StreamProducerImpl *createStreamProducerD3DTexture(
egl::Stream::ConsumerType consumerType, egl::Stream::ConsumerType consumerType,
const egl::AttributeMap &attribs) = 0; 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 } // namespace rx
......
...@@ -11,6 +11,8 @@ ...@@ -11,6 +11,8 @@
#include "common/angleutils.h" #include "common/angleutils.h"
#include "libANGLE/Error.h" #include "libANGLE/Error.h"
#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/FramebufferAttachmentObjectImpl.h"
namespace gl namespace gl
{ {
...@@ -26,6 +28,18 @@ struct ImageState; ...@@ -26,6 +28,18 @@ struct ImageState;
namespace rx 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 class ImageImpl : angle::NonCopyable
{ {
public: public:
......
...@@ -131,6 +131,8 @@ void DisplayEGL::generateExtensions(egl::DisplayExtensions *outExtensions) const ...@@ -131,6 +131,8 @@ void DisplayEGL::generateExtensions(egl::DisplayExtensions *outExtensions) const
outExtensions->glTexture3DImage = mEGL->hasExtension("EGL_KHR_gl_texture_3D_image"); outExtensions->glTexture3DImage = mEGL->hasExtension("EGL_KHR_gl_texture_3D_image");
outExtensions->glRenderbufferImage = mEGL->hasExtension("EGL_KHR_gl_renderbuffer_image"); outExtensions->glRenderbufferImage = mEGL->hasExtension("EGL_KHR_gl_renderbuffer_image");
outExtensions->imageNativeBuffer = mEGL->hasExtension("EGL_ANDROID_image_native_buffer");
DisplayGL::generateExtensions(outExtensions); DisplayGL::generateExtensions(outExtensions);
} }
......
//
// 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_
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "libANGLE/renderer/gl/StateManagerGL.h" #include "libANGLE/renderer/gl/StateManagerGL.h"
#include "libANGLE/renderer/gl/TextureGL.h" #include "libANGLE/renderer/gl/TextureGL.h"
#include "libANGLE/renderer/gl/egl/ContextEGL.h" #include "libANGLE/renderer/gl/egl/ContextEGL.h"
#include "libANGLE/renderer/gl/egl/ExternalImageSiblingEGL.h"
#include "libANGLE/renderer/gl/egl/FunctionsEGL.h" #include "libANGLE/renderer/gl/egl/FunctionsEGL.h"
namespace rx namespace rx
...@@ -71,6 +72,13 @@ egl::Error ImageEGL::initialize(const egl::Display *display) ...@@ -71,6 +72,13 @@ egl::Error ImageEGL::initialize(const egl::Display *display)
buffer = gl_egl::GLObjectHandleToEGLClientBuffer(renderbufferGL->getRenderbufferID()); buffer = gl_egl::GLObjectHandleToEGLClientBuffer(renderbufferGL->getRenderbufferID());
mNativeInternalFormat = renderbufferGL->getNativeInternalFormat(); 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 else
{ {
UNREACHABLE(); UNREACHABLE();
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "libANGLE/renderer/gl/egl/PbufferSurfaceEGL.h" #include "libANGLE/renderer/gl/egl/PbufferSurfaceEGL.h"
#include "libANGLE/renderer/gl/egl/RendererEGL.h" #include "libANGLE/renderer/gl/egl/RendererEGL.h"
#include "libANGLE/renderer/gl/egl/WindowSurfaceEGL.h" #include "libANGLE/renderer/gl/egl/WindowSurfaceEGL.h"
#include "libANGLE/renderer/gl/egl/android/NativeBufferImageSiblingAndroid.h"
#include "libANGLE/renderer/gl/renderergl_utils.h" #include "libANGLE/renderer/gl/renderergl_utils.h"
namespace namespace
...@@ -453,6 +454,37 @@ bool DisplayAndroid::isValidNativeWindow(EGLNativeWindowType window) const ...@@ -453,6 +454,37 @@ bool DisplayAndroid::isValidNativeWindow(EGLNativeWindowType window) const
return ANativeWindow_getFormat(window) >= 0; 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() DeviceImpl *DisplayAndroid::createDevice()
{ {
UNIMPLEMENTED(); UNIMPLEMENTED();
......
...@@ -54,6 +54,15 @@ class DisplayAndroid : public DisplayEGL ...@@ -54,6 +54,15 @@ class DisplayAndroid : public DisplayEGL
egl::Error restoreLostDevice(const egl::Display *display) override; egl::Error restoreLostDevice(const egl::Display *display) override;
bool isValidNativeWindow(EGLNativeWindowType window) const 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; DeviceImpl *createDevice() override;
......
//
// 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
//
// 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_
//
// 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;
}
}
}
}
//
// 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
...@@ -1649,7 +1649,8 @@ Error ValidateCreateImageKHR(const Display *display, ...@@ -1649,7 +1649,8 @@ Error ValidateCreateImageKHR(const Display *display,
EGLClientBuffer buffer, EGLClientBuffer buffer,
const AttributeMap &attributes) const AttributeMap &attributes)
{ {
ANGLE_TRY(ValidateContext(display, context));
ANGLE_TRY(ValidateDisplay(display));
const DisplayExtensions &displayExtensions = display->getExtensions(); const DisplayExtensions &displayExtensions = display->getExtensions();
...@@ -1728,6 +1729,7 @@ Error ValidateCreateImageKHR(const Display *display, ...@@ -1728,6 +1729,7 @@ Error ValidateCreateImageKHR(const Display *display,
return EglBadParameter() << "buffer cannot reference a 2D texture with the name 0."; return EglBadParameter() << "buffer cannot reference a 2D texture with the name 0.";
} }
ANGLE_TRY(ValidateContext(display, context));
const gl::Texture *texture = const gl::Texture *texture =
context->getTexture(egl_gl::EGLClientBufferToGLObjectHandle(buffer)); context->getTexture(egl_gl::EGLClientBufferToGLObjectHandle(buffer));
if (texture == nullptr || texture->getType() != gl::TextureType::_2D) if (texture == nullptr || texture->getType() != gl::TextureType::_2D)
...@@ -1770,6 +1772,7 @@ Error ValidateCreateImageKHR(const Display *display, ...@@ -1770,6 +1772,7 @@ Error ValidateCreateImageKHR(const Display *display,
<< "buffer cannot reference a cubemap texture with the name 0."; << "buffer cannot reference a cubemap texture with the name 0.";
} }
ANGLE_TRY(ValidateContext(display, context));
const gl::Texture *texture = const gl::Texture *texture =
context->getTexture(egl_gl::EGLClientBufferToGLObjectHandle(buffer)); context->getTexture(egl_gl::EGLClientBufferToGLObjectHandle(buffer));
if (texture == nullptr || texture->getType() != gl::TextureType::CubeMap) if (texture == nullptr || texture->getType() != gl::TextureType::CubeMap)
...@@ -1815,6 +1818,7 @@ Error ValidateCreateImageKHR(const Display *display, ...@@ -1815,6 +1818,7 @@ Error ValidateCreateImageKHR(const Display *display,
return EglBadParameter() << "buffer cannot reference a 3D texture with the name 0."; return EglBadParameter() << "buffer cannot reference a 3D texture with the name 0.";
} }
ANGLE_TRY(ValidateContext(display, context));
const gl::Texture *texture = const gl::Texture *texture =
context->getTexture(egl_gl::EGLClientBufferToGLObjectHandle(buffer)); context->getTexture(egl_gl::EGLClientBufferToGLObjectHandle(buffer));
if (texture == nullptr || texture->getType() != gl::TextureType::_3D) if (texture == nullptr || texture->getType() != gl::TextureType::_3D)
...@@ -1868,6 +1872,7 @@ Error ValidateCreateImageKHR(const Display *display, ...@@ -1868,6 +1872,7 @@ Error ValidateCreateImageKHR(const Display *display,
<< "buffer cannot reference a renderbuffer with the name 0."; << "buffer cannot reference a renderbuffer with the name 0.";
} }
ANGLE_TRY(ValidateContext(display, context));
const gl::Renderbuffer *renderbuffer = const gl::Renderbuffer *renderbuffer =
context->getRenderbuffer(egl_gl::EGLClientBufferToGLObjectHandle(buffer)); context->getRenderbuffer(egl_gl::EGLClientBufferToGLObjectHandle(buffer));
if (renderbuffer == nullptr) if (renderbuffer == nullptr)
...@@ -1882,6 +1887,22 @@ Error ValidateCreateImageKHR(const Display *display, ...@@ -1882,6 +1887,22 @@ Error ValidateCreateImageKHR(const Display *display,
} }
break; 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: default:
return EglBadParameter() return EglBadParameter()
<< "invalid target: 0x" << std::hex << std::uppercase << target; << "invalid target: 0x" << std::hex << std::uppercase << target;
......
...@@ -690,6 +690,7 @@ libangle_gl_egl_sources = [ ...@@ -690,6 +690,7 @@ libangle_gl_egl_sources = [
"src/libANGLE/renderer/gl/egl/ContextEGL.h", "src/libANGLE/renderer/gl/egl/ContextEGL.h",
"src/libANGLE/renderer/gl/egl/DisplayEGL.cpp", "src/libANGLE/renderer/gl/egl/DisplayEGL.cpp",
"src/libANGLE/renderer/gl/egl/DisplayEGL.h", "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.cpp",
"src/libANGLE/renderer/gl/egl/egl_utils.h", "src/libANGLE/renderer/gl/egl/egl_utils.h",
"src/libANGLE/renderer/gl/egl/FunctionsEGL.cpp", "src/libANGLE/renderer/gl/egl/FunctionsEGL.cpp",
...@@ -717,8 +718,12 @@ libangle_gl_ozone_sources = [ ...@@ -717,8 +718,12 @@ libangle_gl_ozone_sources = [
"src/libANGLE/renderer/gl/egl/ozone/SurfaceOzone.h", "src/libANGLE/renderer/gl/egl/ozone/SurfaceOzone.h",
] ]
libangle_gl_egl_android_sources = [ 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.cpp",
"src/libANGLE/renderer/gl/egl/android/DisplayAndroid.h", "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 = [ libangle_gl_cgl_sources = [
"src/libANGLE/renderer/gl/cgl/DisplayCGL.mm", "src/libANGLE/renderer/gl/cgl/DisplayCGL.mm",
......
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