Bug 1092294 - Use SurfaceTextures for painted content on android (preffed off). r=nical,snorp

Add a new TextureClientData type, AndroidNativeWindowTextureData,
backed by a SurfaceTexture in single-buffer mode. It uses the
NativeWindow API, which provides producer-side access to the buffer.
This provides a DrawTarget which can be used to paint directly in to
the SurfaceTexture, which can then be composited using a SurfaceTextureHost.

Due to API restrictions it is not possible to read from a NativeWindow
while the corresponding SurfaceTexture has ownership of the
buffer. TiledContentClient now handles that by painting the additional
region that it cannot copy from the front buffer, if required.

MozReview-Commit-ID: 1NZq6MQqwFq

--HG--
extra : rebase_source : 9d1db721d4892f3df033d43127489a85421e8863
This commit is contained in:
Jamie Nicol 2017-10-28 11:59:58 +01:00
parent 8c8b85caa1
commit 21b5b6db95
15 changed files with 345 additions and 64 deletions

View File

@ -274,7 +274,12 @@ SharedSurface_SurfaceTexture::WaitForBufferOwnership()
bool
SharedSurface_SurfaceTexture::ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor)
{
*out_descriptor = layers::SurfaceTextureDescriptor(mSurface->GetHandle(), mSize, false /* NOT continuous */);
*out_descriptor =
layers::SurfaceTextureDescriptor(mSurface->GetHandle(),
mSize,
gfx::SurfaceFormat::R8G8B8A8,
false /* NOT continuous */,
false /* Do not ignore transform */);
return true;
}

View File

@ -151,6 +151,15 @@ ClientSingleTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
extraPainted,
&backBufferOnWhite);
// Mark the area we need to paint in the back buffer as invalid in the
// front buffer as they will become out of sync.
mTile.mInvalidFront.OrWith(tileDirtyRegion);
// Add backbuffer's invalid region to the dirty region to be painted.
// This will be empty if we were able to copy from the front in to the back.
paintRegion.OrWith(mTile.mInvalidBack.MovedBy(mTilingOrigin));
tileDirtyRegion.OrWith(mTile.mInvalidBack);
mTile.mUpdateRect = tileDirtyRegion.GetBounds().Union(extraPainted.GetBounds());
extraPainted.MoveBy(mTilingOrigin);
@ -198,26 +207,26 @@ ClientSingleTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
const gfx::IntPoint dest = iter.Get().TopLeft() - mTilingOrigin;
discardedFrontBuffer->CopyToTextureClient(backBuffer, &rect, &dest);
}
}
if (discardedFrontBufferOnWhite && backBufferOnWhite) {
TextureClientAutoLock frontOnWhiteLock(discardedFrontBufferOnWhite,
OpenMode::OPEN_READ);
if (frontOnWhiteLock.Succeeded()) {
for (auto iter = copyableRegion.RectIter(); !iter.Done(); iter.Next()) {
const gfx::IntRect rect = iter.Get() - discardedValidRegion.GetBounds().TopLeft();
const gfx::IntPoint dest = iter.Get().TopLeft() - mTilingOrigin;
if (discardedFrontBufferOnWhite && backBufferOnWhite) {
TextureClientAutoLock frontOnWhiteLock(discardedFrontBufferOnWhite,
OpenMode::OPEN_READ);
if (frontOnWhiteLock.Succeeded()) {
for (auto iter = copyableRegion.RectIter(); !iter.Done(); iter.Next()) {
const gfx::IntRect rect = iter.Get() - discardedValidRegion.GetBounds().TopLeft();
const gfx::IntPoint dest = iter.Get().TopLeft() - mTilingOrigin;
discardedFrontBufferOnWhite->CopyToTextureClient(backBufferOnWhite,
&rect, &dest);
discardedFrontBufferOnWhite->CopyToTextureClient(backBufferOnWhite,
&rect, &dest);
}
TILING_LOG("TILING %p: Region copied from discarded frontbuffer %s\n", &mPaintedLayer, Stringify(copyableRegion).c_str());
// We don't need to repaint valid content that was just copied.
paintRegion.SubOut(copyableRegion);
}
}
}
TILING_LOG("TILING %p: Region copied from discarded frontbuffer %s\n", &mPaintedLayer, Stringify(copyableRegion).c_str());
// We don't need to repaint valid content that was just copied.
paintRegion.SubOut(copyableRegion);
}
}
@ -237,10 +246,6 @@ ClientSingleTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
aCallback(&mPaintedLayer, ctx, paintRegion, paintRegion, DrawRegionClip::DRAW, nsIntRegion(), aCallbackData);
}
// Mark the area we just drew into the back buffer as invalid in the front buffer as they're
// now out of sync.
mTile.mInvalidFront.OrWith(tileDirtyRegion);
// The new buffer is now validated, remove the dirty region from it.
mTile.mInvalidBack.SubOut(tileDirtyRegion);

