1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/layers/client/SimpleTiledContentClient.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,321 @@ 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 "mozilla/layers/SimpleTiledContentClient.h" 1.10 + 1.11 +#include <math.h> // for ceil, ceilf, floor 1.12 +#include "ClientTiledThebesLayer.h" // for ClientTiledThebesLayer 1.13 +#include "GeckoProfiler.h" // for PROFILER_LABEL 1.14 +#include "Units.h" // for ScreenIntRect, CSSPoint, etc 1.15 +#include "UnitTransforms.h" // for TransformTo 1.16 +#include "ClientLayerManager.h" // for ClientLayerManager 1.17 +#include "CompositorChild.h" // for CompositorChild 1.18 +#include "gfxContext.h" // for gfxContext, etc 1.19 +#include "gfxPlatform.h" // for gfxPlatform 1.20 +#include "gfxPrefs.h" // for gfxPrefs::LayersTileWidth/Height 1.21 +#include "gfxRect.h" // for gfxRect 1.22 +#include "mozilla/Attributes.h" // for MOZ_THIS_IN_INITIALIZER_LIST 1.23 +#include "mozilla/MathAlgorithms.h" // for Abs 1.24 +#include "mozilla/gfx/Point.h" // for IntSize 1.25 +#include "mozilla/gfx/Rect.h" // for Rect 1.26 +#include "mozilla/layers/CompositableForwarder.h" 1.27 +#include "mozilla/layers/ShadowLayers.h" // for ShadowLayerForwarder 1.28 +#include "SimpleTextureClientPool.h" 1.29 +#include "nsDebug.h" // for NS_ASSERTION 1.30 +#include "nsISupportsImpl.h" // for gfxContext::AddRef, etc 1.31 +#include "nsSize.h" // for nsIntSize 1.32 +#include "gfxReusableSharedImageSurfaceWrapper.h" 1.33 +#include "nsMathUtils.h" // for NS_roundf 1.34 +#include "gfx2DGlue.h" 1.35 + 1.36 +#define ALOG(...) __android_log_print(ANDROID_LOG_INFO, "SimpleTiles", __VA_ARGS__) 1.37 + 1.38 +using namespace mozilla::gfx; 1.39 + 1.40 +namespace mozilla { 1.41 +namespace layers { 1.42 + 1.43 +void 1.44 +SimpleTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion, 1.45 + const nsIntRegion& aPaintRegion, 1.46 + LayerManager::DrawThebesLayerCallback aCallback, 1.47 + void* aCallbackData) 1.48 +{ 1.49 + mCallback = aCallback; 1.50 + mCallbackData = aCallbackData; 1.51 + 1.52 +#ifdef GFX_TILEDLAYER_PREF_WARNINGS 1.53 + long start = PR_IntervalNow(); 1.54 +#endif 1.55 + 1.56 + // If this region is empty XMost() - 1 will give us a negative value. 1.57 + NS_ASSERTION(!aPaintRegion.GetBounds().IsEmpty(), "Empty paint region\n"); 1.58 + 1.59 + PROFILER_LABEL("SimpleTiledLayerBuffer", "PaintThebesUpdate"); 1.60 + 1.61 + Update(aNewValidRegion, aPaintRegion); 1.62 + 1.63 +#ifdef GFX_TILEDLAYER_PREF_WARNINGS 1.64 + if (PR_IntervalNow() - start > 10) { 1.65 + const nsIntRect bounds = aPaintRegion.GetBounds(); 1.66 + printf_stderr("Time to tile [%i, %i, %i, %i] -> %i\n", bounds.x, bounds.y, bounds.width, bounds.height, PR_IntervalNow() - start); 1.67 + } 1.68 +#endif 1.69 + 1.70 + mLastPaintOpaque = mThebesLayer->CanUseOpaqueSurface(); 1.71 + mCallback = nullptr; 1.72 + mCallbackData = nullptr; 1.73 +} 1.74 + 1.75 +SimpleTiledLayerTile 1.76 +SimpleTiledLayerBuffer::ValidateTile(SimpleTiledLayerTile aTile, 1.77 + const nsIntPoint& aTileOrigin, 1.78 + const nsIntRegion& aDirtyRegion) 1.79 +{ 1.80 + PROFILER_LABEL("SimpleTiledLayerBuffer", "ValidateTile"); 1.81 + static gfx::IntSize kTileSize(gfxPrefs::LayersTileWidth(), gfxPrefs::LayersTileHeight()); 1.82 + 1.83 + gfx::SurfaceFormat tileFormat = gfxPlatform::GetPlatform()->Optimal2DFormatForContent(GetContentType()); 1.84 + 1.85 + // if this is true, we're using a separate buffer to do our drawing first 1.86 + bool doBufferedDrawing = true; 1.87 + bool fullPaint = false; 1.88 + 1.89 + RefPtr<TextureClient> textureClient = mManager->GetSimpleTileTexturePool(tileFormat)->GetTextureClientWithAutoRecycle(); 1.90 + 1.91 + if (!textureClient) { 1.92 + NS_WARNING("TextureClient allocation failed"); 1.93 + return SimpleTiledLayerTile(); 1.94 + } 1.95 + 1.96 + if (!textureClient->Lock(OPEN_READ_WRITE)) { 1.97 + NS_WARNING("TextureClient lock failed"); 1.98 + return SimpleTiledLayerTile(); 1.99 + } 1.100 + 1.101 + if (!textureClient->CanExposeDrawTarget()) { 1.102 + doBufferedDrawing = false; 1.103 + } 1.104 + 1.105 + RefPtr<DrawTarget> drawTarget; 1.106 + 1.107 + unsigned char *bufferData = nullptr; 1.108 + 1.109 + // these are set/updated differently based on doBufferedDrawing 1.110 + nsIntRect drawBounds; 1.111 + nsIntRegion drawRegion; 1.112 + nsIntRegion invalidateRegion; 1.113 + 1.114 + RefPtr<DrawTarget> srcDT; 1.115 + uint8_t* srcData = nullptr; 1.116 + int32_t srcStride = 0; 1.117 + gfx::IntSize srcSize; 1.118 + gfx::SurfaceFormat srcFormat = gfx::SurfaceFormat::UNKNOWN; 1.119 + 1.120 + if (doBufferedDrawing) { 1.121 + // try to directly access the pixels of the TextureClient 1.122 + srcDT = textureClient->GetAsDrawTarget(); 1.123 + if (srcDT->LockBits(&srcData, &srcSize, &srcStride, &srcFormat)) { 1.124 + if (!aTile.mCachedBuffer) { 1.125 + aTile.mCachedBuffer = SharedBuffer::Create(srcStride * srcSize.height); 1.126 + fullPaint = true; 1.127 + } 1.128 + bufferData = (unsigned char*) aTile.mCachedBuffer->Data(); 1.129 + 1.130 + drawTarget = gfxPlatform::GetPlatform()->CreateDrawTargetForData(bufferData, 1.131 + kTileSize, 1.132 + srcStride, 1.133 + tileFormat); 1.134 + 1.135 + if (fullPaint) { 1.136 + drawBounds = nsIntRect(aTileOrigin.x, aTileOrigin.y, GetScaledTileSize().width, GetScaledTileSize().height); 1.137 + drawRegion = nsIntRegion(drawBounds); 1.138 + } else { 1.139 + drawBounds = aDirtyRegion.GetBounds(); 1.140 + drawRegion = nsIntRegion(drawBounds); 1.141 + if (GetContentType() == gfxContentType::COLOR_ALPHA) 1.142 + drawTarget->ClearRect(Rect(drawBounds.x - aTileOrigin.x, drawBounds.y - aTileOrigin.y, 1.143 + drawBounds.width, drawBounds.height)); 1.144 + } 1.145 + } else { 1.146 + // failed to obtain the client as an ImageSurface 1.147 + doBufferedDrawing = false; 1.148 + } 1.149 + } 1.150 + 1.151 + // this might get set above if we couldn't extract out a buffer 1.152 + if (!doBufferedDrawing) { 1.153 + drawTarget = textureClient->GetAsDrawTarget(); 1.154 + 1.155 + fullPaint = true; 1.156 + drawBounds = nsIntRect(aTileOrigin.x, aTileOrigin.y, GetScaledTileSize().width, GetScaledTileSize().height); 1.157 + drawRegion = nsIntRegion(drawBounds); 1.158 + 1.159 + if (GetContentType() == gfxContentType::COLOR_ALPHA) 1.160 + drawTarget->ClearRect(Rect(0, 0, drawBounds.width, drawBounds.height)); 1.161 + } 1.162 + 1.163 + // do the drawing 1.164 + RefPtr<gfxContext> ctxt = new gfxContext(drawTarget); 1.165 + 1.166 + ctxt->Scale(mResolution, mResolution); 1.167 + ctxt->Translate(gfxPoint(-aTileOrigin.x, -aTileOrigin.y)); 1.168 + 1.169 + mCallback(mThebesLayer, ctxt, 1.170 + drawRegion, 1.171 + fullPaint ? DrawRegionClip::CLIP_NONE : DrawRegionClip::DRAW_SNAPPED, // XXX DRAW or DRAW_SNAPPED? 1.172 + invalidateRegion, 1.173 + mCallbackData); 1.174 + 1.175 + ctxt = nullptr; 1.176 + 1.177 + if (doBufferedDrawing) { 1.178 + memcpy(srcData, bufferData, srcSize.height * srcStride); 1.179 + bufferData = nullptr; 1.180 + srcDT->ReleaseBits(srcData); 1.181 + srcDT = nullptr; 1.182 + } 1.183 + 1.184 + drawTarget = nullptr; 1.185 + textureClient->Unlock(); 1.186 + 1.187 + if (!mCompositableClient->AddTextureClient(textureClient)) { 1.188 + NS_WARNING("Failed to add tile TextureClient [simple]"); 1.189 + return SimpleTiledLayerTile(); 1.190 + } 1.191 + 1.192 + // aTile.mCachedBuffer was set earlier 1.193 + aTile.mTileBuffer = textureClient; 1.194 + aTile.mManager = mManager; 1.195 + aTile.mLastUpdate = TimeStamp::Now(); 1.196 + 1.197 + return aTile; 1.198 +} 1.199 + 1.200 +SurfaceDescriptorTiles 1.201 +SimpleTiledLayerBuffer::GetSurfaceDescriptorTiles() 1.202 +{ 1.203 + InfallibleTArray<TileDescriptor> tiles; 1.204 + 1.205 + for (size_t i = 0; i < mRetainedTiles.Length(); i++) { 1.206 + tiles.AppendElement(mRetainedTiles[i].GetTileDescriptor()); 1.207 + } 1.208 + 1.209 + return SurfaceDescriptorTiles(mValidRegion, mPaintedRegion, 1.210 + tiles, mRetainedWidth, mRetainedHeight, 1.211 + mResolution, mFrameResolution.scale); 1.212 +} 1.213 + 1.214 +bool 1.215 +SimpleTiledLayerBuffer::HasFormatChanged() const 1.216 +{ 1.217 + return mThebesLayer->CanUseOpaqueSurface() != mLastPaintOpaque; 1.218 +} 1.219 + 1.220 +gfxContentType 1.221 +SimpleTiledLayerBuffer::GetContentType() const 1.222 +{ 1.223 + if (mThebesLayer->CanUseOpaqueSurface()) 1.224 + return gfxContentType::COLOR; 1.225 + 1.226 + return gfxContentType::COLOR_ALPHA; 1.227 +} 1.228 + 1.229 +SimpleTiledContentClient::SimpleTiledContentClient(SimpleClientTiledThebesLayer* aThebesLayer, 1.230 + ClientLayerManager* aManager) 1.231 + : CompositableClient(aManager->AsShadowForwarder()) 1.232 + , mTiledBuffer(aThebesLayer, MOZ_THIS_IN_INITIALIZER_LIST(), aManager) 1.233 +{ 1.234 + MOZ_COUNT_CTOR(SimpleTiledContentClient); 1.235 +} 1.236 + 1.237 +SimpleTiledContentClient::~SimpleTiledContentClient() 1.238 +{ 1.239 + MOZ_COUNT_DTOR(SimpleTiledContentClient); 1.240 + mTiledBuffer.Release(); 1.241 +} 1.242 + 1.243 +void 1.244 +SimpleTiledContentClient::UseTiledLayerBuffer() 1.245 +{ 1.246 + mForwarder->UseTiledLayerBuffer(this, mTiledBuffer.GetSurfaceDescriptorTiles()); 1.247 + mTiledBuffer.ClearPaintedRegion(); 1.248 +} 1.249 + 1.250 +SimpleClientTiledThebesLayer::SimpleClientTiledThebesLayer(ClientLayerManager* aManager) 1.251 + : ThebesLayer(aManager, 1.252 + static_cast<ClientLayer*>(MOZ_THIS_IN_INITIALIZER_LIST())) 1.253 + , mContentClient() 1.254 +{ 1.255 + MOZ_COUNT_CTOR(SimpleClientTiledThebesLayer); 1.256 +} 1.257 + 1.258 +SimpleClientTiledThebesLayer::~SimpleClientTiledThebesLayer() 1.259 +{ 1.260 + MOZ_COUNT_DTOR(SimpleClientTiledThebesLayer); 1.261 +} 1.262 + 1.263 +void 1.264 +SimpleClientTiledThebesLayer::FillSpecificAttributes(SpecificLayerAttributes& aAttrs) 1.265 +{ 1.266 + aAttrs = ThebesLayerAttributes(GetValidRegion()); 1.267 +} 1.268 + 1.269 +void 1.270 +SimpleClientTiledThebesLayer::RenderLayer() 1.271 +{ 1.272 + LayerManager::DrawThebesLayerCallback callback = 1.273 + ClientManager()->GetThebesLayerCallback(); 1.274 + void *data = ClientManager()->GetThebesLayerCallbackData(); 1.275 + if (!callback) { 1.276 + ClientManager()->SetTransactionIncomplete(); 1.277 + return; 1.278 + } 1.279 + 1.280 + // First time? Create a content client. 1.281 + if (!mContentClient) { 1.282 + mContentClient = new SimpleTiledContentClient(this, ClientManager()); 1.283 + 1.284 + mContentClient->Connect(); 1.285 + ClientManager()->AsShadowForwarder()->Attach(mContentClient, this); 1.286 + MOZ_ASSERT(mContentClient->GetForwarder()); 1.287 + } 1.288 + 1.289 + // If the format changed, nothing is valid 1.290 + if (mContentClient->mTiledBuffer.HasFormatChanged()) { 1.291 + mValidRegion = nsIntRegion(); 1.292 + } 1.293 + 1.294 + nsIntRegion invalidRegion = mVisibleRegion; 1.295 + invalidRegion.Sub(invalidRegion, mValidRegion); 1.296 + if (invalidRegion.IsEmpty()) { 1.297 + return; 1.298 + } 1.299 + 1.300 + // Only paint the mask layer on the first transaction. 1.301 + if (GetMaskLayer() && !ClientManager()->IsRepeatTransaction()) { 1.302 + ToClientLayer(GetMaskLayer())->RenderLayer(); 1.303 + } 1.304 + 1.305 + // SimpleTiledContentClient doesn't support progressive updates or the low 1.306 + // precision buffer yet. 1.307 + MOZ_ASSERT(!gfxPrefs::UseProgressiveTilePainting() && 1.308 + !gfxPrefs::UseLowPrecisionBuffer()); 1.309 + 1.310 + mValidRegion = mVisibleRegion; 1.311 + 1.312 + NS_ASSERTION(!ClientManager()->IsRepeatTransaction(), "Didn't paint our mask layer"); 1.313 + 1.314 + mContentClient->mTiledBuffer.PaintThebes(mValidRegion, invalidRegion, 1.315 + callback, data); 1.316 + 1.317 + ClientManager()->Hold(this); 1.318 + 1.319 + mContentClient->UseTiledLayerBuffer(); 1.320 +} 1.321 + 1.322 + 1.323 +} 1.324 +}