bool RenderViewMLGPU::UpdateVisibleRegion(ItemInfo& aItem) { // If the item has some kind of complex transform, we perform a very // simple occlusion test and move on. We using a depth buffer we skip // CPU-based occlusion culling as well, since the GPU will do most of our // culling work for us. if (mUseDepthBuffer || !aItem.translation || !gfxPrefs::AdvancedLayersEnableCPUOcclusion()) { // Update the render region even if we won't compute visibility, since some // layer types (like Canvas and Image) need to have the visible region // clamped. LayerIntRegion region = aItem.layer->GetShadowVisibleRegion(); aItem.layer->SetRenderRegion(std::move(region)); AL_LOG("RenderView %p simple occlusion test, bounds=%s, translation?=%d\n", this, Stringify(aItem.bounds).c_str(), aItem.translation ? 1 : 0); return mInvalidBounds.Intersects(aItem.bounds); } MOZ_ASSERT(aItem.rectilinear); AL_LOG("RenderView %p starting visibility tests:\n", this); AL_LOG(" occluded=%s\n", Stringify(mOccludedRegion).c_str()); // Compute the translation into render target space. LayerIntPoint translation = LayerIntPoint::FromUnknownPoint( aItem.translation.value() - mTargetOffset); AL_LOG(" translation=%s\n", Stringify(translation).c_str()); IntRect clip = aItem.layer->GetComputedClipRect().ToUnknownRect(); AL_LOG(" clip=%s\n", Stringify(translation).c_str()); LayerIntRegion region = aItem.layer->GetShadowVisibleRegion(); region.MoveBy(translation); AL_LOG(" effective-visible=%s\n", Stringify(region).c_str()); region.SubOut(mOccludedRegion); region.AndWith(LayerIntRect::FromUnknownRect(mInvalidBounds)); region.AndWith(LayerIntRect::FromUnknownRect(clip)); if (region.IsEmpty()) { return false; } // Move the visible region back into layer space. region.MoveBy(-translation); AL_LOG(" new-local-visible=%s\n", Stringify(region).c_str()); aItem.layer->SetRenderRegion(std::move(region)); // Apply the new occluded area. We do another dance with the translation to // avoid copying the region. We do this after the SetRegionToRender call to // accomodate the possiblity of a layer changing its visible region. if (aItem.opaque) { mOccludedRegion.MoveBy(-translation); mOccludedRegion.OrWith(aItem.layer->GetRenderRegion()); mOccludedRegion.MoveBy(translation); AL_LOG(" new-occluded=%s\n", Stringify(mOccludedRegion).c_str()); // If the occluded region gets too complicated, we reset it. if (mOccludedRegion.GetNumRects() >= 32) { mOccludedRegion.SetEmpty(); AL_LOG(" clear-occluded, too many rects\n"); } } return true; }
void WebRenderPaintedLayerBlob::RenderLayer(wr::DisplayListBuilder& aBuilder, const StackingContextHelper& aSc) { LayerIntRegion visibleRegion = GetVisibleRegion(); LayerIntRect bounds = visibleRegion.GetBounds(); LayerIntSize size = bounds.Size(); if (visibleRegion.IsEmpty()) { if (gfxPrefs::LayersDump()) { printf_stderr("PaintedLayer %p skipping\n", this->GetLayer()); } return; } nsIntRegion regionToPaint; regionToPaint.Sub(mVisibleRegion.ToUnknownRegion(), mValidRegion); // We have something to paint but can't. This usually happens only in // empty transactions if (!regionToPaint.IsEmpty() && !WrManager()->GetPaintedLayerCallback()) { WrManager()->SetTransactionIncomplete(); return; } IntSize imageSize(size.ToUnknownSize()); if (!regionToPaint.IsEmpty() && WrManager()->GetPaintedLayerCallback()) { RefPtr<gfx::DrawEventRecorderMemory> recorder = MakeAndAddRef<gfx::DrawEventRecorderMemory>(); RefPtr<gfx::DrawTarget> dummyDt = gfx::Factory::CreateDrawTarget(gfx::BackendType::SKIA, imageSize, gfx::SurfaceFormat::B8G8R8X8); RefPtr<gfx::DrawTarget> dt = gfx::Factory::CreateRecordingDrawTarget(recorder, dummyDt); dt->ClearRect(Rect(0, 0, imageSize.width, imageSize.height)); dt->SetTransform(Matrix().PreTranslate(-bounds.x, -bounds.y)); RefPtr<gfxContext> ctx = gfxContext::CreatePreservingTransformOrNull(dt); MOZ_ASSERT(ctx); // already checked the target above WrManager()->GetPaintedLayerCallback()(this, ctx, visibleRegion.ToUnknownRegion(), visibleRegion.ToUnknownRegion(), DrawRegionClip::DRAW, nsIntRegion(), WrManager()->GetPaintedLayerCallbackData()); if (gfxPrefs::WebRenderHighlightPaintedLayers()) { dt->SetTransform(Matrix()); dt->FillRect(Rect(0, 0, imageSize.width, imageSize.height), ColorPattern(Color(1.0, 0.0, 0.0, 0.5))); } wr::ByteBuffer bytes; bytes.Allocate(recorder->RecordingSize()); DebugOnly<bool> ok = recorder->CopyRecording((char*)bytes.AsSlice().begin().get(), bytes.AsSlice().length()); MOZ_ASSERT(ok); //XXX: We should switch to updating the blob image instead of adding a new one // That will get rid of this discard bit if (mImageKey.isSome()) { WrManager()->AddImageKeyForDiscard(mImageKey.value()); } mImageKey = Some(GetImageKey()); WrBridge()->SendAddBlobImage(mImageKey.value(), imageSize, size.width * 4, dt->GetFormat(), bytes); } else { MOZ_ASSERT(GetInvalidRegion().IsEmpty()); } ScrollingLayersHelper scroller(this, aBuilder, aSc); StackingContextHelper sc(aSc, aBuilder, this); LayerRect rect = Bounds(); DumpLayerInfo("PaintedLayer", rect); LayerRect clipRect = ClipRect().valueOr(rect); Maybe<WrImageMask> mask = BuildWrMaskLayer(&sc); WrClipRegionToken clip = aBuilder.PushClipRegion( sc.ToRelativeWrRect(clipRect), mask.ptrOr(nullptr)); aBuilder.PushImage(sc.ToRelativeWrRect(rect), clip, wr::ImageRendering::Auto, mImageKey.value()); }