View File

@ -502,8 +502,11 @@ TextureClient::Lock(OpenMode aMode)
return mOpenMode == aMode;
}
if (aMode & OpenMode::OPEN_WRITE && !TryReadLock()) {
NS_WARNING("Attempt to Lock a texture that is being read by the compositor!");
if ((aMode & OpenMode::OPEN_WRITE || !mInfo.canConcurrentlyReadLock) && !TryReadLock()) {
// Only warn if attempting to write. Attempting to read is acceptable usage.
if (aMode & OpenMode::OPEN_WRITE) {
NS_WARNING("Attempt to Lock a texture that is being read by the compositor!");
}
return false;
}
@ -594,6 +597,10 @@ TextureClient::EnableReadLock()
bool
TextureClient::SerializeReadLock(ReadLockDescriptor& aDescriptor)
{
if (mData) {
mData->OnForwardedToHost();
}
if (mReadLock && mUpdated) {
// Take a read lock on behalf of the TextureHost. The latter will unlock
// after the shared data is available again for drawing.
@ -1124,6 +1131,12 @@ TextureClient::CreateForDrawing(TextureForwarder* aAllocator,
}
#endif
#ifdef MOZ_WIDGET_ANDROID
if (!data && gfxPrefs::UseSurfaceTextureTextures()) {
data = AndroidNativeWindowTextureData::Create(aSize, aFormat);
}
#endif
if (data) {
return MakeAndAddRef<TextureClient>(data, aTextureFlags, aAllocator);
}

View File

@ -236,6 +236,7 @@ public:
bool hasSynchronization;
bool supportsMoz2D;
bool canExposeMappedData;
bool canConcurrentlyReadLock;
Info()
: format(gfx::SurfaceFormat::UNKNOWN)
@ -243,6 +244,7 @@ public:
, hasSynchronization(false)
, supportsMoz2D(false)
, canExposeMappedData(false)
, canConcurrentlyReadLock(true)
{}
};
@ -270,6 +272,8 @@ public:
virtual bool Serialize(SurfaceDescriptor& aDescriptor) = 0;
virtual void GetSubDescriptor(GPUVideoSubDescriptor* aOutDesc) { }
virtual void OnForwardedToHost() {}
virtual TextureData*
CreateSimilar(LayersIPCChannel* aAllocator,
LayersBackend aLayersBackend,

View File

@ -480,7 +480,6 @@ CopyFrontToBack(TextureClient* aFront,
{
TextureClientAutoLock frontLock(aFront, OpenMode::OPEN_READ);
if (!frontLock.Succeeded()) {
gfxCriticalError() << "[Tiling:Client] Failed to lock the tile's front buffer";
return false;
}
@ -524,14 +523,14 @@ TileClient::ValidateBackBufferFromFront(const nsIntRegion& aDirtyRegion,
// region, but we can reevaluate this if it becomes an issue.
const IntRect rectToCopy = regionToCopy.GetBounds();
gfx::IntRect gfxRectToCopy(rectToCopy.x, rectToCopy.y, rectToCopy.Width(), rectToCopy.Height());
CopyFrontToBack(mFrontBuffer, mBackBuffer, gfxRectToCopy);
if (mBackBufferOnWhite) {
MOZ_ASSERT(mFrontBufferOnWhite);
CopyFrontToBack(mFrontBufferOnWhite, mBackBufferOnWhite, gfxRectToCopy);
if (CopyFrontToBack(mFrontBuffer, mBackBuffer, gfxRectToCopy)) {
if (mBackBufferOnWhite) {
MOZ_ASSERT(mFrontBufferOnWhite);
if (CopyFrontToBack(mFrontBufferOnWhite, mBackBufferOnWhite, gfxRectToCopy)) {
mInvalidBack.SetEmpty();
}
}
}
mInvalidBack.SetEmpty();
}
}
}
@ -951,13 +950,15 @@ void ClientMultiTiledLayerBuffer::Update(const nsIntRegion& newValidRegion,
oldRetainedTiles.Clear();
if (!aPaintRegion.IsEmpty()) {
nsIntRegion paintRegion = aPaintRegion;
nsIntRegion dirtyRegion = aDirtyRegion;
if (!paintRegion.IsEmpty()) {
for (size_t i = 0; i < newTileCount; ++i) {
const TileIntPoint tilePosition = newTiles.TilePosition(i);
IntPoint tileOffset = GetTileOffset(tilePosition);
nsIntRegion tileDrawRegion = IntRect(tileOffset, scaledTileSize);
tileDrawRegion.AndWith(aPaintRegion);
tileDrawRegion.AndWith(paintRegion);
if (tileDrawRegion.IsEmpty()) {
continue;
@ -967,6 +968,10 @@ void ClientMultiTiledLayerBuffer::Update(const nsIntRegion& newValidRegion,
if (!ValidateTile(tile, GetTileOffset(tilePosition), tileDrawRegion)) {
gfxCriticalError() << "ValidateTile failed";
}
// Validating the tile may have required more to be painted.
paintRegion.OrWith(tileDrawRegion);
dirtyRegion.OrWith(tileDrawRegion);
}
if (!mMoz2DTiles.empty()) {
@ -988,7 +993,7 @@ void ClientMultiTiledLayerBuffer::Update(const nsIntRegion& newValidRegion,
ctx->SetMatrix(
ctx->CurrentMatrix().PreScale(mResolution, mResolution).PreTranslate(ThebesPoint(-mTilingOrigin)));
mCallback(&mPaintedLayer, ctx, aPaintRegion, aDirtyRegion,
mCallback(&mPaintedLayer, ctx, paintRegion, dirtyRegion,
DrawRegionClip::DRAW, nsIntRegion(), mCallbackData);
mMoz2DTiles.clear();
// Reset:
@ -1015,7 +1020,7 @@ void ClientMultiTiledLayerBuffer::Update(const nsIntRegion& newValidRegion,
GetTileSize().width, GetTileSize().height);
nsIntRegion tileDrawRegion = IntRect(tileOffset, scaledTileSize);
tileDrawRegion.AndWith(aPaintRegion);
tileDrawRegion.AndWith(paintRegion);
nsIntRegion tileValidRegion = mValidRegion;
tileValidRegion.OrWith(tileDrawRegion);
@ -1035,13 +1040,13 @@ void ClientMultiTiledLayerBuffer::Update(const nsIntRegion& newValidRegion,
mTiles = newTiles;
mValidRegion = newValidRegion;
mPaintedRegion.OrWith(aPaintRegion);
mPaintedRegion.OrWith(paintRegion);
}
bool
ClientMultiTiledLayerBuffer::ValidateTile(TileClient& aTile,
const nsIntPoint& aTileOrigin,
const nsIntRegion& aDirtyRegion)
nsIntRegion& aDirtyRegion)
{
AUTO_PROFILER_LABEL("ClientMultiTiledLayerBuffer::ValidateTile", GRAPHICS);
@ -1074,6 +1079,19 @@ ClientMultiTiledLayerBuffer::ValidateTile(TileClient& aTile,
extraPainted,
&backBufferOnWhite);
// Mark the area we need to paint in the back buffer as invalid in the
// front buffer as they will become out of sync.
aTile.mInvalidFront.OrWith(offsetScaledDirtyRegion);
// Add backbuffer's invalid region to the dirty region to be painted.
// This will be empty if we were able to copy from the front in to the back.
nsIntRegion invalidBack = aTile.mInvalidBack;
invalidBack.MoveBy(aTileOrigin);
invalidBack.ScaleInverseRoundOut(mResolution, mResolution);
invalidBack.AndWith(mNewValidRegion);
aDirtyRegion.OrWith(invalidBack);
offsetScaledDirtyRegion.OrWith(aTile.mInvalidBack);
aTile.mUpdateRect = offsetScaledDirtyRegion.GetBounds().Union(extraPainted.GetBounds());
extraPainted.MoveBy(aTileOrigin);
@ -1103,16 +1121,9 @@ ClientMultiTiledLayerBuffer::ValidateTile(TileClient& aTile,
mTilingOrigin.x = std::min(mTilingOrigin.x, moz2DTile.mTileOrigin.x);
mTilingOrigin.y = std::min(mTilingOrigin.y, moz2DTile.mTileOrigin.y);
for (auto iter = aDirtyRegion.RectIter(); !iter.Done(); iter.Next()) {
const IntRect& dirtyRect = iter.Get();
gfx::Rect drawRect(dirtyRect.x - aTileOrigin.x,
dirtyRect.y - aTileOrigin.y,
dirtyRect.Width(),
dirtyRect.Height());
drawRect.Scale(mResolution);
// Mark the newly updated area as invalid in the front buffer
aTile.mInvalidFront.Or(aTile.mInvalidFront, IntRect::RoundOut(drawRect));
for (auto iter = offsetScaledDirtyRegion.RectIter(); !iter.Done(); iter.Next()) {
const gfx::Rect drawRect(iter.Get().x, iter.Get().y,
iter.Get().width, iter.Get().height);
if (mode == SurfaceMode::SURFACE_COMPONENT_ALPHA) {
dt->FillRect(drawRect, ColorPattern(Color(0.0, 0.0, 0.0, 1.0)));

View File

@ -412,8 +412,8 @@ public:
protected:
bool ValidateTile(TileClient& aTile,
const nsIntPoint& aTileRect,
const nsIntRegion& dirtyRect);
nsIntRegion& aDirtyRegion);
void Update(const nsIntRegion& aNewValidRegion,
const nsIntRegion& aPaintRegion,
const nsIntRegion& aDirtyRegion);

View File

@ -62,7 +62,9 @@ struct SurfaceDescriptorMacIOSurface {
struct SurfaceTextureDescriptor {
uint64_t handle;
IntSize size;
SurfaceFormat format;
bool continuous;
bool ignoreTransform;
};
struct EGLImageDescriptor {

View File

@ -866,7 +866,10 @@ CompositorOGL::GetShaderConfigFor(Effect *aEffect,
TextureSourceOGL* source = texturedEffect->mTexture->AsSourceOGL();
MOZ_ASSERT_IF(source->GetTextureTarget() == LOCAL_GL_TEXTURE_EXTERNAL,
source->GetFormat() == gfx::SurfaceFormat::R8G8B8A8 ||
source->GetFormat() == gfx::SurfaceFormat::R8G8B8X8);
source->GetFormat() == gfx::SurfaceFormat::R8G8B8X8 ||
source->GetFormat() == gfx::SurfaceFormat::B8G8R8A8 ||
source->GetFormat() == gfx::SurfaceFormat::B8G8R8X8 ||
source->GetFormat() == gfx::SurfaceFormat::R5G6B5_UINT16);
MOZ_ASSERT_IF(source->GetTextureTarget() == LOCAL_GL_TEXTURE_RECTANGLE_ARB,
source->GetFormat() == gfx::SurfaceFormat::R8G8B8A8 ||
source->GetFormat() == gfx::SurfaceFormat::R8G8B8X8 ||

View File

@ -8,9 +8,16 @@
#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 {
@ -67,11 +74,171 @@ AndroidSurfaceTextureData::FillInfo(TextureData::Info& aInfo) const
bool
AndroidSurfaceTextureData::Serialize(SurfaceDescriptor& aOutDescriptor)
{
aOutDescriptor = SurfaceTextureDescriptor(mHandle, mSize, mContinuous);
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 < 0) {
MOZ_CRASH("ANativeWindow_lock failed\n.");
return false;
}
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

View File

@ -16,6 +16,10 @@
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor
#include "mozilla/layers/TextureClient.h" // for TextureClient, etc
#include "AndroidSurfaceTexture.h"
#include "AndroidNativeWindow.h"
#ifdef MOZ_WIDGET_ANDROID
#include "GeneratedJNIWrappers.h"
#endif
namespace mozilla {
@ -58,6 +62,45 @@ protected:
#endif // MOZ_WIDGET_ANDROID
#ifdef MOZ_WIDGET_ANDROID
class AndroidNativeWindowTextureData : public TextureData
{
public:
static AndroidNativeWindowTextureData* Create(gfx::IntSize aSize, SurfaceFormat aFormat);
virtual void FillInfo(TextureData::Info& aInfo) const override;
virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override;
virtual bool Lock(OpenMode) override;
virtual void Unlock() override;
virtual void Forget(LayersIPCChannel*) override;
virtual void Deallocate(LayersIPCChannel*) override {}
virtual already_AddRefed<DrawTarget> BorrowDrawTarget() override;
virtual void OnForwardedToHost() override;
protected:
AndroidNativeWindowTextureData(java::GeckoSurface::Param aSurface,
gfx::IntSize aSize,
SurfaceFormat aFormat);
private:
java::GeckoSurface::GlobalRef mSurface;
ANativeWindow* mNativeWindow;
ANativeWindow_Buffer mBuffer;
// Keeps track of whether the underlying NativeWindow is actually locked.
bool mIsLocked;
const gfx::IntSize mSize;
const SurfaceFormat mFormat;
};
#endif // MOZ_WIDGET_ANDROID
} // namespace layers
} // namespace mozilla

View File

@ -62,7 +62,9 @@ CreateTextureHostOGL(const SurfaceDescriptor& aDesc,
result = new SurfaceTextureHost(aFlags,
surfaceTexture,
desc.size(),
desc.continuous());
desc.format(),
desc.continuous(),
desc.ignoreTransform());
break;
}
#endif
@ -343,13 +345,15 @@ SurfaceTextureSource::SurfaceTextureSource(TextureSourceProvider* aProvider,
gfx::SurfaceFormat aFormat,
GLenum aTarget,
GLenum aWrapMode,
gfx::IntSize aSize)
gfx::IntSize aSize,
bool aIgnoreTransform)
: mGL(aProvider->GetGLContext())
, mSurfTex(aSurfTex)
, mFormat(aFormat)
, mTextureTarget(aTarget)
, mWrapMode(aWrapMode)
, mSize(aSize)
, mIgnoreTransform(aIgnoreTransform)
{
}
@ -395,8 +399,14 @@ SurfaceTextureSource::GetTextureTransform()
gfx::Matrix4x4 ret;
const auto& surf = java::sdk::SurfaceTexture::LocalRef(java::sdk::SurfaceTexture::Ref::From(mSurfTex));
AndroidSurfaceTexture::GetTransformMatrix(surf, 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;
}
@ -412,11 +422,15 @@ SurfaceTextureSource::DeallocateDeviceData()
SurfaceTextureHost::SurfaceTextureHost(TextureFlags aFlags,
mozilla::java::GeckoSurfaceTexture::Ref& aSurfTex,
gfx::IntSize aSize,
bool aContinuousUpdate)
gfx::SurfaceFormat aFormat,
bool aContinuousUpdate,
bool aIgnoreTransform)
: TextureHost(aFlags)
, mSurfTex(aSurfTex)
, mSize(aSize)
, mFormat(aFormat)
, mContinuousUpdate(aContinuousUpdate)
, mIgnoreTransform(aIgnoreTransform)
{
if (!mSurfTex) {
return;
@ -476,15 +490,15 @@ SurfaceTextureHost::Lock()
}
if (!mTextureSource) {
gfx::SurfaceFormat format = gfx::SurfaceFormat::R8G8B8A8;
GLenum target = LOCAL_GL_TEXTURE_EXTERNAL; // This is required by SurfaceTexture
GLenum wrapMode = LOCAL_GL_CLAMP_TO_EDGE;
mTextureSource = new SurfaceTextureSource(mProvider,
mSurfTex,
format,
mFormat,
target,
wrapMode,
mSize);
mSize,
mIgnoreTransform);
}
return true;
@ -519,7 +533,7 @@ SurfaceTextureHost::NotifyNotUsed()
gfx::SurfaceFormat
SurfaceTextureHost::GetFormat() const
{
return mTextureSource ? mTextureSource->GetFormat() : gfx::SurfaceFormat::UNKNOWN;
return mFormat;
}
void

View File

@ -347,7 +347,8 @@ public:
gfx::SurfaceFormat aFormat,
GLenum aTarget,
GLenum aWrapMode,
gfx::IntSize aSize);
gfx::IntSize aSize,
bool aIgnoreTransform);
virtual const char* Name() const override { return "SurfaceTextureSource"; }
@ -383,6 +384,7 @@ protected:
const GLenum mTextureTarget;
const GLenum mWrapMode;
const gfx::IntSize mSize;
const bool mIgnoreTransform;
};
class SurfaceTextureHost : public TextureHost
@ -391,7 +393,9 @@ public:
SurfaceTextureHost(TextureFlags aFlags,
mozilla::java::GeckoSurfaceTexture::Ref& aSurfTex,
gfx::IntSize aSize,
bool aContinuousUpdate);
gfx::SurfaceFormat aFormat,
bool aContinuousUpdate,
bool aIgnoreTransform);
virtual ~SurfaceTextureHost();
@ -427,7 +431,9 @@ public:
protected:
mozilla::java::GeckoSurfaceTexture::GlobalRef mSurfTex;
const gfx::IntSize mSize;
const gfx::SurfaceFormat mFormat;
bool mContinuousUpdate;
const bool mIgnoreTransform;
RefPtr<CompositorOGL> mCompositor;
RefPtr<SurfaceTextureSource> mTextureSource;
};

View File

@ -491,6 +491,7 @@ private:
DECL_GFX_PREF(Live, "gfx.use-glx-texture-from-pixmap", UseGLXTextureFromPixmap, bool, false);
DECL_GFX_PREF(Once, "gfx.use-iosurface-textures", UseIOSurfaceTextures, bool, false);
DECL_GFX_PREF(Once, "gfx.use-mutex-on-present", UseMutexOnPresent, bool, false);
DECL_GFX_PREF(Once, "gfx.use-surfacetexture-textures", UseSurfaceTextureTextures, bool, false);
// These times should be in milliseconds
DECL_GFX_PREF(Once, "gfx.touch.resample.delay-threshold", TouchResampleVsyncDelayThreshold, int32_t, 20);
DECL_GFX_PREF(Once, "gfx.touch.resample.max-predict", TouchResampleMaxPredict, int32_t, 8);

View File

@ -333,6 +333,9 @@ pref("gfx.android.rgb16.force", false);
// Allow GLContexts to be attached/detached from SurfaceTextures
pref("gfx.SurfaceTexture.detach.enabled", true);
// Use SurfaceTextures as preferred backend for TextureClient/Host
pref("gfx.use-surfacetexture-textures", false);
// don't allow JS to move and resize existing windows
pref("dom.disable_window_move_resize", true);

View File

@ -80,9 +80,13 @@ public final class GeckoSurfaceTexture extends SurfaceTexture {
return;
}
super.releaseTexImage();
if (mListener != null) {
mListener.onReleaseTexImage();
try {
super.releaseTexImage();
if (mListener != null) {
mListener.onReleaseTexImage();
}
} catch (Exception e) {
Log.w(LOGTAG, "releaseTexImage() failed", e);
}
}