gfx/layers/composite/TiledContentHost.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/layers/composite/TiledContentHost.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,518 @@
     1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#include "TiledContentHost.h"
    1.10 +#include "ThebesLayerComposite.h"       // for ThebesLayerComposite
    1.11 +#include "mozilla/gfx/BaseSize.h"       // for BaseSize
    1.12 +#include "mozilla/gfx/Matrix.h"         // for Matrix4x4
    1.13 +#include "mozilla/layers/Compositor.h"  // for Compositor
    1.14 +#include "mozilla/layers/Effects.h"     // for TexturedEffect, Effect, etc
    1.15 +#include "mozilla/layers/TextureHostOGL.h"  // for TextureHostOGL
    1.16 +#include "nsAString.h"
    1.17 +#include "nsDebug.h"                    // for NS_WARNING
    1.18 +#include "nsPoint.h"                    // for nsIntPoint
    1.19 +#include "nsPrintfCString.h"            // for nsPrintfCString
    1.20 +#include "nsRect.h"                     // for nsIntRect
    1.21 +#include "nsSize.h"                     // for nsIntSize
    1.22 +#include "mozilla/layers/TiledContentClient.h"
    1.23 +
    1.24 +class gfxReusableSurfaceWrapper;
    1.25 +
    1.26 +namespace mozilla {
    1.27 +using namespace gfx;
    1.28 +namespace layers {
    1.29 +
    1.30 +class Layer;
    1.31 +
    1.32 +TiledLayerBufferComposite::TiledLayerBufferComposite()
    1.33 +  : mFrameResolution(1.0)
    1.34 +  , mHasDoubleBufferedTiles(false)
    1.35 +  , mUninitialized(true)
    1.36 +{}
    1.37 +
    1.38 +/* static */ void
    1.39 +TiledLayerBufferComposite::RecycleCallback(TextureHost* textureHost, void* aClosure)
    1.40 +{
    1.41 +  textureHost->CompositorRecycle();
    1.42 +}
    1.43 +
    1.44 +TiledLayerBufferComposite::TiledLayerBufferComposite(ISurfaceAllocator* aAllocator,
    1.45 +                                                     const SurfaceDescriptorTiles& aDescriptor,
    1.46 +                                                     const nsIntRegion& aOldPaintedRegion)
    1.47 +{
    1.48 +  mUninitialized = false;
    1.49 +  mHasDoubleBufferedTiles = false;
    1.50 +  mValidRegion = aDescriptor.validRegion();
    1.51 +  mPaintedRegion = aDescriptor.paintedRegion();
    1.52 +  mRetainedWidth = aDescriptor.retainedWidth();
    1.53 +  mRetainedHeight = aDescriptor.retainedHeight();
    1.54 +  mResolution = aDescriptor.resolution();
    1.55 +  mFrameResolution = CSSToParentLayerScale(aDescriptor.frameResolution());
    1.56 +
    1.57 +  // Combine any valid content that wasn't already uploaded
    1.58 +  nsIntRegion oldPaintedRegion(aOldPaintedRegion);
    1.59 +  oldPaintedRegion.And(oldPaintedRegion, mValidRegion);
    1.60 +  mPaintedRegion.Or(mPaintedRegion, oldPaintedRegion);
    1.61 +
    1.62 +  const InfallibleTArray<TileDescriptor>& tiles = aDescriptor.tiles();
    1.63 +  for(size_t i = 0; i < tiles.Length(); i++) {
    1.64 +    RefPtr<TextureHost> texture;
    1.65 +    const TileDescriptor& tileDesc = tiles[i];
    1.66 +    switch (tileDesc.type()) {
    1.67 +      case TileDescriptor::TTexturedTileDescriptor : {
    1.68 +        texture = TextureHost::AsTextureHost(tileDesc.get_TexturedTileDescriptor().textureParent());
    1.69 +#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
    1.70 +        if (!gfxPrefs::LayersUseSimpleTiles()) {
    1.71 +          texture->SetRecycleCallback(RecycleCallback, nullptr);
    1.72 +        }
    1.73 +#endif
    1.74 +        const TileLock& ipcLock = tileDesc.get_TexturedTileDescriptor().sharedLock();
    1.75 +        nsRefPtr<gfxSharedReadLock> sharedLock;
    1.76 +        if (ipcLock.type() == TileLock::TShmemSection) {
    1.77 +          sharedLock = gfxShmSharedReadLock::Open(aAllocator, ipcLock.get_ShmemSection());
    1.78 +        } else {
    1.79 +          sharedLock = reinterpret_cast<gfxMemorySharedReadLock*>(ipcLock.get_uintptr_t());
    1.80 +          if (sharedLock) {
    1.81 +            // The corresponding AddRef is in TiledClient::GetTileDescriptor
    1.82 +            sharedLock->Release();
    1.83 +          }
    1.84 +        }
    1.85 +
    1.86 +        mRetainedTiles.AppendElement(TileHost(sharedLock, texture));
    1.87 +        break;
    1.88 +      }
    1.89 +      default:
    1.90 +        NS_WARNING("Unrecognised tile descriptor type");
    1.91 +        // Fall through
    1.92 +      case TileDescriptor::TPlaceholderTileDescriptor :
    1.93 +        mRetainedTiles.AppendElement(GetPlaceholderTile());
    1.94 +        break;
    1.95 +    }
    1.96 +    if (texture && !texture->HasInternalBuffer()) {
    1.97 +      mHasDoubleBufferedTiles = true;
    1.98 +    }
    1.99 +  }
   1.100 +}
   1.101 +
   1.102 +void
   1.103 +TiledLayerBufferComposite::ReadUnlock()
   1.104 +{
   1.105 +  if (!IsValid()) {
   1.106 +    return;
   1.107 +  }
   1.108 +  for (size_t i = 0; i < mRetainedTiles.Length(); i++) {
   1.109 +    mRetainedTiles[i].ReadUnlock();
   1.110 +  }
   1.111 +}
   1.112 +
   1.113 +void
   1.114 +TiledLayerBufferComposite::ReleaseTextureHosts()
   1.115 +{
   1.116 +  if (!IsValid()) {
   1.117 +    return;
   1.118 +  }
   1.119 +  for (size_t i = 0; i < mRetainedTiles.Length(); i++) {
   1.120 +    mRetainedTiles[i].mTextureHost = nullptr;
   1.121 +  }
   1.122 +}
   1.123 +
   1.124 +void
   1.125 +TiledLayerBufferComposite::Upload()
   1.126 +{
   1.127 +  if(!IsValid()) {
   1.128 +    return;
   1.129 +  }
   1.130 +  // The TextureClients were created with the TEXTURE_IMMEDIATE_UPLOAD flag,
   1.131 +  // so calling Update on all the texture hosts will perform the texture upload.
   1.132 +  Update(mValidRegion, mPaintedRegion);
   1.133 +  ClearPaintedRegion();
   1.134 +}
   1.135 +
   1.136 +TileHost
   1.137 +TiledLayerBufferComposite::ValidateTile(TileHost aTile,
   1.138 +                                        const nsIntPoint& aTileOrigin,
   1.139 +                                        const nsIntRegion& aDirtyRect)
   1.140 +{
   1.141 +  if (aTile.IsPlaceholderTile()) {
   1.142 +    NS_WARNING("Placeholder tile encountered in painted region");
   1.143 +    return aTile;
   1.144 +  }
   1.145 +
   1.146 +#ifdef GFX_TILEDLAYER_PREF_WARNINGS
   1.147 +  printf_stderr("Upload tile %i, %i\n", aTileOrigin.x, aTileOrigin.y);
   1.148 +  long start = PR_IntervalNow();
   1.149 +#endif
   1.150 +
   1.151 +  MOZ_ASSERT(aTile.mTextureHost->GetFlags() & TEXTURE_IMMEDIATE_UPLOAD);
   1.152 +  // We possibly upload the entire texture contents here. This is a purposeful
   1.153 +  // decision, as sub-image upload can often be slow and/or unreliable, but
   1.154 +  // we may want to reevaluate this in the future.
   1.155 +  // For !HasInternalBuffer() textures, this is likely a no-op.
   1.156 +  aTile.mTextureHost->Updated(nullptr);
   1.157 +
   1.158 +#ifdef GFX_TILEDLAYER_PREF_WARNINGS
   1.159 +  if (PR_IntervalNow() - start > 1) {
   1.160 +    printf_stderr("Tile Time to upload %i\n", PR_IntervalNow() - start);
   1.161 +  }
   1.162 +#endif
   1.163 +  return aTile;
   1.164 +}
   1.165 +
   1.166 +void
   1.167 +TiledLayerBufferComposite::SetCompositor(Compositor* aCompositor)
   1.168 +{
   1.169 +  if (!IsValid()) {
   1.170 +    return;
   1.171 +  }
   1.172 +  for (size_t i = 0; i < mRetainedTiles.Length(); i++) {
   1.173 +    if (mRetainedTiles[i].IsPlaceholderTile()) continue;
   1.174 +    mRetainedTiles[i].mTextureHost->SetCompositor(aCompositor);
   1.175 +  }
   1.176 +}
   1.177 +
   1.178 +#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
   1.179 +void
   1.180 +TiledLayerBufferComposite::SetReleaseFence(const android::sp<android::Fence>& aReleaseFence)
   1.181 +{
   1.182 +  for (size_t i = 0; i < mRetainedTiles.Length(); i++) {
   1.183 +    if (!mRetainedTiles[i].mTextureHost) {
   1.184 +      continue;
   1.185 +    }
   1.186 +    TextureHostOGL* texture = mRetainedTiles[i].mTextureHost->AsHostOGL();
   1.187 +    if (!texture) {
   1.188 +      continue;
   1.189 +    }
   1.190 +    texture->SetReleaseFence(new android::Fence(aReleaseFence->dup()));
   1.191 +  }
   1.192 +}
   1.193 +#endif
   1.194 +
   1.195 +TiledContentHost::TiledContentHost(const TextureInfo& aTextureInfo)
   1.196 +  : ContentHost(aTextureInfo)
   1.197 +  , mTiledBuffer(TiledLayerBufferComposite())
   1.198 +  , mLowPrecisionTiledBuffer(TiledLayerBufferComposite())
   1.199 +  , mOldTiledBuffer(TiledLayerBufferComposite())
   1.200 +  , mOldLowPrecisionTiledBuffer(TiledLayerBufferComposite())
   1.201 +  , mPendingUpload(false)
   1.202 +  , mPendingLowPrecisionUpload(false)
   1.203 +{
   1.204 +  MOZ_COUNT_CTOR(TiledContentHost);
   1.205 +}
   1.206 +
   1.207 +TiledContentHost::~TiledContentHost()
   1.208 +{
   1.209 +  MOZ_COUNT_DTOR(TiledContentHost);
   1.210 +
   1.211 +  // Unlock any buffers that may still be locked. If we have a pending upload,
   1.212 +  // we will need to unlock the buffer that was about to be uploaded.
   1.213 +  // If a buffer that was being composited had double-buffered tiles, we will
   1.214 +  // need to unlock that buffer too.
   1.215 +  if (mPendingUpload) {
   1.216 +    mTiledBuffer.ReadUnlock();
   1.217 +    if (mOldTiledBuffer.HasDoubleBufferedTiles()) {
   1.218 +      mOldTiledBuffer.ReadUnlock();
   1.219 +    }
   1.220 +  } else if (mTiledBuffer.HasDoubleBufferedTiles()) {
   1.221 +    mTiledBuffer.ReadUnlock();
   1.222 +  }
   1.223 +
   1.224 +  if (mPendingLowPrecisionUpload) {
   1.225 +    mLowPrecisionTiledBuffer.ReadUnlock();
   1.226 +    if (mOldLowPrecisionTiledBuffer.HasDoubleBufferedTiles()) {
   1.227 +      mOldLowPrecisionTiledBuffer.ReadUnlock();
   1.228 +    }
   1.229 +  } else if (mLowPrecisionTiledBuffer.HasDoubleBufferedTiles()) {
   1.230 +    mLowPrecisionTiledBuffer.ReadUnlock();
   1.231 +  }
   1.232 +}
   1.233 +
   1.234 +void
   1.235 +TiledContentHost::Attach(Layer* aLayer,
   1.236 +                         Compositor* aCompositor,
   1.237 +                         AttachFlags aFlags /* = NO_FLAGS */)
   1.238 +{
   1.239 +  CompositableHost::Attach(aLayer, aCompositor, aFlags);
   1.240 +  static_cast<ThebesLayerComposite*>(aLayer)->EnsureTiled();
   1.241 +}
   1.242 +
   1.243 +void
   1.244 +TiledContentHost::UseTiledLayerBuffer(ISurfaceAllocator* aAllocator,
   1.245 +                                      const SurfaceDescriptorTiles& aTiledDescriptor)
   1.246 +{
   1.247 +  if (aTiledDescriptor.resolution() < 1) {
   1.248 +    if (mPendingLowPrecisionUpload) {
   1.249 +      mLowPrecisionTiledBuffer.ReadUnlock();
   1.250 +    } else {
   1.251 +      mPendingLowPrecisionUpload = true;
   1.252 +      // If the old buffer has double-buffered tiles, hang onto it so we can
   1.253 +      // unlock it after we've composited the new buffer.
   1.254 +      // We only need to hang onto the locks, but not the textures.
   1.255 +      // Releasing the textures here can help prevent a memory spike in the
   1.256 +      // situation that the client starts rendering new content before we get
   1.257 +      // to composite the new buffer.
   1.258 +      if (mLowPrecisionTiledBuffer.HasDoubleBufferedTiles()) {
   1.259 +        mOldLowPrecisionTiledBuffer = mLowPrecisionTiledBuffer;
   1.260 +        mOldLowPrecisionTiledBuffer.ReleaseTextureHosts();
   1.261 +      }
   1.262 +    }
   1.263 +    mLowPrecisionTiledBuffer =
   1.264 +      TiledLayerBufferComposite(aAllocator, aTiledDescriptor,
   1.265 +                                mLowPrecisionTiledBuffer.GetPaintedRegion());
   1.266 +  } else {
   1.267 +    if (mPendingUpload) {
   1.268 +      mTiledBuffer.ReadUnlock();
   1.269 +    } else {
   1.270 +      mPendingUpload = true;
   1.271 +      if (mTiledBuffer.HasDoubleBufferedTiles()) {
   1.272 +        mOldTiledBuffer = mTiledBuffer;
   1.273 +        mOldTiledBuffer.ReleaseTextureHosts();
   1.274 +      }
   1.275 +    }
   1.276 +    mTiledBuffer = TiledLayerBufferComposite(aAllocator, aTiledDescriptor,
   1.277 +                                             mTiledBuffer.GetPaintedRegion());
   1.278 +  }
   1.279 +}
   1.280 +
   1.281 +void
   1.282 +TiledContentHost::Composite(EffectChain& aEffectChain,
   1.283 +                            float aOpacity,
   1.284 +                            const gfx::Matrix4x4& aTransform,
   1.285 +                            const gfx::Filter& aFilter,
   1.286 +                            const gfx::Rect& aClipRect,
   1.287 +                            const nsIntRegion* aVisibleRegion /* = nullptr */,
   1.288 +                            TiledLayerProperties* aLayerProperties /* = nullptr */)
   1.289 +{
   1.290 +  MOZ_ASSERT(aLayerProperties, "aLayerProperties required for TiledContentHost");
   1.291 +
   1.292 +  if (mPendingUpload) {
   1.293 +    mTiledBuffer.SetCompositor(mCompositor);
   1.294 +    mTiledBuffer.Upload();
   1.295 +
   1.296 +    // For a single-buffered tiled buffer, Upload will upload the shared memory
   1.297 +    // surface to texture memory and we no longer need to read from them.
   1.298 +    if (!mTiledBuffer.HasDoubleBufferedTiles()) {
   1.299 +      mTiledBuffer.ReadUnlock();
   1.300 +    }
   1.301 +  }
   1.302 +  if (mPendingLowPrecisionUpload) {
   1.303 +    mLowPrecisionTiledBuffer.SetCompositor(mCompositor);
   1.304 +    mLowPrecisionTiledBuffer.Upload();
   1.305 +
   1.306 +    if (!mLowPrecisionTiledBuffer.HasDoubleBufferedTiles()) {
   1.307 +      mLowPrecisionTiledBuffer.ReadUnlock();
   1.308 +    }
   1.309 +  }
   1.310 +
   1.311 +  RenderLayerBuffer(mLowPrecisionTiledBuffer, aEffectChain, aOpacity, aFilter,
   1.312 +                    aClipRect, aLayerProperties->mVisibleRegion, aTransform);
   1.313 +  RenderLayerBuffer(mTiledBuffer, aEffectChain, aOpacity, aFilter,
   1.314 +                    aClipRect, aLayerProperties->mVisibleRegion, aTransform);
   1.315 +
   1.316 +  // Now release the old buffer if it had double-buffered tiles, as we can
   1.317 +  // guarantee that they're no longer on the screen (and so any locks that may
   1.318 +  // have been held have been released).
   1.319 +  if (mPendingUpload && mOldTiledBuffer.HasDoubleBufferedTiles()) {
   1.320 +    mOldTiledBuffer.ReadUnlock();
   1.321 +    mOldTiledBuffer = TiledLayerBufferComposite();
   1.322 +  }
   1.323 +  if (mPendingLowPrecisionUpload && mOldLowPrecisionTiledBuffer.HasDoubleBufferedTiles()) {
   1.324 +    mOldLowPrecisionTiledBuffer.ReadUnlock();
   1.325 +    mOldLowPrecisionTiledBuffer = TiledLayerBufferComposite();
   1.326 +  }
   1.327 +  mPendingUpload = mPendingLowPrecisionUpload = false;
   1.328 +}
   1.329 +
   1.330 +
   1.331 +void
   1.332 +TiledContentHost::RenderTile(const TileHost& aTile,
   1.333 +                             EffectChain& aEffectChain,
   1.334 +                             float aOpacity,
   1.335 +                             const gfx::Matrix4x4& aTransform,
   1.336 +                             const gfx::Filter& aFilter,
   1.337 +                             const gfx::Rect& aClipRect,
   1.338 +                             const nsIntRegion& aScreenRegion,
   1.339 +                             const nsIntPoint& aTextureOffset,
   1.340 +                             const nsIntSize& aTextureBounds)
   1.341 +{
   1.342 +  if (aTile.IsPlaceholderTile()) {
   1.343 +    // This shouldn't ever happen, but let's fail semi-gracefully. No need
   1.344 +    // to warn, the texture update would have already caught this.
   1.345 +    return;
   1.346 +  }
   1.347 +
   1.348 +  nsIntRect screenBounds = aScreenRegion.GetBounds();
   1.349 +  Rect quad(screenBounds.x, screenBounds.y, screenBounds.width, screenBounds.height);
   1.350 +  quad = aTransform.TransformBounds(quad);
   1.351 +
   1.352 +  if (!quad.Intersects(mCompositor->ClipRectInLayersCoordinates(aClipRect))) {
   1.353 +    return;
   1.354 +  }
   1.355 +
   1.356 +  AutoLockTextureHost autoLock(aTile.mTextureHost);
   1.357 +  if (autoLock.Failed()) {
   1.358 +    NS_WARNING("Failed to lock tile");
   1.359 +    return;
   1.360 +  }
   1.361 +  RefPtr<NewTextureSource> source = aTile.mTextureHost->GetTextureSources();
   1.362 +  if (!source) {
   1.363 +    return;
   1.364 +  }
   1.365 +
   1.366 +  RefPtr<TexturedEffect> effect =
   1.367 +    CreateTexturedEffect(aTile.mTextureHost->GetFormat(), source, aFilter);
   1.368 +  if (!effect) {
   1.369 +    return;
   1.370 +  }
   1.371 +
   1.372 +  aEffectChain.mPrimaryEffect = effect;
   1.373 +
   1.374 +  nsIntRegionRectIterator it(aScreenRegion);
   1.375 +  for (const nsIntRect* rect = it.Next(); rect != nullptr; rect = it.Next()) {
   1.376 +    Rect graphicsRect(rect->x, rect->y, rect->width, rect->height);
   1.377 +    Rect textureRect(rect->x - aTextureOffset.x, rect->y - aTextureOffset.y,
   1.378 +                     rect->width, rect->height);
   1.379 +
   1.380 +    effect->mTextureCoords = Rect(textureRect.x / aTextureBounds.width,
   1.381 +                                  textureRect.y / aTextureBounds.height,
   1.382 +                                  textureRect.width / aTextureBounds.width,
   1.383 +                                  textureRect.height / aTextureBounds.height);
   1.384 +    mCompositor->DrawQuad(graphicsRect, aClipRect, aEffectChain, aOpacity, aTransform);
   1.385 +  }
   1.386 +  mCompositor->DrawDiagnostics(DIAGNOSTIC_CONTENT|DIAGNOSTIC_TILE,
   1.387 +                               aScreenRegion, aClipRect, aTransform, mFlashCounter);
   1.388 +}
   1.389 +
   1.390 +void
   1.391 +TiledContentHost::RenderLayerBuffer(TiledLayerBufferComposite& aLayerBuffer,
   1.392 +                                    EffectChain& aEffectChain,
   1.393 +                                    float aOpacity,
   1.394 +                                    const gfx::Filter& aFilter,
   1.395 +                                    const gfx::Rect& aClipRect,
   1.396 +                                    nsIntRegion aVisibleRegion,
   1.397 +                                    gfx::Matrix4x4 aTransform)
   1.398 +{
   1.399 +  if (!mCompositor) {
   1.400 +    NS_WARNING("Can't render tiled content host - no compositor");
   1.401 +    return;
   1.402 +  }
   1.403 +  float resolution = aLayerBuffer.GetResolution();
   1.404 +  gfx::Size layerScale(1, 1);
   1.405 +
   1.406 +  // We assume that the current frame resolution is the one used in our high
   1.407 +  // precision layer buffer. Compensate for a changing frame resolution when
   1.408 +  // rendering the low precision buffer.
   1.409 +  if (aLayerBuffer.GetFrameResolution() != mTiledBuffer.GetFrameResolution()) {
   1.410 +    const CSSToParentLayerScale& layerResolution = aLayerBuffer.GetFrameResolution();
   1.411 +    const CSSToParentLayerScale& localResolution = mTiledBuffer.GetFrameResolution();
   1.412 +    layerScale.width = layerScale.height = layerResolution.scale / localResolution.scale;
   1.413 +    aVisibleRegion.ScaleRoundOut(layerScale.width, layerScale.height);
   1.414 +  }
   1.415 +
   1.416 +  // If we're drawing the low precision buffer, make sure the high precision
   1.417 +  // buffer is masked out to avoid overdraw and rendering artifacts with
   1.418 +  // non-opaque layers.
   1.419 +  nsIntRegion maskRegion;
   1.420 +  if (resolution != mTiledBuffer.GetResolution()) {
   1.421 +    maskRegion = mTiledBuffer.GetValidRegion();
   1.422 +    // XXX This should be ScaleRoundIn, but there is no such function on
   1.423 +    //     nsIntRegion.
   1.424 +    maskRegion.ScaleRoundOut(layerScale.width, layerScale.height);
   1.425 +  }
   1.426 +
   1.427 +  // Make sure the resolution and difference in frame resolution are accounted
   1.428 +  // for in the layer transform.
   1.429 +  aTransform.Scale(1/(resolution * layerScale.width),
   1.430 +                   1/(resolution * layerScale.height), 1);
   1.431 +
   1.432 +  uint32_t rowCount = 0;
   1.433 +  uint32_t tileX = 0;
   1.434 +  nsIntRect visibleRect = aVisibleRegion.GetBounds();
   1.435 +  gfx::IntSize scaledTileSize = aLayerBuffer.GetScaledTileSize();
   1.436 +  for (int32_t x = visibleRect.x; x < visibleRect.x + visibleRect.width;) {
   1.437 +    rowCount++;
   1.438 +    int32_t tileStartX = aLayerBuffer.GetTileStart(x, scaledTileSize.width);
   1.439 +    int32_t w = scaledTileSize.width - tileStartX;
   1.440 +    if (x + w > visibleRect.x + visibleRect.width) {
   1.441 +      w = visibleRect.x + visibleRect.width - x;
   1.442 +    }
   1.443 +    int tileY = 0;
   1.444 +    for (int32_t y = visibleRect.y; y < visibleRect.y + visibleRect.height;) {
   1.445 +      int32_t tileStartY = aLayerBuffer.GetTileStart(y, scaledTileSize.height);
   1.446 +      int32_t h = scaledTileSize.height - tileStartY;
   1.447 +      if (y + h > visibleRect.y + visibleRect.height) {
   1.448 +        h = visibleRect.y + visibleRect.height - y;
   1.449 +      }
   1.450 +
   1.451 +      TileHost tileTexture = aLayerBuffer.
   1.452 +        GetTile(nsIntPoint(aLayerBuffer.RoundDownToTileEdge(x, scaledTileSize.width),
   1.453 +                           aLayerBuffer.RoundDownToTileEdge(y, scaledTileSize.height)));
   1.454 +      if (tileTexture != aLayerBuffer.GetPlaceholderTile()) {
   1.455 +        nsIntRegion tileDrawRegion;
   1.456 +        tileDrawRegion.And(nsIntRect(x, y, w, h), aLayerBuffer.GetValidRegion());
   1.457 +        tileDrawRegion.And(tileDrawRegion, aVisibleRegion);
   1.458 +        tileDrawRegion.Sub(tileDrawRegion, maskRegion);
   1.459 +
   1.460 +        if (!tileDrawRegion.IsEmpty()) {
   1.461 +          tileDrawRegion.ScaleRoundOut(resolution, resolution);
   1.462 +          nsIntPoint tileOffset((x - tileStartX) * resolution,
   1.463 +                                (y - tileStartY) * resolution);
   1.464 +          gfx::IntSize tileSize = aLayerBuffer.GetTileSize();
   1.465 +          RenderTile(tileTexture, aEffectChain, aOpacity, aTransform, aFilter, aClipRect, tileDrawRegion,
   1.466 +                     tileOffset, nsIntSize(tileSize.width, tileSize.height));
   1.467 +        }
   1.468 +      }
   1.469 +      tileY++;
   1.470 +      y += h;
   1.471 +    }
   1.472 +    tileX++;
   1.473 +    x += w;
   1.474 +  }
   1.475 +  gfx::Rect rect(visibleRect.x, visibleRect.y,
   1.476 +                 visibleRect.width, visibleRect.height);
   1.477 +  GetCompositor()->DrawDiagnostics(DIAGNOSTIC_CONTENT,
   1.478 +                                   rect, aClipRect, aTransform, mFlashCounter);
   1.479 +}
   1.480 +
   1.481 +void
   1.482 +TiledContentHost::PrintInfo(nsACString& aTo, const char* aPrefix)
   1.483 +{
   1.484 +  aTo += aPrefix;
   1.485 +  aTo += nsPrintfCString("TiledContentHost (0x%p)", this);
   1.486 +
   1.487 +}
   1.488 +
   1.489 +#ifdef MOZ_DUMP_PAINTING
   1.490 +void
   1.491 +TiledContentHost::Dump(FILE* aFile,
   1.492 +                       const char* aPrefix,
   1.493 +                       bool aDumpHtml)
   1.494 +{
   1.495 +  if (!aFile) {
   1.496 +    aFile = stderr;
   1.497 +  }
   1.498 +
   1.499 +  TiledLayerBufferComposite::Iterator it = mTiledBuffer.TilesBegin();
   1.500 +  TiledLayerBufferComposite::Iterator stop = mTiledBuffer.TilesEnd();
   1.501 +  if (aDumpHtml) {
   1.502 +    fprintf_stderr(aFile, "<ul>");
   1.503 +  }
   1.504 +  for (;it != stop; ++it) {
   1.505 +    fprintf_stderr(aFile, "%s", aPrefix);
   1.506 +    fprintf_stderr(aFile, aDumpHtml ? "<li> <a href=" : "Tile ");
   1.507 +    if (it->IsPlaceholderTile()) {
   1.508 +      fprintf_stderr(aFile, "empty tile");
   1.509 +    } else {
   1.510 +      DumpTextureHost(aFile, it->mTextureHost);
   1.511 +    }
   1.512 +    fprintf_stderr(aFile, aDumpHtml ? " >Tile</a></li>" : " ");
   1.513 +  }
   1.514 +    if (aDumpHtml) {
   1.515 +    fprintf_stderr(aFile, "</ul>");
   1.516 +  }
   1.517 +}
   1.518 +#endif
   1.519 +
   1.520 +} // namespace
   1.521 +} // namespace

mercurial