Line data Source code
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/. */
5 :
6 : #include "mozilla/layers/SingleTiledContentClient.h"
7 :
8 : #include "ClientTiledPaintedLayer.h"
9 :
10 : namespace mozilla {
11 : namespace layers {
12 :
13 :
14 0 : SingleTiledContentClient::SingleTiledContentClient(ClientTiledPaintedLayer& aPaintedLayer,
15 0 : ClientLayerManager* aManager)
16 0 : : TiledContentClient(aManager, "Single")
17 : {
18 0 : MOZ_COUNT_CTOR(SingleTiledContentClient);
19 :
20 0 : mTiledBuffer = new ClientSingleTiledLayerBuffer(aPaintedLayer, *this, aManager);
21 0 : }
22 :
23 : void
24 0 : SingleTiledContentClient::ClearCachedResources()
25 : {
26 0 : CompositableClient::ClearCachedResources();
27 0 : mTiledBuffer->DiscardBuffers();
28 0 : }
29 :
30 : void
31 0 : SingleTiledContentClient::UpdatedBuffer(TiledBufferType aType)
32 : {
33 0 : mForwarder->UseTiledLayerBuffer(this, mTiledBuffer->GetSurfaceDescriptorTiles());
34 0 : mTiledBuffer->ClearPaintedRegion();
35 0 : }
36 :
37 : /* static */ bool
38 0 : SingleTiledContentClient::ClientSupportsLayerSize(const gfx::IntSize& aSize, ClientLayerManager* aManager)
39 : {
40 0 : int32_t maxTextureSize = aManager->GetMaxTextureSize();
41 0 : return aSize.width <= maxTextureSize && aSize.height <= maxTextureSize;
42 : }
43 :
44 0 : ClientSingleTiledLayerBuffer::ClientSingleTiledLayerBuffer(ClientTiledPaintedLayer& aPaintedLayer,
45 : CompositableClient& aCompositableClient,
46 0 : ClientLayerManager* aManager)
47 : : ClientTiledLayerBuffer(aPaintedLayer, aCompositableClient)
48 : , mWasLastPaintProgressive(false)
49 0 : , mFormat(gfx::SurfaceFormat::UNKNOWN)
50 : {
51 0 : }
52 :
53 : void
54 0 : ClientSingleTiledLayerBuffer::ReleaseTiles()
55 : {
56 0 : if (!mTile.IsPlaceholderTile()) {
57 0 : mTile.DiscardBuffers();
58 : }
59 0 : mTile.SetTextureAllocator(nullptr);
60 0 : }
61 :
62 : void
63 0 : ClientSingleTiledLayerBuffer::DiscardBuffers()
64 : {
65 0 : if (!mTile.IsPlaceholderTile()) {
66 0 : mTile.DiscardFrontBuffer();
67 0 : mTile.DiscardBackBuffer();
68 : }
69 0 : }
70 :
71 : SurfaceDescriptorTiles
72 0 : ClientSingleTiledLayerBuffer::GetSurfaceDescriptorTiles()
73 : {
74 0 : InfallibleTArray<TileDescriptor> tiles;
75 :
76 0 : TileDescriptor tileDesc = mTile.GetTileDescriptor();
77 0 : tiles.AppendElement(tileDesc);
78 0 : mTile.mUpdateRect = gfx::IntRect();
79 :
80 : return SurfaceDescriptorTiles(mValidRegion,
81 : tiles,
82 : mTilingOrigin,
83 : mSize,
84 : 0, 0, 1, 1,
85 : 1.0,
86 : mFrameResolution.xScale,
87 : mFrameResolution.yScale,
88 0 : mWasLastPaintProgressive);
89 : }
90 :
91 : already_AddRefed<TextureClient>
92 0 : ClientSingleTiledLayerBuffer::GetTextureClient()
93 : {
94 0 : MOZ_ASSERT(mFormat != gfx::SurfaceFormat::UNKNOWN);
95 0 : return mCompositableClient.CreateTextureClientForDrawing(
96 : gfx::ImageFormatToSurfaceFormat(mFormat), mSize, BackendSelector::Content,
97 0 : TextureFlags::DISALLOW_BIGIMAGE | TextureFlags::IMMEDIATE_UPLOAD);
98 : }
99 :
100 : void
101 0 : ClientSingleTiledLayerBuffer::PaintThebes(const nsIntRegion& aNewValidRegion,
102 : const nsIntRegion& aPaintRegion,
103 : const nsIntRegion& aDirtyRegion,
104 : LayerManager::DrawPaintedLayerCallback aCallback,
105 : void* aCallbackData,
106 : bool aIsProgressive)
107 : {
108 0 : mWasLastPaintProgressive = aIsProgressive;
109 :
110 : // Compare layer valid region size to current backbuffer size, discard if not matching.
111 0 : gfx::IntSize size = aNewValidRegion.GetBounds().Size();
112 0 : gfx::IntPoint origin = aNewValidRegion.GetBounds().TopLeft();
113 0 : nsIntRegion paintRegion = aPaintRegion;
114 :
115 0 : RefPtr<TextureClient> discardedFrontBuffer = nullptr;
116 0 : RefPtr<TextureClient> discardedFrontBufferOnWhite = nullptr;
117 0 : nsIntRegion discardedValidRegion;
118 :
119 0 : if (mSize != size ||
120 0 : mTilingOrigin != origin) {
121 0 : discardedFrontBuffer = mTile.mFrontBuffer;
122 0 : discardedFrontBufferOnWhite = mTile.mFrontBufferOnWhite;
123 0 : discardedValidRegion = mValidRegion;
124 :
125 : TILING_LOG("TILING %p: Single-tile valid region changed. Discarding buffers.\n", &mPaintedLayer)
126 : ;
127 0 : ResetPaintedAndValidState();
128 0 : mSize = size;
129 0 : mTilingOrigin = origin;
130 0 : paintRegion = aNewValidRegion;
131 : }
132 :
133 : SurfaceMode mode;
134 0 : gfxContentType content = GetContentType(&mode);
135 0 : mFormat = gfxPlatform::GetPlatform()->OptimalFormatForContent(content);
136 :
137 0 : if (mTile.IsPlaceholderTile()) {
138 0 : mTile.SetTextureAllocator(this);
139 : }
140 :
141 : // The dirty region relative to the top-left of the tile.
142 0 : nsIntRegion tileDirtyRegion = paintRegion.MovedBy(-mTilingOrigin);
143 :
144 0 : nsIntRegion extraPainted;
145 0 : RefPtr<TextureClient> backBufferOnWhite;
146 : RefPtr<TextureClient> backBuffer =
147 : mTile.GetBackBuffer(mCompositableClient,
148 : tileDirtyRegion,
149 : content, mode,
150 : extraPainted,
151 0 : &backBufferOnWhite);
152 :
153 0 : mTile.mUpdateRect = tileDirtyRegion.GetBounds().Union(extraPainted.GetBounds());
154 :
155 0 : extraPainted.MoveBy(mTilingOrigin);
156 0 : extraPainted.And(extraPainted, aNewValidRegion);
157 0 : mPaintedRegion.OrWith(paintRegion);
158 0 : mPaintedRegion.OrWith(extraPainted);
159 :
160 0 : if (!backBuffer) {
161 0 : return;
162 : }
163 :
164 0 : RefPtr<gfx::DrawTarget> dt = backBuffer->BorrowDrawTarget();
165 0 : RefPtr<gfx::DrawTarget> dtOnWhite;
166 0 : if (backBufferOnWhite) {
167 0 : dtOnWhite = backBufferOnWhite->BorrowDrawTarget();
168 : }
169 :
170 0 : if (mode != SurfaceMode::SURFACE_OPAQUE) {
171 0 : for (auto iter = tileDirtyRegion.RectIter(); !iter.Done(); iter.Next()) {
172 0 : const gfx::IntRect& rect = iter.Get();
173 0 : if (dtOnWhite) {
174 0 : dt->FillRect(gfx::Rect(rect.x, rect.y, rect.width, rect.height),
175 0 : gfx::ColorPattern(gfx::Color(0.0, 0.0, 0.0, 1.0)));
176 0 : dtOnWhite->FillRect(gfx::Rect(rect.x, rect.y, rect.width, rect.height),
177 0 : gfx::ColorPattern(gfx::Color(1.0, 1.0, 1.0, 1.0)));
178 : } else {
179 0 : dt->ClearRect(gfx::Rect(rect.x, rect.y, rect.width, rect.height));
180 : }
181 : }
182 : }
183 :
184 : // If the old frontbuffer was discarded then attempt to copy what we
185 : // can from it to the new backbuffer.
186 0 : if (discardedFrontBuffer) {
187 0 : nsIntRegion copyableRegion;
188 0 : copyableRegion.And(aNewValidRegion, discardedValidRegion);
189 0 : copyableRegion.SubOut(aDirtyRegion);
190 :
191 0 : if (!copyableRegion.IsEmpty()) {
192 : TextureClientAutoLock frontLock(discardedFrontBuffer,
193 0 : OpenMode::OPEN_READ);
194 0 : if (frontLock.Succeeded()) {
195 0 : for (auto iter = copyableRegion.RectIter(); !iter.Done(); iter.Next()) {
196 0 : const gfx::IntRect rect = iter.Get() - discardedValidRegion.GetBounds().TopLeft();
197 0 : const gfx::IntPoint dest = iter.Get().TopLeft() - mTilingOrigin;
198 0 : discardedFrontBuffer->CopyToTextureClient(backBuffer, &rect, &dest);
199 : }
200 : }
201 :
202 0 : if (discardedFrontBufferOnWhite && backBufferOnWhite) {
203 : TextureClientAutoLock frontOnWhiteLock(discardedFrontBufferOnWhite,
204 0 : OpenMode::OPEN_READ);
205 0 : if (frontOnWhiteLock.Succeeded()) {
206 0 : for (auto iter = copyableRegion.RectIter(); !iter.Done(); iter.Next()) {
207 0 : const gfx::IntRect rect = iter.Get() - discardedValidRegion.GetBounds().TopLeft();
208 0 : const gfx::IntPoint dest = iter.Get().TopLeft() - mTilingOrigin;
209 :
210 0 : discardedFrontBufferOnWhite->CopyToTextureClient(backBufferOnWhite,
211 0 : &rect, &dest);
212 : }
213 : }
214 : }
215 :
216 : TILING_LOG("TILING %p: Region copied from discarded frontbuffer %s\n", &mPaintedLayer, Stringify(copyableRegion).c_str());
217 :
218 : // We don't need to repaint valid content that was just copied.
219 0 : paintRegion.SubOut(copyableRegion);
220 : }
221 : }
222 :
223 0 : if (dtOnWhite) {
224 0 : dt = gfx::Factory::CreateDualDrawTarget(dt, dtOnWhite);
225 0 : dtOnWhite = nullptr;
226 : }
227 :
228 : {
229 0 : RefPtr<gfxContext> ctx = gfxContext::CreateOrNull(dt);
230 0 : if (!ctx) {
231 0 : gfxDevCrash(gfx::LogReason::InvalidContext) << "SingleTiledContextClient context problem " << gfx::hexa(dt);
232 0 : return;
233 : }
234 0 : ctx->SetMatrix(ctx->CurrentMatrix().PreTranslate(-mTilingOrigin.x, -mTilingOrigin.y));
235 :
236 0 : aCallback(&mPaintedLayer, ctx, paintRegion, paintRegion, DrawRegionClip::DRAW, nsIntRegion(), aCallbackData);
237 : }
238 :
239 : // Mark the area we just drew into the back buffer as invalid in the front buffer as they're
240 : // now out of sync.
241 0 : mTile.mInvalidFront.OrWith(tileDirtyRegion);
242 :
243 : // The new buffer is now validated, remove the dirty region from it.
244 0 : mTile.mInvalidBack.SubOut(tileDirtyRegion);
245 :
246 0 : dt = nullptr;
247 :
248 0 : mTile.Flip();
249 0 : UnlockTile(mTile);
250 :
251 0 : if (backBuffer->HasIntermediateBuffer()) {
252 : // If our new buffer has an internal buffer, we don't want to keep another
253 : // TextureClient around unnecessarily, so discard the back-buffer.
254 0 : mTile.DiscardBackBuffer();
255 : }
256 :
257 0 : mValidRegion = aNewValidRegion;
258 0 : mLastPaintSurfaceMode = mode;
259 0 : mLastPaintContentType = content;
260 : }
261 :
262 : } // namespace layers
263 : } // namespace mozilla
|