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

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

mercurial