|
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 "TiledContentHost.h" |
|
7 #include "ThebesLayerComposite.h" // for ThebesLayerComposite |
|
8 #include "mozilla/gfx/BaseSize.h" // for BaseSize |
|
9 #include "mozilla/gfx/Matrix.h" // for Matrix4x4 |
|
10 #include "mozilla/layers/Compositor.h" // for Compositor |
|
11 #include "mozilla/layers/Effects.h" // for TexturedEffect, Effect, etc |
|
12 #include "mozilla/layers/TextureHostOGL.h" // for TextureHostOGL |
|
13 #include "nsAString.h" |
|
14 #include "nsDebug.h" // for NS_WARNING |
|
15 #include "nsPoint.h" // for nsIntPoint |
|
16 #include "nsPrintfCString.h" // for nsPrintfCString |
|
17 #include "nsRect.h" // for nsIntRect |
|
18 #include "nsSize.h" // for nsIntSize |
|
19 #include "mozilla/layers/TiledContentClient.h" |
|
20 |
|
21 class gfxReusableSurfaceWrapper; |
|
22 |
|
23 namespace mozilla { |
|
24 using namespace gfx; |
|
25 namespace layers { |
|
26 |
|
27 class Layer; |
|
28 |
|
29 TiledLayerBufferComposite::TiledLayerBufferComposite() |
|
30 : mFrameResolution(1.0) |
|
31 , mHasDoubleBufferedTiles(false) |
|
32 , mUninitialized(true) |
|
33 {} |
|
34 |
|
35 /* static */ void |
|
36 TiledLayerBufferComposite::RecycleCallback(TextureHost* textureHost, void* aClosure) |
|
37 { |
|
38 textureHost->CompositorRecycle(); |
|
39 } |
|
40 |
|
41 TiledLayerBufferComposite::TiledLayerBufferComposite(ISurfaceAllocator* aAllocator, |
|
42 const SurfaceDescriptorTiles& aDescriptor, |
|
43 const nsIntRegion& aOldPaintedRegion) |
|
44 { |
|
45 mUninitialized = false; |
|
46 mHasDoubleBufferedTiles = false; |
|
47 mValidRegion = aDescriptor.validRegion(); |
|
48 mPaintedRegion = aDescriptor.paintedRegion(); |
|
49 mRetainedWidth = aDescriptor.retainedWidth(); |
|
50 mRetainedHeight = aDescriptor.retainedHeight(); |
|
51 mResolution = aDescriptor.resolution(); |
|
52 mFrameResolution = CSSToParentLayerScale(aDescriptor.frameResolution()); |
|
53 |
|
54 // Combine any valid content that wasn't already uploaded |
|
55 nsIntRegion oldPaintedRegion(aOldPaintedRegion); |
|
56 oldPaintedRegion.And(oldPaintedRegion, mValidRegion); |
|
57 mPaintedRegion.Or(mPaintedRegion, oldPaintedRegion); |
|
58 |
|
59 const InfallibleTArray<TileDescriptor>& tiles = aDescriptor.tiles(); |
|
60 for(size_t i = 0; i < tiles.Length(); i++) { |
|
61 RefPtr<TextureHost> texture; |
|
62 const TileDescriptor& tileDesc = tiles[i]; |
|
63 switch (tileDesc.type()) { |
|
64 case TileDescriptor::TTexturedTileDescriptor : { |
|
65 texture = TextureHost::AsTextureHost(tileDesc.get_TexturedTileDescriptor().textureParent()); |
|
66 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17 |
|
67 if (!gfxPrefs::LayersUseSimpleTiles()) { |
|
68 texture->SetRecycleCallback(RecycleCallback, nullptr); |
|
69 } |
|
70 #endif |
|
71 const TileLock& ipcLock = tileDesc.get_TexturedTileDescriptor().sharedLock(); |
|
72 nsRefPtr<gfxSharedReadLock> sharedLock; |
|
73 if (ipcLock.type() == TileLock::TShmemSection) { |
|
74 sharedLock = gfxShmSharedReadLock::Open(aAllocator, ipcLock.get_ShmemSection()); |
|
75 } else { |
|
76 sharedLock = reinterpret_cast<gfxMemorySharedReadLock*>(ipcLock.get_uintptr_t()); |
|
77 if (sharedLock) { |
|
78 // The corresponding AddRef is in TiledClient::GetTileDescriptor |
|
79 sharedLock->Release(); |
|
80 } |
|
81 } |
|
82 |
|
83 mRetainedTiles.AppendElement(TileHost(sharedLock, texture)); |
|
84 break; |
|
85 } |
|
86 default: |
|
87 NS_WARNING("Unrecognised tile descriptor type"); |
|
88 // Fall through |
|
89 case TileDescriptor::TPlaceholderTileDescriptor : |
|
90 mRetainedTiles.AppendElement(GetPlaceholderTile()); |
|
91 break; |
|
92 } |
|
93 if (texture && !texture->HasInternalBuffer()) { |
|
94 mHasDoubleBufferedTiles = true; |
|
95 } |
|
96 } |
|
97 } |
|
98 |
|
99 void |
|
100 TiledLayerBufferComposite::ReadUnlock() |
|
101 { |
|
102 if (!IsValid()) { |
|
103 return; |
|
104 } |
|
105 for (size_t i = 0; i < mRetainedTiles.Length(); i++) { |
|
106 mRetainedTiles[i].ReadUnlock(); |
|
107 } |
|
108 } |
|
109 |
|
110 void |
|
111 TiledLayerBufferComposite::ReleaseTextureHosts() |
|
112 { |
|
113 if (!IsValid()) { |
|
114 return; |
|
115 } |
|
116 for (size_t i = 0; i < mRetainedTiles.Length(); i++) { |
|
117 mRetainedTiles[i].mTextureHost = nullptr; |
|
118 } |
|
119 } |
|
120 |
|
121 void |
|
122 TiledLayerBufferComposite::Upload() |
|
123 { |
|
124 if(!IsValid()) { |
|
125 return; |
|
126 } |
|
127 // The TextureClients were created with the TEXTURE_IMMEDIATE_UPLOAD flag, |
|
128 // so calling Update on all the texture hosts will perform the texture upload. |
|
129 Update(mValidRegion, mPaintedRegion); |
|
130 ClearPaintedRegion(); |
|
131 } |
|
132 |
|
133 TileHost |
|
134 TiledLayerBufferComposite::ValidateTile(TileHost aTile, |
|
135 const nsIntPoint& aTileOrigin, |
|
136 const nsIntRegion& aDirtyRect) |
|
137 { |
|
138 if (aTile.IsPlaceholderTile()) { |
|
139 NS_WARNING("Placeholder tile encountered in painted region"); |
|
140 return aTile; |
|
141 } |
|
142 |
|
143 #ifdef GFX_TILEDLAYER_PREF_WARNINGS |
|
144 printf_stderr("Upload tile %i, %i\n", aTileOrigin.x, aTileOrigin.y); |
|
145 long start = PR_IntervalNow(); |
|
146 #endif |
|
147 |
|
148 MOZ_ASSERT(aTile.mTextureHost->GetFlags() & TEXTURE_IMMEDIATE_UPLOAD); |
|
149 // We possibly upload the entire texture contents here. This is a purposeful |
|
150 // decision, as sub-image upload can often be slow and/or unreliable, but |
|
151 // we may want to reevaluate this in the future. |
|
152 // For !HasInternalBuffer() textures, this is likely a no-op. |
|
153 aTile.mTextureHost->Updated(nullptr); |
|
154 |
|
155 #ifdef GFX_TILEDLAYER_PREF_WARNINGS |
|
156 if (PR_IntervalNow() - start > 1) { |
|
157 printf_stderr("Tile Time to upload %i\n", PR_IntervalNow() - start); |
|
158 } |
|
159 #endif |
|
160 return aTile; |
|
161 } |
|
162 |
|
163 void |
|
164 TiledLayerBufferComposite::SetCompositor(Compositor* aCompositor) |
|
165 { |
|
166 if (!IsValid()) { |
|
167 return; |
|
168 } |
|
169 for (size_t i = 0; i < mRetainedTiles.Length(); i++) { |
|
170 if (mRetainedTiles[i].IsPlaceholderTile()) continue; |
|
171 mRetainedTiles[i].mTextureHost->SetCompositor(aCompositor); |
|
172 } |
|
173 } |
|
174 |
|
175 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17 |
|
176 void |
|
177 TiledLayerBufferComposite::SetReleaseFence(const android::sp<android::Fence>& aReleaseFence) |
|
178 { |
|
179 for (size_t i = 0; i < mRetainedTiles.Length(); i++) { |
|
180 if (!mRetainedTiles[i].mTextureHost) { |
|
181 continue; |
|
182 } |
|
183 TextureHostOGL* texture = mRetainedTiles[i].mTextureHost->AsHostOGL(); |
|
184 if (!texture) { |
|
185 continue; |
|
186 } |
|
187 texture->SetReleaseFence(new android::Fence(aReleaseFence->dup())); |
|
188 } |
|
189 } |
|
190 #endif |
|
191 |
|
192 TiledContentHost::TiledContentHost(const TextureInfo& aTextureInfo) |
|
193 : ContentHost(aTextureInfo) |
|
194 , mTiledBuffer(TiledLayerBufferComposite()) |
|
195 , mLowPrecisionTiledBuffer(TiledLayerBufferComposite()) |
|
196 , mOldTiledBuffer(TiledLayerBufferComposite()) |
|
197 , mOldLowPrecisionTiledBuffer(TiledLayerBufferComposite()) |
|
198 , mPendingUpload(false) |
|
199 , mPendingLowPrecisionUpload(false) |
|
200 { |
|
201 MOZ_COUNT_CTOR(TiledContentHost); |
|
202 } |
|
203 |
|
204 TiledContentHost::~TiledContentHost() |
|
205 { |
|
206 MOZ_COUNT_DTOR(TiledContentHost); |
|
207 |
|
208 // Unlock any buffers that may still be locked. If we have a pending upload, |
|
209 // we will need to unlock the buffer that was about to be uploaded. |
|
210 // If a buffer that was being composited had double-buffered tiles, we will |
|
211 // need to unlock that buffer too. |
|
212 if (mPendingUpload) { |
|
213 mTiledBuffer.ReadUnlock(); |
|
214 if (mOldTiledBuffer.HasDoubleBufferedTiles()) { |
|
215 mOldTiledBuffer.ReadUnlock(); |
|
216 } |
|
217 } else if (mTiledBuffer.HasDoubleBufferedTiles()) { |
|
218 mTiledBuffer.ReadUnlock(); |
|
219 } |
|
220 |
|
221 if (mPendingLowPrecisionUpload) { |
|
222 mLowPrecisionTiledBuffer.ReadUnlock(); |
|
223 if (mOldLowPrecisionTiledBuffer.HasDoubleBufferedTiles()) { |
|
224 mOldLowPrecisionTiledBuffer.ReadUnlock(); |
|
225 } |
|
226 } else if (mLowPrecisionTiledBuffer.HasDoubleBufferedTiles()) { |
|
227 mLowPrecisionTiledBuffer.ReadUnlock(); |
|
228 } |
|
229 } |
|
230 |
|
231 void |
|
232 TiledContentHost::Attach(Layer* aLayer, |
|
233 Compositor* aCompositor, |
|
234 AttachFlags aFlags /* = NO_FLAGS */) |
|
235 { |
|
236 CompositableHost::Attach(aLayer, aCompositor, aFlags); |
|
237 static_cast<ThebesLayerComposite*>(aLayer)->EnsureTiled(); |
|
238 } |
|
239 |
|
240 void |
|
241 TiledContentHost::UseTiledLayerBuffer(ISurfaceAllocator* aAllocator, |
|
242 const SurfaceDescriptorTiles& aTiledDescriptor) |
|
243 { |
|
244 if (aTiledDescriptor.resolution() < 1) { |
|
245 if (mPendingLowPrecisionUpload) { |
|
246 mLowPrecisionTiledBuffer.ReadUnlock(); |
|
247 } else { |
|
248 mPendingLowPrecisionUpload = true; |
|
249 // If the old buffer has double-buffered tiles, hang onto it so we can |
|
250 // unlock it after we've composited the new buffer. |
|
251 // We only need to hang onto the locks, but not the textures. |
|
252 // Releasing the textures here can help prevent a memory spike in the |
|
253 // situation that the client starts rendering new content before we get |
|
254 // to composite the new buffer. |
|
255 if (mLowPrecisionTiledBuffer.HasDoubleBufferedTiles()) { |
|
256 mOldLowPrecisionTiledBuffer = mLowPrecisionTiledBuffer; |
|
257 mOldLowPrecisionTiledBuffer.ReleaseTextureHosts(); |
|
258 } |
|
259 } |
|
260 mLowPrecisionTiledBuffer = |
|
261 TiledLayerBufferComposite(aAllocator, aTiledDescriptor, |
|
262 mLowPrecisionTiledBuffer.GetPaintedRegion()); |
|
263 } else { |
|
264 if (mPendingUpload) { |
|
265 mTiledBuffer.ReadUnlock(); |
|
266 } else { |
|
267 mPendingUpload = true; |
|
268 if (mTiledBuffer.HasDoubleBufferedTiles()) { |
|
269 mOldTiledBuffer = mTiledBuffer; |
|
270 mOldTiledBuffer.ReleaseTextureHosts(); |
|
271 } |
|
272 } |
|
273 mTiledBuffer = TiledLayerBufferComposite(aAllocator, aTiledDescriptor, |
|
274 mTiledBuffer.GetPaintedRegion()); |
|
275 } |
|
276 } |
|
277 |
|
278 void |
|
279 TiledContentHost::Composite(EffectChain& aEffectChain, |
|
280 float aOpacity, |
|
281 const gfx::Matrix4x4& aTransform, |
|
282 const gfx::Filter& aFilter, |
|
283 const gfx::Rect& aClipRect, |
|
284 const nsIntRegion* aVisibleRegion /* = nullptr */, |
|
285 TiledLayerProperties* aLayerProperties /* = nullptr */) |
|
286 { |
|
287 MOZ_ASSERT(aLayerProperties, "aLayerProperties required for TiledContentHost"); |
|
288 |
|
289 if (mPendingUpload) { |
|
290 mTiledBuffer.SetCompositor(mCompositor); |
|
291 mTiledBuffer.Upload(); |
|
292 |
|
293 // For a single-buffered tiled buffer, Upload will upload the shared memory |
|
294 // surface to texture memory and we no longer need to read from them. |
|
295 if (!mTiledBuffer.HasDoubleBufferedTiles()) { |
|
296 mTiledBuffer.ReadUnlock(); |
|
297 } |
|
298 } |
|
299 if (mPendingLowPrecisionUpload) { |
|
300 mLowPrecisionTiledBuffer.SetCompositor(mCompositor); |
|
301 mLowPrecisionTiledBuffer.Upload(); |
|
302 |
|
303 if (!mLowPrecisionTiledBuffer.HasDoubleBufferedTiles()) { |
|
304 mLowPrecisionTiledBuffer.ReadUnlock(); |
|
305 } |
|
306 } |
|
307 |
|
308 RenderLayerBuffer(mLowPrecisionTiledBuffer, aEffectChain, aOpacity, aFilter, |
|
309 aClipRect, aLayerProperties->mVisibleRegion, aTransform); |
|
310 RenderLayerBuffer(mTiledBuffer, aEffectChain, aOpacity, aFilter, |
|
311 aClipRect, aLayerProperties->mVisibleRegion, aTransform); |
|
312 |
|
313 // Now release the old buffer if it had double-buffered tiles, as we can |
|
314 // guarantee that they're no longer on the screen (and so any locks that may |
|
315 // have been held have been released). |
|
316 if (mPendingUpload && mOldTiledBuffer.HasDoubleBufferedTiles()) { |
|
317 mOldTiledBuffer.ReadUnlock(); |
|
318 mOldTiledBuffer = TiledLayerBufferComposite(); |
|
319 } |
|
320 if (mPendingLowPrecisionUpload && mOldLowPrecisionTiledBuffer.HasDoubleBufferedTiles()) { |
|
321 mOldLowPrecisionTiledBuffer.ReadUnlock(); |
|
322 mOldLowPrecisionTiledBuffer = TiledLayerBufferComposite(); |
|
323 } |
|
324 mPendingUpload = mPendingLowPrecisionUpload = false; |
|
325 } |
|
326 |
|
327 |
|
328 void |
|
329 TiledContentHost::RenderTile(const TileHost& aTile, |
|
330 EffectChain& aEffectChain, |
|
331 float aOpacity, |
|
332 const gfx::Matrix4x4& aTransform, |
|
333 const gfx::Filter& aFilter, |
|
334 const gfx::Rect& aClipRect, |
|
335 const nsIntRegion& aScreenRegion, |
|
336 const nsIntPoint& aTextureOffset, |
|
337 const nsIntSize& aTextureBounds) |
|
338 { |
|
339 if (aTile.IsPlaceholderTile()) { |
|
340 // This shouldn't ever happen, but let's fail semi-gracefully. No need |
|
341 // to warn, the texture update would have already caught this. |
|
342 return; |
|
343 } |
|
344 |
|
345 nsIntRect screenBounds = aScreenRegion.GetBounds(); |
|
346 Rect quad(screenBounds.x, screenBounds.y, screenBounds.width, screenBounds.height); |
|
347 quad = aTransform.TransformBounds(quad); |
|
348 |
|
349 if (!quad.Intersects(mCompositor->ClipRectInLayersCoordinates(aClipRect))) { |
|
350 return; |
|
351 } |
|
352 |
|
353 AutoLockTextureHost autoLock(aTile.mTextureHost); |
|
354 if (autoLock.Failed()) { |
|
355 NS_WARNING("Failed to lock tile"); |
|
356 return; |
|
357 } |
|
358 RefPtr<NewTextureSource> source = aTile.mTextureHost->GetTextureSources(); |
|
359 if (!source) { |
|
360 return; |
|
361 } |
|
362 |
|
363 RefPtr<TexturedEffect> effect = |
|
364 CreateTexturedEffect(aTile.mTextureHost->GetFormat(), source, aFilter); |
|
365 if (!effect) { |
|
366 return; |
|
367 } |
|
368 |
|
369 aEffectChain.mPrimaryEffect = effect; |
|
370 |
|
371 nsIntRegionRectIterator it(aScreenRegion); |
|
372 for (const nsIntRect* rect = it.Next(); rect != nullptr; rect = it.Next()) { |
|
373 Rect graphicsRect(rect->x, rect->y, rect->width, rect->height); |
|
374 Rect textureRect(rect->x - aTextureOffset.x, rect->y - aTextureOffset.y, |
|
375 rect->width, rect->height); |
|
376 |
|
377 effect->mTextureCoords = Rect(textureRect.x / aTextureBounds.width, |
|
378 textureRect.y / aTextureBounds.height, |
|
379 textureRect.width / aTextureBounds.width, |
|
380 textureRect.height / aTextureBounds.height); |
|
381 mCompositor->DrawQuad(graphicsRect, aClipRect, aEffectChain, aOpacity, aTransform); |
|
382 } |
|
383 mCompositor->DrawDiagnostics(DIAGNOSTIC_CONTENT|DIAGNOSTIC_TILE, |
|
384 aScreenRegion, aClipRect, aTransform, mFlashCounter); |
|
385 } |
|
386 |
|
387 void |
|
388 TiledContentHost::RenderLayerBuffer(TiledLayerBufferComposite& aLayerBuffer, |
|
389 EffectChain& aEffectChain, |
|
390 float aOpacity, |
|
391 const gfx::Filter& aFilter, |
|
392 const gfx::Rect& aClipRect, |
|
393 nsIntRegion aVisibleRegion, |
|
394 gfx::Matrix4x4 aTransform) |
|
395 { |
|
396 if (!mCompositor) { |
|
397 NS_WARNING("Can't render tiled content host - no compositor"); |
|
398 return; |
|
399 } |
|
400 float resolution = aLayerBuffer.GetResolution(); |
|
401 gfx::Size layerScale(1, 1); |
|
402 |
|
403 // We assume that the current frame resolution is the one used in our high |
|
404 // precision layer buffer. Compensate for a changing frame resolution when |
|
405 // rendering the low precision buffer. |
|
406 if (aLayerBuffer.GetFrameResolution() != mTiledBuffer.GetFrameResolution()) { |
|
407 const CSSToParentLayerScale& layerResolution = aLayerBuffer.GetFrameResolution(); |
|
408 const CSSToParentLayerScale& localResolution = mTiledBuffer.GetFrameResolution(); |
|
409 layerScale.width = layerScale.height = layerResolution.scale / localResolution.scale; |
|
410 aVisibleRegion.ScaleRoundOut(layerScale.width, layerScale.height); |
|
411 } |
|
412 |
|
413 // If we're drawing the low precision buffer, make sure the high precision |
|
414 // buffer is masked out to avoid overdraw and rendering artifacts with |
|
415 // non-opaque layers. |
|
416 nsIntRegion maskRegion; |
|
417 if (resolution != mTiledBuffer.GetResolution()) { |
|
418 maskRegion = mTiledBuffer.GetValidRegion(); |
|
419 // XXX This should be ScaleRoundIn, but there is no such function on |
|
420 // nsIntRegion. |
|
421 maskRegion.ScaleRoundOut(layerScale.width, layerScale.height); |
|
422 } |
|
423 |
|
424 // Make sure the resolution and difference in frame resolution are accounted |
|
425 // for in the layer transform. |
|
426 aTransform.Scale(1/(resolution * layerScale.width), |
|
427 1/(resolution * layerScale.height), 1); |
|
428 |
|
429 uint32_t rowCount = 0; |
|
430 uint32_t tileX = 0; |
|
431 nsIntRect visibleRect = aVisibleRegion.GetBounds(); |
|
432 gfx::IntSize scaledTileSize = aLayerBuffer.GetScaledTileSize(); |
|
433 for (int32_t x = visibleRect.x; x < visibleRect.x + visibleRect.width;) { |
|
434 rowCount++; |
|
435 int32_t tileStartX = aLayerBuffer.GetTileStart(x, scaledTileSize.width); |
|
436 int32_t w = scaledTileSize.width - tileStartX; |
|
437 if (x + w > visibleRect.x + visibleRect.width) { |
|
438 w = visibleRect.x + visibleRect.width - x; |
|
439 } |
|
440 int tileY = 0; |
|
441 for (int32_t y = visibleRect.y; y < visibleRect.y + visibleRect.height;) { |
|
442 int32_t tileStartY = aLayerBuffer.GetTileStart(y, scaledTileSize.height); |
|
443 int32_t h = scaledTileSize.height - tileStartY; |
|
444 if (y + h > visibleRect.y + visibleRect.height) { |
|
445 h = visibleRect.y + visibleRect.height - y; |
|
446 } |
|
447 |
|
448 TileHost tileTexture = aLayerBuffer. |
|
449 GetTile(nsIntPoint(aLayerBuffer.RoundDownToTileEdge(x, scaledTileSize.width), |
|
450 aLayerBuffer.RoundDownToTileEdge(y, scaledTileSize.height))); |
|
451 if (tileTexture != aLayerBuffer.GetPlaceholderTile()) { |
|
452 nsIntRegion tileDrawRegion; |
|
453 tileDrawRegion.And(nsIntRect(x, y, w, h), aLayerBuffer.GetValidRegion()); |
|
454 tileDrawRegion.And(tileDrawRegion, aVisibleRegion); |
|
455 tileDrawRegion.Sub(tileDrawRegion, maskRegion); |
|
456 |
|
457 if (!tileDrawRegion.IsEmpty()) { |
|
458 tileDrawRegion.ScaleRoundOut(resolution, resolution); |
|
459 nsIntPoint tileOffset((x - tileStartX) * resolution, |
|
460 (y - tileStartY) * resolution); |
|
461 gfx::IntSize tileSize = aLayerBuffer.GetTileSize(); |
|
462 RenderTile(tileTexture, aEffectChain, aOpacity, aTransform, aFilter, aClipRect, tileDrawRegion, |
|
463 tileOffset, nsIntSize(tileSize.width, tileSize.height)); |
|
464 } |
|
465 } |
|
466 tileY++; |
|
467 y += h; |
|
468 } |
|
469 tileX++; |
|
470 x += w; |
|
471 } |
|
472 gfx::Rect rect(visibleRect.x, visibleRect.y, |
|
473 visibleRect.width, visibleRect.height); |
|
474 GetCompositor()->DrawDiagnostics(DIAGNOSTIC_CONTENT, |
|
475 rect, aClipRect, aTransform, mFlashCounter); |
|
476 } |
|
477 |
|
478 void |
|
479 TiledContentHost::PrintInfo(nsACString& aTo, const char* aPrefix) |
|
480 { |
|
481 aTo += aPrefix; |
|
482 aTo += nsPrintfCString("TiledContentHost (0x%p)", this); |
|
483 |
|
484 } |
|
485 |
|
486 #ifdef MOZ_DUMP_PAINTING |
|
487 void |
|
488 TiledContentHost::Dump(FILE* aFile, |
|
489 const char* aPrefix, |
|
490 bool aDumpHtml) |
|
491 { |
|
492 if (!aFile) { |
|
493 aFile = stderr; |
|
494 } |
|
495 |
|
496 TiledLayerBufferComposite::Iterator it = mTiledBuffer.TilesBegin(); |
|
497 TiledLayerBufferComposite::Iterator stop = mTiledBuffer.TilesEnd(); |
|
498 if (aDumpHtml) { |
|
499 fprintf_stderr(aFile, "<ul>"); |
|
500 } |
|
501 for (;it != stop; ++it) { |
|
502 fprintf_stderr(aFile, "%s", aPrefix); |
|
503 fprintf_stderr(aFile, aDumpHtml ? "<li> <a href=" : "Tile "); |
|
504 if (it->IsPlaceholderTile()) { |
|
505 fprintf_stderr(aFile, "empty tile"); |
|
506 } else { |
|
507 DumpTextureHost(aFile, it->mTextureHost); |
|
508 } |
|
509 fprintf_stderr(aFile, aDumpHtml ? " >Tile</a></li>" : " "); |
|
510 } |
|
511 if (aDumpHtml) { |
|
512 fprintf_stderr(aFile, "</ul>"); |
|
513 } |
|
514 } |
|
515 #endif |
|
516 |
|
517 } // namespace |
|
518 } // namespace |