Bug 1037147 - Replace SharedTextureHandle with a TextureClient variant r=mattwoodrow,snorp

This commit is contained in:
Jeff Gilbert 2014-09-12 13:39:20 -05:00
parent 8e1d73dfaf
commit a399ede263
25 changed files with 935 additions and 864 deletions

View File

@ -56,9 +56,10 @@ using namespace mozilla::dom;
#include "GLContextProvider.h"
#include "GLContext.h"
#include "TexturePoolOGL.h"
#include "GLSharedHandleHelpers.h"
#include "SurfaceTypes.h"
#include "EGLUtils.h"
using namespace mozilla;
using namespace mozilla::gl;
typedef nsNPAPIPluginInstance::VideoInfo VideoInfo;
@ -127,7 +128,7 @@ public:
mLock.Unlock();
}
SharedTextureHandle CreateSharedHandle()
EGLImage CreateEGLImage()
{
MutexAutoLock lock(mLock);
@ -137,18 +138,15 @@ public:
if (mTextureInfo.mWidth == 0 || mTextureInfo.mHeight == 0)
return 0;
SharedTextureHandle handle =
gl::CreateSharedHandle(sPluginContext,
gl::SharedTextureShareType::SameProcess,
(void*)mTextureInfo.mTexture,
gl::SharedTextureBufferType::TextureID);
GLuint& tex = mTextureInfo.mTexture;
EGLImage image = gl::CreateEGLImage(sPluginContext, tex);
// We want forget about this now, so delete the texture. Assigning it to zero
// ensures that we create a new one in Lock()
sPluginContext->fDeleteTextures(1, &mTextureInfo.mTexture);
mTextureInfo.mTexture = 0;
sPluginContext->fDeleteTextures(1, &tex);
tex = 0;
return handle;
return image;
}
private:
@ -985,17 +983,22 @@ void* nsNPAPIPluginInstance::AcquireContentWindow()
return mContentSurface->GetNativeWindow();
}
SharedTextureHandle nsNPAPIPluginInstance::CreateSharedHandle()
EGLImage
nsNPAPIPluginInstance::AsEGLImage()
{
if (mContentTexture) {
return mContentTexture->CreateSharedHandle();
} else if (mContentSurface) {
EnsureGLContext();
return gl::CreateSharedHandle(sPluginContext,
gl::SharedTextureShareType::SameProcess,
mContentSurface,
gl::SharedTextureBufferType::SurfaceTexture);
} else return 0;
if (!mContentTexture)
return 0;
return mContentTexture->CreateEGLImage();
}
nsSurfaceTexture*
nsNPAPIPluginInstance::AsSurfaceTexture()
{
if (!mContentSurface)
return nullptr;
return mContentSurface;
}
void* nsNPAPIPluginInstance::AcquireVideoWindow()

View File

