void ColorLayerComposite::RenderLayer(const nsIntPoint& aOffset, const nsIntRect& aClipRect) { EffectChain effects; gfxRGBA color(GetColor()); effects.mPrimaryEffect = new EffectSolidColor(gfx::Color(color.r, color.g, color.b, color.a)); nsIntRect visibleRect = GetEffectiveVisibleRegion().GetBounds(); LayerManagerComposite::AddMaskEffect(GetMaskLayer(), effects); gfx::Rect rect(visibleRect.x, visibleRect.y, visibleRect.width, visibleRect.height); gfx::Rect clipRect(aClipRect.x, aClipRect.y, aClipRect.width, aClipRect.height); float opacity = GetEffectiveOpacity(); gfx::Matrix4x4 transform; ToMatrix4x4(GetEffectiveTransform(), transform); mCompositor->DrawQuad(rect, clipRect, effects, opacity, transform, gfx::Point(aOffset.x, aOffset.y)); mCompositor->DrawDiagnostics(gfx::Color(0.0, 1.0, 1.0, 1.0), rect, clipRect, transform, gfx::Point(aOffset.x, aOffset.y)); }
void ThebesLayerComposite::RenderLayer(const nsIntPoint& aOffset, const nsIntRect& aClipRect) { if (!mBuffer || !mBuffer->IsAttached()) { return; } MOZ_ASSERT(mBuffer->GetCompositor() == mCompositeManager->GetCompositor() && mBuffer->GetLayer() == this, "buffer is corrupted"); gfx::Matrix4x4 transform; ToMatrix4x4(GetEffectiveTransform(), transform); gfx::Rect clipRect(aClipRect.x, aClipRect.y, aClipRect.width, aClipRect.height); #ifdef MOZ_DUMP_PAINTING if (gfxUtils::sDumpPainting) { nsRefPtr<gfxImageSurface> surf = mBuffer->GetAsSurface(); WriteSnapshotToDumpFile(this, surf); } #endif EffectChain effectChain; LayerManagerComposite::AddMaskEffect(mMaskLayer, effectChain); nsIntRegion visibleRegion = GetEffectiveVisibleRegion(); TiledLayerProperties tiledLayerProps; if (mRequiresTiledProperties) { // calculating these things can be a little expensive, so don't // do them if we don't have to tiledLayerProps.mVisibleRegion = visibleRegion; tiledLayerProps.mDisplayPort = GetDisplayPort(); tiledLayerProps.mEffectiveResolution = GetEffectiveResolution(); tiledLayerProps.mCompositionBounds = GetCompositionBounds(); tiledLayerProps.mRetainTiles = !mIsFixedPosition; tiledLayerProps.mValidRegion = mValidRegion; } mBuffer->SetPaintWillResample(MayResample()); mBuffer->Composite(effectChain, GetEffectiveOpacity(), transform, gfx::Point(aOffset.x, aOffset.y), gfx::FILTER_LINEAR, clipRect, &visibleRegion, mRequiresTiledProperties ? &tiledLayerProps : nullptr); if (mRequiresTiledProperties) { mValidRegion = tiledLayerProps.mValidRegion; } LayerManagerComposite::RemoveMaskEffect(mMaskLayer); mCompositeManager->GetCompositor()->MakeCurrent(); }
void ImageLayerComposite::RenderLayer(const nsIntRect& aClipRect) { if (!mImageHost || !mImageHost->IsAttached()) { return; } #ifdef MOZ_DUMP_PAINTING if (gfxUtils::sDumpPainting) { nsRefPtr<gfxImageSurface> surf = mImageHost->GetAsSurface(); WriteSnapshotToDumpFile(this, surf); } #endif mCompositor->MakeCurrent(); EffectChain effectChain; LayerManagerComposite::AutoAddMaskEffect autoMaskEffect(mMaskLayer, effectChain); gfx::Matrix4x4 transform; ToMatrix4x4(GetEffectiveTransform(), transform); gfx::Rect clipRect(aClipRect.x, aClipRect.y, aClipRect.width, aClipRect.height); mImageHost->SetCompositor(mCompositor); mImageHost->Composite(effectChain, GetEffectiveOpacity(), transform, gfx::ToFilter(mFilter), clipRect); }
void ImageLayerComposite::RenderLayer(const nsIntRect& aClipRect) { if (!mImageHost || !mImageHost->IsAttached()) { return; } #ifdef MOZ_DUMP_PAINTING if (gfxUtils::sDumpPainting) { RefPtr<gfx::DataSourceSurface> dSurf = mImageHost->GetAsSurface(); gfxPlatform *platform = gfxPlatform::GetPlatform(); RefPtr<gfx::DrawTarget> dt = platform->CreateDrawTargetForData(dSurf->GetData(), dSurf->GetSize(), dSurf->Stride(), dSurf->GetFormat()); nsRefPtr<gfxASurface> surf = platform->GetThebesSurfaceForDrawTarget(dt); WriteSnapshotToDumpFile(this, surf); } #endif mCompositor->MakeCurrent(); EffectChain effectChain; LayerManagerComposite::AutoAddMaskEffect autoMaskEffect(mMaskLayer, effectChain); gfx::Matrix4x4 transform; ToMatrix4x4(GetEffectiveTransform(), transform); gfx::Rect clipRect(aClipRect.x, aClipRect.y, aClipRect.width, aClipRect.height); mImageHost->SetCompositor(mCompositor); mImageHost->Composite(effectChain, GetEffectiveOpacity(), transform, gfx::ToFilter(mFilter), clipRect); }
void ColorLayerComposite::RenderLayer(const nsIntRect& aClipRect) { EffectChain effects(this); gfxRGBA color(GetColor()); effects.mPrimaryEffect = new EffectSolidColor(gfx::Color(color.r, color.g, color.b, color.a)); nsIntRect boundRect = GetBounds(); LayerManagerComposite::AutoAddMaskEffect autoMaskEffect(GetMaskLayer(), effects); gfx::Rect rect(boundRect.x, boundRect.y, boundRect.width, boundRect.height); gfx::Rect clipRect(aClipRect.x, aClipRect.y, aClipRect.width, aClipRect.height); float opacity = GetEffectiveOpacity(); const gfx::Matrix4x4& transform = GetEffectiveTransform(); mCompositor->DrawQuad(rect, clipRect, effects, opacity, transform); mCompositor->DrawDiagnostics(DIAGNOSTIC_COLOR, rect, clipRect, transform); }
void ContainerLayer::DefaultComputeSupportsComponentAlphaChildren(bool* aNeedsSurfaceCopy) { bool supportsComponentAlphaChildren = false; bool needsSurfaceCopy = false; CompositionOp blendMode = GetEffectiveMixBlendMode(); if (UseIntermediateSurface()) { if (GetEffectiveVisibleRegion().GetNumRects() == 1 && (GetContentFlags() & Layer::CONTENT_OPAQUE)) { supportsComponentAlphaChildren = true; } else { gfx::Matrix transform; if (HasOpaqueAncestorLayer(this) && GetEffectiveTransform().Is2D(&transform) && !gfx::ThebesMatrix(transform).HasNonIntegerTranslation() && blendMode == gfx::CompositionOp::OP_OVER) { supportsComponentAlphaChildren = true; needsSurfaceCopy = true; } } } else if (blendMode == gfx::CompositionOp::OP_OVER) { supportsComponentAlphaChildren = (GetContentFlags() & Layer::CONTENT_OPAQUE) || (GetParent() && GetParent()->SupportsComponentAlphaChildren()); } mSupportsComponentAlphaChildren = supportsComponentAlphaChildren && gfxPrefs::ComponentAlphaEnabled(); if (aNeedsSurfaceCopy) { *aNeedsSurfaceCopy = mSupportsComponentAlphaChildren && needsSurfaceCopy; } }
bool Layer::MayResample() { Matrix transform2d; return !GetEffectiveTransform().Is2D(&transform2d) || ThebesMatrix(transform2d).HasNonIntegerTranslation() || AncestorLayerMayChangeTransform(this); }
void ThebesLayerComposite::RenderLayer(const nsIntRect& aClipRect) { if (!mBuffer || !mBuffer->IsAttached()) { return; } PROFILER_LABEL("ThebesLayerComposite", "RenderLayer", js::ProfileEntry::Category::GRAPHICS); MOZ_ASSERT(mBuffer->GetCompositor() == mCompositeManager->GetCompositor() && mBuffer->GetLayer() == this, "buffer is corrupted"); gfx::Rect clipRect(aClipRect.x, aClipRect.y, aClipRect.width, aClipRect.height); #ifdef MOZ_DUMP_PAINTING if (gfxUtils::sDumpPainting) { RefPtr<gfx::DataSourceSurface> surf = mBuffer->GetAsSurface(); if (surf) { WriteSnapshotToDumpFile(this, surf); } } #endif EffectChain effectChain(this); LayerManagerComposite::AutoAddMaskEffect autoMaskEffect(mMaskLayer, effectChain); AddBlendModeEffect(effectChain); const nsIntRegion& visibleRegion = GetEffectiveVisibleRegion(); TiledLayerProperties tiledLayerProps; if (mRequiresTiledProperties) { tiledLayerProps.mVisibleRegion = visibleRegion; tiledLayerProps.mEffectiveResolution = GetEffectiveResolution(); tiledLayerProps.mValidRegion = mValidRegion; } mBuffer->SetPaintWillResample(MayResample()); mBuffer->Composite(effectChain, GetEffectiveOpacity(), GetEffectiveTransform(), gfx::Filter::LINEAR, clipRect, &visibleRegion, mRequiresTiledProperties ? &tiledLayerProps : nullptr); mBuffer->BumpFlashCounter(); if (mRequiresTiledProperties) { mValidRegion = tiledLayerProps.mValidRegion; } mCompositeManager->GetCompositor()->MakeCurrent(); }
void PaintedLayerComposite::RenderLayer(const gfx::IntRect& aClipRect) { if (!mBuffer || !mBuffer->IsAttached()) { return; } PROFILER_LABEL("PaintedLayerComposite", "RenderLayer", js::ProfileEntry::Category::GRAPHICS); Compositor* compositor = mCompositeManager->GetCompositor(); MOZ_ASSERT(mBuffer->GetCompositor() == compositor && mBuffer->GetLayer() == this, "buffer is corrupted"); const nsIntRegion& visibleRegion = GetEffectiveVisibleRegion(); #ifdef MOZ_DUMP_PAINTING if (gfxUtils::sDumpPainting) { RefPtr<gfx::DataSourceSurface> surf = mBuffer->GetAsSurface(); if (surf) { WriteSnapshotToDumpFile(this, surf); } } #endif RenderWithAllMasks(this, compositor, aClipRect, [&](EffectChain& effectChain, const Rect& clipRect) { mBuffer->SetPaintWillResample(MayResample()); mBuffer->Composite(this, effectChain, GetEffectiveOpacity(), GetEffectiveTransform(), GetEffectFilter(), clipRect, &visibleRegion); }); mBuffer->BumpFlashCounter(); compositor->MakeCurrent(); }
void ContainerLayerD3D10::Validate() { nsIntRect visibleRect = mVisibleRegion.GetBounds(); mSupportsComponentAlphaChildren = false; if (UseIntermediateSurface()) { const gfx3DMatrix& transform3D = GetEffectiveTransform(); gfxMatrix transform; if (mVisibleRegion.GetNumRects() == 1 && (GetContentFlags() & CONTENT_OPAQUE)) { // don't need a background, we're going to paint all opaque stuff mSupportsComponentAlphaChildren = true; } else { if (HasOpaqueAncestorLayer(this) && transform3D.Is2D(&transform) && !transform.HasNonIntegerTranslation() && GetParent()->GetEffectiveVisibleRegion().GetBounds().Contains(visibleRect)) { // In this case we can copy up the background. See RenderLayer. mSupportsComponentAlphaChildren = true; } } } else { mSupportsComponentAlphaChildren = (GetContentFlags() & CONTENT_OPAQUE) || (mParent && mParent->SupportsComponentAlphaChildren()); } ReadbackProcessor readback; readback.BuildUpdates(this); Layer *layer = GetFirstChild(); while (layer) { if (layer->GetType() == TYPE_THEBES) { static_cast<ThebesLayerD3D10*>(layer)->Validate(&readback); } else { static_cast<LayerD3D10*>(layer->ImplData())->Validate(); } layer = layer->GetNextSibling(); } }
bool BasicContainerLayer::ChildrenPartitionVisibleRegion(const gfx::IntRect& aInRect) { Matrix transform; if (!GetEffectiveTransform().CanDraw2D(&transform) || ThebesMatrix(transform).HasNonIntegerTranslation()) return false; nsIntPoint offset(int32_t(transform._31), int32_t(transform._32)); gfx::IntRect rect = aInRect.Intersect(GetEffectiveVisibleRegion().GetBounds() + offset); nsIntRegion covered; for (Layer* l = mFirstChild; l; l = l->GetNextSibling()) { if (ToData(l)->IsHidden()) continue; Matrix childTransform; if (!l->GetEffectiveTransform().CanDraw2D(&childTransform) || ThebesMatrix(childTransform).HasNonIntegerTranslation() || l->GetEffectiveOpacity() != 1.0) return false; nsIntRegion childRegion = l->GetEffectiveVisibleRegion(); childRegion.MoveBy(int32_t(childTransform._31), int32_t(childTransform._32)); childRegion.And(childRegion, rect); if (l->GetClipRect()) { childRegion.And(childRegion, ParentLayerIntRect::ToUntyped(*l->GetClipRect()) + offset); } nsIntRegion intersection; intersection.And(covered, childRegion); if (!intersection.IsEmpty()) return false; covered.Or(covered, childRegion); } return covered.Contains(rect); }
void ImageLayerComposite::RenderLayer(const nsIntPoint& aOffset, const nsIntRect& aClipRect) { if (!mImageHost) { return; } mCompositor->MakeCurrent(); EffectChain effectChain; LayerManagerComposite::AddMaskEffect(mMaskLayer, effectChain); gfx::Matrix4x4 transform; ToMatrix4x4(GetEffectiveTransform(), transform); gfx::Rect clipRect(aClipRect.x, aClipRect.y, aClipRect.width, aClipRect.height); mImageHost->SetCompositor(mCompositor); mImageHost->Composite(effectChain, GetEffectiveOpacity(), transform, gfx::Point(aOffset.x, aOffset.y), gfx::ToFilter(mFilter), clipRect); }
void ThebesLayerD3D10::Validate(ReadbackProcessor *aReadback) { if (mVisibleRegion.IsEmpty()) { return; } nsIntRect newTextureRect = mVisibleRegion.GetBounds(); SurfaceMode mode = GetSurfaceMode(); if (mode == SURFACE_COMPONENT_ALPHA && (!mParent || !mParent->SupportsComponentAlphaChildren())) { mode = SURFACE_SINGLE_CHANNEL_ALPHA; } // If we have a transform that requires resampling of our texture, then // we need to make sure we don't sample pixels that haven't been drawn. // We clamp sample coordinates to the texture rect, but when the visible region // doesn't fill the entire texture rect we need to make sure we draw all the // pixels in the texture rect anyway in case they get sampled. nsIntRegion neededRegion = mVisibleRegion; if (!neededRegion.GetBounds().IsEqualInterior(newTextureRect) || neededRegion.GetNumRects() > 1) { gfxMatrix transform2d; if (!GetEffectiveTransform().Is2D(&transform2d) || transform2d.HasNonIntegerTranslation()) { neededRegion = newTextureRect; if (mode == SURFACE_OPAQUE) { // We're going to paint outside the visible region, but layout hasn't // promised that it will paint opaquely there, so we'll have to // treat this layer as transparent. mode = SURFACE_SINGLE_CHANNEL_ALPHA; } } } mCurrentSurfaceMode = mode; VerifyContentType(mode); nsTArray<ReadbackProcessor::Update> readbackUpdates; nsIntRegion readbackRegion; if (aReadback && UsedForReadback()) { aReadback->GetThebesLayerUpdates(this, &readbackUpdates, &readbackRegion); } if (mTexture) { if (!mTextureRect.IsEqualInterior(newTextureRect)) { nsRefPtr<ID3D10Texture2D> oldTexture = mTexture; mTexture = nullptr; nsRefPtr<ID3D10Texture2D> oldTextureOnWhite = mTextureOnWhite; mTextureOnWhite = nullptr; nsIntRegion retainRegion = mTextureRect; // Old visible region will become the region that is covered by both the // old and the new visible region. retainRegion.And(retainRegion, mVisibleRegion); // No point in retaining parts which were not valid. retainRegion.And(retainRegion, mValidRegion); CreateNewTextures(gfxIntSize(newTextureRect.width, newTextureRect.height), mode); nsIntRect largeRect = retainRegion.GetLargestRectangle(); // If we had no hardware texture before, or have no retained area larger than // the retention threshold, we're not retaining and are done here. // If our texture creation failed this can mean a device reset is pending // and we should silently ignore the failure. In the future when device // failures are properly handled we should test for the type of failure // and gracefully handle different failures. See bug 569081. if (!oldTexture || !mTexture || largeRect.width * largeRect.height < RETENTION_THRESHOLD) { mValidRegion.SetEmpty(); } else { CopyRegion(oldTexture, mTextureRect.TopLeft(), mTexture, newTextureRect.TopLeft(), retainRegion, &mValidRegion); if (oldTextureOnWhite) { CopyRegion(oldTextureOnWhite, mTextureRect.TopLeft(), mTextureOnWhite, newTextureRect.TopLeft(), retainRegion, &mValidRegion); } } } } mTextureRect = newTextureRect; if (!mTexture || (mode == SURFACE_COMPONENT_ALPHA && !mTextureOnWhite)) { CreateNewTextures(gfxIntSize(newTextureRect.width, newTextureRect.height), mode); mValidRegion.SetEmpty(); } nsIntRegion drawRegion; drawRegion.Sub(neededRegion, mValidRegion); if (!drawRegion.IsEmpty()) { LayerManagerD3D10::CallbackInfo cbInfo = mD3DManager->GetCallbackInfo(); if (!cbInfo.Callback) { NS_ERROR("D3D10 should never need to update ThebesLayers in an empty transaction"); return; } DrawRegion(drawRegion, mode); if (readbackUpdates.Length() > 0) { CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, newTextureRect.width, newTextureRect.height, 1, 1, 0, D3D10_USAGE_STAGING, D3D10_CPU_ACCESS_READ); nsRefPtr<ID3D10Texture2D> readbackTexture; HRESULT hr = device()->CreateTexture2D(&desc, NULL, getter_AddRefs(readbackTexture)); if (FAILED(hr)) { LayerManagerD3D10::ReportFailure(NS_LITERAL_CSTRING("ThebesLayerD3D10::Validate(): Failed to create texture"), hr); return; } device()->CopyResource(readbackTexture, mTexture); for (uint32_t i = 0; i < readbackUpdates.Length(); i++) { mD3DManager->readbackManager()->PostTask(readbackTexture, &readbackUpdates[i], gfxPoint(newTextureRect.x, newTextureRect.y)); } } mValidRegion = neededRegion; } }
void ContainerLayerD3D10::RenderLayer() { float renderTargetOffset[] = { 0, 0 }; nsIntRect visibleRect = mVisibleRegion.GetBounds(); float opacity = GetEffectiveOpacity(); bool useIntermediate = UseIntermediateSurface(); nsRefPtr<ID3D10RenderTargetView> previousRTView; nsRefPtr<ID3D10Texture2D> renderTexture; nsRefPtr<ID3D10RenderTargetView> rtView; float previousRenderTargetOffset[2]; nsIntSize previousViewportSize; gfx3DMatrix oldViewMatrix; if (useIntermediate) { device()->OMGetRenderTargets(1, getter_AddRefs(previousRTView), NULL); D3D10_TEXTURE2D_DESC desc; memset(&desc, 0, sizeof(D3D10_TEXTURE2D_DESC)); desc.ArraySize = 1; desc.MipLevels = 1; desc.Width = visibleRect.width; desc.Height = visibleRect.height; desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE; desc.SampleDesc.Count = 1; desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; HRESULT hr; hr = device()->CreateTexture2D(&desc, NULL, getter_AddRefs(renderTexture)); if (FAILED(hr)) { LayerManagerD3D10::ReportFailure(NS_LITERAL_CSTRING("Failed to create new texture for ContainerLayerD3D10!"), hr); return; } hr = device()->CreateRenderTargetView(renderTexture, NULL, getter_AddRefs(rtView)); NS_ASSERTION(SUCCEEDED(hr), "Failed to create render target view for ContainerLayerD3D10!"); effect()->GetVariableByName("vRenderTargetOffset")-> GetRawValue(previousRenderTargetOffset, 0, 8); previousViewportSize = mD3DManager->GetViewport(); if (mVisibleRegion.GetNumRects() != 1 || !(GetContentFlags() & CONTENT_OPAQUE)) { const gfx3DMatrix& transform3D = GetEffectiveTransform(); gfxMatrix transform; // If we have an opaque ancestor layer, then we can be sure that // all the pixels we draw into are either opaque already or will be // covered by something opaque. Otherwise copying up the background is // not safe. if (mSupportsComponentAlphaChildren) { bool is2d = transform3D.Is2D(&transform); NS_ASSERTION(is2d, "Transform should be 2d when mSupportsComponentAlphaChildren."); // Copy background up from below. This applies any 2D transform that is // applied to use relative to our parent, and compensates for the offset // that was applied on our parent's rendering. D3D10_BOX srcBox; srcBox.left = std::max<int32_t>(visibleRect.x + int32_t(transform.x0) - int32_t(previousRenderTargetOffset[0]), 0); srcBox.top = std::max<int32_t>(visibleRect.y + int32_t(transform.y0) - int32_t(previousRenderTargetOffset[1]), 0); srcBox.right = std::min<int32_t>(srcBox.left + visibleRect.width, previousViewportSize.width); srcBox.bottom = std::min<int32_t>(srcBox.top + visibleRect.height, previousViewportSize.height); srcBox.back = 1; srcBox.front = 0; nsRefPtr<ID3D10Resource> srcResource; previousRTView->GetResource(getter_AddRefs(srcResource)); device()->CopySubresourceRegion(renderTexture, 0, 0, 0, 0, srcResource, 0, &srcBox); } else { float black[] = { 0, 0, 0, 0}; device()->ClearRenderTargetView(rtView, black); } } ID3D10RenderTargetView *rtViewPtr = rtView; device()->OMSetRenderTargets(1, &rtViewPtr, NULL); renderTargetOffset[0] = (float)visibleRect.x; renderTargetOffset[1] = (float)visibleRect.y; effect()->GetVariableByName("vRenderTargetOffset")-> SetRawValue(renderTargetOffset, 0, 8); mD3DManager->SetViewport(nsIntSize(visibleRect.Size())); } D3D10_RECT oldD3D10Scissor; UINT numRects = 1; device()->RSGetScissorRects(&numRects, &oldD3D10Scissor); // Convert scissor to an nsIntRect. D3D10_RECT's are exclusive // on the bottom and right values. nsIntRect oldScissor(oldD3D10Scissor.left, oldD3D10Scissor.top, oldD3D10Scissor.right - oldD3D10Scissor.left, oldD3D10Scissor.bottom - oldD3D10Scissor.top); nsAutoTArray<Layer*, 12> children; SortChildrenBy3DZOrder(children); /* * Render this container's contents. */ for (uint32_t i = 0; i < children.Length(); i++) { LayerD3D10* layerToRender = static_cast<LayerD3D10*>(children.ElementAt(i)->ImplData()); if (layerToRender->GetLayer()->GetEffectiveVisibleRegion().IsEmpty()) { continue; } nsIntRect scissorRect = layerToRender->GetLayer()->CalculateScissorRect(oldScissor, nullptr); if (scissorRect.IsEmpty()) { continue; } D3D10_RECT d3drect; d3drect.left = scissorRect.x; d3drect.top = scissorRect.y; d3drect.right = scissorRect.x + scissorRect.width; d3drect.bottom = scissorRect.y + scissorRect.height; device()->RSSetScissorRects(1, &d3drect); layerToRender->RenderLayer(); } device()->RSSetScissorRects(1, &oldD3D10Scissor); if (useIntermediate) { mD3DManager->SetViewport(previousViewportSize); ID3D10RenderTargetView *rtView = previousRTView; device()->OMSetRenderTargets(1, &rtView, NULL); effect()->GetVariableByName("vRenderTargetOffset")-> SetRawValue(previousRenderTargetOffset, 0, 8); SetEffectTransformAndOpacity(); ID3D10EffectTechnique *technique; if (LoadMaskTexture()) { if (GetTransform().CanDraw2D()) { technique = SelectShader(SHADER_RGBA | SHADER_PREMUL | SHADER_MASK); } else { technique = SelectShader(SHADER_RGBA | SHADER_PREMUL | SHADER_MASK_3D); } } else { technique = SelectShader(SHADER_RGBA | SHADER_PREMUL | SHADER_NO_MASK); } effect()->GetVariableByName("vLayerQuad")->AsVector()->SetFloatVector( ShaderConstantRectD3D10( (float)visibleRect.x, (float)visibleRect.y, (float)visibleRect.width, (float)visibleRect.height) ); technique->GetPassByIndex(0)->Apply(0); ID3D10ShaderResourceView *view; device()->CreateShaderResourceView(renderTexture, NULL, &view); device()->PSSetShaderResources(0, 1, &view); device()->Draw(4, 0); view->Release(); } }
void ContainerLayerD3D9::RenderLayer() { nsRefPtr<IDirect3DSurface9> previousRenderTarget; nsRefPtr<IDirect3DTexture9> renderTexture; float previousRenderTargetOffset[4]; float renderTargetOffset[] = { 0, 0, 0, 0 }; float oldViewMatrix[4][4]; RECT containerD3D9ClipRect; device()->GetScissorRect(&containerD3D9ClipRect); // Convert scissor to an nsIntRect. RECT's are exclusive on the bottom and // right values. nsIntRect oldScissor(containerD3D9ClipRect.left, containerD3D9ClipRect.top, containerD3D9ClipRect.right - containerD3D9ClipRect.left, containerD3D9ClipRect.bottom - containerD3D9ClipRect.top); ReadbackProcessor readback; readback.BuildUpdates(this); nsIntRect visibleRect = GetEffectiveVisibleRegion().GetBounds(); bool useIntermediate = UseIntermediateSurface(); mSupportsComponentAlphaChildren = false; if (useIntermediate) { nsRefPtr<IDirect3DSurface9> renderSurface; if (!mD3DManager->CompositingDisabled()) { device()->GetRenderTarget(0, getter_AddRefs(previousRenderTarget)); HRESULT hr = device()->CreateTexture(visibleRect.width, visibleRect.height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, getter_AddRefs(renderTexture), nullptr); if (FAILED(hr)) { ReportFailure(NS_LITERAL_CSTRING("ContainerLayerD3D9::ContainerRender(): Failed to create texture"), hr); return; } nsRefPtr<IDirect3DSurface9> renderSurface; renderTexture->GetSurfaceLevel(0, getter_AddRefs(renderSurface)); device()->SetRenderTarget(0, renderSurface); } if (mVisibleRegion.GetNumRects() == 1 && (GetContentFlags() & CONTENT_OPAQUE)) { // don't need a background, we're going to paint all opaque stuff mSupportsComponentAlphaChildren = true; } else { Matrix4x4 transform3D = GetEffectiveTransform(); Matrix transform; // If we have an opaque ancestor layer, then we can be sure that // all the pixels we draw into are either opaque already or will be // covered by something opaque. Otherwise copying up the background is // not safe. HRESULT hr = E_FAIL; if (HasOpaqueAncestorLayer(this) && transform3D.Is2D(&transform) && !ThebesMatrix(transform).HasNonIntegerTranslation()) { // Copy background up from below RECT dest = { 0, 0, visibleRect.width, visibleRect.height }; RECT src = dest; ::OffsetRect(&src, visibleRect.x + int32_t(transform._31), visibleRect.y + int32_t(transform._32)); if (!mD3DManager->CompositingDisabled()) { hr = device()-> StretchRect(previousRenderTarget, &src, renderSurface, &dest, D3DTEXF_NONE); } } if (hr == S_OK) { mSupportsComponentAlphaChildren = true; } else if (!mD3DManager->CompositingDisabled()) { device()-> Clear(0, 0, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 0), 0, 0); } } device()-> GetVertexShaderConstantF(CBvRenderTargetOffset, previousRenderTargetOffset, 1); renderTargetOffset[0] = (float)visibleRect.x; renderTargetOffset[1] = (float)visibleRect.y; device()-> SetVertexShaderConstantF(CBvRenderTargetOffset, renderTargetOffset, 1); gfx3DMatrix viewMatrix; /* * Matrix to transform to viewport space ( <-1.0, 1.0> topleft, * <1.0, -1.0> bottomright) */ viewMatrix._11 = 2.0f / visibleRect.width; viewMatrix._22 = -2.0f / visibleRect.height; viewMatrix._41 = -1.0f; viewMatrix._42 = 1.0f; device()-> GetVertexShaderConstantF(CBmProjection, &oldViewMatrix[0][0], 4); device()-> SetVertexShaderConstantF(CBmProjection, &viewMatrix._11, 4); } else { mSupportsComponentAlphaChildren = (GetContentFlags() & CONTENT_OPAQUE) || (mParent && mParent->SupportsComponentAlphaChildren()); } nsAutoTArray<Layer*, 12> children; SortChildrenBy3DZOrder(children); /* * Render this container's contents. */ for (uint32_t i = 0; i < children.Length(); i++) { LayerD3D9* layerToRender = static_cast<LayerD3D9*>(children.ElementAt(i)->ImplData()); if (layerToRender->GetLayer()->GetEffectiveVisibleRegion().IsEmpty()) { continue; } nsIntRect scissorRect = RenderTargetPixel::ToUntyped(layerToRender->GetLayer()->CalculateScissorRect(RenderTargetPixel::FromUntyped(oldScissor), nullptr)); if (scissorRect.IsEmpty()) { continue; } RECT d3drect; d3drect.left = scissorRect.x; d3drect.top = scissorRect.y; d3drect.right = scissorRect.x + scissorRect.width; d3drect.bottom = scissorRect.y + scissorRect.height; device()->SetScissorRect(&d3drect); if (layerToRender->GetLayer()->GetType() == TYPE_THEBES) { static_cast<ThebesLayerD3D9*>(layerToRender)->RenderThebesLayer(&readback); } else { layerToRender->RenderLayer(); } } if (useIntermediate && !mD3DManager->CompositingDisabled()) { device()->SetRenderTarget(0, previousRenderTarget); device()->SetVertexShaderConstantF(CBvRenderTargetOffset, previousRenderTargetOffset, 1); device()->SetVertexShaderConstantF(CBmProjection, &oldViewMatrix[0][0], 4); device()->SetVertexShaderConstantF(CBvLayerQuad, ShaderConstantRect(visibleRect.x, visibleRect.y, visibleRect.width, visibleRect.height), 1); SetShaderTransformAndOpacity(); mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBALAYER, GetMaskLayer(), GetTransform().CanDraw2D()); device()->SetTexture(0, renderTexture); device()->SetScissorRect(&containerD3D9ClipRect); device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); } else { device()->SetScissorRect(&containerD3D9ClipRect); } }
void ContainerLayerD3D9::RenderLayer() { nsRefPtr<IDirect3DSurface9> previousRenderTarget; nsRefPtr<IDirect3DTexture9> renderTexture; float previousRenderTargetOffset[4]; RECT containerClipRect; float renderTargetOffset[] = { 0, 0, 0, 0 }; float oldViewMatrix[4][4]; device()->GetScissorRect(&containerClipRect); ReadbackProcessor readback; readback.BuildUpdates(this); nsIntRect visibleRect = mVisibleRegion.GetBounds(); PRBool useIntermediate = UseIntermediateSurface(); mSupportsComponentAlphaChildren = PR_FALSE; gfxMatrix contTransform; if (useIntermediate) { device()->GetRenderTarget(0, getter_AddRefs(previousRenderTarget)); device()->CreateTexture(visibleRect.width, visibleRect.height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, getter_AddRefs(renderTexture), NULL); nsRefPtr<IDirect3DSurface9> renderSurface; renderTexture->GetSurfaceLevel(0, getter_AddRefs(renderSurface)); device()->SetRenderTarget(0, renderSurface); if (mVisibleRegion.GetNumRects() == 1 && (GetContentFlags() & CONTENT_OPAQUE)) { // don't need a background, we're going to paint all opaque stuff mSupportsComponentAlphaChildren = PR_TRUE; } else { const gfx3DMatrix& transform3D = GetEffectiveTransform(); gfxMatrix transform; // If we have an opaque ancestor layer, then we can be sure that // all the pixels we draw into are either opaque already or will be // covered by something opaque. Otherwise copying up the background is // not safe. HRESULT hr = E_FAIL; if (HasOpaqueAncestorLayer(this) && transform3D.Is2D(&transform) && !transform.HasNonIntegerTranslation()) { // Copy background up from below RECT dest = { 0, 0, visibleRect.width, visibleRect.height }; RECT src = dest; ::OffsetRect(&src, visibleRect.x + PRInt32(transform.x0), visibleRect.y + PRInt32(transform.y0)); hr = device()-> StretchRect(previousRenderTarget, &src, renderSurface, &dest, D3DTEXF_NONE); } if (hr == S_OK) { mSupportsComponentAlphaChildren = PR_TRUE; } else { device()->Clear(0, 0, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 0), 0, 0); } } device()->GetVertexShaderConstantF(CBvRenderTargetOffset, previousRenderTargetOffset, 1); renderTargetOffset[0] = (float)visibleRect.x; renderTargetOffset[1] = (float)visibleRect.y; device()->SetVertexShaderConstantF(CBvRenderTargetOffset, renderTargetOffset, 1); gfx3DMatrix viewMatrix; /* * Matrix to transform to viewport space ( <-1.0, 1.0> topleft, * <1.0, -1.0> bottomright) */ viewMatrix._11 = 2.0f / visibleRect.width; viewMatrix._22 = -2.0f / visibleRect.height; viewMatrix._41 = -1.0f; viewMatrix._42 = 1.0f; device()->GetVertexShaderConstantF(CBmProjection, &oldViewMatrix[0][0], 4); device()->SetVertexShaderConstantF(CBmProjection, &viewMatrix._11, 4); } else { #ifdef DEBUG PRBool is2d = #endif GetEffectiveTransform().Is2D(&contTransform); NS_ASSERTION(is2d, "Transform must be 2D"); mSupportsComponentAlphaChildren = (GetContentFlags() & CONTENT_OPAQUE) || (mParent && mParent->SupportsComponentAlphaChildren()); } /* * Render this container's contents. */ for (LayerD3D9* layerToRender = GetFirstChildD3D9(); layerToRender != nsnull; layerToRender = GetNextSiblingD3D9(layerToRender)) { const nsIntRect* clipRect = layerToRender->GetLayer()->GetClipRect(); if ((clipRect && clipRect->IsEmpty()) || layerToRender->GetLayer()->GetEffectiveVisibleRegion().IsEmpty()) { continue; } if (clipRect || useIntermediate) { RECT r; if (clipRect) { r.left = (LONG)(clipRect->x - renderTargetOffset[0]); r.top = (LONG)(clipRect->y - renderTargetOffset[1]); r.right = (LONG)(clipRect->x - renderTargetOffset[0] + clipRect->width); r.bottom = (LONG)(clipRect->y - renderTargetOffset[1] + clipRect->height); } else { r.left = 0; r.top = 0; r.right = visibleRect.width; r.bottom = visibleRect.height; } nsRefPtr<IDirect3DSurface9> renderSurface; device()->GetRenderTarget(0, getter_AddRefs(renderSurface)); D3DSURFACE_DESC desc; renderSurface->GetDesc(&desc); if (!useIntermediate) { // Transform clip rect if (clipRect) { gfxRect cliprect(r.left, r.top, r.right - r.left, r.bottom - r.top); gfxRect trScissor = contTransform.TransformBounds(cliprect); trScissor.Round(); nsIntRect trIntScissor; if (gfxUtils::GfxRectToIntRect(trScissor, &trIntScissor)) { r.left = trIntScissor.x; r.top = trIntScissor.y; r.right = trIntScissor.XMost(); r.bottom = trIntScissor.YMost(); } else { r.left = 0; r.top = 0; r.right = visibleRect.width; r.bottom = visibleRect.height; clipRect = nsnull; } } // Intersect with current clip rect. r.left = NS_MAX<PRInt32>(containerClipRect.left, r.left); r.right = NS_MIN<PRInt32>(containerClipRect.right, r.right); r.top = NS_MAX<PRInt32>(containerClipRect.top, r.top); r.bottom = NS_MIN<PRInt32>(containerClipRect.bottom, r.bottom); } else { // > 0 is implied during the intersection when useIntermediate == true; r.left = NS_MAX<LONG>(0, r.left); r.top = NS_MAX<LONG>(0, r.top); } r.bottom = NS_MIN<LONG>(r.bottom, desc.Height); r.right = NS_MIN<LONG>(r.right, desc.Width); device()->SetScissorRect(&r); } if (layerToRender->GetLayer()->GetType() == TYPE_THEBES) { static_cast<ThebesLayerD3D9*>(layerToRender)->RenderThebesLayer(&readback); } else { layerToRender->RenderLayer(); } if (clipRect && !useIntermediate) { // In this situation we've set a new scissor rect and we will continue // to render directly to our container. We need to restore its scissor. // Not setting this when useIntermediate is true is an optimization since // we'll get a new one set anyway. device()->SetScissorRect(&containerClipRect); } } if (useIntermediate) { device()->SetRenderTarget(0, previousRenderTarget); device()->SetVertexShaderConstantF(CBvRenderTargetOffset, previousRenderTargetOffset, 1); device()->SetVertexShaderConstantF(CBmProjection, &oldViewMatrix[0][0], 4); device()->SetVertexShaderConstantF(CBvLayerQuad, ShaderConstantRect(visibleRect.x, visibleRect.y, visibleRect.width, visibleRect.height), 1); SetShaderTransformAndOpacity(); mD3DManager->SetShaderMode(DeviceManagerD3D9::RGBALAYER); device()->SetScissorRect(&containerClipRect); device()->SetTexture(0, renderTexture); device()->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); } }
void ClientTiledThebesLayer::BeginPaint() { if (ClientManager()->IsRepeatTransaction()) { return; } mPaintData.mLowPrecisionPaintCount = 0; mPaintData.mPaintFinished = false; // Calculate the transform required to convert screen space into layer space mPaintData.mTransformScreenToLayer = GetEffectiveTransform(); // XXX Not sure if this code for intermediate surfaces is correct. // It rarely gets hit though, and shouldn't have terrible consequences // even if it is wrong. for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) { if (parent->UseIntermediateSurface()) { mPaintData.mTransformScreenToLayer.PreMultiply(parent->GetEffectiveTransform()); } } mPaintData.mTransformScreenToLayer.Invert(); // Compute the critical display port in layer space. mPaintData.mLayerCriticalDisplayPort.SetEmpty(); const gfx::Rect& criticalDisplayPort = GetParent()->GetFrameMetrics().mCriticalDisplayPort; if (!criticalDisplayPort.IsEmpty()) { gfxRect transformedCriticalDisplayPort = mPaintData.mTransformScreenToLayer.TransformBounds( gfxRect(criticalDisplayPort.x, criticalDisplayPort.y, criticalDisplayPort.width, criticalDisplayPort.height)); transformedCriticalDisplayPort.RoundOut(); mPaintData.mLayerCriticalDisplayPort = nsIntRect(transformedCriticalDisplayPort.x, transformedCriticalDisplayPort.y, transformedCriticalDisplayPort.width, transformedCriticalDisplayPort.height); } // Calculate the frame resolution. mPaintData.mResolution.SizeTo(1, 1); for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) { const FrameMetrics& metrics = parent->GetFrameMetrics(); mPaintData.mResolution.width *= metrics.mResolution.width; mPaintData.mResolution.height *= metrics.mResolution.height; } // Calculate the scroll offset since the last transaction, and the // composition bounds. mPaintData.mCompositionBounds.SetEmpty(); mPaintData.mScrollOffset.MoveTo(0, 0); Layer* primaryScrollable = ClientManager()->GetPrimaryScrollableLayer(); if (primaryScrollable) { const FrameMetrics& metrics = primaryScrollable->AsContainerLayer()->GetFrameMetrics(); mPaintData.mScrollOffset = metrics.mScrollOffset; gfxRect transformedViewport = mPaintData.mTransformScreenToLayer.TransformBounds( gfxRect(metrics.mCompositionBounds.x, metrics.mCompositionBounds.y, metrics.mCompositionBounds.width, metrics.mCompositionBounds.height)); transformedViewport.RoundOut(); mPaintData.mCompositionBounds = nsIntRect(transformedViewport.x, transformedViewport.y, transformedViewport.width, transformedViewport.height); } }
void ContainerLayerOGL::RenderLayer(int aPreviousFrameBuffer, const nsIntPoint& aOffset) { /** * Setup our temporary texture for rendering the contents of this container. */ GLuint containerSurface; GLuint frameBuffer; nsIntPoint childOffset(aOffset); nsIntRect visibleRect = GetEffectiveVisibleRegion().GetBounds(); nsIntRect cachedScissor = gl()->ScissorRect(); gl()->PushScissorRect(); mSupportsComponentAlphaChildren = false; float opacity = GetEffectiveOpacity(); const gfx3DMatrix& transform = GetEffectiveTransform(); bool needsFramebuffer = UseIntermediateSurface(); if (needsFramebuffer) { nsIntRect framebufferRect = visibleRect; // we're about to create a framebuffer backed by textures to use as an intermediate // surface. What to do if its size (as given by framebufferRect) would exceed the // maximum texture size supported by the GL? The present code chooses the compromise // of just clamping the framebuffer's size to the max supported size. // This gives us a lower resolution rendering of the intermediate surface (children layers). // See bug 827170 for a discussion. GLint maxTexSize; gl()->fGetIntegerv(LOCAL_GL_MAX_TEXTURE_SIZE, &maxTexSize); framebufferRect.width = std::min(framebufferRect.width, maxTexSize); framebufferRect.height = std::min(framebufferRect.height, maxTexSize); LayerManagerOGL::InitMode mode = LayerManagerOGL::InitModeClear; if (GetEffectiveVisibleRegion().GetNumRects() == 1 && (GetContentFlags() & Layer::CONTENT_OPAQUE)) { // don't need a background, we're going to paint all opaque stuff mSupportsComponentAlphaChildren = true; mode = LayerManagerOGL::InitModeNone; } else { const gfx3DMatrix& transform3D = GetEffectiveTransform(); gfxMatrix transform; // If we have an opaque ancestor layer, then we can be sure that // all the pixels we draw into are either opaque already or will be // covered by something opaque. Otherwise copying up the background is // not safe. if (HasOpaqueAncestorLayer(this) && transform3D.Is2D(&transform) && !transform.HasNonIntegerTranslation()) { mode = gfxPlatform::ComponentAlphaEnabled() ? LayerManagerOGL::InitModeCopy : LayerManagerOGL::InitModeClear; framebufferRect.x += transform.x0; framebufferRect.y += transform.y0; mSupportsComponentAlphaChildren = gfxPlatform::ComponentAlphaEnabled(); } } gl()->PushViewportRect(); framebufferRect -= childOffset; if (!mOGLManager->CompositingDisabled()) { if (!mOGLManager->CreateFBOWithTexture(framebufferRect, mode, aPreviousFrameBuffer, &frameBuffer, &containerSurface)) { gl()->PopViewportRect(); gl()->PopScissorRect(); gl()->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, aPreviousFrameBuffer); return; } } childOffset.x = visibleRect.x; childOffset.y = visibleRect.y; } else { frameBuffer = aPreviousFrameBuffer; mSupportsComponentAlphaChildren = (GetContentFlags() & Layer::CONTENT_OPAQUE) || (GetParent() && GetParent()->SupportsComponentAlphaChildren()); } nsAutoTArray<Layer*, 12> children; SortChildrenBy3DZOrder(children); /** * Render this container's contents. */ for (uint32_t i = 0; i < children.Length(); i++) { LayerOGL* layerToRender = static_cast<LayerOGL*>(children.ElementAt(i)->ImplData()); if (layerToRender->GetLayer()->GetEffectiveVisibleRegion().IsEmpty()) { continue; } nsIntRect scissorRect = layerToRender->GetLayer()-> CalculateScissorRect(cachedScissor, &mOGLManager->GetWorldTransform()); if (scissorRect.IsEmpty()) { continue; } gl()->fScissor(scissorRect.x, scissorRect.y, scissorRect.width, scissorRect.height); layerToRender->RenderLayer(frameBuffer, childOffset); gl()->MakeCurrent(); } if (needsFramebuffer) { // Unbind the current framebuffer and rebind the previous one. #ifdef MOZ_DUMP_PAINTING if (gfxUtils::sDumpPainting) { nsRefPtr<gfxImageSurface> surf = gl()->GetTexImage(containerSurface, true, mOGLManager->GetFBOTextureFormat()); WriteSnapshotToDumpFile(this, surf); } #endif // Restore the viewport gl()->PopViewportRect(); nsIntRect viewport = gl()->ViewportRect(); mOGLManager->SetupPipeline(viewport.width, viewport.height, LayerManagerOGL::ApplyWorldTransform); gl()->PopScissorRect(); if (!mOGLManager->CompositingDisabled()) { gl()->fBindFramebuffer(LOCAL_GL_FRAMEBUFFER, aPreviousFrameBuffer); gl()->fDeleteFramebuffers(1, &frameBuffer); gl()->fActiveTexture(LOCAL_GL_TEXTURE0); gl()->fBindTexture(mOGLManager->FBOTextureTarget(), containerSurface); MaskType maskType = MaskNone; if (GetMaskLayer()) { if (!GetTransform().CanDraw2D()) { maskType = Mask3d; } else { maskType = Mask2d; } } ShaderProgramOGL *rgb = mOGLManager->GetFBOLayerProgram(maskType); rgb->Activate(); rgb->SetLayerQuadRect(visibleRect); rgb->SetLayerTransform(transform); rgb->SetTextureTransform(gfx3DMatrix()); rgb->SetLayerOpacity(opacity); rgb->SetRenderOffset(aOffset); rgb->SetTextureUnit(0); rgb->LoadMask(GetMaskLayer()); if (rgb->GetTexCoordMultiplierUniformLocation() != -1) { // 2DRect case, get the multiplier right for a sampler2DRect rgb->SetTexCoordMultiplier(visibleRect.width, visibleRect.height); } // Drawing is always flipped, but when copying between surfaces we want to avoid // this. Pass true for the flip parameter to introduce a second flip // that cancels the other one out. mOGLManager->BindAndDrawQuad(rgb, true); // Clean up resources. This also unbinds the texture. gl()->fDeleteTextures(1, &containerSurface); } } else { gl()->PopScissorRect(); } }
void ClientTiledThebesLayer::BeginPaint() { if (ClientManager()->IsRepeatTransaction()) { return; } mPaintData.mLowPrecisionPaintCount = 0; mPaintData.mPaintFinished = false; // Get the metrics of the nearest scroll container. ContainerLayer* scrollParent = nullptr; for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) { const FrameMetrics& metrics = parent->GetFrameMetrics(); if (metrics.mScrollId != FrameMetrics::NULL_SCROLL_ID) { scrollParent = parent; break; } } if (!scrollParent) { // XXX I don't think this can happen, but if it does, warn and set the // composition bounds to empty so that progressive updates are disabled. NS_WARNING("Tiled Thebes layer with no scrollable container parent"); mPaintData.mCompositionBounds.SetEmpty(); return; } const FrameMetrics& metrics = scrollParent->GetFrameMetrics(); // Calculate the transform required to convert screen space into transformed // layout device space. gfx::Matrix4x4 effectiveTransform = GetEffectiveTransform(); for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) { if (parent->UseIntermediateSurface()) { effectiveTransform = effectiveTransform * parent->GetEffectiveTransform(); } } gfx3DMatrix layoutToScreen; gfx::To3DMatrix(effectiveTransform, layoutToScreen); layoutToScreen.ScalePost(metrics.mCumulativeResolution.scale, metrics.mCumulativeResolution.scale, 1.f); mPaintData.mTransformScreenToLayout = layoutToScreen.Inverse(); // Compute the critical display port in layer space. mPaintData.mLayoutCriticalDisplayPort.SetEmpty(); if (!metrics.mCriticalDisplayPort.IsEmpty()) { // Convert the display port to screen space first so that we can transform // it into layout device space. const ScreenRect& criticalDisplayPort = metrics.mCriticalDisplayPort * metrics.mZoom; LayoutDeviceRect transformedCriticalDisplayPort = ApplyScreenToLayoutTransform(mPaintData.mTransformScreenToLayout, criticalDisplayPort); mPaintData.mLayoutCriticalDisplayPort = LayoutDeviceIntRect::ToUntyped(RoundedOut(transformedCriticalDisplayPort)); } // Calculate the frame resolution. Because this is Gecko-side, before any // async transforms have occurred, we can use mZoom for this. mPaintData.mResolution = metrics.mZoom; // Calculate the scroll offset since the last transaction, and the // composition bounds. mPaintData.mCompositionBounds.SetEmpty(); mPaintData.mScrollOffset.MoveTo(0, 0); Layer* primaryScrollable = ClientManager()->GetPrimaryScrollableLayer(); if (primaryScrollable) { const FrameMetrics& metrics = primaryScrollable->AsContainerLayer()->GetFrameMetrics(); mPaintData.mScrollOffset = metrics.mScrollOffset * metrics.mZoom; mPaintData.mCompositionBounds = ApplyScreenToLayoutTransform(mPaintData.mTransformScreenToLayout, ScreenRect(metrics.mCompositionBounds)); } }