Bug 942505 - Move everything SharedHandle-related out of GLContext - r=jgilbert

This commit is contained in:
Benoit Jacob 2013-12-03 13:44:38 -05:00
parent 6f935c23a0
commit 41b5c423b1
8 changed files with 432 additions and 426 deletions

View File

@ -54,6 +54,7 @@ using namespace mozilla;
#include "GLContextProvider.h"
#include "GLContext.h"
#include "TexturePoolOGL.h"
#include "GLSharedHandleHelpers.h"
using namespace mozilla::gl;
@ -138,9 +139,10 @@ public:
return 0;
SharedTextureHandle handle =
sPluginContext->CreateSharedHandle(gl::SameProcess,
(void*)mTextureInfo.mTexture,
gl::TextureID);
gl::CreateSharedHandle(sPluginContext,
gl::SameProcess,
(void*)mTextureInfo.mTexture,
gl::TextureID);
// We want forget about this now, so delete the texture. Assigning it to zero
// ensures that we create a new one in Lock()
@ -1018,9 +1020,10 @@ SharedTextureHandle nsNPAPIPluginInstance::CreateSharedHandle()
return mContentTexture->CreateSharedHandle();
} else if (mContentSurface) {
EnsureGLContext();
return sPluginContext->CreateSharedHandle(gl::SameProcess,
mContentSurface,
gl::SurfaceTexture);
return gl::CreateSharedHandle(sPluginContext,
gl::SameProcess,
mContentSurface,
gl::SurfaceTexture);
} else return 0;
}

View File

@ -59,6 +59,7 @@ using mozilla::DefaultXDisplay;
#include "ImageContainer.h"
#include "nsIDOMHTMLCollection.h"
#include "GLContext.h"
#include "GLSharedHandleHelpers.h"
#include "nsIContentInlines.h"
#include "mozilla/MiscEvents.h"
#include "mozilla/MouseEvents.h"
@ -1508,9 +1509,10 @@ already_AddRefed<ImageContainer> nsPluginInstanceOwner::GetImageContainerForVide
SharedTextureImage::Data data;
data.mShareType = gl::SameProcess;
data.mHandle = mInstance->GLContext()->CreateSharedHandle(data.mShareType,
aVideoInfo->mSurfaceTexture,
gl::SurfaceTexture);
data.mHandle = gl::CreateSharedHandle(mInstance->GLContext(),
data.mShareType,
aVideoInfo->mSurfaceTexture,
gl::SurfaceTexture);
// The logic below for Honeycomb is just a guess, but seems to work. We don't have a separate
// inverted flag for video.

View File

@ -2549,71 +2549,6 @@ public:
*/
const gfxIntSize& OffscreenSize() const;
/*
* Create a new shared GLContext content handle, using the passed buffer as a source.
* Must be released by ReleaseSharedHandle. UpdateSharedHandle will have no effect
* on handles created with this method, as the caller owns the source (the passed buffer)
* and is responsible for updating it accordingly.
*/
virtual SharedTextureHandle CreateSharedHandle(SharedTextureShareType shareType,
void* buffer,
SharedTextureBufferType bufferType)
{ return 0; }
/**
* Publish GLContext content to intermediate buffer attached to shared handle.
* Shared handle content is ready to be used after call returns, and no need extra Flush/Finish are required.
* GLContext must be current before this call
*/
virtual void UpdateSharedHandle(SharedTextureShareType shareType,
SharedTextureHandle sharedHandle)
{ }
/**
* - 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).
*/
virtual void ReleaseSharedHandle(SharedTextureShareType shareType,
SharedTextureHandle sharedHandle)
{ }
typedef struct {
GLenum mTarget;
SurfaceFormat mTextureFormat;
gfx3DMatrix mTextureTransform;
} SharedHandleDetails;
/**
* Returns information necessary for rendering a shared handle.
* These values change depending on what sharing mechanism is in use
*/
virtual bool GetSharedHandleDetails(SharedTextureShareType shareType,
SharedTextureHandle sharedHandle,
SharedHandleDetails& details)
{ return false; }
/**
* Attach Shared GL Handle to GL_TEXTURE_2D target
* GLContext must be current before this call
*/
virtual bool AttachSharedHandle(SharedTextureShareType shareType,
SharedTextureHandle sharedHandle)
{ return false; }
/**
* Detach Shared GL Handle from GL_TEXTURE_2D target
*/
virtual void DetachSharedHandle(SharedTextureShareType shareType,
SharedTextureHandle sharedHandle)
{ }
void BindFB(GLuint fb) {
fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, fb);
MOZ_ASSERT(!fb || fIsFramebuffer(fb));

