mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-05 22:05:40 +00:00
Bug 942505 - Move everything SharedHandle-related out of GLContext - r=jgilbert
This commit is contained in:
parent
6f935c23a0
commit
41b5c423b1
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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));
|
||||
|
@ -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)
|
||||
{
|
||||
|
328
gfx/gl/GLSharedHandleHelpers.cpp
Normal file
328
gfx/gl/GLSharedHandleHelpers.cpp
Normal 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
|
||||
}
|
||||
|
||||
}
|
||||
}
|
73
gfx/gl/GLSharedHandleHelpers.h
Normal file
73
gfx/gl/GLSharedHandleHelpers.h
Normal 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
|
@ -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',
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user