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/. */
6 #include "mozilla/layers/CanvasClient.h"
7 #include "ClientCanvasLayer.h" // for ClientCanvasLayer
8 #include "CompositorChild.h" // for CompositorChild
9 #include "GLContext.h" // for GLContext
10 #include "GLScreenBuffer.h" // for GLScreenBuffer
11 #include "SurfaceStream.h" // for SurfaceStream
12 #include "SurfaceTypes.h" // for SurfaceStreamHandle
13 #include "gfx2DGlue.h" // for ImageFormatToSurfaceFormat
14 #include "gfxPlatform.h" // for gfxPlatform
15 #include "mozilla/gfx/BaseSize.h" // for BaseSize
16 #include "mozilla/layers/CompositableForwarder.h"
17 #include "mozilla/layers/GrallocTextureClient.h"
18 #include "mozilla/layers/LayersTypes.h"
19 #include "mozilla/layers/TextureClient.h" // for TextureClient, etc
20 #include "mozilla/layers/TextureClientOGL.h"
21 #include "nsAutoPtr.h" // for nsRefPtr
22 #include "nsDebug.h" // for printf_stderr, NS_ASSERTION
23 #include "nsXULAppAPI.h" // for XRE_GetProcessType, etc
24 #ifdef MOZ_WIDGET_GONK
25 #include "SharedSurfaceGralloc.h"
28 using namespace mozilla::gfx
;
29 using namespace mozilla::gl
;
34 /* static */ TemporaryRef
<CanvasClient
>
35 CanvasClient::CreateCanvasClient(CanvasClientType aType
,
36 CompositableForwarder
* aForwarder
,
39 #ifndef MOZ_WIDGET_GONK
40 if (XRE_GetProcessType() != GeckoProcessType_Default
) {
41 NS_WARNING("Most platforms still need an optimized way to share GL cross process.");
42 return new CanvasClient2D(aForwarder
, aFlags
);
45 if (aType
== CanvasClientGLContext
&&
46 aForwarder
->GetCompositorBackendType() == LayersBackend::LAYERS_OPENGL
) {
47 aFlags
|= TextureFlags::DEALLOCATE_CLIENT
;
48 return new CanvasClientSurfaceStream(aForwarder
, aFlags
);
50 return new CanvasClient2D(aForwarder
, aFlags
);
54 CanvasClient2D::Update(gfx::IntSize aSize
, ClientCanvasLayer
* aLayer
)
56 AutoRemoveTexture
autoRemove(this);
58 (mBuffer
->IsImmutable() || mBuffer
->GetSize() != aSize
)) {
59 autoRemove
.mTexture
= mBuffer
;
63 bool bufferCreated
= false;
65 bool isOpaque
= (aLayer
->GetContentFlags() & Layer::CONTENT_OPAQUE
);
66 gfxContentType contentType
= isOpaque
67 ? gfxContentType::COLOR
68 : gfxContentType::COLOR_ALPHA
;
70 = gfxPlatform::GetPlatform()->OptimalFormatForContent(contentType
);
71 TextureFlags flags
= TextureFlags::DEFAULT
;
72 if (mTextureFlags
& TextureFlags::NEEDS_Y_FLIP
) {
73 flags
|= TextureFlags::NEEDS_Y_FLIP
;
76 gfx::SurfaceFormat surfaceFormat
= gfx::ImageFormatToSurfaceFormat(format
);
77 mBuffer
= CreateTextureClientForCanvas(surfaceFormat
, aSize
, flags
, aLayer
);
78 MOZ_ASSERT(mBuffer
->CanExposeDrawTarget());
79 mBuffer
->AllocateForSurface(aSize
);
84 if (!mBuffer
->Lock(OpenMode::OPEN_WRITE_ONLY
)) {
91 // Restrict drawTarget to a scope so that terminates before Unlock.
92 RefPtr
<DrawTarget
> target
=
93 mBuffer
->BorrowDrawTarget();
95 aLayer
->UpdateTarget(target
);
101 if (bufferCreated
&& !AddTextureClient(mBuffer
)) {
107 GetForwarder()->UpdatedTexture(this, mBuffer
, nullptr);
108 GetForwarder()->UseTexture(this, mBuffer
);
112 TemporaryRef
<TextureClient
>
113 CanvasClient2D::CreateTextureClientForCanvas(gfx::SurfaceFormat aFormat
,
116 ClientCanvasLayer
* aLayer
)
118 if (aLayer
->IsGLLayer()) {
119 // We want a cairo backend here as we don't want to be copying into
120 // an accelerated backend and we like LockBits to work. This is currently
121 // the most effective way to make this work.
122 return CreateBufferTextureClient(aFormat
, aFlags
, BackendType::CAIRO
);
125 gfx::BackendType backend
= gfxPlatform::GetPlatform()->GetPreferredCanvasBackend();
127 return CreateTextureClientForDrawing(aFormat
, aFlags
, backend
, aSize
);
129 // XXX - We should use CreateTextureClientForDrawing, but we first need
130 // to use double buffering.
131 return CreateBufferTextureClient(aFormat
, aFlags
, backend
);
135 CanvasClientSurfaceStream::CanvasClientSurfaceStream(CompositableForwarder
* aLayerForwarder
,
137 : CanvasClient(aLayerForwarder
, aFlags
)
142 CanvasClientSurfaceStream::Update(gfx::IntSize aSize
, ClientCanvasLayer
* aLayer
)
144 aLayer
->mGLContext
->MakeCurrent();
145 GLScreenBuffer
* screen
= aLayer
->mGLContext
->Screen();
146 SurfaceStream
* stream
= nullptr;
148 if (aLayer
->mStream
) {
149 stream
= aLayer
->mStream
;
151 // Copy our current surface to the current producer surface in our stream, then
152 // call SwapProducer to make a new buffer ready.
153 stream
->CopySurfaceToProducer(aLayer
->mTextureSurface
, aLayer
->mFactory
);
154 stream
->SwapProducer(aLayer
->mFactory
, gfx::IntSize(aSize
.width
, aSize
.height
));
156 stream
= screen
->Stream();
159 bool isCrossProcess
= !(XRE_GetProcessType() == GeckoProcessType_Default
);
160 bool bufferCreated
= false;
161 if (isCrossProcess
) {
162 #ifdef MOZ_WIDGET_GONK
163 SharedSurface
* surf
= stream
->SwapConsumer();
165 printf_stderr("surf is null post-SwapConsumer!\n");
169 if (surf
->Type() != SharedSurfaceType::Gralloc
) {
170 printf_stderr("Unexpected non-Gralloc SharedSurface in IPC path!");
175 SharedSurface_Gralloc
* grallocSurf
= SharedSurface_Gralloc::Cast(surf
);
177 RefPtr
<GrallocTextureClientOGL
> grallocTextureClient
=
178 static_cast<GrallocTextureClientOGL
*>(grallocSurf
->GetTextureClient());
180 // If IPDLActor is null means this TextureClient didn't AddTextureClient yet
181 if (!grallocTextureClient
->GetIPDLActor()) {
182 grallocTextureClient
->SetTextureFlags(mTextureInfo
.mTextureFlags
);
183 AddTextureClient(grallocTextureClient
);
186 if (grallocTextureClient
->GetIPDLActor()) {
187 UseTexture(grallocTextureClient
);
191 // remove old buffer from CompositableHost
192 RefPtr
<AsyncTransactionTracker
> tracker
= new RemoveTextureFromCompositableTracker();
193 // Hold TextureClient until transaction complete.
194 tracker
->SetTextureClient(mBuffer
);
195 mBuffer
->SetRemoveFromCompositableTracker(tracker
);
196 // RemoveTextureFromCompositableAsync() expects CompositorChild's presence.
197 GetForwarder()->RemoveTextureFromCompositableAsync(tracker
, this, mBuffer
);
199 mBuffer
= grallocTextureClient
;
201 printf_stderr("isCrossProcess, but not MOZ_WIDGET_GONK! Someone needs to write some code!");
206 StreamTextureClientOGL
* textureClient
=
207 new StreamTextureClientOGL(mTextureInfo
.mTextureFlags
);
208 textureClient
->InitWith(stream
);
209 mBuffer
= textureClient
;
210 bufferCreated
= true;
213 if (bufferCreated
&& !AddTextureClient(mBuffer
)) {
218 GetForwarder()->UseTexture(this, mBuffer
);