View File

@ -271,7 +271,6 @@ public:
, mIsDoubleBuffered(false)
, mCanBindToTexture(false)
, mShareWithEGLImage(false)
, mTemporaryEGLImageTexture(0)
{
// any EGL contexts will always be GLESv2
SetProfileVersion(ContextProfile::OpenGLES, 200);
@ -294,13 +293,6 @@ public:
~GLContextEGL()
{
if (MakeCurrent()) {
if (mTemporaryEGLImageTexture != 0) {
fDeleteTextures(1, &mTemporaryEGLImageTexture);
mTemporaryEGLImageTexture = 0;
}
}
MarkDestroyed();
#ifdef DEBUG
@ -577,19 +569,6 @@ public:
static already_AddRefed<GLContextEGL>
CreateEGLPBufferOffscreenContext(const gfxIntSize& size);
virtual SharedTextureHandle CreateSharedHandle(SharedTextureShareType shareType,
void* buffer,
SharedTextureBufferType bufferType);
virtual void UpdateSharedHandle(SharedTextureShareType shareType,
SharedTextureHandle sharedHandle);
virtual void ReleaseSharedHandle(SharedTextureShareType shareType,
SharedTextureHandle sharedHandle);
virtual bool GetSharedHandleDetails(SharedTextureShareType shareType,
SharedTextureHandle sharedHandle,
SharedHandleDetails& details);
virtual bool AttachSharedHandle(SharedTextureShareType shareType,
SharedTextureHandle sharedHandle);
protected:
friend class GLContextProviderEGL;
@ -608,10 +587,6 @@ protected:
nsRefPtr<HwcComposer2D> mHwc;
#endif
// A dummy texture ID that can be used when we need a texture object whose
// images we're going to define with EGLImageTargetTexture2D.
GLuint mTemporaryEGLImageTexture;
static EGLSurface CreatePBufferSurfaceTryingPowerOfTwo(EGLConfig config,
EGLenum bindToTextureFormat,
gfxIntSize& pbsize)
@ -656,319 +631,6 @@ protected:
}
};
enum SharedHandleType {
SharedHandleType_Image
#ifdef MOZ_WIDGET_ANDROID
, SharedHandleType_SurfaceTexture
#endif
};
class SharedTextureHandleWrapper
{
public:
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(GLContextEGL *ctx, GLuint texture) {
MOZ_ASSERT(!mEGLImage && texture && sEGLLibrary.HasKHRImageBase());
static const EGLint eglAttributes[] = {
LOCAL_EGL_NONE
};
EGLContext eglContext = (EGLContext)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;
};
void
GLContextEGL::UpdateSharedHandle(SharedTextureShareType shareType,
SharedTextureHandle sharedHandle)
{
if (shareType != SameProcess) {
NS_ERROR("Implementation not available for this sharing type");
return;
}
SharedTextureHandleWrapper* wrapper = reinterpret_cast<SharedTextureHandleWrapper*>(sharedHandle);
NS_ASSERTION(wrapper->Type() == SharedHandleType_Image, "Expected EGLImage shared handle");
NS_ASSERTION(mShareWithEGLImage, "EGLImage not supported or disabled in runtime");
EGLTextureWrapper* wrap = reinterpret_cast<EGLTextureWrapper*>(wrapper);
// We need to copy the current GLContext drawing buffer to the texture
// exported by the EGLImage. Need to save both the read FBO and the texture
// binding, because we're going to munge them to do this.
ScopedBindTexture autoTex(this, mTemporaryEGLImageTexture);
fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_2D, wrap->GetEGLImage());
// CopyTexSubImage2D, is ~2x slower than simple FBO render to texture with
// draw quads, but if we want that, we need to assure that our default
// framebuffer is texture-backed.
gfxIntSize size = OffscreenSize();
BlitHelper()->BlitFramebufferToTexture(0, mTemporaryEGLImageTexture, size, size);
// Make sure our copy is finished, so that we can be ready to draw
// in different thread GLContext. If we have KHR_fence_sync, then
// we insert a sync object, otherwise we have to do a GuaranteeResolve.
wrap->MakeSync(this);
}
SharedTextureHandle
GLContextEGL::CreateSharedHandle(SharedTextureShareType shareType,
void* buffer,
SharedTextureBufferType bufferType)
{
// 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 != SameProcess)
return 0;
switch (bufferType) {
#ifdef MOZ_WIDGET_ANDROID
case SharedTextureBufferType::SurfaceTexture:
if (!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 (!mShareWithEGLImage)
return 0;
GLuint texture = (uintptr_t)buffer;
EGLTextureWrapper* tex = new EGLTextureWrapper();
if (!tex->CreateEGLImage(this, 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 GLContextEGL::ReleaseSharedHandle(SharedTextureShareType shareType,
SharedTextureHandle sharedHandle)
{
if (shareType != 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(mShareWithEGLImage, "EGLImage not supported or disabled in runtime");
EGLTextureWrapper* wrap = (EGLTextureWrapper*)sharedHandle;
delete wrap;
break;
}
default:
NS_ERROR("Unknown shared handle type");
return;
}
}
bool GLContextEGL::GetSharedHandleDetails(SharedTextureShareType shareType,
SharedTextureHandle sharedHandle,
SharedHandleDetails& details)
{
if (shareType != 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 = FORMAT_R8G8B8A8;
surfaceWrapper->SurfaceTexture()->GetTransformMatrix(details.mTextureTransform);
break;
}
#endif
case SharedHandleType_Image:
details.mTarget = LOCAL_GL_TEXTURE_2D;
details.mTextureFormat = FORMAT_R8G8B8A8;
break;
default:
NS_ERROR("Unknown shared handle type");
return false;
}
return true;
}
bool GLContextEGL::AttachSharedHandle(SharedTextureShareType shareType,
SharedTextureHandle sharedHandle)
{
if (shareType != 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.
*/
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(mShareWithEGLImage, "EGLImage not supported or disabled in runtime");
EGLTextureWrapper* wrap = (EGLTextureWrapper*)sharedHandle;
wrap->WaitSync();
fEGLImageTargetTexture2D(LOCAL_GL_TEXTURE_2D, wrap->GetEGLImage());
break;
}
default:
NS_ERROR("Unknown shared handle type");
return false;
}
return true;
}
bool
GLContextEGL::ResizeOffscreen(const gfxIntSize& aNewSize)
{

View File

@ -0,0 +1,328 @@
/* 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 "GLContext.h"
#include "GLLibraryEGL.h"
#include "GLSharedHandleHelpers.h"
namespace mozilla {
namespace gl {
enum SharedHandleType {
SharedHandleType_Image
#ifdef MOZ_WIDGET_ANDROID
, SharedHandleType_SurfaceTexture
#endif
};
class SharedTextureHandleWrapper
{
public:
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 = (EGLContext)ctx->GetNativeData(GLContext::NativeGLContext);
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() != ContextTypeEGL)
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 != 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() != ContextTypeEGL)
return;
if (shareType != 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() != ContextTypeEGL)
return false;
if (shareType != 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::FORMAT_R8G8B8A8;
surfaceWrapper->SurfaceTexture()->GetTransformMatrix(details.mTextureTransform);
break;
}
#endif
case SharedHandleType_Image:
details.mTarget = LOCAL_GL_TEXTURE_2D;
details.mTextureFormat = gfx::FORMAT_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() != ContextTypeEGL)
return false;
if (shareType != 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

@ -0,0 +1,73 @@
/* 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;
gfx3DMatrix 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

@ -41,6 +41,7 @@ EXPORTS += [
'GLLibraryEGL.h',
'GLLibraryLoader.h',
'GLScreenBuffer.h',
'GLSharedHandleHelpers.h',
'GLTextureImage.h',
'GLTypes.h',
'ScopedGLHelpers.h',
@ -117,6 +118,7 @@ UNIFIED_SOURCES += [
'GLLibraryEGL.cpp',
'GLLibraryLoader.cpp',
'GLScreenBuffer.cpp',
'GLSharedHandleHelpers.cpp',
'GLTextureImage.cpp',
'ScopedGLHelpers.cpp',
'SharedSurface.cpp',

View File

@ -5,6 +5,7 @@
#include "TextureHostOGL.h"
#include "GLContext.h" // for GLContext, etc
#include "GLSharedHandleHelpers.h"
#include "GLContextUtils.h" // for GLContextUtils
#include "SharedSurface.h" // for SharedSurface
#include "SharedSurfaceEGL.h" // for SharedSurface_EGLImage
@ -325,7 +326,7 @@ SharedTextureSourceOGL::BindTexture(GLenum aTextureUnit)
gl()->fActiveTexture(aTextureUnit);
gl()->fBindTexture(mTextureTarget, tex);
if (!gl()->AttachSharedHandle(mShareType, mSharedHandle)) {
if (!AttachSharedHandle(gl(), mShareType, mSharedHandle)) {
NS_ERROR("Failed to bind shared texture handle");
return;
}
@ -338,7 +339,7 @@ SharedTextureSourceOGL::DetachSharedHandle()
if (!gl()) {
return;
}
gl()->DetachSharedHandle(mShareType, mSharedHandle);
gl::DetachSharedHandle(gl(), mShareType, mSharedHandle);
}
void
@ -362,8 +363,8 @@ SharedTextureSourceOGL::gl() const
gfx3DMatrix
SharedTextureSourceOGL::GetTextureTransform()
{
GLContext::SharedHandleDetails handleDetails;
if (!gl()->GetSharedHandleDetails(mShareType, mSharedHandle, handleDetails)) {
SharedHandleDetails handleDetails;
if (!GetSharedHandleDetails(gl(), mShareType, mSharedHandle, handleDetails)) {
NS_WARNING("Could not get shared handle details");
return gfx3DMatrix();
}
@ -407,8 +408,8 @@ SharedTextureHostOGL::Lock()
if (!mTextureSource) {
// XXX on android GetSharedHandleDetails can call into Java which we'd
// rather not do from the compositor
GLContext::SharedHandleDetails handleDetails;
if (!gl()->GetSharedHandleDetails(mShareType, mSharedHandle, handleDetails)) {
SharedHandleDetails handleDetails;
if (!GetSharedHandleDetails(gl(), mShareType, mSharedHandle, handleDetails)) {
NS_WARNING("Could not get shared handle details");
return false;
}
@ -616,7 +617,7 @@ SharedDeprecatedTextureHostOGL::DeleteTextures()
return;
}
if (mSharedHandle) {
mGL->ReleaseSharedHandle(mShareType, mSharedHandle);
ReleaseSharedHandle(mGL, mShareType, mSharedHandle);
mSharedHandle = 0;
}
if (mTextureHandle) {
@ -650,14 +651,14 @@ SharedDeprecatedTextureHostOGL::SwapTexturesImpl(const SurfaceDescriptor& aImage
}
if (mSharedHandle && mSharedHandle != newHandle) {
mGL->ReleaseSharedHandle(mShareType, mSharedHandle);
ReleaseSharedHandle(mGL, mShareType, mSharedHandle);
}
mShareType = texture.shareType();
mSharedHandle = newHandle;
GLContext::SharedHandleDetails handleDetails;
if (mSharedHandle && mGL->GetSharedHandleDetails(mShareType, mSharedHandle, handleDetails)) {
SharedHandleDetails handleDetails;
if (mSharedHandle && GetSharedHandleDetails(mGL, mShareType, mSharedHandle, handleDetails)) {
mTextureTarget = handleDetails.mTarget;
mFormat = handleDetails.mTextureFormat;
}
@ -670,7 +671,7 @@ SharedDeprecatedTextureHostOGL::Lock()
mGL->fActiveTexture(LOCAL_GL_TEXTURE0);
mGL->fBindTexture(mTextureTarget, mTextureHandle);
if (!mGL->AttachSharedHandle(mShareType, mSharedHandle)) {
if (!AttachSharedHandle(mGL, mShareType, mSharedHandle)) {
NS_ERROR("Failed to bind shared texture handle");
return false;
}
@ -681,7 +682,7 @@ SharedDeprecatedTextureHostOGL::Lock()
void
SharedDeprecatedTextureHostOGL::Unlock()
{
mGL->DetachSharedHandle(mShareType, mSharedHandle);
DetachSharedHandle(mGL, mShareType, mSharedHandle);
mGL->fBindTexture(LOCAL_GL_TEXTURE_2D, 0);
}
@ -689,11 +690,11 @@ SharedDeprecatedTextureHostOGL::Unlock()
gfx3DMatrix
SharedDeprecatedTextureHostOGL::GetTextureTransform()
{
GLContext::SharedHandleDetails handleDetails;
SharedHandleDetails handleDetails;
// GetSharedHandleDetails can call into Java which we'd
// rather not do from the compositor
if (mSharedHandle) {
mGL->GetSharedHandleDetails(mShareType, mSharedHandle, handleDetails);
GetSharedHandleDetails(mGL, mShareType, mSharedHandle, handleDetails);
}
return handleDetails.mTextureTransform;
}