Bug 825928: Land layers refactoring. r=jrmuizel,bas,nical,mattwoodrow,roc,nrc,benwa,bjacob,jgilbert,kchen CLOSED TREE
Please contact Bas Schouten <bschouten@mozilla.com>, Nicolas Silva <nsilva@mozilla.com> or Nicholas Cameron <ncameron@mozilla.com> with general questions. Below is a rough list of authors to contact with specific questions.
Authors:
gfx/layers/Compositor.* gfx/layers/Effects.h - Compositor Interface - bas,nrc,nical
gfx/layers/d3d* - D3D9/D3D10 - bas
gfx/layers/ThebesLayer* - ThebesLayers - nrc,bas
gfx/layers/composite/* - CompositeLayers - nrc,nical
gfx/layers/client/* - Client - nrc,nical,bas
gfx/layers/*Image* - nical
gfx/layers/ipc ipc - IPC - nical
gfx/layers/opengl - CompositorOGL - nrc,nical
gfx/2d - bas,nrc
gfx/gl - GLContext - bjacob
dom/* layout/* - DOM - mattwoodrow
2013-04-10 09:20:52 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
|
|
* 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 "ImageHost.h"
|
2015-07-06 03:02:26 +00:00
|
|
|
|
2013-08-11 23:17:23 +00:00
|
|
|
#include "LayersLogging.h" // for AppendToString
|
|
|
|
#include "composite/CompositableHost.h" // for CompositableHost, etc
|
|
|
|
#include "ipc/IPCMessageUtils.h" // for null_t
|
|
|
|
#include "mozilla/layers/Compositor.h" // for Compositor
|
|
|
|
#include "mozilla/layers/Effects.h" // for TexturedEffect, Effect, etc
|
2015-07-06 03:02:26 +00:00
|
|
|
#include "mozilla/layers/LayerManagerComposite.h" // for TexturedEffect, Effect, etc
|
2013-08-11 23:17:23 +00:00
|
|
|
#include "nsAString.h"
|
|
|
|
#include "nsDebug.h" // for NS_WARNING, NS_ASSERTION
|
|
|
|
#include "nsPrintfCString.h" // for nsPrintfCString
|
|
|
|
#include "nsString.h" // for nsAutoCString
|
|
|
|
|
2017-02-07 09:37:57 +00:00
|
|
|
// this is also defined in ImageComposite.cpp
|
|
|
|
#define BIAS_TIME_MS 1.0
|
|
|
|
|
Bug 825928: Land layers refactoring. r=jrmuizel,bas,nical,mattwoodrow,roc,nrc,benwa,bjacob,jgilbert,kchen CLOSED TREE
Please contact Bas Schouten <bschouten@mozilla.com>, Nicolas Silva <nsilva@mozilla.com> or Nicholas Cameron <ncameron@mozilla.com> with general questions. Below is a rough list of authors to contact with specific questions.
Authors:
gfx/layers/Compositor.* gfx/layers/Effects.h - Compositor Interface - bas,nrc,nical
gfx/layers/d3d* - D3D9/D3D10 - bas
gfx/layers/ThebesLayer* - ThebesLayers - nrc,bas
gfx/layers/composite/* - CompositeLayers - nrc,nical
gfx/layers/client/* - Client - nrc,nical,bas
gfx/layers/*Image* - nical
gfx/layers/ipc ipc - IPC - nical
gfx/layers/opengl - CompositorOGL - nrc,nical
gfx/2d - bas,nrc
gfx/gl - GLContext - bjacob
dom/* layout/* - DOM - mattwoodrow
2013-04-10 09:20:52 +00:00
|
|
|
namespace mozilla {
|
|
|
|
|
|
|
|
using namespace gfx;
|
|
|
|
|
|
|
|
namespace layers {
|
|
|
|
|
2013-08-11 23:17:23 +00:00
|
|
|
class ISurfaceAllocator;
|
|
|
|
|
2013-07-30 09:59:51 +00:00
|
|
|
ImageHost::ImageHost(const TextureInfo& aTextureInfo)
|
|
|
|
: CompositableHost(aTextureInfo)
|
2017-02-07 08:07:00 +00:00
|
|
|
, ImageComposite()
|
2014-06-22 17:06:00 +00:00
|
|
|
, mLocked(false)
|
2013-07-30 09:59:51 +00:00
|
|
|
{}
|
|
|
|
|
2014-09-26 11:30:11 +00:00
|
|
|
ImageHost::~ImageHost()
|
2015-07-06 03:02:26 +00:00
|
|
|
{
|
|
|
|
}
|
2014-10-24 18:25:25 +00:00
|
|
|
|
|
|
|
void
|
2015-05-04 10:59:02 +00:00
|
|
|
ImageHost::UseTextureHost(const nsTArray<TimedTexture>& aTextures)
|
2014-10-24 18:25:25 +00:00
|
|
|
{
|
2015-05-25 10:48:09 +00:00
|
|
|
MOZ_ASSERT(!mLocked);
|
|
|
|
|
2015-05-04 10:59:02 +00:00
|
|
|
CompositableHost::UseTextureHost(aTextures);
|
|
|
|
MOZ_ASSERT(aTextures.Length() >= 1);
|
2015-05-25 10:48:09 +00:00
|
|
|
|
|
|
|
nsTArray<TimedImage> newImages;
|
|
|
|
|
2015-07-06 03:02:26 +00:00
|
|
|
for (uint32_t i = 0; i < aTextures.Length(); ++i) {
|
|
|
|
const TimedTexture& t = aTextures[i];
|
2015-05-25 10:48:09 +00:00
|
|
|
MOZ_ASSERT(t.mTexture);
|
2015-07-06 03:02:26 +00:00
|
|
|
if (i + 1 < aTextures.Length() &&
|
|
|
|
t.mProducerID == mLastProducerID && t.mFrameID < mLastFrameID) {
|
|
|
|
// Ignore frames before a frame that we already composited. We don't
|
|
|
|
// ever want to display these frames. This could be important if
|
|
|
|
// the frame producer adjusts timestamps (e.g. to track the audio clock)
|
|
|
|
// and the new frame times are earlier.
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
TimedImage& img = *newImages.AppendElement();
|
2016-02-25 13:15:40 +00:00
|
|
|
img.mTextureHost = t.mTexture;
|
2015-05-25 10:48:09 +00:00
|
|
|
img.mTimeStamp = t.mTimeStamp;
|
|
|
|
img.mPictureRect = t.mPictureRect;
|
2015-07-06 03:02:26 +00:00
|
|
|
img.mFrameID = t.mFrameID;
|
|
|
|
img.mProducerID = t.mProducerID;
|
2016-02-25 13:15:40 +00:00
|
|
|
img.mTextureHost->SetCropRect(img.mPictureRect);
|
|
|
|
img.mTextureHost->Updated();
|
2014-09-26 11:30:11 +00:00
|
|
|
}
|
2016-02-25 13:15:40 +00:00
|
|
|
|
2015-05-25 10:48:09 +00:00
|
|
|
mImages.SwapElements(newImages);
|
2016-02-25 13:15:40 +00:00
|
|
|
newImages.Clear();
|
|
|
|
|
|
|
|
// If we only have one image we can upload it right away, otherwise we'll upload
|
|
|
|
// on-demand during composition after we have picked the proper timestamp.
|
|
|
|
if (mImages.Length() == 1) {
|
|
|
|
SetCurrentTextureHost(mImages[0].mTextureHost);
|
|
|
|
}
|
2015-08-01 22:37:11 +00:00
|
|
|
|
|
|
|
// Video producers generally send replacement images with the same frameID but
|
|
|
|
// slightly different timestamps in order to sync with the audio clock. This
|
|
|
|
// means that any CompositeUntil() call we made in Composite() may no longer
|
|
|
|
// guarantee that we'll composite until the next frame is ready. Fix that here.
|
|
|
|
if (GetCompositor() && mLastFrameID >= 0) {
|
|
|
|
for (size_t i = 0; i < mImages.Length(); ++i) {
|
|
|
|
bool frameComesAfter = mImages[i].mFrameID > mLastFrameID ||
|
|
|
|
mImages[i].mProducerID != mLastProducerID;
|
|
|
|
if (frameComesAfter && !mImages[i].mTimeStamp.IsNull()) {
|
|
|
|
GetCompositor()->CompositeUntil(mImages[i].mTimeStamp +
|
|
|
|
TimeDuration::FromMilliseconds(BIAS_TIME_MS));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-07-30 09:59:51 +00:00
|
|
|
}
|
|
|
|
|
2016-02-25 13:15:40 +00:00
|
|
|
void
|
|
|
|
ImageHost::SetCurrentTextureHost(TextureHost* aTexture)
|
|
|
|
{
|
|
|
|
if (aTexture == mCurrentTextureHost.get()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool swapTextureSources = !!mCurrentTextureHost && !!mCurrentTextureSource
|
2016-02-25 13:15:58 +00:00
|
|
|
&& mCurrentTextureHost->HasIntermediateBuffer();
|
2016-02-25 13:15:40 +00:00
|
|
|
|
|
|
|
if (swapTextureSources) {
|
|
|
|
auto dataSource = mCurrentTextureSource->AsDataTextureSource();
|
|
|
|
if (dataSource) {
|
|
|
|
// The current textureHost has an internal buffer in the form of the
|
|
|
|
// DataTextureSource. Removing the ownership of the texture source
|
|
|
|
// will enable the next texture host we bind to the texture source to
|
|
|
|
// acquire it instead of creating a new one. This is desirable in
|
|
|
|
// ImageHost because the current texture won't be used again with the
|
|
|
|
// same content. It wouldn't be desirable with ContentHost for instance,
|
|
|
|
// because the latter reuses the texture's valid regions.
|
|
|
|
dataSource->SetOwner(nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
RefPtr<TextureSource> tmp = mExtraTextureSource;
|
|
|
|
mExtraTextureSource = mCurrentTextureSource.get();
|
|
|
|
mCurrentTextureSource = tmp;
|
|
|
|
} else {
|
|
|
|
mExtraTextureSource = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
mCurrentTextureHost = aTexture;
|
|
|
|
mCurrentTextureHost->PrepareTextureSource(mCurrentTextureSource);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ImageHost::CleanupResources()
|
|
|
|
{
|
|
|
|
mExtraTextureSource = nullptr;
|
|
|
|
mCurrentTextureSource = nullptr;
|
|
|
|
mCurrentTextureHost = nullptr;
|
|
|
|
}
|
|
|
|
|
2014-02-10 20:52:35 +00:00
|
|
|
void
|
|
|
|
ImageHost::RemoveTextureHost(TextureHost* aTexture)
|
|
|
|
{
|
2015-05-25 10:48:09 +00:00
|
|
|
MOZ_ASSERT(!mLocked);
|
|
|
|
|
2014-02-10 20:52:35 +00:00
|
|
|
CompositableHost::RemoveTextureHost(aTexture);
|
2015-05-25 10:48:09 +00:00
|
|
|
|
|
|
|
for (int32_t i = mImages.Length() - 1; i >= 0; --i) {
|
2016-02-25 13:15:40 +00:00
|
|
|
if (mImages[i].mTextureHost == aTexture) {
|
2015-05-25 10:48:09 +00:00
|
|
|
aTexture->UnbindTextureSource();
|
|
|
|
mImages.RemoveElementAt(i);
|
|
|
|
}
|
2014-02-10 20:52:35 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-02-07 08:07:00 +00:00
|
|
|
TimeStamp
|
|
|
|
ImageHost::GetCompositionTime() const
|
2015-06-15 03:27:02 +00:00
|
|
|
{
|
2017-02-07 08:07:00 +00:00
|
|
|
TimeStamp time;
|
|
|
|
if (GetCompositor()) {
|
|
|
|
time = GetCompositor()->GetCompositionTime();
|
2015-06-15 03:27:02 +00:00
|
|
|
}
|
2017-02-07 08:07:00 +00:00
|
|
|
return time;
|
2015-05-25 10:48:09 +00:00
|
|
|
}
|
|
|
|
|
2013-07-30 09:59:51 +00:00
|
|
|
TextureHost*
|
2015-07-03 22:52:42 +00:00
|
|
|
ImageHost::GetAsTextureHost(IntRect* aPictureRect)
|
2013-07-30 09:59:51 +00:00
|
|
|
{
|
2015-05-25 10:48:09 +00:00
|
|
|
TimedImage* img = ChooseImage();
|
2016-02-25 13:15:40 +00:00
|
|
|
if (img) {
|
|
|
|
SetCurrentTextureHost(img->mTextureHost);
|
|
|
|
}
|
2015-05-25 10:48:09 +00:00
|
|
|
if (aPictureRect && img) {
|
|
|
|
*aPictureRect = img->mPictureRect;
|
2015-07-03 22:52:42 +00:00
|
|
|
}
|
2016-02-25 13:15:40 +00:00
|
|
|
return img ? img->mTextureHost.get() : nullptr;
|
2013-07-30 09:59:51 +00:00
|
|
|
}
|
|
|
|
|
2015-05-04 10:59:02 +00:00
|
|
|
void ImageHost::Attach(Layer* aLayer,
|
|
|
|
Compositor* aCompositor,
|
|
|
|
AttachFlags aFlags)
|
|
|
|
{
|
|
|
|
CompositableHost::Attach(aLayer, aCompositor, aFlags);
|
2015-05-25 10:48:09 +00:00
|
|
|
for (auto& img : mImages) {
|
2015-05-04 10:59:02 +00:00
|
|
|
if (GetCompositor()) {
|
2016-02-25 13:15:40 +00:00
|
|
|
img.mTextureHost->SetCompositor(GetCompositor());
|
2015-05-04 10:59:02 +00:00
|
|
|
}
|
2016-02-25 13:15:40 +00:00
|
|
|
img.mTextureHost->Updated();
|
2015-05-04 10:59:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-30 09:59:51 +00:00
|
|
|
void
|
2015-07-06 03:02:26 +00:00
|
|
|
ImageHost::Composite(LayerComposite* aLayer,
|
|
|
|
EffectChain& aEffectChain,
|
2013-07-30 09:59:51 +00:00
|
|
|
float aOpacity,
|
|
|
|
const gfx::Matrix4x4& aTransform,
|
2016-05-25 16:01:18 +00:00
|
|
|
const gfx::SamplingFilter aSamplingFilter,
|
2016-05-13 20:15:17 +00:00
|
|
|
const gfx::IntRect& aClipRect,
|
2016-12-06 23:39:01 +00:00
|
|
|
const nsIntRegion* aVisibleRegion,
|
|
|
|
const Maybe<gfx::Polygon>& aGeometry)
|
2013-07-30 09:59:51 +00:00
|
|
|
{
|
|
|
|
if (!GetCompositor()) {
|
|
|
|
// should only happen when a tab is dragged to another window and
|
|
|
|
// async-video is still sending frames but we haven't attached the
|
|
|
|
// set the new compositor yet.
|
|
|
|
return;
|
|
|
|
}
|
2015-12-29 09:07:33 +00:00
|
|
|
|
2015-03-19 06:58:16 +00:00
|
|
|
int imageIndex = ChooseImageIndex();
|
|
|
|
if (imageIndex < 0) {
|
2013-07-30 09:59:51 +00:00
|
|
|
return;
|
|
|
|
}
|
2013-12-12 01:44:41 +00:00
|
|
|
|
2015-03-19 06:58:16 +00:00
|
|
|
if (uint32_t(imageIndex) + 1 < mImages.Length()) {
|
2015-08-01 22:37:11 +00:00
|
|
|
GetCompositor()->CompositeUntil(mImages[imageIndex + 1].mTimeStamp + TimeDuration::FromMilliseconds(BIAS_TIME_MS));
|
2015-03-19 06:58:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TimedImage* img = &mImages[imageIndex];
|
2016-03-22 14:28:27 +00:00
|
|
|
img->mTextureHost->SetCompositor(GetCompositor());
|
2016-02-25 13:15:40 +00:00
|
|
|
SetCurrentTextureHost(img->mTextureHost);
|
2013-12-12 01:44:41 +00:00
|
|
|
|
2015-06-15 03:27:02 +00:00
|
|
|
{
|
|
|
|
AutoLockCompositableHost autoLock(this);
|
|
|
|
if (autoLock.Failed()) {
|
|
|
|
NS_WARNING("failed to lock front buffer");
|
|
|
|
return;
|
|
|
|
}
|
2014-10-16 17:08:32 +00:00
|
|
|
|
2016-02-25 13:15:40 +00:00
|
|
|
if (!mCurrentTextureHost->BindTextureSource(mCurrentTextureSource)) {
|
2015-06-15 03:27:02 +00:00
|
|
|
return;
|
|
|
|
}
|
2014-10-16 17:08:32 +00:00
|
|
|
|
2016-02-25 13:15:40 +00:00
|
|
|
if (!mCurrentTextureSource) {
|
2015-06-15 03:27:02 +00:00
|
|
|
// BindTextureSource above should have returned false!
|
|
|
|
MOZ_ASSERT(false);
|
|
|
|
return;
|
|
|
|
}
|
2014-06-19 00:04:06 +00:00
|
|
|
|
2015-06-15 03:27:02 +00:00
|
|
|
bool isAlphaPremultiplied =
|
2016-02-25 13:15:40 +00:00
|
|
|
!(mCurrentTextureHost->GetFlags() & TextureFlags::NON_PREMULTIPLIED);
|
2015-10-18 05:24:48 +00:00
|
|
|
RefPtr<TexturedEffect> effect =
|
2016-10-18 17:09:00 +00:00
|
|
|
CreateTexturedEffect(mCurrentTextureHost,
|
2017-02-14 20:29:39 +00:00
|
|
|
mCurrentTextureSource.get(), aSamplingFilter, isAlphaPremultiplied);
|
2015-06-15 03:27:02 +00:00
|
|
|
if (!effect) {
|
|
|
|
return;
|
|
|
|
}
|
2013-11-21 22:07:56 +00:00
|
|
|
|
2015-09-04 18:31:52 +00:00
|
|
|
if (!GetCompositor()->SupportsEffect(effect->mType)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-10-22 23:51:20 +00:00
|
|
|
DiagnosticFlags diagnosticFlags = DiagnosticFlags::IMAGE;
|
|
|
|
if (effect->mType == EffectTypes::NV12) {
|
|
|
|
diagnosticFlags |= DiagnosticFlags::NV12;
|
|
|
|
} else if (effect->mType == EffectTypes::YCBCR) {
|
|
|
|
diagnosticFlags |= DiagnosticFlags::YCBCR;
|
|
|
|
}
|
|
|
|
|
2015-06-15 03:27:02 +00:00
|
|
|
if (mLastFrameID != img->mFrameID || mLastProducerID != img->mProducerID) {
|
2017-01-04 15:19:30 +00:00
|
|
|
if (mAsyncRef) {
|
|
|
|
ImageCompositeNotificationInfo info;
|
|
|
|
info.mImageBridgeProcessId = mAsyncRef.mProcessId;
|
|
|
|
info.mNotification = ImageCompositeNotification(
|
2017-01-18 02:47:06 +00:00
|
|
|
mAsyncRef.mHandle,
|
2017-01-04 15:19:30 +00:00
|
|
|
img->mTimeStamp, GetCompositor()->GetCompositionTime(),
|
|
|
|
img->mFrameID, img->mProducerID);
|
2016-11-24 05:11:27 +00:00
|
|
|
static_cast<LayerManagerComposite*>(aLayer->GetLayerManager())->
|
2017-01-04 15:19:30 +00:00
|
|
|
AppendImageCompositeNotification(info);
|
2015-06-15 03:27:02 +00:00
|
|
|
}
|
|
|
|
mLastFrameID = img->mFrameID;
|
|
|
|
mLastProducerID = img->mProducerID;
|
2015-07-06 03:02:26 +00:00
|
|
|
}
|
2015-06-15 03:27:02 +00:00
|
|
|
aEffectChain.mPrimaryEffect = effect;
|
|
|
|
gfx::Rect pictureRect(0, 0, img->mPictureRect.width, img->mPictureRect.height);
|
2016-02-25 13:15:40 +00:00
|
|
|
BigImageIterator* it = mCurrentTextureSource->AsBigImageIterator();
|
2015-06-15 03:27:02 +00:00
|
|
|
if (it) {
|
|
|
|
|
|
|
|
// This iteration does not work if we have multiple texture sources here
|
|
|
|
// (e.g. 3 YCbCr textures). There's nothing preventing the different
|
|
|
|
// planes from having different resolutions or tile sizes. For example, a
|
|
|
|
// YCbCr frame could have Cb and Cr planes that are half the resolution of
|
|
|
|
// the Y plane, in such a way that the Y plane overflows the maximum
|
|
|
|
// texture size and the Cb and Cr planes do not. Then the Y plane would be
|
|
|
|
// split into multiple tiles and the Cb and Cr planes would just be one
|
|
|
|
// tile each.
|
|
|
|
// To handle the general case correctly, we'd have to create a grid of
|
|
|
|
// intersected tiles over all planes, and then draw each grid tile using
|
|
|
|
// the corresponding source tiles from all planes, with appropriate
|
|
|
|
// per-plane per-tile texture coords.
|
|
|
|
// DrawQuad currently assumes that all planes use the same texture coords.
|
2016-02-25 13:15:40 +00:00
|
|
|
MOZ_ASSERT(it->GetTileCount() == 1 || !mCurrentTextureSource->GetNextSibling(),
|
2015-06-15 03:27:02 +00:00
|
|
|
"Can't handle multi-plane BigImages");
|
|
|
|
|
|
|
|
it->BeginBigImageIteration();
|
|
|
|
do {
|
|
|
|
IntRect tileRect = it->GetTileRect();
|
|
|
|
gfx::Rect rect(tileRect.x, tileRect.y, tileRect.width, tileRect.height);
|
|
|
|
rect = rect.Intersect(pictureRect);
|
|
|
|
effect->mTextureCoords = Rect(Float(rect.x - tileRect.x) / tileRect.width,
|
|
|
|
Float(rect.y - tileRect.y) / tileRect.height,
|
|
|
|
Float(rect.width) / tileRect.width,
|
|
|
|
Float(rect.height) / tileRect.height);
|
2016-02-25 13:15:40 +00:00
|
|
|
if (img->mTextureHost->GetFlags() & TextureFlags::ORIGIN_BOTTOM_LEFT) {
|
2015-06-15 03:27:02 +00:00
|
|
|
effect->mTextureCoords.y = effect->mTextureCoords.YMost();
|
|
|
|
effect->mTextureCoords.height = -effect->mTextureCoords.height;
|
|
|
|
}
|
2016-12-06 23:39:01 +00:00
|
|
|
GetCompositor()->DrawGeometry(rect, aClipRect, aEffectChain,
|
|
|
|
aOpacity, aTransform, aGeometry);
|
2015-10-22 23:51:20 +00:00
|
|
|
GetCompositor()->DrawDiagnostics(diagnosticFlags | DiagnosticFlags::BIGIMAGE,
|
2015-06-15 03:27:02 +00:00
|
|
|
rect, aClipRect, aTransform, mFlashCounter);
|
|
|
|
} while (it->NextTile());
|
|
|
|
it->EndBigImageIteration();
|
|
|
|
// layer border
|
2015-10-22 23:51:20 +00:00
|
|
|
GetCompositor()->DrawDiagnostics(diagnosticFlags, pictureRect,
|
2015-06-15 03:27:02 +00:00
|
|
|
aClipRect, aTransform, mFlashCounter);
|
|
|
|
} else {
|
2016-02-25 13:15:40 +00:00
|
|
|
IntSize textureSize = mCurrentTextureSource->GetSize();
|
2015-06-15 03:27:02 +00:00
|
|
|
effect->mTextureCoords = Rect(Float(img->mPictureRect.x) / textureSize.width,
|
|
|
|
Float(img->mPictureRect.y) / textureSize.height,
|
|
|
|
Float(img->mPictureRect.width) / textureSize.width,
|
|
|
|
Float(img->mPictureRect.height) / textureSize.height);
|
|
|
|
|
2016-02-25 13:15:40 +00:00
|
|
|
if (img->mTextureHost->GetFlags() & TextureFlags::ORIGIN_BOTTOM_LEFT) {
|
2014-05-13 02:20:26 +00:00
|
|
|
effect->mTextureCoords.y = effect->mTextureCoords.YMost();
|
|
|
|
effect->mTextureCoords.height = -effect->mTextureCoords.height;
|
|
|
|
}
|
2015-06-15 03:27:02 +00:00
|
|
|
|
2016-12-06 23:39:01 +00:00
|
|
|
GetCompositor()->DrawGeometry(pictureRect, aClipRect, aEffectChain,
|
|
|
|
aOpacity, aTransform, aGeometry);
|
2015-10-22 23:51:20 +00:00
|
|
|
GetCompositor()->DrawDiagnostics(diagnosticFlags,
|
2015-06-15 03:27:02 +00:00
|
|
|
pictureRect, aClipRect,
|
|
|
|
aTransform, mFlashCounter);
|
2013-07-30 09:59:51 +00:00
|
|
|
}
|
|
|
|
}
|
2015-06-15 03:27:02 +00:00
|
|
|
|
|
|
|
// Update mBias last. This can change which frame ChooseImage(Index) would
|
|
|
|
// return, and we don't want to do that until we've finished compositing
|
|
|
|
// since callers of ChooseImage(Index) assume the same image will be chosen
|
|
|
|
// during a given composition. This must happen after autoLock's
|
|
|
|
// destructor!
|
|
|
|
mBias = UpdateBias(
|
|
|
|
GetCompositor()->GetCompositionTime(), mImages[imageIndex].mTimeStamp,
|
|
|
|
uint32_t(imageIndex + 1) < mImages.Length() ?
|
|
|
|
mImages[imageIndex + 1].mTimeStamp : TimeStamp(),
|
|
|
|
mBias);
|
2013-07-30 09:59:51 +00:00
|
|
|
}
|
|
|
|
|
2013-12-12 01:44:49 +00:00
|
|
|
void
|
|
|
|
ImageHost::SetCompositor(Compositor* aCompositor)
|
|
|
|
{
|
2015-05-25 10:48:09 +00:00
|
|
|
if (mCompositor != aCompositor) {
|
|
|
|
for (auto& img : mImages) {
|
2016-02-25 13:15:40 +00:00
|
|
|
img.mTextureHost->SetCompositor(aCompositor);
|
2015-05-25 10:48:09 +00:00
|
|
|
}
|
2013-12-12 01:44:49 +00:00
|
|
|
}
|
|
|
|
CompositableHost::SetCompositor(aCompositor);
|
|
|
|
}
|
|
|
|
|
2013-07-30 09:59:51 +00:00
|
|
|
void
|
2014-06-19 22:36:25 +00:00
|
|
|
ImageHost::PrintInfo(std::stringstream& aStream, const char* aPrefix)
|
2013-07-30 09:59:51 +00:00
|
|
|
{
|
2014-06-19 22:36:25 +00:00
|
|
|
aStream << aPrefix;
|
|
|
|
aStream << nsPrintfCString("ImageHost (0x%p)", this).get();
|
2013-07-30 09:59:51 +00:00
|
|
|
|
2015-05-25 10:48:09 +00:00
|
|
|
nsAutoCString pfx(aPrefix);
|
|
|
|
pfx += " ";
|
|
|
|
for (auto& img : mImages) {
|
2014-06-19 22:36:25 +00:00
|
|
|
aStream << "\n";
|
2016-02-25 13:15:40 +00:00
|
|
|
img.mTextureHost->PrintInfo(aStream, pfx.get());
|
2015-05-25 10:48:09 +00:00
|
|
|
AppendToString(aStream, img.mPictureRect, " [picture-rect=", "]");
|
2013-07-30 09:59:51 +00:00
|
|
|
}
|
|
|
|
}
|
2013-08-08 12:53:12 +00:00
|
|
|
|
2013-07-30 09:59:51 +00:00
|
|
|
void
|
2014-06-19 22:36:25 +00:00
|
|
|
ImageHost::Dump(std::stringstream& aStream,
|
2013-07-30 09:59:51 +00:00
|
|
|
const char* aPrefix,
|
|
|
|
bool aDumpHtml)
|
|
|
|
{
|
2015-05-25 10:48:09 +00:00
|
|
|
for (auto& img : mImages) {
|
2014-06-19 22:36:25 +00:00
|
|
|
aStream << aPrefix;
|
|
|
|
aStream << (aDumpHtml ? "<ul><li>TextureHost: "
|
2013-07-30 09:59:51 +00:00
|
|
|
: "TextureHost: ");
|
2016-02-25 13:15:40 +00:00
|
|
|
DumpTextureHost(aStream, img.mTextureHost);
|
2014-06-19 22:36:25 +00:00
|
|
|
aStream << (aDumpHtml ? " </li></ul> " : " ");
|
2013-07-30 09:59:51 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-17 14:00:52 +00:00
|
|
|
already_AddRefed<gfx::DataSourceSurface>
|
2013-07-30 09:59:51 +00:00
|
|
|
ImageHost::GetAsSurface()
|
|
|
|
{
|
2015-05-25 10:48:09 +00:00
|
|
|
TimedImage* img = ChooseImage();
|
|
|
|
if (img) {
|
2016-02-25 13:15:40 +00:00
|
|
|
return img->mTextureHost->GetAsSurface();
|
2015-05-25 10:48:09 +00:00
|
|
|
}
|
|
|
|
return nullptr;
|
2013-07-30 09:59:51 +00:00
|
|
|
}
|
|
|
|
|
2014-06-22 17:06:00 +00:00
|
|
|
bool
|
|
|
|
ImageHost::Lock()
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(!mLocked);
|
2015-05-25 10:48:09 +00:00
|
|
|
TimedImage* img = ChooseImage();
|
|
|
|
if (!img) {
|
2014-12-20 22:16:00 +00:00
|
|
|
return false;
|
|
|
|
}
|
2016-02-25 13:15:40 +00:00
|
|
|
|
|
|
|
SetCurrentTextureHost(img->mTextureHost);
|
|
|
|
|
|
|
|
if (!mCurrentTextureHost->Lock()) {
|
2014-06-22 17:06:00 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
mLocked = true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
ImageHost::Unlock()
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(mLocked);
|
2016-02-25 13:15:40 +00:00
|
|
|
|
|
|
|
if (mCurrentTextureHost) {
|
|
|
|
mCurrentTextureHost->Unlock();
|
2014-12-20 22:16:00 +00:00
|
|
|
}
|
2014-06-22 17:06:00 +00:00
|
|
|
mLocked = false;
|
|
|
|
}
|
|
|
|
|
2014-11-12 21:44:42 +00:00
|
|
|
IntSize
|
|
|
|
ImageHost::GetImageSize() const
|
|
|
|
{
|
2015-05-25 10:48:09 +00:00
|
|
|
const TimedImage* img = ChooseImage();
|
|
|
|
if (img) {
|
|
|
|
return IntSize(img->mPictureRect.width, img->mPictureRect.height);
|
2014-11-12 21:44:42 +00:00
|
|
|
}
|
|
|
|
return IntSize();
|
|
|
|
}
|
|
|
|
|
2016-04-11 02:51:21 +00:00
|
|
|
bool
|
|
|
|
ImageHost::IsOpaque()
|
|
|
|
{
|
|
|
|
const TimedImage* img = ChooseImage();
|
|
|
|
if (!img) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (img->mPictureRect.width == 0 ||
|
|
|
|
img->mPictureRect.height == 0 ||
|
|
|
|
!img->mTextureHost) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
gfx::SurfaceFormat format = img->mTextureHost->GetFormat();
|
|
|
|
if (gfx::IsOpaque(format)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-06-17 14:00:52 +00:00
|
|
|
already_AddRefed<TexturedEffect>
|
2016-05-25 16:01:18 +00:00
|
|
|
ImageHost::GenEffect(const gfx::SamplingFilter aSamplingFilter)
|
2014-06-22 17:06:00 +00:00
|
|
|
{
|
2015-05-25 10:48:09 +00:00
|
|
|
TimedImage* img = ChooseImage();
|
|
|
|
if (!img) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2016-02-25 13:15:40 +00:00
|
|
|
SetCurrentTextureHost(img->mTextureHost);
|
|
|
|
if (!mCurrentTextureHost->BindTextureSource(mCurrentTextureSource)) {
|
2014-06-22 17:06:00 +00:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
bool isAlphaPremultiplied = true;
|
2016-02-25 13:15:40 +00:00
|
|
|
if (mCurrentTextureHost->GetFlags() & TextureFlags::NON_PREMULTIPLIED) {
|
2014-06-22 17:06:00 +00:00
|
|
|
isAlphaPremultiplied = false;
|
2015-05-25 10:48:09 +00:00
|
|
|
}
|
2014-06-22 17:06:00 +00:00
|
|
|
|
2016-10-18 17:09:00 +00:00
|
|
|
return CreateTexturedEffect(mCurrentTextureHost,
|
2016-02-25 13:15:40 +00:00
|
|
|
mCurrentTextureSource,
|
2016-05-25 16:01:18 +00:00
|
|
|
aSamplingFilter,
|
2017-02-14 20:29:39 +00:00
|
|
|
isAlphaPremultiplied);
|
2014-06-22 17:06:00 +00:00
|
|
|
}
|
|
|
|
|
2015-05-07 09:07:42 +00:00
|
|
|
} // namespace layers
|
|
|
|
} // namespace mozilla
|
2017-02-07 09:37:57 +00:00
|
|
|
|
|
|
|
#undef BIAS_TIME_MS
|