michael@0: /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "ImageLayerComposite.h" michael@0: #include "CompositableHost.h" // for CompositableHost michael@0: #include "Layers.h" // for WriteSnapshotToDumpFile, etc michael@0: #include "gfx2DGlue.h" // for ToFilter, ToMatrix4x4 michael@0: #include "gfxRect.h" // for gfxRect michael@0: #include "gfxUtils.h" // for gfxUtils, etc michael@0: #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc michael@0: #include "mozilla/gfx/Matrix.h" // for Matrix4x4 michael@0: #include "mozilla/gfx/Point.h" // for IntSize, Point michael@0: #include "mozilla/gfx/Rect.h" // for Rect michael@0: #include "mozilla/layers/Compositor.h" // for Compositor michael@0: #include "mozilla/layers/Effects.h" // for EffectChain michael@0: #include "mozilla/layers/TextureHost.h" // for TextureHost, etc michael@0: #include "mozilla/mozalloc.h" // for operator delete michael@0: #include "nsAString.h" michael@0: #include "nsAutoPtr.h" // for nsRefPtr michael@0: #include "nsDebug.h" // for NS_ASSERTION michael@0: #include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc michael@0: #include "nsPoint.h" // for nsIntPoint michael@0: #include "nsRect.h" // for nsIntRect michael@0: #include "nsString.h" // for nsAutoCString michael@0: michael@0: using namespace mozilla::gfx; michael@0: michael@0: namespace mozilla { michael@0: namespace layers { michael@0: michael@0: ImageLayerComposite::ImageLayerComposite(LayerManagerComposite* aManager) michael@0: : ImageLayer(aManager, nullptr) michael@0: , LayerComposite(aManager) michael@0: , mImageHost(nullptr) michael@0: { michael@0: MOZ_COUNT_CTOR(ImageLayerComposite); michael@0: mImplData = static_cast(this); michael@0: } michael@0: michael@0: ImageLayerComposite::~ImageLayerComposite() michael@0: { michael@0: MOZ_COUNT_DTOR(ImageLayerComposite); michael@0: MOZ_ASSERT(mDestroyed); michael@0: michael@0: CleanupResources(); michael@0: } michael@0: michael@0: bool michael@0: ImageLayerComposite::SetCompositableHost(CompositableHost* aHost) michael@0: { michael@0: switch (aHost->GetType()) { michael@0: case BUFFER_IMAGE_SINGLE: michael@0: case BUFFER_IMAGE_BUFFERED: michael@0: case COMPOSITABLE_IMAGE: michael@0: mImageHost = aHost; michael@0: return true; michael@0: default: michael@0: return false; michael@0: } michael@0: } michael@0: michael@0: void michael@0: ImageLayerComposite::Disconnect() michael@0: { michael@0: Destroy(); michael@0: } michael@0: michael@0: LayerRenderState michael@0: ImageLayerComposite::GetRenderState() michael@0: { michael@0: if (mImageHost && mImageHost->IsAttached()) { michael@0: return mImageHost->GetRenderState(); michael@0: } michael@0: return LayerRenderState(); michael@0: } michael@0: michael@0: Layer* michael@0: ImageLayerComposite::GetLayer() michael@0: { michael@0: return this; michael@0: } michael@0: michael@0: void michael@0: ImageLayerComposite::RenderLayer(const nsIntRect& aClipRect) michael@0: { michael@0: if (!mImageHost || !mImageHost->IsAttached()) { michael@0: return; michael@0: } michael@0: michael@0: #ifdef MOZ_DUMP_PAINTING michael@0: if (gfxUtils::sDumpPainting) { michael@0: RefPtr surf = mImageHost->GetAsSurface(); michael@0: WriteSnapshotToDumpFile(this, surf); michael@0: } michael@0: #endif michael@0: michael@0: mCompositor->MakeCurrent(); michael@0: michael@0: EffectChain effectChain(this); michael@0: LayerManagerComposite::AutoAddMaskEffect autoMaskEffect(mMaskLayer, effectChain); michael@0: michael@0: gfx::Rect clipRect(aClipRect.x, aClipRect.y, aClipRect.width, aClipRect.height); michael@0: mImageHost->SetCompositor(mCompositor); michael@0: mImageHost->Composite(effectChain, michael@0: GetEffectiveOpacity(), michael@0: GetEffectiveTransform(), michael@0: gfx::ToFilter(mFilter), michael@0: clipRect); michael@0: mImageHost->BumpFlashCounter(); michael@0: } michael@0: michael@0: void michael@0: ImageLayerComposite::ComputeEffectiveTransforms(const gfx::Matrix4x4& aTransformToSurface) michael@0: { michael@0: gfx::Matrix4x4 local = GetLocalTransform(); michael@0: michael@0: // Snap image edges to pixel boundaries michael@0: gfxRect sourceRect(0, 0, 0, 0); michael@0: if (mImageHost && michael@0: mImageHost->IsAttached() && michael@0: mImageHost->GetAsTextureHost()) { michael@0: IntSize size = mImageHost->GetAsTextureHost()->GetSize(); michael@0: sourceRect.SizeTo(size.width, size.height); michael@0: if (mScaleMode != ScaleMode::SCALE_NONE && michael@0: sourceRect.width != 0.0 && sourceRect.height != 0.0) { michael@0: NS_ASSERTION(mScaleMode == ScaleMode::STRETCH, michael@0: "No other scalemodes than stretch and none supported yet."); michael@0: local.Scale(mScaleToSize.width / sourceRect.width, michael@0: mScaleToSize.height / sourceRect.height, 1.0); michael@0: } michael@0: } michael@0: // Snap our local transform first, and snap the inherited transform as well. michael@0: // This makes our snapping equivalent to what would happen if our content michael@0: // was drawn into a ThebesLayer (gfxContext would snap using the local michael@0: // transform, then we'd snap again when compositing the ThebesLayer). michael@0: mEffectiveTransform = michael@0: SnapTransform(local, sourceRect, nullptr) * michael@0: SnapTransformTranslation(aTransformToSurface, nullptr); michael@0: ComputeEffectiveTransformForMaskLayer(aTransformToSurface); michael@0: } michael@0: michael@0: CompositableHost* michael@0: ImageLayerComposite::GetCompositableHost() michael@0: { michael@0: if (mImageHost && mImageHost->IsAttached()) { michael@0: return mImageHost.get(); michael@0: } michael@0: michael@0: return nullptr; michael@0: } michael@0: michael@0: void michael@0: ImageLayerComposite::CleanupResources() michael@0: { michael@0: if (mImageHost) { michael@0: mImageHost->Detach(this); michael@0: } michael@0: mImageHost = nullptr; michael@0: } michael@0: michael@0: nsACString& michael@0: ImageLayerComposite::PrintInfo(nsACString& aTo, const char* aPrefix) michael@0: { michael@0: ImageLayer::PrintInfo(aTo, aPrefix); michael@0: aTo += "\n"; michael@0: if (mImageHost && mImageHost->IsAttached()) { michael@0: nsAutoCString pfx(aPrefix); michael@0: pfx += " "; michael@0: mImageHost->PrintInfo(aTo, pfx.get()); michael@0: } michael@0: return aTo; michael@0: } michael@0: michael@0: } /* layers */ michael@0: } /* mozilla */