Line data Source code
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/. */
5 :
6 : #include "BasicCanvasLayer.h"
7 : #include "AsyncCanvasRenderer.h"
8 : #include "basic/BasicLayers.h" // for BasicLayerManager
9 : #include "basic/BasicLayersImpl.h" // for GetEffectiveOperator
10 : #include "mozilla/mozalloc.h" // for operator new
11 : #include "nsCOMPtr.h" // for already_AddRefed
12 : #include "nsISupportsImpl.h" // for Layer::AddRef, etc
13 : #include "gfx2DGlue.h"
14 : #include "GLScreenBuffer.h"
15 : #include "GLContext.h"
16 : #include "gfxUtils.h"
17 : #include "mozilla/layers/PersistentBufferProvider.h"
18 : #include "client/TextureClientSharedSurface.h"
19 :
20 : class gfxContext;
21 :
22 : using namespace mozilla::gfx;
23 : using namespace mozilla::gl;
24 :
25 : namespace mozilla {
26 : namespace layers {
27 :
28 : already_AddRefed<SourceSurface>
29 0 : BasicCanvasLayer::UpdateSurface()
30 : {
31 0 : if (mAsyncRenderer) {
32 0 : MOZ_ASSERT(!mBufferProvider);
33 0 : MOZ_ASSERT(!mGLContext);
34 0 : return mAsyncRenderer->GetSurface();
35 : }
36 :
37 0 : if (!mGLContext) {
38 0 : return nullptr;
39 : }
40 :
41 0 : SharedSurface* frontbuffer = nullptr;
42 0 : if (mGLFrontbuffer) {
43 0 : frontbuffer = mGLFrontbuffer.get();
44 : } else {
45 0 : GLScreenBuffer* screen = mGLContext->Screen();
46 0 : const auto& front = screen->Front();
47 0 : if (front) {
48 0 : frontbuffer = front->Surf();
49 : }
50 : }
51 :
52 0 : if (!frontbuffer) {
53 0 : NS_WARNING("Null frame received.");
54 0 : return nullptr;
55 : }
56 :
57 0 : IntSize readSize(frontbuffer->mSize);
58 0 : SurfaceFormat format = (GetContentFlags() & CONTENT_OPAQUE)
59 0 : ? SurfaceFormat::B8G8R8X8
60 0 : : SurfaceFormat::B8G8R8A8;
61 0 : bool needsPremult = frontbuffer->mHasAlpha && !mIsAlphaPremultiplied;
62 :
63 0 : RefPtr<DataSourceSurface> resultSurf = GetTempSurface(readSize, format);
64 : // There will already be a warning from inside of GetTempSurface, but
65 : // it doesn't hurt to complain:
66 0 : if (NS_WARN_IF(!resultSurf)) {
67 0 : return nullptr;
68 : }
69 :
70 : // Readback handles Flush/MarkDirty.
71 0 : mGLContext->Readback(frontbuffer, resultSurf);
72 0 : if (needsPremult) {
73 0 : gfxUtils::PremultiplyDataSurface(resultSurf, resultSurf);
74 : }
75 0 : MOZ_ASSERT(resultSurf);
76 :
77 0 : return resultSurf.forget();
78 : }
79 :
80 : void
81 0 : BasicCanvasLayer::Paint(DrawTarget* aDT,
82 : const Point& aDeviceOffset,
83 : Layer* aMaskLayer)
84 : {
85 0 : if (IsHidden())
86 0 : return;
87 :
88 0 : RefPtr<SourceSurface> surface;
89 0 : if (IsDirty()) {
90 0 : Painted();
91 :
92 0 : FirePreTransactionCallback();
93 0 : surface = UpdateSurface();
94 0 : FireDidTransactionCallback();
95 : }
96 :
97 0 : bool bufferPoviderSnapshot = false;
98 0 : if (!surface && mBufferProvider) {
99 0 : surface = mBufferProvider->BorrowSnapshot();
100 0 : bufferPoviderSnapshot = !!surface;
101 : }
102 :
103 0 : if (!surface) {
104 0 : return;
105 : }
106 :
107 0 : const bool needsYFlip = (mOriginPos == gl::OriginPos::BottomLeft);
108 :
109 0 : Matrix oldTM;
110 0 : if (needsYFlip) {
111 0 : oldTM = aDT->GetTransform();
112 0 : aDT->SetTransform(Matrix(oldTM).
113 0 : PreTranslate(0.0f, mBounds.height).
114 0 : PreScale(1.0f, -1.0f));
115 : }
116 :
117 0 : FillRectWithMask(aDT, aDeviceOffset,
118 0 : Rect(0, 0, mBounds.width, mBounds.height),
119 : surface, mSamplingFilter,
120 0 : DrawOptions(GetEffectiveOpacity(), GetEffectiveOperator(this)),
121 0 : aMaskLayer);
122 :
123 0 : if (needsYFlip) {
124 0 : aDT->SetTransform(oldTM);
125 : }
126 :
127 0 : if (bufferPoviderSnapshot) {
128 0 : mBufferProvider->ReturnSnapshot(surface.forget());
129 : }
130 : }
131 :
132 : already_AddRefed<CanvasLayer>
133 0 : BasicLayerManager::CreateCanvasLayer()
134 : {
135 0 : NS_ASSERTION(InConstruction(), "Only allowed in construction phase");
136 0 : RefPtr<CanvasLayer> layer = new BasicCanvasLayer(this);
137 0 : return layer.forget();
138 : }
139 :
140 : } // namespace layers
141 : } // namespace mozilla
|