1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #include "WebRenderTextureHost.h"
8 
9 #include "mozilla/layers/ImageDataSerializer.h"
10 #include "mozilla/layers/LayersSurfaces.h"
11 #include "mozilla/layers/TextureSourceProvider.h"
12 #include "mozilla/webrender/RenderThread.h"
13 #include "mozilla/webrender/WebRenderAPI.h"
14 
15 #ifdef MOZ_WIDGET_ANDROID
16 #  include "mozilla/layers/TextureHostOGL.h"
17 #endif
18 
19 namespace mozilla::layers {
20 
21 class ScheduleHandleRenderTextureOps : public wr::NotificationHandler {
22  public:
ScheduleHandleRenderTextureOps()23   explicit ScheduleHandleRenderTextureOps() {}
24 
Notify(wr::Checkpoint aCheckpoint)25   virtual void Notify(wr::Checkpoint aCheckpoint) override {
26     if (aCheckpoint == wr::Checkpoint::FrameTexturesUpdated) {
27       MOZ_ASSERT(wr::RenderThread::IsInRenderThread());
28       wr::RenderThread::Get()->HandleRenderTextureOps();
29     } else {
30       MOZ_ASSERT(aCheckpoint == wr::Checkpoint::TransactionDropped);
31     }
32   }
33 
34  protected:
35 };
36 
WebRenderTextureHost(const SurfaceDescriptor & aDesc,TextureFlags aFlags,TextureHost * aTexture,wr::ExternalImageId & aExternalImageId)37 WebRenderTextureHost::WebRenderTextureHost(
38     const SurfaceDescriptor& aDesc, TextureFlags aFlags, TextureHost* aTexture,
39     wr::ExternalImageId& aExternalImageId)
40     : TextureHost(aFlags), mWrappedTextureHost(aTexture) {
41   // The wrapped textureHost will be used in WebRender, and the WebRender could
42   // run at another thread. It's hard to control the life-time when gecko
43   // receives PTextureParent destroy message. It's possible that textureHost is
44   // still used by WebRender. So, we only accept the textureHost without
45   // DEALLOCATE_CLIENT flag here. If the buffer deallocation is controlled by
46   // parent, we could do something to make sure the wrapped textureHost is not
47   // used by WebRender and then release it.
48   MOZ_ASSERT(!(aFlags & TextureFlags::DEALLOCATE_CLIENT));
49   MOZ_ASSERT(mWrappedTextureHost);
50 
51   MOZ_COUNT_CTOR(WebRenderTextureHost);
52 
53   mExternalImageId = Some(aExternalImageId);
54 }
55 
~WebRenderTextureHost()56 WebRenderTextureHost::~WebRenderTextureHost() {
57   MOZ_COUNT_DTOR(WebRenderTextureHost);
58 }
59 
GetExternalImageKey()60 wr::ExternalImageId WebRenderTextureHost::GetExternalImageKey() {
61   if (IsValid()) {
62     mWrappedTextureHost->EnsureRenderTexture(mExternalImageId);
63   }
64   MOZ_ASSERT(mWrappedTextureHost->mExternalImageId.isSome());
65   return mWrappedTextureHost->mExternalImageId.ref();
66 }
67 
IsValid()68 bool WebRenderTextureHost::IsValid() { return mWrappedTextureHost->IsValid(); }
69 
Lock()70 bool WebRenderTextureHost::Lock() {
71   MOZ_ASSERT(mWrappedTextureHost->AsBufferTextureHost());
72 
73   if (mWrappedTextureHost->AsBufferTextureHost()) {
74     return mWrappedTextureHost->Lock();
75   }
76   return false;
77 }
78 
Unlock()79 void WebRenderTextureHost::Unlock() {
80   MOZ_ASSERT(mWrappedTextureHost->AsBufferTextureHost());
81 
82   if (mWrappedTextureHost->AsBufferTextureHost()) {
83     mWrappedTextureHost->Unlock();
84   }
85 }
86 
PrepareTextureSource(CompositableTextureSourceRef & aTexture)87 void WebRenderTextureHost::PrepareTextureSource(
88     CompositableTextureSourceRef& aTexture) {
89   MOZ_ASSERT(mWrappedTextureHost->AsBufferTextureHost());
90 
91   if (mWrappedTextureHost->AsBufferTextureHost()) {
92     mWrappedTextureHost->PrepareTextureSource(aTexture);
93   }
94 }
95 
BindTextureSource(CompositableTextureSourceRef & aTexture)96 bool WebRenderTextureHost::BindTextureSource(
97     CompositableTextureSourceRef& aTexture) {
98   MOZ_ASSERT(mWrappedTextureHost->AsBufferTextureHost());
99 
100   if (mWrappedTextureHost->AsBufferTextureHost()) {
101     return mWrappedTextureHost->BindTextureSource(aTexture);
102   }
103   return false;
104 }
105 
UnbindTextureSource()106 void WebRenderTextureHost::UnbindTextureSource() {
107   if (mWrappedTextureHost->AsBufferTextureHost()) {
108     mWrappedTextureHost->UnbindTextureSource();
109   }
110   // Handle read unlock
111   TextureHost::UnbindTextureSource();
112 }
113 
SetTextureSourceProvider(TextureSourceProvider * aProvider)114 void WebRenderTextureHost::SetTextureSourceProvider(
115     TextureSourceProvider* aProvider) {
116   // During using WebRender, only BasicCompositor could exist
117   MOZ_ASSERT(!aProvider || aProvider->AsBasicCompositor());
118   MOZ_ASSERT(mWrappedTextureHost->AsBufferTextureHost());
119 
120   if (mWrappedTextureHost->AsBufferTextureHost()) {
121     mWrappedTextureHost->SetTextureSourceProvider(aProvider);
122   }
123 }
124 
GetAsSurface()125 already_AddRefed<gfx::DataSourceSurface> WebRenderTextureHost::GetAsSurface() {
126   return mWrappedTextureHost->GetAsSurface();
127 }
128 
GetYUVColorSpace() const129 gfx::YUVColorSpace WebRenderTextureHost::GetYUVColorSpace() const {
130   return mWrappedTextureHost->GetYUVColorSpace();
131 }
132 
GetColorRange() const133 gfx::ColorRange WebRenderTextureHost::GetColorRange() const {
134   return mWrappedTextureHost->GetColorRange();
135 }
136 
GetSize() const137 gfx::IntSize WebRenderTextureHost::GetSize() const {
138   return mWrappedTextureHost->GetSize();
139 }
140 
GetFormat() const141 gfx::SurfaceFormat WebRenderTextureHost::GetFormat() const {
142   return mWrappedTextureHost->GetFormat();
143 }
144 
NotifyNotUsed()145 void WebRenderTextureHost::NotifyNotUsed() {
146 #ifdef MOZ_WIDGET_ANDROID
147   if (mWrappedTextureHost->AsSurfaceTextureHost()) {
148     wr::RenderThread::Get()->NotifyNotUsed(wr::AsUint64(GetExternalImageKey()));
149   }
150 #endif
151   TextureHost::NotifyNotUsed();
152 }
153 
MaybeNotifyForUse(wr::TransactionBuilder & aTxn)154 void WebRenderTextureHost::MaybeNotifyForUse(wr::TransactionBuilder& aTxn) {
155 #if defined(MOZ_WIDGET_ANDROID)
156   if (mWrappedTextureHost->AsSurfaceTextureHost()) {
157     wr::RenderThread::Get()->NotifyForUse(wr::AsUint64(GetExternalImageKey()));
158     aTxn.Notify(wr::Checkpoint::FrameTexturesUpdated,
159                 MakeUnique<ScheduleHandleRenderTextureOps>());
160   }
161 #endif
162 }
163 
PrepareForUse()164 void WebRenderTextureHost::PrepareForUse() {
165   if (mWrappedTextureHost->AsSurfaceTextureHost() ||
166       mWrappedTextureHost->AsBufferTextureHost()) {
167     // Call PrepareForUse on render thread.
168     // See RenderAndroidSurfaceTextureHostOGL::PrepareForUse.
169     wr::RenderThread::Get()->PrepareForUse(wr::AsUint64(GetExternalImageKey()));
170   }
171 }
172 
GetReadFormat() const173 gfx::SurfaceFormat WebRenderTextureHost::GetReadFormat() const {
174   return mWrappedTextureHost->GetReadFormat();
175 }
176 
GetRGBStride()177 int32_t WebRenderTextureHost::GetRGBStride() {
178   gfx::SurfaceFormat format = GetFormat();
179   if (GetFormat() == gfx::SurfaceFormat::YUV) {
180     // XXX this stride is used until yuv image rendering by webrender is used.
181     // Software converted RGB buffers strides are aliened to 16
182     return gfx::GetAlignedStride<16>(
183         GetSize().width, BytesPerPixel(gfx::SurfaceFormat::B8G8R8A8));
184   }
185   return ImageDataSerializer::ComputeRGBStride(format, GetSize().width);
186 }
187 
HasIntermediateBuffer() const188 bool WebRenderTextureHost::HasIntermediateBuffer() const {
189   return mWrappedTextureHost->HasIntermediateBuffer();
190 }
191 
NeedsDeferredDeletion() const192 bool WebRenderTextureHost::NeedsDeferredDeletion() const {
193   return mWrappedTextureHost->NeedsDeferredDeletion();
194 }
195 
NumSubTextures()196 uint32_t WebRenderTextureHost::NumSubTextures() {
197   return mWrappedTextureHost->NumSubTextures();
198 }
199 
PushResourceUpdates(wr::TransactionBuilder & aResources,ResourceUpdateOp aOp,const Range<wr::ImageKey> & aImageKeys,const wr::ExternalImageId & aExtID)200 void WebRenderTextureHost::PushResourceUpdates(
201     wr::TransactionBuilder& aResources, ResourceUpdateOp aOp,
202     const Range<wr::ImageKey>& aImageKeys, const wr::ExternalImageId& aExtID) {
203   MOZ_ASSERT(GetExternalImageKey() == aExtID);
204 
205   mWrappedTextureHost->PushResourceUpdates(aResources, aOp, aImageKeys, aExtID);
206 }
207 
PushDisplayItems(wr::DisplayListBuilder & aBuilder,const wr::LayoutRect & aBounds,const wr::LayoutRect & aClip,wr::ImageRendering aFilter,const Range<wr::ImageKey> & aImageKeys,PushDisplayItemFlagSet aFlags)208 void WebRenderTextureHost::PushDisplayItems(
209     wr::DisplayListBuilder& aBuilder, const wr::LayoutRect& aBounds,
210     const wr::LayoutRect& aClip, wr::ImageRendering aFilter,
211     const Range<wr::ImageKey>& aImageKeys, PushDisplayItemFlagSet aFlags) {
212   MOZ_ASSERT(aImageKeys.length() > 0);
213 
214   mWrappedTextureHost->PushDisplayItems(aBuilder, aBounds, aClip, aFilter,
215                                         aImageKeys, aFlags);
216 }
217 
SupportsExternalCompositing(WebRenderBackend aBackend)218 bool WebRenderTextureHost::SupportsExternalCompositing(
219     WebRenderBackend aBackend) {
220   return mWrappedTextureHost->SupportsExternalCompositing(aBackend);
221 }
222 
NeedsYFlip() const223 bool WebRenderTextureHost::NeedsYFlip() const {
224   bool yFlip = TextureHost::NeedsYFlip();
225   if (mWrappedTextureHost->AsSurfaceTextureHost()) {
226     MOZ_ASSERT(yFlip);
227     // With WebRender, SurfaceTextureHost always requests y-flip.
228     // But y-flip should not be handled, since
229     // SurfaceTexture.getTransformMatrix() is not handled yet.
230     // See Bug 1507076.
231     yFlip = false;
232   }
233   return yFlip;
234 }
235 
SetAcquireFence(mozilla::ipc::FileDescriptor && aFenceFd)236 void WebRenderTextureHost::SetAcquireFence(
237     mozilla::ipc::FileDescriptor&& aFenceFd) {
238   mWrappedTextureHost->SetAcquireFence(std::move(aFenceFd));
239 }
240 
SetReleaseFence(mozilla::ipc::FileDescriptor && aFenceFd)241 void WebRenderTextureHost::SetReleaseFence(
242     mozilla::ipc::FileDescriptor&& aFenceFd) {
243   mWrappedTextureHost->SetReleaseFence(std::move(aFenceFd));
244 }
245 
GetAndResetReleaseFence()246 mozilla::ipc::FileDescriptor WebRenderTextureHost::GetAndResetReleaseFence() {
247   return mWrappedTextureHost->GetAndResetReleaseFence();
248 }
249 
GetAndroidHardwareBuffer() const250 AndroidHardwareBuffer* WebRenderTextureHost::GetAndroidHardwareBuffer() const {
251   return mWrappedTextureHost->GetAndroidHardwareBuffer();
252 }
253 
254 }  // namespace mozilla::layers
255