Bug 792663: Don't SyncFrontBufferToBackBuffer() while a buffer tracker isn't around...
[gecko.git] / gfx / layers / basic / BasicThebesLayer.cpp
blob52d96dad4987936f925befd76867bc8ec10e9698
1 /* -*- Mode: C++; tab-width: 2; 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 "BasicThebesLayer.h"
8 #include "nsIWidget.h"
9 #include "RenderTrace.h"
10 #include "sampler.h"
11 #include "gfxUtils.h"
13 #include "prprf.h"
15 using namespace mozilla::gfx;
17 namespace mozilla {
18 namespace layers {
20 already_AddRefed<gfxASurface>
21 BasicThebesLayer::CreateBuffer(Buffer::ContentType aType, const nsIntSize& aSize)
23 nsRefPtr<gfxASurface> referenceSurface = mBuffer.GetBuffer();
24 if (!referenceSurface) {
25 gfxContext* defaultTarget = BasicManager()->GetDefaultTarget();
26 if (defaultTarget) {
27 referenceSurface = defaultTarget->CurrentSurface();
28 } else {
29 nsIWidget* widget = BasicManager()->GetRetainerWidget();
30 if (!widget || !(referenceSurface = widget->GetThebesSurface())) {
31 referenceSurface = BasicManager()->GetTarget()->CurrentSurface();
35 return referenceSurface->CreateSimilarSurface(
36 aType, gfxIntSize(aSize.width, aSize.height));
39 static nsIntRegion
40 IntersectWithClip(const nsIntRegion& aRegion, gfxContext* aContext)
42 gfxRect clip = aContext->GetClipExtents();
43 clip.RoundOut();
44 nsIntRect r(clip.X(), clip.Y(), clip.Width(), clip.Height());
45 nsIntRegion result;
46 result.And(aRegion, r);
47 return result;
50 static void
51 SetAntialiasingFlags(Layer* aLayer, gfxContext* aTarget)
53 if (!aTarget->IsCairo()) {
54 RefPtr<DrawTarget> dt = aTarget->GetDrawTarget();
56 if (dt->GetFormat() != FORMAT_B8G8R8A8) {
57 return;
60 const nsIntRect& bounds = aLayer->GetVisibleRegion().GetBounds();
61 gfx::Rect transformedBounds = dt->GetTransform().TransformBounds(gfx::Rect(Float(bounds.x), Float(bounds.y),
62 Float(bounds.width), Float(bounds.height)));
63 transformedBounds.RoundOut();
64 IntRect intTransformedBounds;
65 transformedBounds.ToIntRect(&intTransformedBounds);
66 dt->SetPermitSubpixelAA(!(aLayer->GetContentFlags() & Layer::CONTENT_COMPONENT_ALPHA) ||
67 dt->GetOpaqueRect().Contains(intTransformedBounds));
68 } else {
69 nsRefPtr<gfxASurface> surface = aTarget->CurrentSurface();
70 if (surface->GetContentType() != gfxASurface::CONTENT_COLOR_ALPHA) {
71 // Destination doesn't have alpha channel; no need to set any special flags
72 return;
75 const nsIntRect& bounds = aLayer->GetVisibleRegion().GetBounds();
76 surface->SetSubpixelAntialiasingEnabled(
77 !(aLayer->GetContentFlags() & Layer::CONTENT_COMPONENT_ALPHA) ||
78 surface->GetOpaqueRect().Contains(
79 aTarget->UserToDevice(gfxRect(bounds.x, bounds.y, bounds.width, bounds.height))));
83 void
84 BasicThebesLayer::PaintThebes(gfxContext* aContext,
85 Layer* aMaskLayer,
86 LayerManager::DrawThebesLayerCallback aCallback,
87 void* aCallbackData,
88 ReadbackProcessor* aReadback)
90 SAMPLE_LABEL("BasicThebesLayer", "PaintThebes");
91 NS_ASSERTION(BasicManager()->InDrawing(),
92 "Can only draw in drawing phase");
93 nsRefPtr<gfxASurface> targetSurface = aContext->CurrentSurface();
95 nsTArray<ReadbackProcessor::Update> readbackUpdates;
96 if (aReadback && UsedForReadback()) {
97 aReadback->GetThebesLayerUpdates(this, &readbackUpdates);
99 SyncFrontBufferToBackBuffer();
101 bool canUseOpaqueSurface = CanUseOpaqueSurface();
102 Buffer::ContentType contentType =
103 canUseOpaqueSurface ? gfxASurface::CONTENT_COLOR :
104 gfxASurface::CONTENT_COLOR_ALPHA;
105 float opacity = GetEffectiveOpacity();
107 if (!BasicManager()->IsRetained()) {
108 NS_ASSERTION(readbackUpdates.IsEmpty(), "Can't do readback for non-retained layer");
110 mValidRegion.SetEmpty();
111 mBuffer.Clear();
113 nsIntRegion toDraw = IntersectWithClip(GetEffectiveVisibleRegion(), aContext);
115 RenderTraceInvalidateStart(this, "FFFF00", toDraw.GetBounds());
117 if (!toDraw.IsEmpty() && !IsHidden()) {
118 if (!aCallback) {
119 BasicManager()->SetTransactionIncomplete();
120 return;
123 aContext->Save();
125 bool needsClipToVisibleRegion = GetClipToVisibleRegion();
126 bool needsGroup =
127 opacity != 1.0 || GetOperator() != gfxContext::OPERATOR_OVER || aMaskLayer;
128 nsRefPtr<gfxContext> groupContext;
129 if (needsGroup) {
130 groupContext =
131 BasicManager()->PushGroupForLayer(aContext, this, toDraw,
132 &needsClipToVisibleRegion);
133 if (GetOperator() != gfxContext::OPERATOR_OVER) {
134 needsClipToVisibleRegion = true;
136 } else {
137 groupContext = aContext;
139 SetAntialiasingFlags(this, groupContext);
140 aCallback(this, groupContext, toDraw, nsIntRegion(), aCallbackData);
141 if (needsGroup) {
142 BasicManager()->PopGroupToSourceWithCachedSurface(aContext, groupContext);
143 if (needsClipToVisibleRegion) {
144 gfxUtils::ClipToRegion(aContext, toDraw);
146 AutoSetOperator setOperator(aContext, GetOperator());
147 PaintWithMask(aContext, opacity, aMaskLayer);
150 aContext->Restore();
153 RenderTraceInvalidateEnd(this, "FFFF00");
154 return;
158 uint32_t flags = 0;
159 #ifndef MOZ_GFX_OPTIMIZE_MOBILE
160 gfxMatrix transform;
161 if (!GetEffectiveTransform().CanDraw2D(&transform) ||
162 transform.HasNonIntegerTranslation()) {
163 flags |= ThebesLayerBuffer::PAINT_WILL_RESAMPLE;
165 #endif
166 if (mDrawAtomically) {
167 flags |= ThebesLayerBuffer::PAINT_NO_ROTATION;
169 Buffer::PaintState state =
170 mBuffer.BeginPaint(this, contentType, flags);
171 mValidRegion.Sub(mValidRegion, state.mRegionToInvalidate);
173 if (state.mContext) {
174 // The area that became invalid and is visible needs to be repainted
175 // (this could be the whole visible area if our buffer switched
176 // from RGB to RGBA, because we might need to repaint with
177 // subpixel AA)
178 state.mRegionToInvalidate.And(state.mRegionToInvalidate,
179 GetEffectiveVisibleRegion());
180 nsIntRegion extendedDrawRegion = state.mRegionToDraw;
181 SetAntialiasingFlags(this, state.mContext);
183 RenderTraceInvalidateStart(this, "FFFF00", state.mRegionToDraw.GetBounds());
185 PaintBuffer(state.mContext,
186 state.mRegionToDraw, extendedDrawRegion, state.mRegionToInvalidate,
187 state.mDidSelfCopy,
188 aCallback, aCallbackData);
189 Mutated();
191 RenderTraceInvalidateEnd(this, "FFFF00");
192 } else {
193 // It's possible that state.mRegionToInvalidate is nonempty here,
194 // if we are shrinking the valid region to nothing. So use mRegionToDraw
195 // instead.
196 NS_WARN_IF_FALSE(state.mRegionToDraw.IsEmpty(),
197 "No context when we have something to draw; resource exhaustion?");
201 if (BasicManager()->IsTransactionIncomplete())
202 return;
204 gfxRect clipExtents;
205 clipExtents = aContext->GetClipExtents();
206 if (!IsHidden() && !clipExtents.IsEmpty()) {
207 AutoSetOperator setOperator(aContext, GetOperator());
208 mBuffer.DrawTo(this, aContext, opacity, aMaskLayer);
211 for (uint32_t i = 0; i < readbackUpdates.Length(); ++i) {
212 ReadbackProcessor::Update& update = readbackUpdates[i];
213 nsIntPoint offset = update.mLayer->GetBackgroundLayerOffset();
214 nsRefPtr<gfxContext> ctx =
215 update.mLayer->GetSink()->BeginUpdate(update.mUpdateRect + offset,
216 update.mSequenceCounter);
217 if (ctx) {
218 NS_ASSERTION(opacity == 1.0, "Should only read back opaque layers");
219 ctx->Translate(gfxPoint(offset.x, offset.y));
220 mBuffer.DrawTo(this, ctx, 1.0, aMaskLayer);
221 update.mLayer->GetSink()->EndUpdate(ctx, update.mUpdateRect + offset);
227 * AutoOpenBuffer is a helper that builds on top of AutoOpenSurface,
228 * which we need to get a gfxASurface from a SurfaceDescriptor. For
229 * other layer types, simple lexical scoping of AutoOpenSurface is
230 * easy. For ThebesLayers, the lifetime of buffer mappings doesn't
231 * exactly match simple lexical scopes, so naively putting
232 * AutoOpenSurfaces on the stack doesn't always work. We use this
233 * helper to track openings instead.
235 * Any surface that's opened while painting this ThebesLayer will
236 * notify this helper and register itself for unmapping.
238 * We ignore buffer destruction here because the shadow layers
239 * protocol already ensures that destroyed buffers stay alive until
240 * end-of-transaction.
242 struct NS_STACK_CLASS AutoBufferTracker {
243 AutoBufferTracker(BasicShadowableThebesLayer* aLayer)
244 : mLayer(aLayer)
246 MOZ_ASSERT(!mLayer->mBufferTracker);
248 mLayer->mBufferTracker = this;
249 if (IsSurfaceDescriptorValid(mLayer->mBackBuffer)) {
250 mInitialBuffer.construct(OPEN_READ_WRITE, mLayer->mBackBuffer);
251 mLayer->mBuffer.ProvideBuffer(&mInitialBuffer.ref());
255 ~AutoBufferTracker() {
256 mLayer->mBufferTracker = nullptr;
257 mLayer->mBuffer.RevokeBuffer();
258 // mInitialBuffer and mNewBuffer will clean up after themselves if
259 // they were constructed.
262 gfxASurface*
263 CreatedBuffer(const SurfaceDescriptor& aDescriptor) {
264 Maybe<AutoOpenSurface>* surface = mNewBuffers.AppendElement();
265 surface->construct(OPEN_READ_WRITE, aDescriptor);
266 return surface->ref().Get();
269 Maybe<AutoOpenSurface> mInitialBuffer;
270 nsAutoTArray<Maybe<AutoOpenSurface>, 2> mNewBuffers;
271 BasicShadowableThebesLayer* mLayer;
273 private:
274 AutoBufferTracker(const AutoBufferTracker&) MOZ_DELETE;
275 AutoBufferTracker& operator=(const AutoBufferTracker&) MOZ_DELETE;
278 void
279 BasicShadowableThebesLayer::PaintThebes(gfxContext* aContext,
280 Layer* aMaskLayer,
281 LayerManager::DrawThebesLayerCallback aCallback,
282 void* aCallbackData,
283 ReadbackProcessor* aReadback)
285 if (!HasShadow()) {
286 BasicThebesLayer::PaintThebes(aContext, aMaskLayer, aCallback, aCallbackData, aReadback);
287 return;
290 AutoBufferTracker tracker(this);
292 BasicThebesLayer::PaintThebes(aContext, nullptr, aCallback, aCallbackData, aReadback);
293 if (aMaskLayer) {
294 static_cast<BasicImplData*>(aMaskLayer->ImplData())
295 ->Paint(aContext, nullptr);
300 void
301 BasicShadowableThebesLayer::SetBackBufferAndAttrs(const OptionalThebesBuffer& aBuffer,
302 const nsIntRegion& aValidRegion,
303 const OptionalThebesBuffer& aReadOnlyFrontBuffer,
304 const nsIntRegion& aFrontUpdatedRegion)
306 if (OptionalThebesBuffer::Tnull_t == aBuffer.type()) {
307 mBackBuffer = SurfaceDescriptor();
308 } else {
309 mBackBuffer = aBuffer.get_ThebesBuffer().buffer();
310 mBackBufferRect = aBuffer.get_ThebesBuffer().rect();
311 mBackBufferRectRotation = aBuffer.get_ThebesBuffer().rotation();
313 mFrontAndBackBufferDiffer = true;
314 mROFrontBuffer = aReadOnlyFrontBuffer;
315 mFrontUpdatedRegion = aFrontUpdatedRegion;
316 mFrontValidRegion = aValidRegion;
319 void
320 BasicShadowableThebesLayer::SyncFrontBufferToBackBuffer()
322 if (!mFrontAndBackBufferDiffer) {
323 return;
326 // We temporarily map our back buffer here in order to copy from the
327 // front buffer. We need a live buffer tracker in order to unmap
328 // that buffer when appropriate.
329 MOZ_ASSERT(mBufferTracker);
331 gfxASurface* backBuffer = mBuffer.GetBuffer();
332 if (!IsSurfaceDescriptorValid(mBackBuffer)) {
333 MOZ_ASSERT(!backBuffer);
334 MOZ_ASSERT(mROFrontBuffer.type() == OptionalThebesBuffer::TThebesBuffer);
335 const ThebesBuffer roFront = mROFrontBuffer.get_ThebesBuffer();
336 AutoOpenSurface roFrontBuffer(OPEN_READ_ONLY, roFront.buffer());
337 AllocBackBuffer(roFrontBuffer.ContentType(), roFrontBuffer.Size());
339 mFrontAndBackBufferDiffer = false;
341 Maybe<AutoOpenSurface> autoBackBuffer;
342 if (!backBuffer) {
343 autoBackBuffer.construct(OPEN_READ_WRITE, mBackBuffer);
344 backBuffer = autoBackBuffer.ref().Get();
347 if (OptionalThebesBuffer::Tnull_t == mROFrontBuffer.type()) {
348 // We didn't get back a read-only ref to our old back buffer (the
349 // parent's new front buffer). If the parent is pushing updates
350 // to a texture it owns, then we probably got back the same buffer
351 // we pushed in the update and all is well. If not, ...
352 mValidRegion = mFrontValidRegion;
353 mBuffer.SetBackingBuffer(backBuffer, mBackBufferRect, mBackBufferRectRotation);
354 return;
357 MOZ_LAYERS_LOG(("BasicShadowableThebes(%p): reading back <x=%d,y=%d,w=%d,h=%d>",
358 this,
359 mFrontUpdatedRegion.GetBounds().x,
360 mFrontUpdatedRegion.GetBounds().y,
361 mFrontUpdatedRegion.GetBounds().width,
362 mFrontUpdatedRegion.GetBounds().height));
364 const ThebesBuffer roFront = mROFrontBuffer.get_ThebesBuffer();
365 AutoOpenSurface autoROFront(OPEN_READ_ONLY, roFront.buffer());
366 mBuffer.SetBackingBufferAndUpdateFrom(
367 backBuffer,
368 autoROFront.Get(), roFront.rect(), roFront.rotation(),
369 mFrontUpdatedRegion);
370 mIsNewBuffer = false;
371 // Now the new back buffer has the same (interesting) pixels as the
372 // new front buffer, and mValidRegion et al. are correct wrt the new
373 // back buffer (i.e. as they were for the old back buffer)
376 void
377 BasicShadowableThebesLayer::PaintBuffer(gfxContext* aContext,
378 const nsIntRegion& aRegionToDraw,
379 const nsIntRegion& aExtendedRegionToDraw,
380 const nsIntRegion& aRegionToInvalidate,
381 bool aDidSelfCopy,
382 LayerManager::DrawThebesLayerCallback aCallback,
383 void* aCallbackData)
385 Base::PaintBuffer(aContext,
386 aRegionToDraw, aExtendedRegionToDraw, aRegionToInvalidate,
387 aDidSelfCopy,
388 aCallback, aCallbackData);
389 if (!HasShadow() || BasicManager()->IsTransactionIncomplete()) {
390 return;
393 nsIntRegion updatedRegion;
394 if (mIsNewBuffer || aDidSelfCopy) {
395 // A buffer reallocation clears both buffers. The front buffer has all the
396 // content by now, but the back buffer is still clear. Here, in effect, we
397 // are saying to copy all of the pixels of the front buffer to the back.
398 // Also when we self-copied in the buffer, the buffer space
399 // changes and some changed buffer content isn't reflected in the
400 // draw or invalidate region (on purpose!). When this happens, we
401 // need to read back the entire buffer too.
402 updatedRegion = mVisibleRegion;
403 mIsNewBuffer = false;
404 } else {
405 updatedRegion = aRegionToDraw;
408 NS_ASSERTION(mBuffer.BufferRect().Contains(aRegionToDraw.GetBounds()),
409 "Update outside of buffer rect!");
410 NS_ABORT_IF_FALSE(IsSurfaceDescriptorValid(mBackBuffer),
411 "should have a back buffer by now");
412 BasicManager()->PaintedThebesBuffer(BasicManager()->Hold(this),
413 updatedRegion,
414 mBuffer.BufferRect(),
415 mBuffer.BufferRotation(),
416 mBackBuffer);
419 void
420 BasicShadowableThebesLayer::AllocBackBuffer(Buffer::ContentType aType,
421 const nsIntSize& aSize)
423 // This function may *not* open the buffer it allocates.
424 if (!BasicManager()->AllocBuffer(gfxIntSize(aSize.width, aSize.height),
425 aType,
426 &mBackBuffer)) {
427 enum { buflen = 256 };
428 char buf[buflen];
429 PR_snprintf(buf, buflen,
430 "creating ThebesLayer 'back buffer' failed! width=%d, height=%d, type=%x",
431 aSize.width, aSize.height, int(aType));
432 NS_RUNTIMEABORT(buf);
436 already_AddRefed<gfxASurface>
437 BasicShadowableThebesLayer::CreateBuffer(Buffer::ContentType aType,
438 const nsIntSize& aSize)
440 if (!HasShadow()) {
441 return BasicThebesLayer::CreateBuffer(aType, aSize);
444 MOZ_LAYERS_LOG(("BasicShadowableThebes(%p): creating %d x %d buffer(x2)",
445 this,
446 aSize.width, aSize.height));
448 if (IsSurfaceDescriptorValid(mBackBuffer)) {
449 BasicManager()->DestroyedThebesBuffer(BasicManager()->Hold(this),
450 mBackBuffer);
451 mBackBuffer = SurfaceDescriptor();
454 AllocBackBuffer(aType, aSize);
456 NS_ABORT_IF_FALSE(!mIsNewBuffer,
457 "Bad! Did we create a buffer twice without painting?");
459 mIsNewBuffer = true;
461 nsRefPtr<gfxASurface> buffer = mBufferTracker->CreatedBuffer(mBackBuffer);
462 return buffer.forget();
465 void
466 BasicShadowableThebesLayer::Disconnect()
468 mBackBuffer = SurfaceDescriptor();
469 BasicShadowableLayer::Disconnect();
473 class BasicShadowThebesLayer : public ShadowThebesLayer, public BasicImplData {
474 public:
475 BasicShadowThebesLayer(BasicShadowLayerManager* aLayerManager)
476 : ShadowThebesLayer(aLayerManager, static_cast<BasicImplData*>(this))
478 MOZ_COUNT_CTOR(BasicShadowThebesLayer);
480 virtual ~BasicShadowThebesLayer()
482 // If Disconnect() wasn't called on us, then we assume that the
483 // remote side shut down and IPC is disconnected, so we let IPDL
484 // clean up our front surface Shmem.
485 MOZ_COUNT_DTOR(BasicShadowThebesLayer);
488 virtual void SetValidRegion(const nsIntRegion& aRegion)
490 mOldValidRegion = mValidRegion;
491 ShadowThebesLayer::SetValidRegion(aRegion);
494 virtual void Disconnect()
496 DestroyFrontBuffer();
497 ShadowThebesLayer::Disconnect();
500 virtual void
501 Swap(const ThebesBuffer& aNewFront, const nsIntRegion& aUpdatedRegion,
502 OptionalThebesBuffer* aNewBack, nsIntRegion* aNewBackValidRegion,
503 OptionalThebesBuffer* aReadOnlyFront, nsIntRegion* aFrontUpdatedRegion);
505 virtual void DestroyFrontBuffer()
507 mFrontBuffer.Clear();
508 mValidRegion.SetEmpty();
509 mOldValidRegion.SetEmpty();
511 if (IsSurfaceDescriptorValid(mFrontBufferDescriptor)) {
512 mAllocator->DestroySharedSurface(&mFrontBufferDescriptor);
516 virtual void PaintThebes(gfxContext* aContext,
517 Layer* aMaskLayer,
518 LayerManager::DrawThebesLayerCallback aCallback,
519 void* aCallbackData,
520 ReadbackProcessor* aReadback);
522 private:
523 BasicShadowLayerManager* BasicManager()
525 return static_cast<BasicShadowLayerManager*>(mManager);
528 ShadowThebesLayerBuffer mFrontBuffer;
529 // Describes the gfxASurface we hand out to |mFrontBuffer|.
530 SurfaceDescriptor mFrontBufferDescriptor;
531 // When we receive an update from our remote partner, we stow away
532 // our previous parameters that described our previous front buffer.
533 // Then when we Swap() back/front buffers, we can return these
534 // parameters to our partner (adjusted as needed).
535 nsIntRegion mOldValidRegion;
538 void
539 BasicShadowThebesLayer::Swap(const ThebesBuffer& aNewFront,
540 const nsIntRegion& aUpdatedRegion,
541 OptionalThebesBuffer* aNewBack,
542 nsIntRegion* aNewBackValidRegion,
543 OptionalThebesBuffer* aReadOnlyFront,
544 nsIntRegion* aFrontUpdatedRegion)
546 if (IsSurfaceDescriptorValid(mFrontBufferDescriptor)) {
547 AutoOpenSurface autoNewFrontBuffer(OPEN_READ_ONLY, aNewFront.buffer());
548 AutoOpenSurface autoCurrentFront(OPEN_READ_ONLY, mFrontBufferDescriptor);
549 if (autoCurrentFront.Size() != autoNewFrontBuffer.Size()) {
550 // Current front buffer is obsolete
551 DestroyFrontBuffer();
554 // This code relies on Swap() arriving *after* attribute mutations.
555 if (IsSurfaceDescriptorValid(mFrontBufferDescriptor)) {
556 *aNewBack = ThebesBuffer();
557 aNewBack->get_ThebesBuffer().buffer() = mFrontBufferDescriptor;
558 } else {
559 *aNewBack = null_t();
561 // We have to invalidate the pixels painted into the new buffer.
562 // They might overlap with our old pixels.
563 aNewBackValidRegion->Sub(mOldValidRegion, aUpdatedRegion);
565 nsIntRect backRect;
566 nsIntPoint backRotation;
567 mFrontBuffer.Swap(
568 aNewFront.rect(), aNewFront.rotation(),
569 &backRect, &backRotation);
571 if (aNewBack->type() != OptionalThebesBuffer::Tnull_t) {
572 aNewBack->get_ThebesBuffer().rect() = backRect;
573 aNewBack->get_ThebesBuffer().rotation() = backRotation;
576 mFrontBufferDescriptor = aNewFront.buffer();
578 *aReadOnlyFront = aNewFront;
579 *aFrontUpdatedRegion = aUpdatedRegion;
582 void
583 BasicShadowThebesLayer::PaintThebes(gfxContext* aContext,
584 Layer* aMaskLayer,
585 LayerManager::DrawThebesLayerCallback aCallback,
586 void* aCallbackData,
587 ReadbackProcessor* aReadback)
589 NS_ASSERTION(BasicManager()->InDrawing(),
590 "Can only draw in drawing phase");
591 NS_ASSERTION(BasicManager()->IsRetained(),
592 "ShadowThebesLayer makes no sense without retained mode");
594 if (!IsSurfaceDescriptorValid(mFrontBufferDescriptor)) {
595 return;
598 AutoOpenSurface autoFrontBuffer(OPEN_READ_ONLY, mFrontBufferDescriptor);
599 mFrontBuffer.ProvideBuffer(&autoFrontBuffer);
601 mFrontBuffer.DrawTo(this, aContext, GetEffectiveOpacity(), aMaskLayer);
603 mFrontBuffer.RevokeBuffer();
606 already_AddRefed<ThebesLayer>
607 BasicLayerManager::CreateThebesLayer()
609 NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
610 nsRefPtr<ThebesLayer> layer = new BasicThebesLayer(this);
611 return layer.forget();
614 already_AddRefed<ShadowThebesLayer>
615 BasicShadowLayerManager::CreateShadowThebesLayer()
617 NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
618 nsRefPtr<ShadowThebesLayer> layer = new BasicShadowThebesLayer(this);
619 return layer.forget();