gfx/layers/client/SimpleTiledContentClient.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
     2  * This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "mozilla/layers/SimpleTiledContentClient.h"
     8 #include <math.h>                       // for ceil, ceilf, floor
     9 #include "ClientTiledThebesLayer.h"     // for ClientTiledThebesLayer
    10 #include "GeckoProfiler.h"              // for PROFILER_LABEL
    11 #include "Units.h"                      // for ScreenIntRect, CSSPoint, etc
    12 #include "UnitTransforms.h"             // for TransformTo
    13 #include "ClientLayerManager.h"         // for ClientLayerManager
    14 #include "CompositorChild.h"            // for CompositorChild
    15 #include "gfxContext.h"                 // for gfxContext, etc
    16 #include "gfxPlatform.h"                // for gfxPlatform
    17 #include "gfxPrefs.h"                   // for gfxPrefs::LayersTileWidth/Height
    18 #include "gfxRect.h"                    // for gfxRect
    19 #include "mozilla/Attributes.h"         // for MOZ_THIS_IN_INITIALIZER_LIST
    20 #include "mozilla/MathAlgorithms.h"     // for Abs
    21 #include "mozilla/gfx/Point.h"          // for IntSize
    22 #include "mozilla/gfx/Rect.h"           // for Rect
    23 #include "mozilla/layers/CompositableForwarder.h"
    24 #include "mozilla/layers/ShadowLayers.h"  // for ShadowLayerForwarder
    25 #include "SimpleTextureClientPool.h"
    26 #include "nsDebug.h"                    // for NS_ASSERTION
    27 #include "nsISupportsImpl.h"            // for gfxContext::AddRef, etc
    28 #include "nsSize.h"                     // for nsIntSize
    29 #include "gfxReusableSharedImageSurfaceWrapper.h"
    30 #include "nsMathUtils.h"               // for NS_roundf
    31 #include "gfx2DGlue.h"
    33 #define ALOG(...)  __android_log_print(ANDROID_LOG_INFO, "SimpleTiles", __VA_ARGS__)
    35 using namespace mozilla::gfx;
    37 namespace mozilla {
    38 namespace layers {
    40 void
    41 SimpleTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
    42                                     const nsIntRegion& aPaintRegion,
    43                                     LayerManager::DrawThebesLayerCallback aCallback,
    44                                     void* aCallbackData)
    45 {
    46   mCallback = aCallback;
    47   mCallbackData = aCallbackData;
    49 #ifdef GFX_TILEDLAYER_PREF_WARNINGS
    50   long start = PR_IntervalNow();
    51 #endif
    53   // If this region is empty XMost() - 1 will give us a negative value.
    54   NS_ASSERTION(!aPaintRegion.GetBounds().IsEmpty(), "Empty paint region\n");
    56   PROFILER_LABEL("SimpleTiledLayerBuffer", "PaintThebesUpdate");
    58   Update(aNewValidRegion, aPaintRegion);
    60 #ifdef GFX_TILEDLAYER_PREF_WARNINGS
    61   if (PR_IntervalNow() - start > 10) {
    62     const nsIntRect bounds = aPaintRegion.GetBounds();
    63     printf_stderr("Time to tile [%i, %i, %i, %i] -> %i\n", bounds.x, bounds.y, bounds.width, bounds.height, PR_IntervalNow() - start);
    64   }
    65 #endif
    67   mLastPaintOpaque = mThebesLayer->CanUseOpaqueSurface();
    68   mCallback = nullptr;
    69   mCallbackData = nullptr;
    70 }
    72 SimpleTiledLayerTile
    73 SimpleTiledLayerBuffer::ValidateTile(SimpleTiledLayerTile aTile,
    74                                      const nsIntPoint& aTileOrigin,
    75                                      const nsIntRegion& aDirtyRegion)
    76 {
    77   PROFILER_LABEL("SimpleTiledLayerBuffer", "ValidateTile");
    78   static gfx::IntSize kTileSize(gfxPrefs::LayersTileWidth(), gfxPrefs::LayersTileHeight());
    80   gfx::SurfaceFormat tileFormat = gfxPlatform::GetPlatform()->Optimal2DFormatForContent(GetContentType());
    82   // if this is true, we're using a separate buffer to do our drawing first
    83   bool doBufferedDrawing = true;
    84   bool fullPaint = false;
    86   RefPtr<TextureClient> textureClient = mManager->GetSimpleTileTexturePool(tileFormat)->GetTextureClientWithAutoRecycle();
    88   if (!textureClient) {
    89     NS_WARNING("TextureClient allocation failed");
    90     return SimpleTiledLayerTile();
    91   }
    93   if (!textureClient->Lock(OPEN_READ_WRITE)) {
    94     NS_WARNING("TextureClient lock failed");
    95     return SimpleTiledLayerTile();
    96   }
    98   if (!textureClient->CanExposeDrawTarget()) {
    99     doBufferedDrawing = false;
   100   }
   102   RefPtr<DrawTarget> drawTarget;
   104   unsigned char *bufferData = nullptr;
   106   // these are set/updated differently based on doBufferedDrawing
   107   nsIntRect drawBounds;
   108   nsIntRegion drawRegion;
   109   nsIntRegion invalidateRegion;
   111   RefPtr<DrawTarget> srcDT;
   112   uint8_t* srcData = nullptr;
   113   int32_t srcStride = 0;
   114   gfx::IntSize srcSize;
   115   gfx::SurfaceFormat srcFormat = gfx::SurfaceFormat::UNKNOWN;
   117   if (doBufferedDrawing) {
   118     // try to directly access the pixels of the TextureClient
   119     srcDT = textureClient->GetAsDrawTarget();
   120     if (srcDT->LockBits(&srcData, &srcSize, &srcStride, &srcFormat)) {
   121       if (!aTile.mCachedBuffer) {
   122         aTile.mCachedBuffer = SharedBuffer::Create(srcStride * srcSize.height);
   123         fullPaint = true;
   124       }
   125       bufferData = (unsigned char*) aTile.mCachedBuffer->Data();
   127       drawTarget = gfxPlatform::GetPlatform()->CreateDrawTargetForData(bufferData,
   128                                                                        kTileSize,
   129                                                                        srcStride,
   130                                                                        tileFormat);
   132       if (fullPaint) {
   133         drawBounds = nsIntRect(aTileOrigin.x, aTileOrigin.y, GetScaledTileSize().width, GetScaledTileSize().height);
   134         drawRegion = nsIntRegion(drawBounds);
   135       } else {
   136         drawBounds = aDirtyRegion.GetBounds();
   137         drawRegion = nsIntRegion(drawBounds);
   138         if (GetContentType() == gfxContentType::COLOR_ALPHA)
   139           drawTarget->ClearRect(Rect(drawBounds.x - aTileOrigin.x, drawBounds.y - aTileOrigin.y,
   140                                      drawBounds.width, drawBounds.height));
   141       }
   142     } else {
   143       // failed to obtain the client as an ImageSurface
   144       doBufferedDrawing = false;
   145     }
   146   }
   148   // this might get set above if we couldn't extract out a buffer
   149   if (!doBufferedDrawing) {
   150     drawTarget = textureClient->GetAsDrawTarget();
   152     fullPaint = true;
   153     drawBounds = nsIntRect(aTileOrigin.x, aTileOrigin.y, GetScaledTileSize().width, GetScaledTileSize().height);
   154     drawRegion = nsIntRegion(drawBounds);
   156     if (GetContentType() == gfxContentType::COLOR_ALPHA)
   157       drawTarget->ClearRect(Rect(0, 0, drawBounds.width, drawBounds.height));
   158   }
   160   // do the drawing
   161   RefPtr<gfxContext> ctxt = new gfxContext(drawTarget);
   163   ctxt->Scale(mResolution, mResolution);
   164   ctxt->Translate(gfxPoint(-aTileOrigin.x, -aTileOrigin.y));
   166   mCallback(mThebesLayer, ctxt,
   167             drawRegion,
   168             fullPaint ? DrawRegionClip::CLIP_NONE : DrawRegionClip::DRAW_SNAPPED, // XXX DRAW or DRAW_SNAPPED?
   169             invalidateRegion,
   170             mCallbackData);
   172   ctxt = nullptr;
   174   if (doBufferedDrawing) {
   175     memcpy(srcData, bufferData, srcSize.height * srcStride);
   176     bufferData = nullptr;
   177     srcDT->ReleaseBits(srcData);
   178     srcDT = nullptr;
   179   }
   181   drawTarget = nullptr;
   182   textureClient->Unlock();
   184   if (!mCompositableClient->AddTextureClient(textureClient)) {
   185     NS_WARNING("Failed to add tile TextureClient [simple]");
   186     return SimpleTiledLayerTile();
   187   }
   189   // aTile.mCachedBuffer was set earlier
   190   aTile.mTileBuffer = textureClient;
   191   aTile.mManager = mManager;
   192   aTile.mLastUpdate = TimeStamp::Now();
   194   return aTile;
   195 }
   197 SurfaceDescriptorTiles
   198 SimpleTiledLayerBuffer::GetSurfaceDescriptorTiles()
   199 {
   200   InfallibleTArray<TileDescriptor> tiles;
   202   for (size_t i = 0; i < mRetainedTiles.Length(); i++) {
   203     tiles.AppendElement(mRetainedTiles[i].GetTileDescriptor());
   204   }
   206   return SurfaceDescriptorTiles(mValidRegion, mPaintedRegion,
   207                                 tiles, mRetainedWidth, mRetainedHeight,
   208                                 mResolution, mFrameResolution.scale);
   209 }
   211 bool
   212 SimpleTiledLayerBuffer::HasFormatChanged() const
   213 {
   214   return mThebesLayer->CanUseOpaqueSurface() != mLastPaintOpaque;
   215 }
   217 gfxContentType
   218 SimpleTiledLayerBuffer::GetContentType() const
   219 {
   220   if (mThebesLayer->CanUseOpaqueSurface())
   221     return gfxContentType::COLOR;
   223   return gfxContentType::COLOR_ALPHA;
   224 }
   226 SimpleTiledContentClient::SimpleTiledContentClient(SimpleClientTiledThebesLayer* aThebesLayer,
   227                                                    ClientLayerManager* aManager)
   228   : CompositableClient(aManager->AsShadowForwarder())
   229   , mTiledBuffer(aThebesLayer, MOZ_THIS_IN_INITIALIZER_LIST(), aManager)
   230 {
   231   MOZ_COUNT_CTOR(SimpleTiledContentClient);
   232 }
   234 SimpleTiledContentClient::~SimpleTiledContentClient()
   235 {
   236   MOZ_COUNT_DTOR(SimpleTiledContentClient);
   237   mTiledBuffer.Release();
   238 }
   240 void
   241 SimpleTiledContentClient::UseTiledLayerBuffer()
   242 {
   243   mForwarder->UseTiledLayerBuffer(this, mTiledBuffer.GetSurfaceDescriptorTiles());
   244   mTiledBuffer.ClearPaintedRegion();
   245 }
   247 SimpleClientTiledThebesLayer::SimpleClientTiledThebesLayer(ClientLayerManager* aManager)
   248   : ThebesLayer(aManager,
   249                 static_cast<ClientLayer*>(MOZ_THIS_IN_INITIALIZER_LIST()))
   250   , mContentClient()
   251 {
   252   MOZ_COUNT_CTOR(SimpleClientTiledThebesLayer);
   253 }
   255 SimpleClientTiledThebesLayer::~SimpleClientTiledThebesLayer()
   256 {
   257   MOZ_COUNT_DTOR(SimpleClientTiledThebesLayer);
   258 }
   260 void
   261 SimpleClientTiledThebesLayer::FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
   262 {
   263   aAttrs = ThebesLayerAttributes(GetValidRegion());
   264 }
   266 void
   267 SimpleClientTiledThebesLayer::RenderLayer()
   268 {
   269   LayerManager::DrawThebesLayerCallback callback =
   270     ClientManager()->GetThebesLayerCallback();
   271   void *data = ClientManager()->GetThebesLayerCallbackData();
   272   if (!callback) {
   273     ClientManager()->SetTransactionIncomplete();
   274     return;
   275   }
   277   // First time? Create a content client.
   278   if (!mContentClient) {
   279     mContentClient = new SimpleTiledContentClient(this, ClientManager());
   281     mContentClient->Connect();
   282     ClientManager()->AsShadowForwarder()->Attach(mContentClient, this);
   283     MOZ_ASSERT(mContentClient->GetForwarder());
   284   }
   286   // If the format changed, nothing is valid
   287   if (mContentClient->mTiledBuffer.HasFormatChanged()) {
   288     mValidRegion = nsIntRegion();
   289   }
   291   nsIntRegion invalidRegion = mVisibleRegion;
   292   invalidRegion.Sub(invalidRegion, mValidRegion);
   293   if (invalidRegion.IsEmpty()) {
   294     return;
   295   }
   297   // Only paint the mask layer on the first transaction.
   298   if (GetMaskLayer() && !ClientManager()->IsRepeatTransaction()) {
   299     ToClientLayer(GetMaskLayer())->RenderLayer();
   300   }
   302   // SimpleTiledContentClient doesn't support progressive updates or the low
   303   // precision buffer yet.
   304   MOZ_ASSERT(!gfxPrefs::UseProgressiveTilePainting() &&
   305              !gfxPrefs::UseLowPrecisionBuffer());
   307   mValidRegion = mVisibleRegion;
   309   NS_ASSERTION(!ClientManager()->IsRepeatTransaction(), "Didn't paint our mask layer");
   311   mContentClient->mTiledBuffer.PaintThebes(mValidRegion, invalidRegion,
   312                                            callback, data);
   314   ClientManager()->Hold(this);
   316   mContentClient->UseTiledLayerBuffer();
   317 }
   320 }
   321 }

mercurial