forked from mirrors/gecko-dev
		
	MozReview-Commit-ID: KMCCukiGWID --HG-- extra : rebase_source : cd140e6149f632e102cb92e31142e952cd92bf72
		
			
				
	
	
		
			245 lines
		
	
	
	
		
			7.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			245 lines
		
	
	
	
		
			7.6 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 "GLContext.h"                  // for GLContext, etc
 | 
						|
#include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 | 
						|
#include "mozilla/layers/ISurfaceAllocator.h"
 | 
						|
#include "mozilla/layers/TextureClientOGL.h"
 | 
						|
#include "mozilla/gfx/2D.h"             // for Factory
 | 
						|
#include "mozilla/gfx/Point.h"          // for IntSize
 | 
						|
#include "GLLibraryEGL.h"
 | 
						|
 | 
						|
#ifdef MOZ_WIDGET_ANDROID
 | 
						|
#include <jni.h>
 | 
						|
#include <android/native_window.h>
 | 
						|
#include <android/native_window_jni.h>
 | 
						|
#endif
 | 
						|
 | 
						|
using namespace mozilla::gl;
 | 
						|
 | 
						|
namespace mozilla {
 | 
						|
namespace layers {
 | 
						|
 | 
						|
class CompositableForwarder;
 | 
						|
 | 
						|
////////////////////////////////////////////////////////////////////////
 | 
						|
// AndroidSurface
 | 
						|
 | 
						|
#ifdef MOZ_WIDGET_ANDROID
 | 
						|
 | 
						|
already_AddRefed<TextureClient>
 | 
						|
AndroidSurfaceTextureData::CreateTextureClient(AndroidSurfaceTextureHandle aHandle,
 | 
						|
                                               gfx::IntSize aSize,
 | 
						|
                                               bool aContinuous,
 | 
						|
                                               gl::OriginPos aOriginPos,
 | 
						|
                                               LayersIPCChannel* aAllocator,
 | 
						|
                                               TextureFlags aFlags)
 | 
						|
{
 | 
						|
  if (aOriginPos == gl::OriginPos::BottomLeft) {
 | 
						|
    aFlags |= TextureFlags::ORIGIN_BOTTOM_LEFT;
 | 
						|
  }
 | 
						|
 | 
						|
  return TextureClient::CreateWithData(
 | 
						|
    new AndroidSurfaceTextureData(aHandle, aSize, aContinuous),
 | 
						|
    aFlags, aAllocator
 | 
						|
  );
 | 
						|
}
 | 
						|
 | 
						|
AndroidSurfaceTextureData::AndroidSurfaceTextureData(AndroidSurfaceTextureHandle aHandle,
 | 
						|
                                                     gfx::IntSize aSize, bool aContinuous)
 | 
						|
  : mHandle(aHandle)
 | 
						|
  , mSize(aSize)
 | 
						|
  , mContinuous(aContinuous)
 | 
						|
{
 | 
						|
  MOZ_ASSERT(mHandle);
 | 
						|
}
 | 
						|
 | 
						|
AndroidSurfaceTextureData::~AndroidSurfaceTextureData()
 | 
						|
{}
 | 
						|
 | 
						|
void
 | 
						|
AndroidSurfaceTextureData::FillInfo(TextureData::Info& aInfo) const
 | 
						|
{
 | 
						|
  aInfo.size = mSize;
 | 
						|
  aInfo.format = gfx::SurfaceFormat::UNKNOWN;
 | 
						|
  aInfo.hasIntermediateBuffer = false;
 | 
						|
  aInfo.hasSynchronization = false;
 | 
						|
  aInfo.supportsMoz2D = false;
 | 
						|
  aInfo.canExposeMappedData = false;
 | 
						|
}
 | 
						|
 | 
						|
bool
 | 
						|
AndroidSurfaceTextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
 | 
						|
{
 | 
						|
  aOutDescriptor = SurfaceTextureDescriptor(mHandle,
 | 
						|
                                            mSize,
 | 
						|
                                            gfx::SurfaceFormat::R8G8B8A8,
 | 
						|
                                            mContinuous,
 | 
						|
                                            false /* do not ignore transform */);
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
#endif // MOZ_WIDGET_ANDROID
 | 
						|
 | 
						|
////////////////////////////////////////////////////////////////////////
 | 
						|
// AndroidNativeWindow
 | 
						|
 | 
						|
#ifdef MOZ_WIDGET_ANDROID
 | 
						|
 | 
						|
AndroidNativeWindowTextureData*
 | 
						|
AndroidNativeWindowTextureData::Create(gfx::IntSize aSize,
 | 
						|
                                       SurfaceFormat aFormat)
 | 
						|
{
 | 
						|
  if (aFormat != SurfaceFormat::R8G8B8A8 &&
 | 
						|
      aFormat != SurfaceFormat::R8G8B8X8 &&
 | 
						|
      aFormat != SurfaceFormat::B8G8R8A8 &&
 | 
						|
      aFormat != SurfaceFormat::B8G8R8X8 &&
 | 
						|
      aFormat != SurfaceFormat::R5G6B5_UINT16) {
 | 
						|
    return nullptr;
 | 
						|
  }
 | 
						|
 | 
						|
  auto surface = java::GeckoSurface::LocalRef(
 | 
						|
      java::SurfaceAllocator::AcquireSurface(aSize.width, aSize.height,
 | 
						|
                                             true /* single-buffer mode */));
 | 
						|
  if (surface) {
 | 
						|
    return new AndroidNativeWindowTextureData(surface, aSize, aFormat);
 | 
						|
  }
 | 
						|
 | 
						|
  return nullptr;
 | 
						|
}
 | 
						|
 | 
						|
AndroidNativeWindowTextureData::AndroidNativeWindowTextureData(java::GeckoSurface::Param aSurface,
 | 
						|
                                                               gfx::IntSize aSize,
 | 
						|
                                                               SurfaceFormat aFormat)
 | 
						|
: mSurface(aSurface)
 | 
						|
, mIsLocked(false)
 | 
						|
, mSize(aSize)
 | 
						|
, mFormat(aFormat)
 | 
						|
{
 | 
						|
  mNativeWindow = ANativeWindow_fromSurface(jni::GetEnvForThread(),
 | 
						|
                                            mSurface.Get());
 | 
						|
  MOZ_ASSERT(mNativeWindow, "Failed to create NativeWindow.");
 | 
						|
 | 
						|
  // SurfaceTextures don't technically support BGR, but we can just pretend to be RGB.
 | 
						|
  int32_t format = WINDOW_FORMAT_RGBA_8888;
 | 
						|
  switch (aFormat) {
 | 
						|
  case SurfaceFormat::R8G8B8A8:
 | 
						|
  case SurfaceFormat::B8G8R8A8:
 | 
						|
    format = WINDOW_FORMAT_RGBA_8888;
 | 
						|
    break;
 | 
						|
 | 
						|
  case SurfaceFormat::R8G8B8X8:
 | 
						|
  case SurfaceFormat::B8G8R8X8:
 | 
						|
    format = WINDOW_FORMAT_RGBX_8888;
 | 
						|
    break;
 | 
						|
 | 
						|
  case SurfaceFormat::R5G6B5_UINT16:
 | 
						|
    format = WINDOW_FORMAT_RGB_565;
 | 
						|
    break;
 | 
						|
 | 
						|
  default:
 | 
						|
    MOZ_ASSERT(false, "Unsupported AndroidNativeWindowTextureData format.");
 | 
						|
  }
 | 
						|
 | 
						|
  DebugOnly<int32_t> r = ANativeWindow_setBuffersGeometry(mNativeWindow,
 | 
						|
                                                          mSize.width,
 | 
						|
                                                          mSize.height,
 | 
						|
                                                          format);
 | 
						|
  MOZ_ASSERT(r == 0, "ANativeWindow_setBuffersGeometry failed.");
 | 
						|
 | 
						|
  // Ideally here we'd call ANativeWindow_setBuffersTransform() with the
 | 
						|
  // identity transform, but that is only available on api level >= 26.
 | 
						|
  // Instead use the SurfaceDescriptor's ignoreTransform flag when serializing.
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
AndroidNativeWindowTextureData::FillInfo(TextureData::Info& aInfo) const
 | 
						|
{
 | 
						|
  aInfo.size = mSize;
 | 
						|
  aInfo.format = mFormat;
 | 
						|
  aInfo.hasIntermediateBuffer = false;
 | 
						|
  aInfo.hasSynchronization = false;
 | 
						|
  aInfo.supportsMoz2D = true;
 | 
						|
  aInfo.canExposeMappedData = false;
 | 
						|
  aInfo.canConcurrentlyReadLock = false;
 | 
						|
}
 | 
						|
 | 
						|
bool
 | 
						|
AndroidNativeWindowTextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
 | 
						|
{
 | 
						|
  aOutDescriptor = SurfaceTextureDescriptor(mSurface->GetHandle(),
 | 
						|
                                            mSize,
 | 
						|
                                            mFormat,
 | 
						|
                                            false /* not continuous */,
 | 
						|
                                            true /* ignore transform */);
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
bool
 | 
						|
AndroidNativeWindowTextureData::Lock(OpenMode)
 | 
						|
{
 | 
						|
  // ANativeWindows can only be locked and unlocked a single time, after which
 | 
						|
  // we must wait until they receive ownership back from the host.
 | 
						|
  // Therefore we must only actually call ANativeWindow_lock() once per cycle.
 | 
						|
  if (!mIsLocked) {
 | 
						|
    int32_t r = ANativeWindow_lock(mNativeWindow, &mBuffer, nullptr);
 | 
						|
    if (r == -ENOMEM) {
 | 
						|
      return false;
 | 
						|
    } else if (r < 0) {
 | 
						|
      MOZ_CRASH("ANativeWindow_lock failed.");
 | 
						|
    }
 | 
						|
    mIsLocked = true;
 | 
						|
  }
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
AndroidNativeWindowTextureData::Unlock()
 | 
						|
{
 | 
						|
  // The TextureClient may want to call Lock again before handing ownership
 | 
						|
  // to the host, so we cannot call ANativeWindow_unlockAndPost yet.
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
AndroidNativeWindowTextureData::Forget(LayersIPCChannel*)
 | 
						|
{
 | 
						|
  MOZ_ASSERT(!mIsLocked, "ANativeWindow should not be released while locked.\n");
 | 
						|
  ANativeWindow_release(mNativeWindow);
 | 
						|
  mNativeWindow = nullptr;
 | 
						|
  java::SurfaceAllocator::DisposeSurface(mSurface);
 | 
						|
  mSurface = nullptr;
 | 
						|
}
 | 
						|
 | 
						|
already_AddRefed<DrawTarget>
 | 
						|
AndroidNativeWindowTextureData::BorrowDrawTarget()
 | 
						|
{
 | 
						|
  const int bpp = (mFormat == SurfaceFormat::R5G6B5_UINT16) ? 2 : 4;
 | 
						|
 | 
						|
  return gfx::Factory::CreateDrawTargetForData(
 | 
						|
      gfx::BackendType::SKIA,
 | 
						|
      static_cast<unsigned char*>(mBuffer.bits),
 | 
						|
      IntSize(mBuffer.width, mBuffer.height),
 | 
						|
      mBuffer.stride * bpp,
 | 
						|
      mFormat,
 | 
						|
      true);
 | 
						|
}
 | 
						|
 | 
						|
void
 | 
						|
AndroidNativeWindowTextureData::OnForwardedToHost()
 | 
						|
{
 | 
						|
  if (mIsLocked) {
 | 
						|
    int32_t r = ANativeWindow_unlockAndPost(mNativeWindow);
 | 
						|
    if (r < 0) {
 | 
						|
      MOZ_CRASH("ANativeWindow_unlockAndPost failed\n.");
 | 
						|
    }
 | 
						|
    mIsLocked = false;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
#endif // MOZ_WIDGET_ANDROID
 | 
						|
 | 
						|
} // namespace layers
 | 
						|
} // namespace mozilla
 |