mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-18 06:45:33 +00:00
Bug 1284324 - Implement Canvas Layer mirrors r=bas
- When a canvas layer is set to mirror, it copies the texture from the canvas rather than changing the texture factory with Morph(). - This is useful when a canvas content will be sent to multiple devices simultaneously, such as a VR HMD and a 2d monitor mirror. - This is used by the WebVR 1.0 API, in Bug 1250244 MozReview-Commit-ID: JfMSockO2uz --HG-- extra : rebase_source : ba9633f7cb9a622efb8389d834b4232205c72755
This commit is contained in:
parent
0377b85db7
commit
694ce1cf8d
@ -5811,8 +5811,14 @@ CanvasRenderingContext2D::GetBufferProvider(LayerManager* aManager)
|
||||
already_AddRefed<Layer>
|
||||
CanvasRenderingContext2D::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
|
||||
Layer *aOldLayer,
|
||||
LayerManager *aManager)
|
||||
LayerManager *aManager,
|
||||
bool aMirror /* = false */)
|
||||
{
|
||||
if (aMirror) {
|
||||
// Not supported for CanvasRenderingContext2D
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (mOpaque || mIsSkiaGL) {
|
||||
// If we're opaque then make sure we have a surface so we paint black
|
||||
// instead of transparent.
|
||||
|
@ -466,7 +466,8 @@ public:
|
||||
mozilla::layers::PersistentBufferProvider* GetBufferProvider(mozilla::layers::LayerManager* aManager);
|
||||
already_AddRefed<Layer> GetCanvasLayer(nsDisplayListBuilder* aBuilder,
|
||||
Layer* aOldLayer,
|
||||
LayerManager* aManager) override;
|
||||
LayerManager* aManager,
|
||||
bool aMirror = false) override;
|
||||
virtual bool ShouldForceInactiveLayer(LayerManager* aManager) override;
|
||||
void MarkContextClean() override;
|
||||
void MarkContextCleanForFrameCapture() override;
|
||||
|
@ -214,8 +214,14 @@ ImageBitmapRenderingContext::Reset()
|
||||
already_AddRefed<Layer>
|
||||
ImageBitmapRenderingContext::GetCanvasLayer(nsDisplayListBuilder* aBuilder,
|
||||
Layer* aOldLayer,
|
||||
LayerManager* aManager)
|
||||
LayerManager* aManager,
|
||||
bool aMirror /* = false */)
|
||||
{
|
||||
if (aMirror) {
|
||||
// Not supported for ImageBitmapRenderingContext
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!mImage) {
|
||||
// No DidTransactionCallback will be received, so mark the context clean
|
||||
// now so future invalidations will be dispatched.
|
||||
|
@ -70,7 +70,8 @@ public:
|
||||
NS_IMETHOD Reset() override;
|
||||
virtual already_AddRefed<Layer> GetCanvasLayer(nsDisplayListBuilder* aBuilder,
|
||||
Layer* aOldLayer,
|
||||
LayerManager* aManager) override;
|
||||
LayerManager* aManager,
|
||||
bool aMirror = false) override;
|
||||
virtual void MarkContextClean() override;
|
||||
|
||||
NS_IMETHOD Redraw(const gfxRect& aDirty) override;
|
||||
|
@ -1265,6 +1265,7 @@ WebGLContext::UpdateLastUseIndex()
|
||||
}
|
||||
|
||||
static uint8_t gWebGLLayerUserData;
|
||||
static uint8_t gWebGLMirrorLayerUserData;
|
||||
|
||||
class WebGLContextUserData : public LayerUserData
|
||||
{
|
||||
@ -1307,13 +1308,14 @@ private:
|
||||
already_AddRefed<layers::Layer>
|
||||
WebGLContext::GetCanvasLayer(nsDisplayListBuilder* builder,
|
||||
Layer* oldLayer,
|
||||
LayerManager* manager)
|
||||
LayerManager* manager,
|
||||
bool aMirror /*= false*/)
|
||||
{
|
||||
if (IsContextLost())
|
||||
return nullptr;
|
||||
|
||||
if (!mResetLayer && oldLayer &&
|
||||
oldLayer->HasUserData(&gWebGLLayerUserData)) {
|
||||
oldLayer->HasUserData(aMirror ? &gWebGLMirrorLayerUserData : &gWebGLLayerUserData)) {
|
||||
RefPtr<layers::Layer> ret = oldLayer;
|
||||
return ret.forget();
|
||||
}
|
||||
@ -1325,7 +1327,7 @@ WebGLContext::GetCanvasLayer(nsDisplayListBuilder* builder,
|
||||
}
|
||||
|
||||
WebGLContextUserData* userData = nullptr;
|
||||
if (builder->IsPaintingToWindow() && mCanvasElement) {
|
||||
if (builder->IsPaintingToWindow() && mCanvasElement && !aMirror) {
|
||||
// Make the layer tell us whenever a transaction finishes (including
|
||||
// the current transaction), so we can clear our invalidation state and
|
||||
// start invalidating again. We need to do this for the layer that is
|
||||
@ -1345,13 +1347,14 @@ WebGLContext::GetCanvasLayer(nsDisplayListBuilder* builder,
|
||||
WebGLContextUserData::PreTransactionCallback, userData);
|
||||
}
|
||||
|
||||
canvasLayer->SetUserData(&gWebGLLayerUserData, userData);
|
||||
canvasLayer->SetUserData(aMirror ? &gWebGLMirrorLayerUserData : &gWebGLLayerUserData, userData);
|
||||
|
||||
CanvasLayer::Data data;
|
||||
data.mGLContext = gl;
|
||||
data.mSize = nsIntSize(mWidth, mHeight);
|
||||
data.mHasAlpha = gl->Caps().alpha;
|
||||
data.mIsGLAlphaPremult = IsPremultAlpha() || !data.mHasAlpha;
|
||||
data.mIsMirror = aMirror;
|
||||
|
||||
canvasLayer->Initialize(data);
|
||||
uint32_t flags = gl->Caps().alpha ? 0 : Layer::CONTENT_OPAQUE;
|
||||
|
@ -333,7 +333,8 @@ public:
|
||||
|
||||
already_AddRefed<Layer>
|
||||
GetCanvasLayer(nsDisplayListBuilder* builder, Layer* oldLayer,
|
||||
LayerManager* manager) override;
|
||||
LayerManager* manager,
|
||||
bool aMirror = false) override;
|
||||
|
||||
// Note that 'clean' here refers to its invalidation state, not the
|
||||
// contents of the buffer.
|
||||
|
@ -135,7 +135,8 @@ public:
|
||||
// one for the given layer manager if not available.
|
||||
virtual already_AddRefed<Layer> GetCanvasLayer(nsDisplayListBuilder* builder,
|
||||
Layer *oldLayer,
|
||||
LayerManager *manager) = 0;
|
||||
LayerManager *manager,
|
||||
bool aMirror = false) = 0;
|
||||
|
||||
// Return true if the canvas should be forced to be "inactive" to ensure
|
||||
// it can be drawn to the screen even if it's too large to be blitted by
|
||||
|
@ -37,6 +37,7 @@ CopyableCanvasLayer::CopyableCanvasLayer(LayerManager* aLayerManager, void *aImp
|
||||
, mGLFrontbuffer(nullptr)
|
||||
, mIsAlphaPremultiplied(true)
|
||||
, mOriginPos(gl::OriginPos::TopLeft)
|
||||
, mIsMirror(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(CopyableCanvasLayer);
|
||||
}
|
||||
@ -55,6 +56,7 @@ CopyableCanvasLayer::Initialize(const Data& aData)
|
||||
mGLContext = aData.mGLContext;
|
||||
mIsAlphaPremultiplied = aData.mIsGLAlphaPremult;
|
||||
mOriginPos = gl::OriginPos::BottomLeft;
|
||||
mIsMirror = aData.mIsMirror;
|
||||
|
||||
MOZ_ASSERT(mGLContext->IsOffscreen(), "canvas gl context isn't offscreen");
|
||||
|
||||
|
@ -58,6 +58,7 @@ protected:
|
||||
|
||||
bool mIsAlphaPremultiplied;
|
||||
gl::OriginPos mOriginPos;
|
||||
bool mIsMirror;
|
||||
|
||||
RefPtr<gfx::DataSourceSurface> mCachedTempSurface;
|
||||
|
||||
|
@ -2375,6 +2375,7 @@ public:
|
||||
, mSize(0,0)
|
||||
, mHasAlpha(false)
|
||||
, mIsGLAlphaPremult(true)
|
||||
, mIsMirror(false)
|
||||
{ }
|
||||
|
||||
// One of these three must be specified for Canvas2D, but never more than one
|
||||
@ -2393,6 +2394,10 @@ public:
|
||||
|
||||
// Whether mGLContext contains data that is alpha-premultiplied.
|
||||
bool mIsGLAlphaPremult;
|
||||
|
||||
// Whether the canvas front buffer is already being rendered somewhere else.
|
||||
// When true, do not swap buffers or Morph() to another factory on mGLContext
|
||||
bool mIsMirror;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -411,6 +411,11 @@ CanvasClientSharedSurface::UpdateRenderer(gfx::IntSize aSize, Renderer& aRendere
|
||||
gfxCriticalError() << "Invalid canvas front buffer";
|
||||
return;
|
||||
}
|
||||
} else if (layer && layer->mIsMirror) {
|
||||
mShSurfClient = CloneSurface(gl->Screen()->Front()->Surf(), layer->mFactory.get());
|
||||
if (!mShSurfClient) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
mShSurfClient = gl->Screen()->Front();
|
||||
if (mShSurfClient && mShSurfClient->GetAllocator() &&
|
||||
|
@ -67,7 +67,7 @@ ClientCanvasLayer::Initialize(const Data& aData)
|
||||
|
||||
UniquePtr<SurfaceFactory> factory = GLScreenBuffer::CreateFactory(mGLContext, caps, forwarder, mFlags);
|
||||
|
||||
if (mGLFrontbuffer) {
|
||||
if (mGLFrontbuffer || aData.mIsMirror) {
|
||||
// We're using a source other than the one in the default screen.
|
||||
// (SkiaGL)
|
||||
mFactory = Move(factory);
|
||||
|
Loading…
x
Reference in New Issue
Block a user