void TiledContentHost::Detach(Layer* aLayer, AttachFlags aFlags /* = NO_FLAGS */) { if (!mKeepAttached || aLayer == mLayer || aFlags & FORCE_DETACH) { // Unlock any buffers that may still be locked. If we have a pending upload, // we will need to unlock the buffer that was about to be uploaded. // If a buffer that was being composited had double-buffered tiles, we will // need to unlock that buffer too. if (mPendingUpload) { mTiledBuffer.ReadUnlock(); if (mOldTiledBuffer.HasDoubleBufferedTiles()) { mOldTiledBuffer.ReadUnlock(); } } else if (mTiledBuffer.HasDoubleBufferedTiles()) { mTiledBuffer.ReadUnlock(); } if (mPendingLowPrecisionUpload) { mLowPrecisionTiledBuffer.ReadUnlock(); if (mOldLowPrecisionTiledBuffer.HasDoubleBufferedTiles()) { mOldLowPrecisionTiledBuffer.ReadUnlock(); } } else if (mLowPrecisionTiledBuffer.HasDoubleBufferedTiles()) { mLowPrecisionTiledBuffer.ReadUnlock(); } mTiledBuffer = TiledLayerBufferComposite(); mLowPrecisionTiledBuffer = TiledLayerBufferComposite(); mOldTiledBuffer = TiledLayerBufferComposite(); mOldLowPrecisionTiledBuffer = TiledLayerBufferComposite(); } CompositableHost::Detach(aLayer,aFlags); }
TiledContentHost::TiledContentHost(const TextureInfo& aTextureInfo) : ContentHost(aTextureInfo) , mTiledBuffer(TiledLayerBufferComposite()) , mLowPrecisionTiledBuffer(TiledLayerBufferComposite()) { MOZ_COUNT_CTOR(TiledContentHost); }
bool TiledContentHost::UseTiledLayerBuffer(ISurfaceAllocator* aAllocator, const SurfaceDescriptorTiles& aTiledDescriptor) { if (aTiledDescriptor.resolution() < 1) { if (mPendingLowPrecisionUpload) { mLowPrecisionTiledBuffer.ReadUnlock(); } else { mPendingLowPrecisionUpload = true; // If the old buffer has double-buffered tiles, hang onto it so we can // unlock it after we've composited the new buffer. // We only need to hang onto the locks, but not the textures. // Releasing the textures here can help prevent a memory spike in the // situation that the client starts rendering new content before we get // to composite the new buffer. if (mLowPrecisionTiledBuffer.HasDoubleBufferedTiles()) { mOldLowPrecisionTiledBuffer = mLowPrecisionTiledBuffer; mOldLowPrecisionTiledBuffer.ReleaseTextureHosts(); } } mLowPrecisionTiledBuffer = TiledLayerBufferComposite(aAllocator, aTiledDescriptor, mLowPrecisionTiledBuffer.GetPaintedRegion(), mCompositor); if (!mLowPrecisionTiledBuffer.IsValid()) { // Something bad happened. Stop here, return false (kills the child process), // and do as little work as possible on the received data as it appears // to be corrupted. mPendingLowPrecisionUpload = false; mPendingUpload = false; return false; } } else { if (mPendingUpload) { mTiledBuffer.ReadUnlock(); } else { mPendingUpload = true; if (mTiledBuffer.HasDoubleBufferedTiles()) { mOldTiledBuffer = mTiledBuffer; mOldTiledBuffer.ReleaseTextureHosts(); } } mTiledBuffer = TiledLayerBufferComposite(aAllocator, aTiledDescriptor, mTiledBuffer.GetPaintedRegion(), mCompositor); if (!mTiledBuffer.IsValid()) { // Something bad happened. Stop here, return false (kills the child process), // and do as little work as possible on the received data as it appears // to be corrupted. mPendingLowPrecisionUpload = false; mPendingUpload = false; return false; } } return true; }
TiledContentHost::TiledContentHost(const TextureInfo& aTextureInfo) : ContentHost(aTextureInfo) , mTiledBuffer(TiledLayerBufferComposite()) , mLowPrecisionTiledBuffer(TiledLayerBufferComposite()) , mOldTiledBuffer(TiledLayerBufferComposite()) , mOldLowPrecisionTiledBuffer(TiledLayerBufferComposite()) , mPendingUpload(false) , mPendingLowPrecisionUpload(false) { MOZ_COUNT_CTOR(TiledContentHost); }
void TiledContentHost::Composite(EffectChain& aEffectChain, float aOpacity, const gfx::Matrix4x4& aTransform, const gfx::Filter& aFilter, const gfx::Rect& aClipRect, const nsIntRegion* aVisibleRegion /* = nullptr */) { if (mPendingUpload) { mTiledBuffer.SetCompositor(mCompositor); mTiledBuffer.Upload(); // For a single-buffered tiled buffer, Upload will upload the shared memory // surface to texture memory and we no longer need to read from them. if (!mTiledBuffer.HasDoubleBufferedTiles()) { mTiledBuffer.ReadUnlock(); } } if (mPendingLowPrecisionUpload) { mLowPrecisionTiledBuffer.SetCompositor(mCompositor); mLowPrecisionTiledBuffer.Upload(); if (!mLowPrecisionTiledBuffer.HasDoubleBufferedTiles()) { mLowPrecisionTiledBuffer.ReadUnlock(); } } // Reduce the opacity of the low-precision buffer to make it a // little more subtle and less jarring. In particular, text // rendered at low-resolution and scaled tends to look pretty // heavy and this helps mitigate that. When we reduce the opacity // we also make sure to draw the background color behind the // reduced-opacity tile so that content underneath doesn't show // through. // However, in cases where the background is transparent, or the layer // already has some opacity, we want to skip this behaviour. Otherwise // we end up changing the expected overall transparency of the content, // and it just looks wrong. gfxRGBA backgroundColor(0); if (aOpacity == 1.0f && gfxPrefs::LowPrecisionOpacity() < 1.0f) { // Background colors are only stored on scrollable layers. Grab // the one from the nearest scrollable ancestor layer. for (LayerMetricsWrapper ancestor(GetLayer(), LayerMetricsWrapper::StartAt::BOTTOM); ancestor; ancestor = ancestor.GetParent()) { if (ancestor.Metrics().IsScrollable()) { backgroundColor = ancestor.Metrics().GetBackgroundColor(); break; } } } float lowPrecisionOpacityReduction = (aOpacity == 1.0f && backgroundColor.a == 1.0f) ? gfxPrefs::LowPrecisionOpacity() : 1.0f; nsIntRegion tmpRegion; const nsIntRegion* renderRegion = aVisibleRegion; #ifndef MOZ_IGNORE_PAINT_WILL_RESAMPLE if (PaintWillResample()) { // If we're resampling, then the texture image will contain exactly the // entire visible region's bounds, and we should draw it all in one quad // to avoid unexpected aliasing. tmpRegion = aVisibleRegion->GetBounds(); renderRegion = &tmpRegion; } #endif // Render the low and high precision buffers. RenderLayerBuffer(mLowPrecisionTiledBuffer, lowPrecisionOpacityReduction < 1.0f ? &backgroundColor : nullptr, aEffectChain, lowPrecisionOpacityReduction * aOpacity, aFilter, aClipRect, *renderRegion, aTransform); RenderLayerBuffer(mTiledBuffer, nullptr, aEffectChain, aOpacity, aFilter, aClipRect, *renderRegion, aTransform); // Now release the old buffer if it had double-buffered tiles, as we can // guarantee that they're no longer on the screen (and so any locks that may // have been held have been released). if (mPendingUpload && mOldTiledBuffer.HasDoubleBufferedTiles()) { mOldTiledBuffer.ReadUnlock(); mOldTiledBuffer = TiledLayerBufferComposite(); } if (mPendingLowPrecisionUpload && mOldLowPrecisionTiledBuffer.HasDoubleBufferedTiles()) { mOldLowPrecisionTiledBuffer.ReadUnlock(); mOldLowPrecisionTiledBuffer = TiledLayerBufferComposite(); } mPendingUpload = mPendingLowPrecisionUpload = false; }