forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			817 lines
		
	
	
	
		
			23 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			817 lines
		
	
	
	
		
			23 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | 
						|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
 | 
						|
/* 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 "TextureHostOGL.h"
 | 
						|
 | 
						|
#include "EGLUtils.h"
 | 
						|
#include "GLContext.h"                  // for GLContext, etc
 | 
						|
#include "GLLibraryEGL.h"               // for GLLibraryEGL
 | 
						|
#include "GLUploadHelpers.h"
 | 
						|
#include "GLReadTexImageHelper.h"
 | 
						|
#include "gfx2DGlue.h"                  // for ContentForFormat, etc
 | 
						|
#include "mozilla/gfx/2D.h"             // for DataSourceSurface
 | 
						|
#include "mozilla/gfx/BaseSize.h"       // for BaseSize
 | 
						|
#include "mozilla/gfx/Logging.h"        // for gfxCriticalError
 | 
						|
#include "mozilla/layers/ISurfaceAllocator.h"
 | 
						|
#include "nsRegion.h"                   // for nsIntRegion
 | 
						|
#include "AndroidSurfaceTexture.h"
 | 
						|
#include "GfxTexturesReporter.h"        // for GfxTexturesReporter
 | 
						|
#include "GLBlitTextureImageHelper.h"
 | 
						|
#include "GeckoProfiler.h"
 | 
						|
 | 
						|
#ifdef XP_MACOSX
 | 
						|
#include "mozilla/layers/MacIOSurfaceTextureHostOGL.h"
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef GL_PROVIDER_GLX
 | 
						|
#include "mozilla/layers/X11TextureHost.h"
 | 
						|
#endif
 | 
						|
 | 
						|
using namespace mozilla::gl;
 | 
						|
using namespace mozilla::gfx;
 | 
						|
 | 
						|
namespace mozilla {
 | 
						|
namespace layers {
 | 
						|
 | 
						|
class Compositor;
 | 
						|
 | 
						|
already_AddRefed<TextureHost>
 | 
						|
CreateTextureHostOGL(const SurfaceDescriptor& aDesc,
 | 
						|
                     ISurfaceAllocator* aDeallocator,
 | 
						|
                     LayersBackend aBackend,
 | 
						|
                     TextureFlags aFlags)
 | 
						|
{
 | 
						|
  RefPtr<TextureHost> result;
 | 
						|
  switch (aDesc.type()) {
 | 
						|
    case SurfaceDescriptor::TSurfaceDescriptorBuffer: {
 | 
						|
      result = CreateBackendIndependentTextureHost(aDesc,
 | 
						|
                                                   aDeallocator,
 | 
						|
                                                   aBackend,
 | 
						|
                                                   aFlags);
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
#ifdef MOZ_WIDGET_ANDROID
 | 
						|
    case SurfaceDescriptor::TSurfaceTextureDescriptor: {
 | 
						|
      const SurfaceTextureDescriptor& desc = aDesc.get_SurfaceTextureDescriptor();
 | 
						|
      java::GeckoSurfaceTexture::LocalRef surfaceTexture = java::GeckoSurfaceTexture::Lookup(desc.handle());
 | 
						|
 | 
						|
      result = new SurfaceTextureHost(aFlags,
 | 
						|
                                      surfaceTexture,
 | 
						|
                                      desc.size(),
 | 
						|
                                      desc.format(),
 | 
						|
                                      desc.continuous(),
 | 
						|
                                      desc.ignoreTransform());
 | 
						|
      break;
 | 
						|
    }
 | 
						|
#endif
 | 
						|
 | 
						|
    case SurfaceDescriptor::TEGLImageDescriptor: {
 | 
						|
      const EGLImageDescriptor& desc = aDesc.get_EGLImageDescriptor();
 | 
						|
      result = new EGLImageTextureHost(aFlags,
 | 
						|
                                       (EGLImage)desc.image(),
 | 
						|
                                       (EGLSync)desc.fence(),
 | 
						|
                                       desc.size(),
 | 
						|
                                       desc.hasAlpha());
 | 
						|
      break;
 | 
						|
    }
 | 
						|
 | 
						|
#ifdef XP_MACOSX
 | 
						|
    case SurfaceDescriptor::TSurfaceDescriptorMacIOSurface: {
 | 
						|
      const SurfaceDescriptorMacIOSurface& desc =
 | 
						|
        aDesc.get_SurfaceDescriptorMacIOSurface();
 | 
						|
      result = new MacIOSurfaceTextureHostOGL(aFlags, desc);
 | 
						|
      break;
 | 
						|
    }
 | 
						|
#endif
 | 
						|
 | 
						|
#ifdef GL_PROVIDER_GLX
 | 
						|
    case SurfaceDescriptor::TSurfaceDescriptorX11: {
 | 
						|
      const auto& desc = aDesc.get_SurfaceDescriptorX11();
 | 
						|
      result = new X11TextureHost(aFlags, desc);
 | 
						|
      break;
 | 
						|
    }
 | 
						|
#endif
 | 
						|
 | 
						|
    case SurfaceDescriptor::TSurfaceDescriptorSharedGLTexture: {
 | 
						|
      const auto& desc = aDesc.get_SurfaceDescriptorSharedGLTexture();
 | 
						|
      result = new GLTextureHost(aFlags, desc.texture(),
 | 
						|
                                 desc.target(),
 | 
						|
                                 (GLsync)desc.fence(),
 | 
						|
                                 desc.size(),
 | 
						|
                                 desc.hasAlpha());
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    default: return nullptr;
 | 
						|
  }
 | 
						|
  return result.forget();
 | 
						|
}
 | 
						|
 | 
						|
static gl::TextureImage::Flags
 | 
						|
FlagsToGLFlags(TextureFlags aFlags)
 | 
						|
{
 | 
						|
  uint32_t result = TextureImage::NoFlags;
 | 
						|
 | 
						|
  if (aFlags & TextureFlags::USE_NEAREST_FILTER)
 | 
						|
    result |= TextureImage::UseNearestFilter;
 | 
						|
  if (aFlags & TextureFlags::ORIGIN_BOTTOM_LEFT)
 | 
						|
    result |= TextureImage::OriginBottomLeft;
 | 
						|
  if (aFlags & TextureFlags::DISALLOW_BIGIMAGE)
 | 
						|
    result |= TextureImage::DisallowBigImage;
 | 
						|
 | 
						|
  return static_cast<gl::TextureImage::Flags>(result);
 | 
						|
}
 | 
						|
 | 
						|
bool
 | 
						|
TextureImageTextureSourceOGL::Update(gfx::DataSourceSurface* aSurface,
 | 
						|
                                     nsIntRegion* aDestRegion,
 | 
						|
                                     gfx::IntPoint* aSrcOffset)
 | 
						|
{
 | 
						|
  GLContext *gl = mGL;
 | 
						|
  MOZ_ASSERT(gl);
 | 
						|
  if (!gl || !gl->MakeCurrent()) {
 | 
						|
    NS_WARNING("trying to update TextureImageTextureSourceOGL without a GLContext");
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
  if (!aSurface) {
 | 
						|
    gfxCriticalError() << "Invalid surface for OGL update";
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
  MOZ_ASSERT(aSurface);
 | 
						|
 | 
						|
  IntSize size = aSurface->GetSize();
 | 
						|
  if (!mTexImage ||
 | 
						|
      (mTexImage->GetSize() != size && !aSrcOffset) ||
 | 
						|
      mTexImage->GetContentType() != gfx::ContentForFormat(aSurface->GetFormat())) {
 | 
						|
    if (mFlags & TextureFlags::DISALLOW_BIGIMAGE) {
 | 
						|
      GLint maxTextureSize;
 | 
						|
      gl->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &maxTextureSize);
 | 
						|
      if (size.width > maxTextureSize || size.height > maxTextureSize) {
 | 
						|
        NS_WARNING("Texture exceeds maximum texture size, refusing upload");
 | 
						|
        return false;
 | 
						|
      }
 | 
						|
      // Explicitly use CreateBasicTextureImage instead of CreateTextureImage,
 | 
						|
      // because CreateTextureImage might still choose to create a tiled
 | 
						|
      // texture image.
 | 
						|
      mTexImage = CreateBasicTextureImage(gl, size,
 | 
						|
                                          gfx::ContentForFormat(aSurface->GetFormat()),
 | 
						|
                                          LOCAL_GL_CLAMP_TO_EDGE,
 | 
						|
                                          FlagsToGLFlags(mFlags));
 | 
						|
    } else {
 | 
						|
      // XXX - clarify which size we want to use. IncrementalContentHost will
 | 
						|
      // require the size of the destination surface to be different from
 | 
						|
      // the size of aSurface.
 | 
						|
      // See bug 893300 (tracks the implementation of ContentHost for new textures).
 | 
						|
      mTexImage = CreateTextureImage(gl,
 | 
						|
                                     size,
 | 
						|
                                     gfx::ContentForFormat(aSurface->GetFormat()),
 | 
						|
                                     LOCAL_GL_CLAMP_TO_EDGE,
 | 
						|
                                     FlagsToGLFlags(mFlags),
 | 
						|
                                     SurfaceFormatToImageFormat(aSurface->GetFormat()));
 | 
						|
    }
 | 
						|
    ClearCachedFilter();
 | 
						|
 | 
						|
    if (aDestRegion &&
 | 
						|
        !aSrcOffset &&
 | 
						|
        !aDestRegion->IsEqual(gfx::IntRect(0, 0, size.width, size.height))) {
 | 
						|
      // UpdateFromDataSource will ignore our specified aDestRegion since the texture
 | 
						|
      // hasn't been allocated with glTexImage2D yet. Call Resize() to force the
 | 
						|
      // allocation (full size, but no upload), and then we'll only upload the pixels
 | 
						|
      // we care about below.
 | 
						|
      mTexImage->Resize(size);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  mTexImage->UpdateFromDataSource(aSurface, aDestRegion, aSrcOffset);
 | 
						|
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
TextureImageTextureSourceOGL::EnsureBuffer(const IntSize& aSize,
 | 
						|
                                           gfxContentType aContentType)
 | 
						|
{
 | 
						|
  if (!mTexImage ||
 | 
						|
      mTexImage->GetSize() != aSize ||
 | 
						|
      mTexImage->GetContentType() != aContentType) {
 | 
						|
    mTexImage = CreateTextureImage(mGL,
 | 
						|
                                   aSize,
 | 
						|
                                   aContentType,
 | 
						|
                                   LOCAL_GL_CLAMP_TO_EDGE,
 | 
						|
                                   FlagsToGLFlags(mFlags));
 | 
						|
  }
 | 
						|
  mTexImage->Resize(aSize);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
TextureImageTextureSourceOGL::SetTextureSourceProvider(TextureSourceProvider* aProvider)
 | 
						|
{
 | 
						|
  GLContext* newGL = aProvider ? aProvider->GetGLContext() : nullptr;
 | 
						|
  if (!newGL || mGL != newGL) {
 | 
						|
    DeallocateDeviceData();
 | 
						|
  }
 | 
						|
  mGL = newGL;
 | 
						|
}
 | 
						|
 | 
						|
gfx::IntSize
 | 
						|
TextureImageTextureSourceOGL::GetSize() const
 | 
						|
{
 | 
						|
  if (mTexImage) {
 | 
						|
    if (mIterating) {
 | 
						|
      return mTexImage->GetTileRect().Size();
 | 
						|
    }
 | 
						|
    return mTexImage->GetSize();
 | 
						|
  }
 | 
						|
  NS_WARNING("Trying to query the size of an empty TextureSource.");
 | 
						|
  return gfx::IntSize(0, 0);
 | 
						|
}
 | 
						|
 | 
						|
gfx::SurfaceFormat
 | 
						|
TextureImageTextureSourceOGL::GetFormat() const
 | 
						|
{
 | 
						|
  if (mTexImage) {
 | 
						|
    return mTexImage->GetTextureFormat();
 | 
						|
  }
 | 
						|
  NS_WARNING("Trying to query the format of an empty TextureSource.");
 | 
						|
  return gfx::SurfaceFormat::UNKNOWN;
 | 
						|
}
 | 
						|
 | 
						|
gfx::IntRect TextureImageTextureSourceOGL::GetTileRect()
 | 
						|
{
 | 
						|
  return mTexImage->GetTileRect();
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
TextureImageTextureSourceOGL::BindTexture(GLenum aTextureUnit,
 | 
						|
                                          gfx::SamplingFilter aSamplingFilter)
 | 
						|
{
 | 
						|
  MOZ_ASSERT(mTexImage,
 | 
						|
    "Trying to bind a TextureSource that does not have an underlying GL texture.");
 | 
						|
  mTexImage->BindTexture(aTextureUnit);
 | 
						|
  SetSamplingFilter(mGL, aSamplingFilter);
 | 
						|
}
 | 
						|
 | 
						|
////////////////////////////////////////////////////////////////////////
 | 
						|
// GLTextureSource
 | 
						|
 | 
						|
GLTextureSource::GLTextureSource(TextureSourceProvider* aProvider,
 | 
						|
                                 GLuint aTextureHandle,
 | 
						|
                                 GLenum aTarget,
 | 
						|
                                 gfx::IntSize aSize,
 | 
						|
                                 gfx::SurfaceFormat aFormat,
 | 
						|
                                 bool aExternallyOwned)
 | 
						|
  : mGL(aProvider->GetGLContext())
 | 
						|
  , mTextureHandle(aTextureHandle)
 | 
						|
  , mTextureTarget(aTarget)
 | 
						|
  , mSize(aSize)
 | 
						|
  , mFormat(aFormat)
 | 
						|
  , mExternallyOwned(aExternallyOwned)
 | 
						|
{
 | 
						|
  MOZ_COUNT_CTOR(GLTextureSource);
 | 
						|
}
 | 
						|
 | 
						|
GLTextureSource::~GLTextureSource()
 | 
						|
{
 | 
						|
  MOZ_COUNT_DTOR(GLTextureSource);
 | 
						|
  if (!mExternallyOwned) {
 | 
						|
    DeleteTextureHandle();
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
GLTextureSource::DeallocateDeviceData()
 | 
						|
{
 | 
						|
  if (!mExternallyOwned) {
 | 
						|
    DeleteTextureHandle();
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
GLTextureSource::DeleteTextureHandle()
 | 
						|
{
 | 
						|
  GLContext* gl = this->gl();
 | 
						|
  if (mTextureHandle != 0 && gl && gl->MakeCurrent()) {
 | 
						|
    gl->fDeleteTextures(1, &mTextureHandle);
 | 
						|
  }
 | 
						|
  mTextureHandle = 0;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
GLTextureSource::BindTexture(GLenum aTextureUnit,
 | 
						|
                             gfx::SamplingFilter aSamplingFilter)
 | 
						|
{
 | 
						|
  MOZ_ASSERT(mTextureHandle != 0);
 | 
						|
  GLContext* gl = this->gl();
 | 
						|
  if (!gl || !gl->MakeCurrent()) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
  gl->fActiveTexture(aTextureUnit);
 | 
						|
  gl->fBindTexture(mTextureTarget, mTextureHandle);
 | 
						|
  ApplySamplingFilterToBoundTexture(gl, aSamplingFilter, mTextureTarget);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
GLTextureSource::SetTextureSourceProvider(TextureSourceProvider* aProvider)
 | 
						|
{
 | 
						|
  GLContext* newGL = aProvider ? aProvider->GetGLContext() : nullptr;
 | 
						|
  if (!newGL) {
 | 
						|
    mGL = newGL;
 | 
						|
  } else if (mGL != newGL) {
 | 
						|
    gfxCriticalError() << "GLTextureSource does not support changing compositors";
 | 
						|
  }
 | 
						|
 | 
						|
  if (mNextSibling) {
 | 
						|
    mNextSibling->SetTextureSourceProvider(aProvider);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
bool
 | 
						|
GLTextureSource::IsValid() const
 | 
						|
{
 | 
						|
  return !!gl() && mTextureHandle != 0;
 | 
						|
}
 | 
						|
 | 
						|
////////////////////////////////////////////////////////////////////////
 | 
						|
////////////////////////////////////////////////////////////////////////
 | 
						|
// SurfaceTextureHost
 | 
						|
 | 
						|
#ifdef MOZ_WIDGET_ANDROID
 | 
						|
 | 
						|
SurfaceTextureSource::SurfaceTextureSource(TextureSourceProvider* aProvider,
 | 
						|
                                           mozilla::java::GeckoSurfaceTexture::Ref& aSurfTex,
 | 
						|
                                           gfx::SurfaceFormat aFormat,
 | 
						|
                                           GLenum aTarget,
 | 
						|
                                           GLenum aWrapMode,
 | 
						|
                                           gfx::IntSize aSize,
 | 
						|
                                           bool aIgnoreTransform)
 | 
						|
  : mGL(aProvider->GetGLContext())
 | 
						|
  , mSurfTex(aSurfTex)
 | 
						|
  , mFormat(aFormat)
 | 
						|
  , mTextureTarget(aTarget)
 | 
						|
  , mWrapMode(aWrapMode)
 | 
						|
  , mSize(aSize)
 | 
						|
  , mIgnoreTransform(aIgnoreTransform)
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
SurfaceTextureSource::BindTexture(GLenum aTextureUnit,
 | 
						|
                                  gfx::SamplingFilter aSamplingFilter)
 | 
						|
{
 | 
						|
  MOZ_ASSERT(mSurfTex);
 | 
						|
  GLContext* gl = this->gl();
 | 
						|
  if (!gl || !gl->MakeCurrent()) {
 | 
						|
    NS_WARNING("Trying to bind a texture without a GLContext");
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  gl->fActiveTexture(aTextureUnit);
 | 
						|
  gl->fBindTexture(mTextureTarget, mSurfTex->GetTexName());
 | 
						|
 | 
						|
  ApplySamplingFilterToBoundTexture(gl, aSamplingFilter, mTextureTarget);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
SurfaceTextureSource::SetTextureSourceProvider(TextureSourceProvider* aProvider)
 | 
						|
{
 | 
						|
  GLContext* newGL = aProvider->GetGLContext();
 | 
						|
  if (!newGL || mGL != newGL) {
 | 
						|
    DeallocateDeviceData();
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  mGL = newGL;
 | 
						|
}
 | 
						|
 | 
						|
bool
 | 
						|
SurfaceTextureSource::IsValid() const
 | 
						|
{
 | 
						|
  return !!gl();
 | 
						|
}
 | 
						|
 | 
						|
gfx::Matrix4x4
 | 
						|
SurfaceTextureSource::GetTextureTransform()
 | 
						|
{
 | 
						|
  MOZ_ASSERT(mSurfTex);
 | 
						|
 | 
						|
  gfx::Matrix4x4 ret;
 | 
						|
 | 
						|
  // GetTransformMatrix() returns the transform set by the producer side of
 | 
						|
  // the SurfaceTexture. We should ignore this if we know the transform should
 | 
						|
  // be identity but the producer couldn't set it correctly, like is the
 | 
						|
  // case for AndroidNativeWindowTextureData.
 | 
						|
  if (!mIgnoreTransform) {
 | 
						|
    const auto& surf = java::sdk::SurfaceTexture::LocalRef(java::sdk::SurfaceTexture::Ref::From(mSurfTex));
 | 
						|
    AndroidSurfaceTexture::GetTransformMatrix(surf, &ret);
 | 
						|
  }
 | 
						|
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
SurfaceTextureSource::DeallocateDeviceData()
 | 
						|
{
 | 
						|
  mSurfTex = nullptr;
 | 
						|
}
 | 
						|
 | 
						|
////////////////////////////////////////////////////////////////////////
 | 
						|
 | 
						|
SurfaceTextureHost::SurfaceTextureHost(TextureFlags aFlags,
 | 
						|
                                       mozilla::java::GeckoSurfaceTexture::Ref& aSurfTex,
 | 
						|
                                       gfx::IntSize aSize,
 | 
						|
                                       gfx::SurfaceFormat aFormat,
 | 
						|
                                       bool aContinuousUpdate,
 | 
						|
                                       bool aIgnoreTransform)
 | 
						|
  : TextureHost(aFlags)
 | 
						|
  , mSurfTex(aSurfTex)
 | 
						|
  , mSize(aSize)
 | 
						|
  , mFormat(aFormat)
 | 
						|
  , mContinuousUpdate(aContinuousUpdate)
 | 
						|
  , mIgnoreTransform(aIgnoreTransform)
 | 
						|
{
 | 
						|
  if (!mSurfTex) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  // Continuous update makes no sense with single buffer mode
 | 
						|
  MOZ_ASSERT(!mSurfTex->IsSingleBuffer() || !mContinuousUpdate);
 | 
						|
 | 
						|
  mSurfTex->IncrementUse();
 | 
						|
}
 | 
						|
 | 
						|
SurfaceTextureHost::~SurfaceTextureHost()
 | 
						|
{
 | 
						|
  if (mSurfTex) {
 | 
						|
    mSurfTex->DecrementUse();
 | 
						|
    mSurfTex = nullptr;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
SurfaceTextureHost::PrepareTextureSource(CompositableTextureSourceRef& aTexture)
 | 
						|
{
 | 
						|
  if (!mContinuousUpdate && mSurfTex) {
 | 
						|
    if (!EnsureAttached()) {
 | 
						|
      return;
 | 
						|
    }
 | 
						|
 | 
						|
    // UpdateTexImage() advances the internal buffer queue, so we only want to call this
 | 
						|
    // once per transactionwhen we are not in continuous mode (as we are here). Otherwise,
 | 
						|
    // the SurfaceTexture content will be de-synced from the rest of the page in subsequent
 | 
						|
    // compositor passes.
 | 
						|
    mSurfTex->UpdateTexImage();
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
gl::GLContext*
 | 
						|
SurfaceTextureHost::gl() const
 | 
						|
{
 | 
						|
  return mProvider ? mProvider->GetGLContext() : nullptr;
 | 
						|
}
 | 
						|
 | 
						|
bool
 | 
						|
SurfaceTextureHost::EnsureAttached()
 | 
						|
{
 | 
						|
  GLContext* gl = this->gl();
 | 
						|
  if (!gl || !gl->MakeCurrent()) {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!mSurfTex) {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!mSurfTex->IsAttachedToGLContext((int64_t)gl)) {
 | 
						|
    GLuint texName;
 | 
						|
    gl->fGenTextures(1, &texName);
 | 
						|
    if (NS_FAILED(mSurfTex->AttachToGLContext((int64_t)gl, texName))) {
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
bool
 | 
						|
SurfaceTextureHost::Lock()
 | 
						|
{
 | 
						|
  if (!EnsureAttached()) {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  if (mContinuousUpdate) {
 | 
						|
    mSurfTex->UpdateTexImage();
 | 
						|
  }
 | 
						|
 | 
						|
  if (!mTextureSource) {
 | 
						|
    GLenum target = LOCAL_GL_TEXTURE_EXTERNAL; // This is required by SurfaceTexture
 | 
						|
    GLenum wrapMode = LOCAL_GL_CLAMP_TO_EDGE;
 | 
						|
    mTextureSource = new SurfaceTextureSource(mProvider,
 | 
						|
                                              mSurfTex,
 | 
						|
                                              mFormat,
 | 
						|
                                              target,
 | 
						|
                                              wrapMode,
 | 
						|
                                              mSize,
 | 
						|
                                              mIgnoreTransform);
 | 
						|
  }
 | 
						|
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
SurfaceTextureHost::SetTextureSourceProvider(TextureSourceProvider* aProvider)
 | 
						|
{
 | 
						|
  if (mProvider != aProvider) {
 | 
						|
    if (!aProvider || !aProvider->GetGLContext()) {
 | 
						|
      DeallocateDeviceData();
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    mProvider = aProvider;
 | 
						|
  }
 | 
						|
 | 
						|
  if (mTextureSource) {
 | 
						|
    mTextureSource->SetTextureSourceProvider(aProvider);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
SurfaceTextureHost::NotifyNotUsed()
 | 
						|
{
 | 
						|
  if (mSurfTex && mSurfTex->IsSingleBuffer()) {
 | 
						|
    mSurfTex->ReleaseTexImage();
 | 
						|
  }
 | 
						|
 | 
						|
  TextureHost::NotifyNotUsed();
 | 
						|
}
 | 
						|
 | 
						|
gfx::SurfaceFormat
 | 
						|
SurfaceTextureHost::GetFormat() const
 | 
						|
{
 | 
						|
  return mFormat;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
SurfaceTextureHost::DeallocateDeviceData()
 | 
						|
{
 | 
						|
  if (mTextureSource) {
 | 
						|
    mTextureSource->DeallocateDeviceData();
 | 
						|
  }
 | 
						|
 | 
						|
  if (mSurfTex) {
 | 
						|
    mSurfTex->DecrementUse();
 | 
						|
    mSurfTex = nullptr;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
#endif // MOZ_WIDGET_ANDROID
 | 
						|
 | 
						|
////////////////////////////////////////////////////////////////////////
 | 
						|
////////////////////////////////////////////////////////////////////////
 | 
						|
// EGLImage
 | 
						|
 | 
						|
EGLImageTextureSource::EGLImageTextureSource(TextureSourceProvider* aProvider,
 | 
						|
                                             EGLImage aImage,
 | 
						|
                                             gfx::SurfaceFormat aFormat,
 | 
						|
                                             GLenum aTarget,
 | 
						|
                                             GLenum aWrapMode,
 | 
						|
                                             gfx::IntSize aSize)
 | 
						|
  : mImage(aImage)
 | 
						|
  , mFormat(aFormat)
 | 
						|
  , mTextureTarget(aTarget)
 | 
						|
  , mWrapMode(aWrapMode)
 | 
						|
  , mSize(aSize)
 | 
						|
{
 | 
						|
  MOZ_ASSERT(mTextureTarget == LOCAL_GL_TEXTURE_2D ||
 | 
						|
             mTextureTarget == LOCAL_GL_TEXTURE_EXTERNAL);
 | 
						|
  SetTextureSourceProvider(aProvider);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
EGLImageTextureSource::BindTexture(GLenum aTextureUnit,
 | 
						|
                                   gfx::SamplingFilter aSamplingFilter)
 | 
						|
{
 | 
						|
  GLContext* gl = this->gl();
 | 
						|
  if (!gl || !gl->MakeCurrent()) {
 | 
						|
    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(mTextureTarget, aTextureUnit);
 | 
						|
 | 
						|
  gl->fActiveTexture(aTextureUnit);
 | 
						|
  gl->fBindTexture(mTextureTarget, tex);
 | 
						|
 | 
						|
  gl->fEGLImageTargetTexture2D(mTextureTarget, mImage);
 | 
						|
 | 
						|
  ApplySamplingFilterToBoundTexture(gl, aSamplingFilter, mTextureTarget);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
EGLImageTextureSource::SetTextureSourceProvider(TextureSourceProvider* aProvider)
 | 
						|
{
 | 
						|
  if (mCompositor == aProvider) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!aProvider) {
 | 
						|
    mGL = nullptr;
 | 
						|
    mCompositor = nullptr;
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  mGL = aProvider->GetGLContext();
 | 
						|
  if (Compositor* compositor = aProvider->AsCompositor()) {
 | 
						|
    mCompositor = compositor->AsCompositorOGL();
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
bool
 | 
						|
EGLImageTextureSource::IsValid() const
 | 
						|
{
 | 
						|
  return !!gl();
 | 
						|
}
 | 
						|
 | 
						|
gfx::Matrix4x4
 | 
						|
EGLImageTextureSource::GetTextureTransform()
 | 
						|
{
 | 
						|
  gfx::Matrix4x4 ret;
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
////////////////////////////////////////////////////////////////////////
 | 
						|
 | 
						|
EGLImageTextureHost::EGLImageTextureHost(TextureFlags aFlags,
 | 
						|
                                         EGLImage aImage,
 | 
						|
                                         EGLSync aSync,
 | 
						|
                                         gfx::IntSize aSize,
 | 
						|
                                         bool hasAlpha)
 | 
						|
  : TextureHost(aFlags)
 | 
						|
  , mImage(aImage)
 | 
						|
  , mSync(aSync)
 | 
						|
  , mSize(aSize)
 | 
						|
  , mHasAlpha(hasAlpha)
 | 
						|
{}
 | 
						|
 | 
						|
EGLImageTextureHost::~EGLImageTextureHost()
 | 
						|
{}
 | 
						|
 | 
						|
gl::GLContext*
 | 
						|
EGLImageTextureHost::gl() const
 | 
						|
{
 | 
						|
  return mProvider ? mProvider ->GetGLContext() : nullptr;
 | 
						|
}
 | 
						|
 | 
						|
bool
 | 
						|
EGLImageTextureHost::Lock()
 | 
						|
{
 | 
						|
  GLContext* gl = this->gl();
 | 
						|
  if (!gl || !gl->MakeCurrent()) {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  EGLint status = LOCAL_EGL_CONDITION_SATISFIED;
 | 
						|
 | 
						|
  if (mSync) {
 | 
						|
    MOZ_ASSERT(sEGLLibrary.IsExtensionSupported(GLLibraryEGL::KHR_fence_sync));
 | 
						|
    status = sEGLLibrary.fClientWaitSync(EGL_DISPLAY(), mSync, 0, LOCAL_EGL_FOREVER);
 | 
						|
  }
 | 
						|
 | 
						|
  if (status != LOCAL_EGL_CONDITION_SATISFIED) {
 | 
						|
    MOZ_ASSERT(status != 0,
 | 
						|
               "ClientWaitSync generated an error. Has mSync already been destroyed?");
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!mTextureSource) {
 | 
						|
    gfx::SurfaceFormat format = mHasAlpha ? gfx::SurfaceFormat::R8G8B8A8
 | 
						|
                                          : gfx::SurfaceFormat::R8G8B8X8;
 | 
						|
    GLenum target = gl->GetPreferredEGLImageTextureTarget();
 | 
						|
    GLenum wrapMode = LOCAL_GL_CLAMP_TO_EDGE;
 | 
						|
    mTextureSource = new EGLImageTextureSource(mProvider,
 | 
						|
                                               mImage,
 | 
						|
                                               format,
 | 
						|
                                               target,
 | 
						|
                                               wrapMode,
 | 
						|
                                               mSize);
 | 
						|
  }
 | 
						|
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
EGLImageTextureHost::Unlock()
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
EGLImageTextureHost::SetTextureSourceProvider(TextureSourceProvider* aProvider)
 | 
						|
{
 | 
						|
  if (mProvider != aProvider) {
 | 
						|
    if (!aProvider || !aProvider->GetGLContext()) {
 | 
						|
      mProvider = nullptr;
 | 
						|
      mTextureSource = nullptr;
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    mProvider = aProvider;
 | 
						|
  }
 | 
						|
 | 
						|
  if (mTextureSource) {
 | 
						|
    mTextureSource->SetTextureSourceProvider(aProvider);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
gfx::SurfaceFormat
 | 
						|
EGLImageTextureHost::GetFormat() const
 | 
						|
{
 | 
						|
  MOZ_ASSERT(mTextureSource);
 | 
						|
  return mTextureSource ? mTextureSource->GetFormat() : gfx::SurfaceFormat::UNKNOWN;
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
 | 
						|
GLTextureHost::GLTextureHost(TextureFlags aFlags,
 | 
						|
                             GLuint aTextureHandle,
 | 
						|
                             GLenum aTarget,
 | 
						|
                             GLsync aSync,
 | 
						|
                             gfx::IntSize aSize,
 | 
						|
                             bool aHasAlpha)
 | 
						|
  : TextureHost(aFlags)
 | 
						|
  , mTexture(aTextureHandle)
 | 
						|
  , mTarget(aTarget)
 | 
						|
  , mSync(aSync)
 | 
						|
  , mSize(aSize)
 | 
						|
  , mHasAlpha(aHasAlpha)
 | 
						|
{}
 | 
						|
 | 
						|
GLTextureHost::~GLTextureHost()
 | 
						|
{}
 | 
						|
 | 
						|
gl::GLContext*
 | 
						|
GLTextureHost::gl() const
 | 
						|
{
 | 
						|
  return mProvider ? mProvider->GetGLContext() : nullptr;
 | 
						|
}
 | 
						|
 | 
						|
bool
 | 
						|
GLTextureHost::Lock()
 | 
						|
{
 | 
						|
  GLContext* gl = this->gl();
 | 
						|
  if (!gl || !gl->MakeCurrent()) {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  if (mSync) {
 | 
						|
    if (!gl->MakeCurrent()) {
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
    gl->fWaitSync(mSync, 0, LOCAL_GL_TIMEOUT_IGNORED);
 | 
						|
    gl->fDeleteSync(mSync);
 | 
						|
    mSync = 0;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!mTextureSource) {
 | 
						|
    gfx::SurfaceFormat format = mHasAlpha ? gfx::SurfaceFormat::R8G8B8A8
 | 
						|
                                          : gfx::SurfaceFormat::R8G8B8X8;
 | 
						|
    mTextureSource = new GLTextureSource(mProvider,
 | 
						|
                                         mTexture,
 | 
						|
                                         mTarget,
 | 
						|
                                         mSize,
 | 
						|
                                         format,
 | 
						|
                                         false /* owned by the client */);
 | 
						|
  }
 | 
						|
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
GLTextureHost::SetTextureSourceProvider(TextureSourceProvider* aProvider)
 | 
						|
{
 | 
						|
  if (mProvider != aProvider) {
 | 
						|
    if (!aProvider || !aProvider->GetGLContext()) {
 | 
						|
      mProvider = nullptr;
 | 
						|
      mTextureSource = nullptr;
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    mProvider = aProvider;
 | 
						|
  }
 | 
						|
 | 
						|
  if (mTextureSource) {
 | 
						|
    mTextureSource->SetTextureSourceProvider(aProvider);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
gfx::SurfaceFormat
 | 
						|
GLTextureHost::GetFormat() const
 | 
						|
{
 | 
						|
  MOZ_ASSERT(mTextureSource);
 | 
						|
  return mTextureSource ? mTextureSource->GetFormat() : gfx::SurfaceFormat::UNKNOWN;
 | 
						|
}
 | 
						|
 | 
						|
} // namespace layers
 | 
						|
} // namespace mozilla
 |