@ -191,7 +191,8 @@ public:
// For ANPNativeWindow
void* AcquireContentWindow();
mozilla::gl::SharedTextureHandle CreateSharedHandle();
EGLImage AsEGLImage();
nsSurfaceTexture* AsSurfaceTexture();
// For ANPVideo
class VideoInfo {

View File

@ -22,7 +22,7 @@ using mozilla::DefaultXDisplay;
#include "nsSize.h"
#include "nsDisplayList.h"
#include "ImageLayers.h"
#include "SharedTextureImage.h"
#include "GLImages.h"
#include "nsObjectFrame.h"
#include "nsIPluginDocument.h"
#include "nsIStringStream.h"
@ -49,7 +49,7 @@ using mozilla::DefaultXDisplay;
#include "ImageContainer.h"
#include "nsIDOMHTMLCollection.h"
#include "GLContext.h"
#include "GLSharedHandleHelpers.h"
#include "EGLUtils.h"
#include "nsIContentInlines.h"
#include "mozilla/MiscEvents.h"
#include "mozilla/MouseEvents.h"
@ -148,6 +148,62 @@ nsPluginInstanceOwner::NotifyPaintWaiter(nsDisplayListBuilder* aBuilder)
}
}
#if MOZ_WIDGET_ANDROID
static void
AttachToContainerAsEGLImage(ImageContainer* container,
nsNPAPIPluginInstance* instance,
const LayoutDeviceRect& rect,
nsRefPtr<Image>* out_image)
{
MOZ_ASSERT(out_image);
MOZ_ASSERT(!*out_image);
EGLImage image = instance->AsEGLImage();
if (!image) {
return;
}
nsRefPtr<Image> img = container->CreateImage(ImageFormat::EGLIMAGE);
EGLImageImage::Data data;
data.mImage = image;
data.mSize = gfx::IntSize(rect.width, rect.height);
data.mInverted = instance->Inverted();
EGLImageImage* typedImg = static_cast<EGLImageImage*>(img.get());
typedImg->SetData(data);
*out_image = img;
}
static void
AttachToContainerAsSurfaceTexture(ImageContainer* container,
nsNPAPIPluginInstance* instance,
const LayoutDeviceRect& rect,
nsRefPtr<Image>* out_image)
{
MOZ_ASSERT(out_image);
MOZ_ASSERT(!*out_image);
nsSurfaceTexture* surfTex = instance->AsSurfaceTexture();
if (!surfTex) {
return;
}
nsRefPtr<Image> img = container->CreateImage(ImageFormat::SURFACE_TEXTURE);
SurfaceTextureImage::Data data;
data.mSurfTex = surfTex;
data.mSize = gfx::IntSize(rect.width, rect.height);
data.mInverted = instance->Inverted();
SurfaceTextureImage* typedImg = static_cast<SurfaceTextureImage*>(img.get());
typedImg->SetData(data);
*out_image = img;
}
#endif
already_AddRefed<ImageContainer>
nsPluginInstanceOwner::GetImageContainer()
{
@ -172,23 +228,19 @@ nsPluginInstanceOwner::GetImageContainer()
container = LayerManager::CreateImageContainer();
nsRefPtr<Image> img = container->CreateImage(ImageFormat::SHARED_TEXTURE);
SharedTextureImage::Data data;
data.mSize = gfx::IntSize(r.width, r.height);
data.mHandle = mInstance->CreateSharedHandle();
data.mShareType = mozilla::gl::SharedTextureShareType::SameProcess;
data.mInverted = mInstance->Inverted();
SharedTextureImage* pluginImage = static_cast<SharedTextureImage*>(img.get());
pluginImage->SetData(data);
// Try to get it as an EGLImage first.
nsRefPtr<Image> img;
AttachToContainerAsEGLImage(container, mInstance, r, &img);
if (!img) {
AttachToContainerAsSurfaceTexture(container, mInstance, r, &img);
}
MOZ_ASSERT(img);
container->SetCurrentImageInTransaction(img);
return container.forget();
#else
mInstance->GetImageContainer(getter_AddRefs(container));
#endif
mInstance->GetImageContainer(getter_AddRefs(container));
return container.forget();
}
@ -1113,7 +1165,8 @@ void nsPluginInstanceOwner::RemovePluginView()
sFullScreenInstance = nullptr;
}
void nsPluginInstanceOwner::GetVideos(nsTArray<nsNPAPIPluginInstance::VideoInfo*>& aVideos)
void
nsPluginInstanceOwner::GetVideos(nsTArray<nsNPAPIPluginInstance::VideoInfo*>& aVideos)
{
if (!mInstance)
return;
@ -1121,27 +1174,25 @@ void nsPluginInstanceOwner::GetVideos(nsTArray<nsNPAPIPluginInstance::VideoInfo*
mInstance->GetVideos(aVideos);
}
already_AddRefed<ImageContainer> nsPluginInstanceOwner::GetImageContainerForVideo(nsNPAPIPluginInstance::VideoInfo* aVideoInfo)
already_AddRefed<ImageContainer>
nsPluginInstanceOwner::GetImageContainerForVideo(nsNPAPIPluginInstance::VideoInfo* aVideoInfo)
{
nsRefPtr<ImageContainer> container = LayerManager::CreateImageContainer();
nsRefPtr<Image> img = container->CreateImage(ImageFormat::SHARED_TEXTURE);
nsRefPtr<Image> img = container->CreateImage(ImageFormat::SURFACE_TEXTURE);
SharedTextureImage::Data data;
SurfaceTextureImage::Data data;
data.mShareType = gl::SharedTextureShareType::SameProcess;
data.mHandle = gl::CreateSharedHandle(mInstance->GLContext(),
data.mShareType,
aVideoInfo->mSurfaceTexture,
gl::SharedTextureBufferType::SurfaceTexture);
data.mSurfTex = aVideoInfo->mSurfaceTexture;
// The logic below for Honeycomb is just a guess, but seems to work. We don't have a separate
// inverted flag for video.
data.mInverted = AndroidBridge::Bridge()->IsHoneycomb() ? true : mInstance->Inverted();
data.mSize = gfx::IntSize(aVideoInfo->mDimensions.width, aVideoInfo->mDimensions.height);
SharedTextureImage* pluginImage = static_cast<SharedTextureImage*>(img.get());
pluginImage->SetData(data);
SurfaceTextureImage* typedImg = static_cast<SurfaceTextureImage*>(img.get());
typedImg->SetData(data);
container->SetCurrentImageInTransaction(img);
return container.forget();

View File

@ -28,7 +28,7 @@
#include "gfxUtils.h"
#include "mozilla/gfx/2D.h"
#include "Layers.h"
#include "SharedTextureImage.h"
#include "ImageContainer.h"
#include "GLContext.h"
#include "GLContextProvider.h"

112
gfx/gl/EGLUtils.cpp Normal file
View File

@ -0,0 +1,112 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "EGLUtils.h"
#include "GLContextEGL.h"
namespace mozilla {
namespace gl {
bool
DoesEGLContextSupportSharingWithEGLImage(GLContext* gl)
{
return sEGLLibrary.HasKHRImageBase() &&
sEGLLibrary.HasKHRImageTexture2D() &&
gl->IsExtensionSupported(GLContext::OES_EGL_image);
}
EGLImage
CreateEGLImage(GLContext* gl, GLuint tex)
{
MOZ_ASSERT(DoesEGLContextSupportSharingWithEGLImage(gl));
EGLContext eglContext = GLContextEGL::Cast(gl)->GetEGLContext();
EGLImage image = sEGLLibrary.fCreateImage(EGL_DISPLAY(),
eglContext,
LOCAL_EGL_GL_TEXTURE_2D,
(EGLClientBuffer)tex,
nullptr);
return image;
}
////////////////////////////////////////////////////////////////////////
// EGLImageWrapper
/*static*/ EGLImageWrapper*
EGLImageWrapper::Create(GLContext* gl, GLuint tex)
{
MOZ_ASSERT(DoesEGLContextSupportSharingWithEGLImage(gl));
GLLibraryEGL& library = sEGLLibrary;
EGLDisplay display = EGL_DISPLAY();
EGLContext eglContext = GLContextEGL::Cast(gl)->GetEGLContext();
EGLImage image = library.fCreateImage(display,
eglContext,
LOCAL_EGL_GL_TEXTURE_2D,
(EGLClientBuffer)tex,
nullptr);
if (!image) {
#ifdef DEBUG
printf_stderr("Could not create EGL images: ERROR (0x%04x)\n",
sEGLLibrary.fGetError());
#endif
return nullptr;
}
return new EGLImageWrapper(library, display, image);
}
EGLImageWrapper::~EGLImageWrapper()
{
mLibrary.fDestroyImage(mDisplay, mImage);
}
bool
EGLImageWrapper::FenceSync(GLContext* gl)
{
MOZ_ASSERT(!mSync);
if (mLibrary.IsExtensionSupported(GLLibraryEGL::KHR_fence_sync)) {
mSync = mLibrary.fCreateSync(mDisplay,
LOCAL_EGL_SYNC_FENCE,
nullptr);
// We need to flush to make sure the sync object enters the command stream;
// we can't use EGL_SYNC_FLUSH_COMMANDS_BIT at wait time, because the wait
// happens on a different thread/context.
gl->fFlush();
}
if (!mSync) {
// we failed to create one, so just do a finish
gl->fFinish();
}
return true;
}
bool
EGLImageWrapper::ClientWaitSync()
{
if (!mSync) {
// if we have no sync object, then we did a Finish() earlier
return true;
}
// wait at most 1 second; this should really be never/rarely hit
const uint64_t ns_per_ms = 1000 * 1000;
EGLTime timeout = 1000 * ns_per_ms;
EGLint result = mLibrary.fClientWaitSync(mDisplay,
mSync,
0,
timeout);
mLibrary.fDestroySync(mDisplay, mSync);
mSync = nullptr;
return result == LOCAL_EGL_CONDITION_SATISFIED;
}
} // namespace gl
} // namespace mozilla

60
gfx/gl/EGLUtils.h Normal file
View File

@ -0,0 +1,60 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef EGLUTILS_H_
#define EGLUTILS_H_
#include "GLContextTypes.h"
#include "GLTypes.h"
//#include "mozilla/gfx/Types.h"
namespace mozilla {
namespace gl {
class GLLibraryEGL;
bool DoesEGLContextSupportSharingWithEGLImage(GLContext* gl);
EGLImage CreateEGLImage(GLContext* gl, GLuint tex);
////////////////////////////////////////////////////////////////////////
// EGLImageWrapper
class EGLImageWrapper
{
public:
static EGLImageWrapper* Create(GLContext* gl, GLuint tex);
private:
GLLibraryEGL& mLibrary;
const EGLDisplay mDisplay;
public:
const EGLImage mImage;
private:
EGLSync mSync;
EGLImageWrapper(GLLibraryEGL& library,
EGLDisplay display,
EGLImage image)
: mLibrary(library)
, mDisplay(display)
, mImage(image)
, mSync(0)
{
MOZ_ASSERT(mImage);
}
public:
~EGLImageWrapper();
// Insert a sync point on the given context, which should be the current active
// context.
bool FenceSync(GLContext* gl);
bool ClientWaitSync();
};
} // namespace gl
} // namespace mozilla
#endif

View File

@ -14,19 +14,6 @@ namespace gl {
class GLContext;
typedef uintptr_t SharedTextureHandle;
MOZ_BEGIN_ENUM_CLASS(SharedTextureShareType)
SameProcess = 0,
CrossProcess
MOZ_END_ENUM_CLASS(SharedTextureShareType)
MOZ_BEGIN_ENUM_CLASS(SharedTextureBufferType)
TextureID,
SurfaceTexture,
IOSurface
MOZ_END_ENUM_CLASS(SharedTextureBufferType)
MOZ_BEGIN_ENUM_CLASS(GLContextType)
Unknown,
WGL,

View File

@ -1,330 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "GLContextEGL.h"
#include "GLSharedHandleHelpers.h"
#ifdef MOZ_WIDGET_ANDROID
#include "nsSurfaceTexture.h"
#endif
namespace mozilla {
namespace gl {
enum SharedHandleType {
SharedHandleType_Image
#ifdef MOZ_WIDGET_ANDROID
, SharedHandleType_SurfaceTexture
#endif
};
class SharedTextureHandleWrapper
{
public:
explicit SharedTextureHandleWrapper(SharedHandleType aHandleType) : mHandleType(aHandleType)
{
}
virtual ~SharedTextureHandleWrapper()
{
}
SharedHandleType Type() { return mHandleType; }
SharedHandleType mHandleType;
};
#ifdef MOZ_WIDGET_ANDROID
class SurfaceTextureWrapper: public SharedTextureHandleWrapper
{
public:
SurfaceTextureWrapper(nsSurfaceTexture* aSurfaceTexture) :
SharedTextureHandleWrapper(SharedHandleType_SurfaceTexture)
, mSurfaceTexture(aSurfaceTexture)
{
}
virtual ~SurfaceTextureWrapper() {
mSurfaceTexture = nullptr;
}
nsSurfaceTexture* SurfaceTexture() { return mSurfaceTexture; }
nsRefPtr<nsSurfaceTexture> mSurfaceTexture;
};
#endif // MOZ_WIDGET_ANDROID
class EGLTextureWrapper : public SharedTextureHandleWrapper
{
public:
EGLTextureWrapper() :
SharedTextureHandleWrapper(SharedHandleType_Image)
, mEGLImage(nullptr)
, mSyncObject(nullptr)
{
}
// Args are the active GL context, and a texture in that GL
// context for which to create an EGLImage. After the EGLImage
// is created, the texture is unused by EGLTextureWrapper.
bool CreateEGLImage(GLContext *ctx, uintptr_t texture) {
MOZ_ASSERT(!mEGLImage && texture && sEGLLibrary.HasKHRImageBase());
static const EGLint eglAttributes[] = {
LOCAL_EGL_NONE
};
EGLContext eglContext = GLContextEGL::Cast(ctx)->GetEGLContext();
mEGLImage = sEGLLibrary.fCreateImage(EGL_DISPLAY(), eglContext, LOCAL_EGL_GL_TEXTURE_2D,
(EGLClientBuffer)texture, eglAttributes);
if (!mEGLImage) {
#ifdef DEBUG
printf_stderr("Could not create EGL images: ERROR (0x%04x)\n", sEGLLibrary.fGetError());
#endif
return false;
}
return true;
}
virtual ~EGLTextureWrapper() {
if (mEGLImage) {
sEGLLibrary.fDestroyImage(EGL_DISPLAY(), mEGLImage);
mEGLImage = nullptr;
}
}
const EGLImage GetEGLImage() {
return mEGLImage;
}
// Insert a sync point on the given context, which should be the current active
// context.
bool MakeSync(GLContext *ctx) {
MOZ_ASSERT(mSyncObject == nullptr);
if (sEGLLibrary.IsExtensionSupported(GLLibraryEGL::KHR_fence_sync)) {
mSyncObject = sEGLLibrary.fCreateSync(EGL_DISPLAY(), LOCAL_EGL_SYNC_FENCE, nullptr);
// We need to flush to make sure the sync object enters the command stream;
// we can't use EGL_SYNC_FLUSH_COMMANDS_BIT at wait time, because the wait
// happens on a different thread/context.
ctx->fFlush();
}
if (mSyncObject == EGL_NO_SYNC) {
// we failed to create one, so just do a finish
ctx->fFinish();
}
return true;
}
bool WaitSync() {
if (!mSyncObject) {
// if we have no sync object, then we did a Finish() earlier
return true;
}
// wait at most 1 second; this should really be never/rarely hit
const uint64_t ns_per_ms = 1000 * 1000;
EGLTime timeout = 1000 * ns_per_ms;
EGLint result = sEGLLibrary.fClientWaitSync(EGL_DISPLAY(), mSyncObject, 0, timeout);
sEGLLibrary.fDestroySync(EGL_DISPLAY(), mSyncObject);
mSyncObject = nullptr;
return result == LOCAL_EGL_CONDITION_SATISFIED;
}
private:
EGLImage mEGLImage;
EGLSync mSyncObject;
};
static bool DoesEGLContextSupportSharingWithEGLImage(GLContext *gl)
{
return sEGLLibrary.HasKHRImageBase() &&
sEGLLibrary.HasKHRImageTexture2D() &&
gl->IsExtensionSupported(GLContext::OES_EGL_image);
}
SharedTextureHandle CreateSharedHandle(GLContext* gl,
SharedTextureShareType shareType,
void* buffer,
SharedTextureBufferType bufferType)
{
// unimplemented outside of EGL
if (gl->GetContextType() != GLContextType::EGL)
return 0;
// Both EGLImage and SurfaceTexture only support same-process currently, but
// it's possible to make SurfaceTexture work across processes. We should do that.
if (shareType != SharedTextureShareType::SameProcess)
return 0;
switch (bufferType) {
#ifdef MOZ_WIDGET_ANDROID
case SharedTextureBufferType::SurfaceTexture:
if (!gl->IsExtensionSupported(GLContext::OES_EGL_image_external)) {
NS_WARNING("Missing GL_OES_EGL_image_external");
return 0;
}
return (SharedTextureHandle) new SurfaceTextureWrapper(reinterpret_cast<nsSurfaceTexture*>(buffer));
#endif
case SharedTextureBufferType::TextureID: {
if (!DoesEGLContextSupportSharingWithEGLImage(gl))
return 0;
GLuint texture = (uintptr_t)buffer;
EGLTextureWrapper* tex = new EGLTextureWrapper();
if (!tex->CreateEGLImage(gl, texture)) {
NS_ERROR("EGLImage creation for EGLTextureWrapper failed");
delete tex;
return 0;
}
return (SharedTextureHandle)tex;
}
default:
NS_ERROR("Unknown shared texture buffer type");
return 0;
}
}
void ReleaseSharedHandle(GLContext* gl,
SharedTextureShareType shareType,
SharedTextureHandle sharedHandle)
{
// unimplemented outside of EGL
if (gl->GetContextType() != GLContextType::EGL)
return;
if (shareType != SharedTextureShareType::SameProcess) {
NS_ERROR("Implementation not available for this sharing type");
return;
}
SharedTextureHandleWrapper* wrapper = reinterpret_cast<SharedTextureHandleWrapper*>(sharedHandle);
switch (wrapper->Type()) {
#ifdef MOZ_WIDGET_ANDROID
case SharedHandleType_SurfaceTexture:
delete wrapper;
break;
#endif
case SharedHandleType_Image: {
NS_ASSERTION(DoesEGLContextSupportSharingWithEGLImage(gl), "EGLImage not supported or disabled in runtime");
EGLTextureWrapper* wrap = (EGLTextureWrapper*)sharedHandle;
delete wrap;
break;
}
default:
NS_ERROR("Unknown shared handle type");
return;
}
}
bool GetSharedHandleDetails(GLContext* gl,
SharedTextureShareType shareType,
SharedTextureHandle sharedHandle,
SharedHandleDetails& details)
{
// unimplemented outside of EGL
if (gl->GetContextType() != GLContextType::EGL)
return false;
if (shareType != SharedTextureShareType::SameProcess)
return false;
SharedTextureHandleWrapper* wrapper = reinterpret_cast<SharedTextureHandleWrapper*>(sharedHandle);
switch (wrapper->Type()) {
#ifdef MOZ_WIDGET_ANDROID
case SharedHandleType_SurfaceTexture: {
SurfaceTextureWrapper* surfaceWrapper = reinterpret_cast<SurfaceTextureWrapper*>(wrapper);
details.mTarget = LOCAL_GL_TEXTURE_EXTERNAL;
details.mTextureFormat = gfx::SurfaceFormat::R8G8B8A8;
surfaceWrapper->SurfaceTexture()->GetTransformMatrix(details.mTextureTransform);
break;
}
#endif
case SharedHandleType_Image:
details.mTarget = LOCAL_GL_TEXTURE_2D;
details.mTextureFormat = gfx::SurfaceFormat::R8G8B8A8;
break;
default:
NS_ERROR("Unknown shared handle type");
return false;
}
return true;
}
bool AttachSharedHandle(GLContext* gl,
SharedTextureShareType shareType,
SharedTextureHandle sharedHandle)
{
// unimplemented outside of EGL
if (gl->GetContextType() != GLContextType::EGL)
return false;
if (shareType != SharedTextureShareType::SameProcess)
return false;
SharedTextureHandleWrapper* wrapper = reinterpret_cast<SharedTextureHandleWrapper*>(sharedHandle);
switch (wrapper->Type()) {
#ifdef MOZ_WIDGET_ANDROID
case SharedHandleType_SurfaceTexture: {
#ifndef DEBUG
/*
* NOTE: SurfaceTexture spams us if there are any existing GL errors, so we'll clear
* them here in order to avoid that.
*/
gl->GetAndClearError();
#endif
SurfaceTextureWrapper* surfaceTextureWrapper = reinterpret_cast<SurfaceTextureWrapper*>(wrapper);
// FIXME: SurfaceTexture provides a transform matrix which is supposed to
// be applied to the texture coordinates. We should return that here
// so we can render correctly. Bug 775083
surfaceTextureWrapper->SurfaceTexture()->UpdateTexImage();
break;
}
#endif // MOZ_WIDGET_ANDROID
case SharedHandleType_Image: {
NS_ASSERTION(DoesEGLContextSupportSharingWithEGLImage(gl), "EGLImage not supported or disabled in runtime");
EGLTextureWrapper* wrap = (EGLTextureWrapper*)sharedHandle;
wrap->WaitSync();
gl->fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_2D, wrap->GetEGLImage());
break;
}
default:
NS_ERROR("Unknown shared handle type");
return false;
}
return true;
}
/**
* Detach Shared GL Handle from GL_TEXTURE_2D target
*/
void DetachSharedHandle(GLContext*,
SharedTextureShareType,
SharedTextureHandle)
{
// currently a no-operation
}
}
}

View File

@ -1,73 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef GLSHAREDHANDLEHELPERS_H_
#define GLSHAREDHANDLEHELPERS_H_
#include "GLContextTypes.h"
#include "mozilla/gfx/Types.h"
namespace mozilla {
namespace gl {
/**
* Create a new shared GLContext content handle, using the passed buffer as a source.
* Must be released by ReleaseSharedHandle.
*/
SharedTextureHandle CreateSharedHandle(GLContext* gl,
SharedTextureShareType shareType,
void* buffer,
SharedTextureBufferType bufferType);
/**
* - It is better to call ReleaseSharedHandle before original GLContext destroyed,
* otherwise warning will be thrown on attempt to destroy Texture associated with SharedHandle, depends on backend implementation.
* - It does not require to be called on context where it was created,
* because SharedHandle suppose to keep Context reference internally,
* or don't require specific context at all, for example IPC SharedHandle.
* - Not recommended to call this between AttachSharedHandle and Draw Target call.
* if it is really required for some special backend, then DetachSharedHandle API must be added with related implementation.
* - It is recommended to stop any possible access to SharedHandle (Attachments, pending GL calls) before calling Release,
* otherwise some artifacts might appear or even crash if API backend implementation does not expect that.
* SharedHandle (currently EGLImage) does not require GLContext because it is EGL call, and can be destroyed
* at any time, unless EGLImage have siblings (which are not expected with current API).
*/
void ReleaseSharedHandle(GLContext* gl,
SharedTextureShareType shareType,
SharedTextureHandle sharedHandle);
typedef struct {
GLenum mTarget;
gfx::SurfaceFormat mTextureFormat;
gfx::Matrix4x4 mTextureTransform;
} SharedHandleDetails;
/**
* Returns information necessary for rendering a shared handle.
* These values change depending on what sharing mechanism is in use
*/
bool GetSharedHandleDetails(GLContext* gl,
SharedTextureShareType shareType,
SharedTextureHandle sharedHandle,
SharedHandleDetails& details);
/**
* Attach Shared GL Handle to GL_TEXTURE_2D target
* GLContext must be current before this call
*/
bool AttachSharedHandle(GLContext* gl,
SharedTextureShareType shareType,
SharedTextureHandle sharedHandle);
/**
* Detach Shared GL Handle from GL_TEXTURE_2D target
*/
void DetachSharedHandle(GLContext* gl,
SharedTextureShareType shareType,
SharedTextureHandle sharedHandle);
}
}
#endif

View File

@ -89,8 +89,9 @@ TextureImageEGL::~TextureImageEGL()
// if we don't have a context (either real or shared),
// then they went away when the contex was deleted, because it
// was the only one that had access to it.
mGLContext->MakeCurrent();
mGLContext->fDeleteTextures(1, &mTexture);
if (mGLContext->MakeCurrent()) {
mGLContext->fDeleteTextures(1, &mTexture);
}
ReleaseTexImage();
DestroyEGLSurface();
}

View File

@ -27,6 +27,7 @@ if CONFIG['MOZ_GL_PROVIDER']:
EXPORTS += [
'DecomposeIntoNoRepeatTriangles.h',
'EGLUtils.h',
'ForceDiscreteGPUHelperCGL.h',
'GfxTexturesReporter.h',
'GLBlitHelper.h',
@ -43,7 +44,6 @@ EXPORTS += [
'GLLibraryLoader.h',
'GLReadTexImageHelper.h',
'GLScreenBuffer.h',
'GLSharedHandleHelpers.h',
'GLTextureImage.h',
'GLTypes.h',
'GLUploadHelpers.h',
@ -116,6 +116,7 @@ else:
UNIFIED_SOURCES += [
'DecomposeIntoNoRepeatTriangles.cpp',
'EGLUtils.cpp',
'GfxTexturesReporter.cpp',
'GLBlitHelper.cpp',
'GLBlitTextureImageHelper.cpp',
@ -127,7 +128,6 @@ UNIFIED_SOURCES += [
'GLLibraryLoader.cpp',
'GLReadTexImageHelper.cpp',
'GLScreenBuffer.cpp',
'GLSharedHandleHelpers.cpp',
'GLTextureImage.cpp',
'GLUploadHelpers.cpp',
'ScopedGLHelpers.cpp',

View File

@ -99,7 +99,7 @@
* under gfx/layers/. To add a new backend, implement at least the following
* interfaces:
* - Compositor (ex. CompositorOGL)
* - TextureHost (ex. SharedTextureHostOGL)
* - TextureHost (ex. SurfaceTextureHost)
* Depending on the type of data that needs to be serialized, you may need to
* add specific TextureClient implementations.
*/

View File

@ -6,7 +6,7 @@
#include "ImageContainer.h"
#include <string.h> // for memcpy, memset
#include "SharedTextureImage.h" // for SharedTextureImage
#include "GLImages.h" // for SurfaceTextureImage
#include "gfx2DGlue.h"
#include "gfxPlatform.h" // for gfxPlatform
#include "gfxUtils.h" // for gfxUtils
@ -69,8 +69,14 @@ ImageFactory::CreateImage(ImageFormat aFormat,
img = new CairoImage();
return img.forget();
}
if (aFormat == ImageFormat::SHARED_TEXTURE) {
img = new SharedTextureImage();
#ifdef MOZ_WIDGET_ANDROID
if (aFormat == ImageFormat::SURFACE_TEXTURE) {
img = new SurfaceTextureImage();
return img.forget();
}
#endif
if (aFormat == ImageFormat::EGLIMAGE) {
img = new EGLImageImage();
return img.forget();
}
#ifdef XP_MACOSX

View File

@ -58,9 +58,15 @@ MOZ_BEGIN_ENUM_CLASS(ImageFormat)
REMOTE_IMAGE_BITMAP,
/**
* A OpenGL texture that can be shared across threads or processes
* An Android SurfaceTexture ID that can be shared across threads and
* processes.
*/
SHARED_TEXTURE,
SURFACE_TEXTURE,
/**
* An EGL Image that can be shared across threads.
*/
EGLIMAGE,
/**
* An DXGI shared surface handle that can be shared with a remote process.

View File

@ -1,50 +0,0 @@
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef GFX_SHAREDTEXTUREIMAGE_H
#define GFX_SHAREDTEXTUREIMAGE_H
#include "GLContextProvider.h" // for GLContextProvider
#include "ImageContainer.h" // for Image
#include "ImageTypes.h" // for ImageFormat::SHARED_TEXTURE
#include "nsCOMPtr.h" // for already_AddRefed
#include "mozilla/gfx/Point.h" // for IntSize
// Split into a separate header from ImageLayers.h due to GLContext.h dependence
// Implementation remains in ImageLayers.cpp
namespace mozilla {
namespace layers {
class SharedTextureImage : public Image {
public:
struct Data {
gl::SharedTextureHandle mHandle;
gl::SharedTextureShareType mShareType;
gfx::IntSize mSize;
bool mInverted;
};
void SetData(const Data& aData) { mData = aData; }
const Data* GetData() { return &mData; }
gfx::IntSize GetSize() { return mData.mSize; }
virtual TemporaryRef<gfx::SourceSurface> GetAsSourceSurface() MOZ_OVERRIDE
{
return nullptr;
}
SharedTextureImage() : Image(nullptr, ImageFormat::SHARED_TEXTURE) {}
private:
Data mData;
};
} // layers
} // mozilla
#endif // GFX_SHAREDTEXTUREIMAGE_H

View File

@ -7,7 +7,7 @@
#include <stdint.h> // for uint32_t
#include "ImageContainer.h" // for Image, PlanarYCbCrImage, etc
#include "ImageTypes.h" // for ImageFormat::PLANAR_YCBCR, etc
#include "SharedTextureImage.h" // for SharedTextureImage::Data, etc
#include "GLImages.h" // for SurfaceTextureImage::Data, etc
#include "gfx2DGlue.h" // for ImageFormatToSurfaceFormat
#include "gfxPlatform.h" // for gfxPlatform
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
@ -24,7 +24,7 @@
#include "mozilla/layers/SharedPlanarYCbCrImage.h"
#include "mozilla/layers/SharedRGBImage.h"
#include "mozilla/layers/TextureClient.h" // for TextureClient, etc
#include "mozilla/layers/TextureClientOGL.h" // for SharedTextureClientOGL
#include "mozilla/layers/TextureClientOGL.h" // for SurfaceTextureClient
#include "mozilla/mozalloc.h" // for operator delete, etc
#include "nsAutoPtr.h" // for nsRefPtr
#include "nsCOMPtr.h" // for already_AddRefed
@ -247,9 +247,9 @@ ImageClientSingle::UpdateImageInternal(ImageContainer* aContainer,
return false;
}
} else if (image->GetFormat() == ImageFormat::SHARED_TEXTURE) {
SharedTextureImage* sharedImage = static_cast<SharedTextureImage*>(image);
const SharedTextureImage::Data *data = sharedImage->GetData();
} else if (image->GetFormat() == ImageFormat::SURFACE_TEXTURE ||
image->GetFormat() == ImageFormat::EGLIMAGE)
{
gfx::IntSize size = gfx::IntSize(image->GetSize().width, image->GetSize().height);
if (mFrontBuffer) {
@ -257,8 +257,30 @@ ImageClientSingle::UpdateImageInternal(ImageContainer* aContainer,
mFrontBuffer = nullptr;
}
RefPtr<SharedTextureClientOGL> buffer = new SharedTextureClientOGL(mTextureFlags);
buffer->InitWith(data->mHandle, size, data->mShareType, data->mInverted);
RefPtr<TextureClient> buffer;
if (image->GetFormat() == ImageFormat::EGLIMAGE) {
EGLImageImage* typedImage = static_cast<EGLImageImage*>(image);
const EGLImageImage::Data* data = typedImage->GetData();
buffer = new EGLImageTextureClient(mTextureFlags,
data->mImage,
size,
data->mInverted);
#ifdef MOZ_WIDGET_ANDROID
} else if (image->GetFormat() == ImageFormat::SURFACE_TEXTURE) {
SurfaceTextureImage* typedImage = static_cast<SurfaceTextureImage*>(image);
const SurfaceTextureImage::Data* data = typedImage->GetData();
buffer = new SurfaceTextureClient(mTextureFlags,
data->mSurfTex,
size,
data->mInverted);
#endif
} else {
MOZ_ASSERT(false, "Bad ImageFormat.");
}
mFrontBuffer = buffer;
if (!AddTextureClient(mFrontBuffer)) {
mFrontBuffer = nullptr;
@ -266,6 +288,7 @@ ImageClientSingle::UpdateImageInternal(ImageContainer* aContainer,
}
GetForwarder()->UseTexture(this, mFrontBuffer);
} else {
RefPtr<gfx::SourceSurface> surface = image->GetAsSourceSurface();
MOZ_ASSERT(surface);

View File

@ -205,8 +205,9 @@ TextureHost::Create(const SurfaceDescriptor& aDesc,
case SurfaceDescriptor::TSurfaceDescriptorDIB:
return CreateBackendIndependentTextureHost(aDesc, aDeallocator, aFlags);
case SurfaceDescriptor::TSharedTextureDescriptor:
case SurfaceDescriptor::TEGLImageDescriptor:
case SurfaceDescriptor::TNewSurfaceDescriptorGralloc:
case SurfaceDescriptor::TSurfaceTextureDescriptor:
return CreateTextureHostOGL(aDesc, aDeallocator, aFlags);
case SurfaceDescriptor::TSurfaceStreamDescriptor:

View File

@ -11,8 +11,6 @@ using struct mozilla::layers::GrallocBufferRef from "gfxipc/ShadowLayerUtils.h";
using struct mozilla::layers::SurfaceDescriptorX11 from "gfxipc/ShadowLayerUtils.h";
using struct mozilla::null_t from "ipc/IPCMessageUtils.h";
using mozilla::WindowsHandle from "ipc/IPCMessageUtils.h";
using mozilla::gl::SharedTextureHandle from "GLContextTypes.h";
using mozilla::gl::SharedTextureShareType from "GLContextTypes.h";
using mozilla::gfx::SurfaceFormat from "mozilla/gfx/Types.h";
using mozilla::gfx::IntSize from "mozilla/gfx/Point.h";
using gfxImageFormat from "gfxTypes.h";
@ -58,11 +56,14 @@ struct SurfaceDescriptorMacIOSurface {
bool hasAlpha;
};
struct SharedTextureDescriptor {
SharedTextureShareType shareType;
SharedTextureHandle handle;
struct SurfaceTextureDescriptor {
uintptr_t surfTex;
IntSize size;
};
struct EGLImageDescriptor {
uintptr_t image; // `EGLImage` is a `void*`.
IntSize size;
bool inverted;
};
struct NewSurfaceDescriptorGralloc {
@ -103,7 +104,8 @@ union SurfaceDescriptor {
SurfaceDescriptorDIB;
SurfaceDescriptorD3D10;
SurfaceDescriptorX11;
SharedTextureDescriptor;
SurfaceTextureDescriptor;
EGLImageDescriptor;
SurfaceStreamDescriptor;
SurfaceDescriptorMacIOSurface;
NewSurfaceDescriptorGralloc;

View File

@ -56,29 +56,6 @@ struct ParamTraits<mozilla::layers::SurfaceDescriptorX11> {
};
#endif // !defined(MOZ_HAVE_XSURFACEDESCRIPTORX11)
template<>
struct ParamTraits<mozilla::gl::SharedTextureShareType>
{
typedef mozilla::gl::SharedTextureShareType paramType;
static void Write(Message* msg, const paramType& param)
{
static_assert(sizeof(paramType) <= sizeof(int32_t),
"TextureShareType assumes to be int32_t");
WriteParam(msg, int32_t(param));
}
static bool Read(const Message* msg, void** iter, paramType* result)
{
int32_t type;
if (!ReadParam(msg, iter, &type))
return false;
*result = paramType(type);
return true;
}
};
#if !defined(MOZ_HAVE_SURFACEDESCRIPTORGRALLOC)
template <>
struct ParamTraits<mozilla::layers::MagicGrallocBufferHandle> {

View File

@ -20,6 +20,7 @@ EXPORTS += [
'CopyableCanvasLayer.h',
'D3D9SurfaceImage.h',
'FrameMetrics.h',
'GLImages.h',
'GrallocImages.h',
'ImageContainer.h',
'ImageLayers.h',
@ -38,7 +39,6 @@ EXPORTS += [
'opengl/TexturePoolOGL.h',
'protobuf/LayerScopePacket.pb.h',
'ReadbackLayer.h',
'SharedTextureImage.h',
'TiledLayerBuffer.h',
]

View File

@ -64,7 +64,7 @@ public:
MacIOSurfaceTextureHostOGL(TextureFlags aFlags,
const SurfaceDescriptorMacIOSurface& aDescriptor);
// SharedTextureHostOGL doesn't own any GL texture
// MacIOSurfaceTextureSourceOGL doesn't own any GL texture
virtual void DeallocateDeviceData() MOZ_OVERRIDE {}
virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;

View File

@ -17,52 +17,105 @@ namespace layers {
class CompositableForwarder;
SharedTextureClientOGL::SharedTextureClientOGL(TextureFlags aFlags)
////////////////////////////////////////////////////////////////////////
// EGLImageTextureClient
EGLImageTextureClient::EGLImageTextureClient(TextureFlags aFlags,
EGLImage aImage,
gfx::IntSize aSize,
bool aInverted)
: TextureClient(aFlags)
, mHandle(0)
, mInverted(false)
, mImage(aImage)
, mSize(aSize)
, mIsLocked(false)
{
// SharedTextureClient is always owned externally.
mFlags |= TextureFlags::DEALLOCATE_CLIENT;
}
SharedTextureClientOGL::~SharedTextureClientOGL()
{
// the shared data is owned externally.
}
bool
SharedTextureClientOGL::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
{
MOZ_ASSERT(IsValid());
if (!IsAllocated()) {
return false;
}
aOutDescriptor = SharedTextureDescriptor(mShareType, mHandle, mSize, mInverted);
return true;
}
void
SharedTextureClientOGL::InitWith(gl::SharedTextureHandle aHandle,
gfx::IntSize aSize,
gl::SharedTextureShareType aShareType,
bool aInverted)
{
MOZ_ASSERT(IsValid());
MOZ_ASSERT(!IsAllocated());
mHandle = aHandle;
mSize = aSize;
mShareType = aShareType;
mInverted = aInverted;
if (mInverted) {
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default,
"Can't pass an `EGLImage` between processes.");
// Our data is always owned externally.
AddFlags(TextureFlags::DEALLOCATE_CLIENT);
if (aInverted) {
AddFlags(TextureFlags::NEEDS_Y_FLIP);
}
}
EGLImageTextureClient::~EGLImageTextureClient()
{
// Our data is always owned externally.
}
bool
SharedTextureClientOGL::Lock(OpenMode mode)
EGLImageTextureClient::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
{
MOZ_ASSERT(IsValid());
MOZ_ASSERT(IsAllocated());
aOutDescriptor = EGLImageDescriptor((uintptr_t)mImage, mSize);
return true;
}
bool
EGLImageTextureClient::Lock(OpenMode mode)
{
MOZ_ASSERT(!mIsLocked);
if (!IsValid() || !IsAllocated()) {
return false;
}
mIsLocked = true;
return true;
}
void
EGLImageTextureClient::Unlock()
{
MOZ_ASSERT(mIsLocked);
mIsLocked = false;
}
////////////////////////////////////////////////////////////////////////
// SurfaceTextureClient
#ifdef MOZ_WIDGET_ANDROID
SurfaceTextureClient::SurfaceTextureClient(TextureFlags aFlags,
nsSurfaceTexture* aSurfTex,
gfx::IntSize aSize,
bool aInverted)
: TextureClient(aFlags)
, mSurfTex(aSurfTex)
, mSize(aSize)
, mIsLocked(false)
{
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default,
"Can't pass pointers between processes.");
// Our data is always owned externally.
AddFlags(TextureFlags::DEALLOCATE_CLIENT);
if (aInverted) {
AddFlags(TextureFlags::NEEDS_Y_FLIP);
}
}
SurfaceTextureClient::~SurfaceTextureClient()
{
// Our data is always owned externally.
}
bool
SurfaceTextureClient::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
{
MOZ_ASSERT(IsValid());
MOZ_ASSERT(IsAllocated());
aOutDescriptor = SurfaceTextureDescriptor((uintptr_t)mSurfTex.get(),
mSize);
return true;
}
bool
SurfaceTextureClient::Lock(OpenMode mode)
{
MOZ_ASSERT(!mIsLocked);
if (!IsValid() || !IsAllocated()) {
@ -73,17 +126,13 @@ SharedTextureClientOGL::Lock(OpenMode mode)
}
void
SharedTextureClientOGL::Unlock()
SurfaceTextureClient::Unlock()
{
MOZ_ASSERT(mIsLocked);
mIsLocked = false;
}
bool
SharedTextureClientOGL::IsAllocated() const
{
return mHandle != 0;
}
#endif // MOZ_WIDGET_ANDROID
} // namespace
} // namespace

View File

@ -13,6 +13,7 @@
#include "mozilla/layers/CompositorTypes.h"
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor
#include "mozilla/layers/TextureClient.h" // for TextureClient, etc
#include "nsSurfaceTexture.h"
namespace mozilla {
namespace gl {
@ -25,46 +26,42 @@ namespace layers {
class CompositableForwarder;
/**
* A TextureClient implementation to share TextureMemory that is already
* on the GPU, for the OpenGL backend.
*/
class SharedTextureClientOGL : public TextureClient
class EGLImageTextureClient : public TextureClient
{
public:
explicit SharedTextureClientOGL(TextureFlags aFlags);
EGLImageTextureClient(TextureFlags aFlags,
EGLImage aImage,
gfx::IntSize aSize,
bool aInverted);
~SharedTextureClientOGL();
~EGLImageTextureClient();
virtual bool IsAllocated() const MOZ_OVERRIDE;
virtual bool IsAllocated() const MOZ_OVERRIDE { return true; }
virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return false; }
virtual gfx::IntSize GetSize() const { return mSize; }
virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) MOZ_OVERRIDE;
// Useless functions.
virtual bool Lock(OpenMode mode) MOZ_OVERRIDE;
virtual void Unlock() MOZ_OVERRIDE;
virtual bool IsLocked() const MOZ_OVERRIDE { return mIsLocked; }
virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return false; }
void InitWith(gl::SharedTextureHandle aHandle,
gfx::IntSize aSize,
gl::SharedTextureShareType aShareType,
bool aInverted = false);
virtual gfx::IntSize GetSize() const { return mSize; }
virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE
{
return gfx::SurfaceFormat::UNKNOWN;
}
// This TextureClient should not be used in a context where we use CreateSimilar
// (ex. component alpha) because the underlying texture data is always created by
// an external producer.
virtual TemporaryRef<TextureClient>
CreateSimilar(TextureFlags, TextureAllocationFlags) const MOZ_OVERRIDE { return nullptr; }
CreateSimilar(TextureFlags aFlags = TextureFlags::DEFAULT,
TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const MOZ_OVERRIDE
{
return nullptr;
}
virtual bool AllocateForSurface(gfx::IntSize aSize, TextureAllocationFlags aFlags) MOZ_OVERRIDE
{
@ -72,13 +69,63 @@ public:
}
protected:
gl::SharedTextureHandle mHandle;
gfx::IntSize mSize;
gl::SharedTextureShareType mShareType;
bool mInverted;
const EGLImage mImage;
const gfx::IntSize mSize;
bool mIsLocked;
};
#ifdef MOZ_WIDGET_ANDROID
class SurfaceTextureClient : public TextureClient
{
public:
SurfaceTextureClient(TextureFlags aFlags,
nsSurfaceTexture* aSurfTex,
gfx::IntSize aSize,
bool aInverted);
~SurfaceTextureClient();
virtual bool IsAllocated() const MOZ_OVERRIDE { return true; }
virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return false; }
virtual gfx::IntSize GetSize() const { return mSize; }
virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) MOZ_OVERRIDE;
// Useless functions.
virtual bool Lock(OpenMode mode) MOZ_OVERRIDE;
virtual void Unlock() MOZ_OVERRIDE;
virtual bool IsLocked() const MOZ_OVERRIDE { return mIsLocked; }
virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE
{
return gfx::SurfaceFormat::UNKNOWN;
}
virtual TemporaryRef<TextureClient>
CreateSimilar(TextureFlags aFlags = TextureFlags::DEFAULT,
TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const MOZ_OVERRIDE
{
return nullptr;
}
virtual bool AllocateForSurface(gfx::IntSize aSize, TextureAllocationFlags aFlags) MOZ_OVERRIDE
{
return false;
}
protected:
const nsRefPtr<nsSurfaceTexture> mSurfTex;
const gfx::IntSize mSize;
bool mIsLocked;
};
#endif // MOZ_WIDGET_ANDROID
} // namespace
} // namespace

View File

@ -4,9 +4,10 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "TextureHostOGL.h"
#include "EGLUtils.h"
#include "GLContext.h" // for GLContext, etc
#include "GLLibraryEGL.h" // for GLLibraryEGL
#include "GLSharedHandleHelpers.h"
#include "GLUploadHelpers.h"
#include "GLReadTexImageHelper.h"
#include "gfx2DGlue.h" // for ContentForFormat, etc
@ -23,6 +24,7 @@
#include "mozilla/layers/GrallocTextureHost.h"
#include "nsPoint.h" // for nsIntPoint
#include "nsRegion.h" // for nsIntRegion
#include "nsSurfaceTexture.h"
#include "GfxTexturesReporter.h" // for GfxTexturesReporter
#include "GLBlitTextureImageHelper.h"
#ifdef XP_MACOSX
@ -62,15 +64,25 @@ CreateTextureHostOGL(const SurfaceDescriptor& aDesc,
aDeallocator, aFlags);
break;
}
case SurfaceDescriptor::TSharedTextureDescriptor: {
const SharedTextureDescriptor& desc = aDesc.get_SharedTextureDescriptor();
result = new SharedTextureHostOGL(aFlags,
desc.shareType(),
desc.handle(),
desc.size(),
desc.inverted());
#ifdef MOZ_WIDGET_ANDROID
case SurfaceDescriptor::TSurfaceTextureDescriptor: {
const SurfaceTextureDescriptor& desc = aDesc.get_SurfaceTextureDescriptor();
result = new SurfaceTextureHost(aFlags,
(nsSurfaceTexture*)desc.surfTex(),
desc.size());
break;
}
#endif
case SurfaceDescriptor::TEGLImageDescriptor: {
const EGLImageDescriptor& desc = aDesc.get_EGLImageDescriptor();
result = new EGLImageTextureHost(aFlags,
(EGLImage)desc.image(),
desc.size());
break;
}
#ifdef XP_MACOSX
case SurfaceDescriptor::TSurfaceDescriptorMacIOSurface: {
const SurfaceDescriptorMacIOSurface& desc =
@ -79,6 +91,7 @@ CreateTextureHostOGL(const SurfaceDescriptor& aDesc,
break;
}
#endif
#ifdef MOZ_WIDGET_GONK
case SurfaceDescriptor::TNewSurfaceDescriptorGralloc: {
const NewSurfaceDescriptorGralloc& desc =
@ -409,80 +422,6 @@ TextureImageTextureSourceOGL::BindTexture(GLenum aTextureUnit, gfx::Filter aFilt
SetFilter(mGL, aFilter);
}
SharedTextureSourceOGL::SharedTextureSourceOGL(CompositorOGL* aCompositor,
gl::SharedTextureHandle aHandle,
gfx::SurfaceFormat aFormat,
GLenum aTarget,
GLenum aWrapMode,
SharedTextureShareType aShareType,
gfx::IntSize aSize)
: mSize(aSize)
, mCompositor(aCompositor)
, mSharedHandle(aHandle)
, mFormat(aFormat)
, mShareType(aShareType)
, mTextureTarget(aTarget)
, mWrapMode(aWrapMode)
{}
void
SharedTextureSourceOGL::BindTexture(GLenum aTextureUnit, gfx::Filter aFilter)
{
if (!gl()) {
NS_WARNING("Trying to bind a texture without a GLContext");
return;
}
GLuint tex = mCompositor->GetTemporaryTexture(GetTextureTarget(), aTextureUnit);
gl()->fActiveTexture(aTextureUnit);
gl()->fBindTexture(mTextureTarget, tex);
if (!AttachSharedHandle(gl(), mShareType, mSharedHandle)) {
NS_ERROR("Failed to bind shared texture handle");
return;
}
ApplyFilterToBoundTexture(gl(), aFilter, mTextureTarget);
}
void
SharedTextureSourceOGL::DetachSharedHandle()
{
if (!gl()) {
return;
}
gl::DetachSharedHandle(gl(), mShareType, mSharedHandle);
}
void
SharedTextureSourceOGL::SetCompositor(Compositor* aCompositor)
{
mCompositor = static_cast<CompositorOGL*>(aCompositor);
}
bool
SharedTextureSourceOGL::IsValid() const
{
return !!gl();
}
gl::GLContext*
SharedTextureSourceOGL::gl() const
{
return mCompositor ? mCompositor->gl() : nullptr;
}
gfx::Matrix4x4
SharedTextureSourceOGL::GetTextureTransform()
{
SharedHandleDetails handleDetails;
if (!GetSharedHandleDetails(gl(), mShareType, mSharedHandle, handleDetails)) {
NS_WARNING("Could not get shared handle details");
return gfx::Matrix4x4();
}
return handleDetails.mTextureTransform;
}
////////////////////////////////////////////////////////////////////////
// GLTextureSource
@ -530,72 +469,125 @@ GLTextureSource::gl() const
}
////////////////////////////////////////////////////////////////////////
// SharedTextureHostOGL
////////////////////////////////////////////////////////////////////////
// SurfaceTextureHost
SharedTextureHostOGL::SharedTextureHostOGL(TextureFlags aFlags,
gl::SharedTextureShareType aShareType,
gl::SharedTextureHandle aSharedHandle,
gfx::IntSize aSize,
bool inverted)
: TextureHost(aFlags)
#ifdef MOZ_WIDGET_ANDROID
SurfaceTextureSource::SurfaceTextureSource(CompositorOGL* aCompositor,
nsSurfaceTexture* aSurfTex,
gfx::SurfaceFormat aFormat,
GLenum aTarget,
GLenum aWrapMode,
gfx::IntSize aSize)
: mCompositor(aCompositor)
, mSurfTex(aSurfTex)
, mFormat(aFormat)
, mTextureTarget(aTarget)
, mWrapMode(aWrapMode)
, mSize(aSize)
, mCompositor(nullptr)
, mSharedHandle(aSharedHandle)
, mShareType(aShareType)
{
}
SharedTextureHostOGL::~SharedTextureHostOGL()
void
SurfaceTextureSource::BindTexture(GLenum aTextureUnit, gfx::Filter aFilter)
{
// If need to deallocate textures, call DeallocateSharedData() before
// the destructor
if (!gl()) {
NS_WARNING("Trying to bind a texture without a GLContext");
return;
}
GLuint tex = mCompositor->GetTemporaryTexture(GetTextureTarget(), aTextureUnit);
gl()->fActiveTexture(aTextureUnit);
gl()->fBindTexture(mTextureTarget, tex);
#ifndef DEBUG
// SurfaceTexture spams us if there are any existing GL errors, so
// we'll clear them here in order to avoid that.
gl()->GetAndClearError();
#endif
mSurfTex->UpdateTexImage();
ApplyFilterToBoundTexture(gl(), aFilter, mTextureTarget);
}
void
SurfaceTextureSource::SetCompositor(Compositor* aCompositor)
{
mCompositor = static_cast<CompositorOGL*>(aCompositor);
}
bool
SurfaceTextureSource::IsValid() const
{
return !!gl();
}
gl::GLContext*
SharedTextureHostOGL::gl() const
SurfaceTextureSource::gl() const
{
return mCompositor ? mCompositor->gl() : nullptr;
}
gfx::Matrix4x4
SurfaceTextureSource::GetTextureTransform()
{
gfx::Matrix4x4 ret;
mSurfTex->GetTransformMatrix(ret);
return ret;
}
////////////////////////////////////////////////////////////////////////
SurfaceTextureHost::SurfaceTextureHost(TextureFlags aFlags,
nsSurfaceTexture* aSurfTex,
gfx::IntSize aSize)
: TextureHost(aFlags)
, mSurfTex(aSurfTex)
, mSize(aSize)
, mCompositor(nullptr)
{
}
SurfaceTextureHost::~SurfaceTextureHost()
{
}
gl::GLContext*
SurfaceTextureHost::gl() const
{
return mCompositor ? mCompositor->gl() : nullptr;
}
bool
SharedTextureHostOGL::Lock()
SurfaceTextureHost::Lock()
{
if (!mCompositor) {
return false;
}
if (!mTextureSource) {
// XXX on android GetSharedHandleDetails can call into Java which we'd
// rather not do from the compositor
SharedHandleDetails handleDetails;
if (!GetSharedHandleDetails(gl(), mShareType, mSharedHandle, handleDetails)) {
NS_WARNING("Could not get shared handle details");
return false;
}
gfx::SurfaceFormat format = gfx::SurfaceFormat::R8G8B8A8;
GLenum target = LOCAL_GL_TEXTURE_EXTERNAL;
GLenum wrapMode = LOCAL_GL_CLAMP_TO_EDGE;
mTextureSource = new SharedTextureSourceOGL(mCompositor,
mSharedHandle,
handleDetails.mTextureFormat,
handleDetails.mTarget,
wrapMode,
mShareType,
mSize);
mTextureSource = new SurfaceTextureSource(mCompositor,
mSurfTex,
format,
target,
wrapMode,
mSize);
}
return true;
}
void
SharedTextureHostOGL::Unlock()
SurfaceTextureHost::Unlock()
{
if (!mTextureSource) {
return;
}
mTextureSource->DetachSharedHandle();
}
void
SharedTextureHostOGL::SetCompositor(Compositor* aCompositor)
SurfaceTextureHost::SetCompositor(Compositor* aCompositor)
{
CompositorOGL* glCompositor = static_cast<CompositorOGL*>(aCompositor);
mCompositor = glCompositor;
@ -605,7 +597,141 @@ SharedTextureHostOGL::SetCompositor(Compositor* aCompositor)
}
gfx::SurfaceFormat
SharedTextureHostOGL::GetFormat() const
SurfaceTextureHost::GetFormat() const
{
MOZ_ASSERT(mTextureSource);
return mTextureSource->GetFormat();
}
#endif // MOZ_WIDGET_ANDROID
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// EGLImage
EGLImageTextureSource::EGLImageTextureSource(CompositorOGL* aCompositor,
EGLImage aImage,
gfx::SurfaceFormat aFormat,
GLenum aTarget,
GLenum aWrapMode,
gfx::IntSize aSize)
: mCompositor(aCompositor)
, mImage(aImage)
, mFormat(aFormat)
, mTextureTarget(aTarget)
, mWrapMode(aWrapMode)
, mSize(aSize)
{
}
void
EGLImageTextureSource::BindTexture(GLenum aTextureUnit, gfx::Filter aFilter)
{
if (!gl()) {
NS_WARNING("Trying to bind a texture without a GLContext");
return;
}
MOZ_ASSERT(DoesEGLContextSupportSharingWithEGLImage(gl()),
"EGLImage not supported or disabled in runtime");
GLuint tex = mCompositor->GetTemporaryTexture(GetTextureTarget(), aTextureUnit);
gl()->fActiveTexture(aTextureUnit);
gl()->fBindTexture(mTextureTarget, tex);
MOZ_ASSERT(mTextureTarget == LOCAL_GL_TEXTURE_2D);
gl()->fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_2D, mImage);
ApplyFilterToBoundTexture(gl(), aFilter, mTextureTarget);
}
void
EGLImageTextureSource::SetCompositor(Compositor* aCompositor)
{
mCompositor = static_cast<CompositorOGL*>(aCompositor);
}
bool
EGLImageTextureSource::IsValid() const
{
return !!gl();
}
gl::GLContext*
EGLImageTextureSource::gl() const
{
return mCompositor ? mCompositor->gl() : nullptr;
}
gfx::Matrix4x4
EGLImageTextureSource::GetTextureTransform()
{
gfx::Matrix4x4 ret;
return ret;
}
////////////////////////////////////////////////////////////////////////
EGLImageTextureHost::EGLImageTextureHost(TextureFlags aFlags,
EGLImage aImage,
gfx::IntSize aSize)
: TextureHost(aFlags)
, mImage(aImage)
, mSize(aSize)
, mCompositor(nullptr)
{
}
EGLImageTextureHost::~EGLImageTextureHost()
{
}
gl::GLContext*
EGLImageTextureHost::gl() const
{
return mCompositor ? mCompositor->gl() : nullptr;
}
bool
EGLImageTextureHost::Lock()
{
if (!mCompositor) {
return false;
}
if (!mTextureSource) {
gfx::SurfaceFormat format = gfx::SurfaceFormat::R8G8B8A8;
GLenum target = LOCAL_GL_TEXTURE_2D;
GLenum wrapMode = LOCAL_GL_CLAMP_TO_EDGE;
mTextureSource = new EGLImageTextureSource(mCompositor,
mImage,
format,
target,
wrapMode,
mSize);
}
return true;
}
void
EGLImageTextureHost::Unlock()
{
}
void
EGLImageTextureHost::SetCompositor(Compositor* aCompositor)
{
CompositorOGL* glCompositor = static_cast<CompositorOGL*>(aCompositor);
mCompositor = glCompositor;
if (mTextureSource) {
mTextureSource->SetCompositor(glCompositor);
}
}
gfx::SurfaceFormat
EGLImageTextureHost::GetFormat() const
{
MOZ_ASSERT(mTextureSource);
return mTextureSource->GetFormat();

View File

@ -38,6 +38,7 @@
class gfxReusableSurfaceWrapper;
class nsIntRegion;
class nsSurfaceTexture;
struct nsIntPoint;
struct nsIntRect;
struct nsIntSize;
@ -294,116 +295,7 @@ protected:
};
/**
* A texture source meant for use with SharedTextureHostOGL.
*
* It does not own any GL texture, and attaches its shared handle to one of
* the compositor's temporary textures when binding.
*
* The shared texture handle is owned by the TextureHost.
*/
class SharedTextureSourceOGL : public NewTextureSource
, public TextureSourceOGL
{
public:
typedef gl::SharedTextureShareType SharedTextureShareType;
SharedTextureSourceOGL(CompositorOGL* aCompositor,
gl::SharedTextureHandle aHandle,
gfx::SurfaceFormat aFormat,
GLenum aTarget,
GLenum aWrapMode,
SharedTextureShareType aShareType,
gfx::IntSize aSize);
virtual TextureSourceOGL* AsSourceOGL() { return this; }
virtual void BindTexture(GLenum activetex, gfx::Filter aFilter) MOZ_OVERRIDE;
virtual bool IsValid() const MOZ_OVERRIDE;
virtual gfx::IntSize GetSize() const MOZ_OVERRIDE { return mSize; }
virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE { return mFormat; }
virtual gfx::Matrix4x4 GetTextureTransform() MOZ_OVERRIDE;
virtual GLenum GetTextureTarget() const { return mTextureTarget; }
virtual GLenum GetWrapMode() const MOZ_OVERRIDE { return mWrapMode; }
// SharedTextureSource doesn't own any gl texture
virtual void DeallocateDeviceData() MOZ_OVERRIDE {}
void DetachSharedHandle();
virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
gl::GLContext* gl() const;
protected:
gfx::IntSize mSize;
CompositorOGL* mCompositor;
gl::SharedTextureHandle mSharedHandle;
gfx::SurfaceFormat mFormat;
SharedTextureShareType mShareType;
GLenum mTextureTarget;
GLenum mWrapMode;
};
/**
* A TextureHost for shared GL Textures
*
* Most of the logic actually happens in SharedTextureSourceOGL.
*/
class SharedTextureHostOGL : public TextureHost
{
public:
SharedTextureHostOGL(TextureFlags aFlags,
gl::SharedTextureShareType aShareType,
gl::SharedTextureHandle aSharedhandle,
gfx::IntSize aSize,
bool inverted);
virtual ~SharedTextureHostOGL();
// SharedTextureHostOGL doesn't own any GL texture
virtual void DeallocateDeviceData() MOZ_OVERRIDE {}
virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
virtual bool Lock() MOZ_OVERRIDE;
virtual void Unlock() MOZ_OVERRIDE;
virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE;
virtual NewTextureSource* GetTextureSources() MOZ_OVERRIDE
{
return mTextureSource;
}
virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() MOZ_OVERRIDE
{
return nullptr; // XXX - implement this (for MOZ_DUMP_PAINTING)
}
gl::GLContext* gl() const;
virtual gfx::IntSize GetSize() const MOZ_OVERRIDE { return mSize; }
virtual const char* Name() { return "SharedTextureHostOGL"; }
protected:
gfx::IntSize mSize;
CompositorOGL* mCompositor;
gl::SharedTextureHandle mSharedHandle;
gl::SharedTextureShareType mShareType;
RefPtr<SharedTextureSourceOGL> mTextureSource;
};
/**
* A texture source meant for use with SharedTextureHostOGL.
* A texture source for GL textures.
*
* It does not own any GL texture, and attaches its shared handle to one of
* the compositor's temporary textures when binding.
@ -414,8 +306,6 @@ class GLTextureSource : public NewTextureSource
, public TextureSourceOGL
{
public:
typedef gl::SharedTextureShareType SharedTextureShareType;
GLTextureSource(CompositorOGL* aCompositor,
GLuint aTex,
gfx::SurfaceFormat aFormat,
@ -450,6 +340,188 @@ protected:
const GLenum mTextureTarget;
};
////////////////////////////////////////////////////////////////////////
// SurfaceTexture
#ifdef MOZ_WIDGET_ANDROID
class SurfaceTextureSource : public NewTextureSource
, public TextureSourceOGL
{
public:
SurfaceTextureSource(CompositorOGL* aCompositor,
nsSurfaceTexture* aSurfTex,
gfx::SurfaceFormat aFormat,
GLenum aTarget,
GLenum aWrapMode,
gfx::IntSize aSize);
virtual TextureSourceOGL* AsSourceOGL() { return this; }
virtual void BindTexture(GLenum activetex, gfx::Filter aFilter) MOZ_OVERRIDE;
virtual bool IsValid() const MOZ_OVERRIDE;
virtual gfx::IntSize GetSize() const MOZ_OVERRIDE { return mSize; }
virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE { return mFormat; }
virtual gfx::Matrix4x4 GetTextureTransform() MOZ_OVERRIDE;
virtual GLenum GetTextureTarget() const { return mTextureTarget; }
virtual GLenum GetWrapMode() const MOZ_OVERRIDE { return mWrapMode; }
// We don't own anything.
virtual void DeallocateDeviceData() MOZ_OVERRIDE {}
virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
gl::GLContext* gl() const;
protected:
CompositorOGL* mCompositor;
nsSurfaceTexture* const mSurfTex;
const gfx::SurfaceFormat mFormat;
const GLenum mTextureTarget;
const GLenum mWrapMode;
const gfx::IntSize mSize;
};
class SurfaceTextureHost : public TextureHost
{
public:
SurfaceTextureHost(TextureFlags aFlags,
nsSurfaceTexture* aSurfTex,
gfx::IntSize aSize);
virtual ~SurfaceTextureHost();
// We don't own anything.
virtual void DeallocateDeviceData() MOZ_OVERRIDE {}
virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
virtual bool Lock() MOZ_OVERRIDE;
virtual void Unlock() MOZ_OVERRIDE;
virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE;
virtual NewTextureSource* GetTextureSources() MOZ_OVERRIDE
{
return mTextureSource;
}
virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() MOZ_OVERRIDE
{
return nullptr; // XXX - implement this (for MOZ_DUMP_PAINTING)
}
gl::GLContext* gl() const;
virtual gfx::IntSize GetSize() const MOZ_OVERRIDE { return mSize; }
virtual const char* Name() { return "SurfaceTextureHost"; }
protected:
nsSurfaceTexture* const mSurfTex;
const gfx::IntSize mSize;
CompositorOGL* mCompositor;
RefPtr<SurfaceTextureSource> mTextureSource;
};
#endif // MOZ_WIDGET_ANDROID
////////////////////////////////////////////////////////////////////////
// EGLImage
class EGLImageTextureSource : public NewTextureSource
, public TextureSourceOGL
{
public:
EGLImageTextureSource(CompositorOGL* aCompositor,
EGLImage aImage,
gfx::SurfaceFormat aFormat,
GLenum aTarget,
GLenum aWrapMode,
gfx::IntSize aSize);
virtual TextureSourceOGL* AsSourceOGL() { return this; }
virtual void BindTexture(GLenum activetex, gfx::Filter aFilter) MOZ_OVERRIDE;
virtual bool IsValid() const MOZ_OVERRIDE;
virtual gfx::IntSize GetSize() const MOZ_OVERRIDE { return mSize; }
virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE { return mFormat; }
virtual gfx::Matrix4x4 GetTextureTransform() MOZ_OVERRIDE;
virtual GLenum GetTextureTarget() const { return mTextureTarget; }
virtual GLenum GetWrapMode() const MOZ_OVERRIDE { return mWrapMode; }
// We don't own anything.
virtual void DeallocateDeviceData() MOZ_OVERRIDE {}
virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
gl::GLContext* gl() const;
protected:
CompositorOGL* mCompositor;
const EGLImage mImage;
const gfx::SurfaceFormat mFormat;
const GLenum mTextureTarget;
const GLenum mWrapMode;
const gfx::IntSize mSize;
};
class EGLImageTextureHost : public TextureHost
{
public:
EGLImageTextureHost(TextureFlags aFlags,
EGLImage aImage,
gfx::IntSize aSize);
virtual ~EGLImageTextureHost();
// We don't own anything.
virtual void DeallocateDeviceData() MOZ_OVERRIDE {}
virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
virtual bool Lock() MOZ_OVERRIDE;
virtual void Unlock() MOZ_OVERRIDE;
virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE;
virtual NewTextureSource* GetTextureSources() MOZ_OVERRIDE
{
return mTextureSource;
}
virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() MOZ_OVERRIDE
{
return nullptr; // XXX - implement this (for MOZ_DUMP_PAINTING)
}
gl::GLContext* gl() const;
virtual gfx::IntSize GetSize() const MOZ_OVERRIDE { return mSize; }
virtual const char* Name() { return "EGLImageTextureHost"; }
protected:
const EGLImage mImage;
const gfx::IntSize mSize;
CompositorOGL* mCompositor;
RefPtr<EGLImageTextureSource> mTextureSource;
};
} // namespace
} // namespace