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 "GPUVideoTextureHost.h"
8
9 #include "ImageContainer.h"
10 #include "mozilla/RemoteDecoderManagerParent.h"
11 #include "mozilla/layers/ImageBridgeParent.h"
12 #include "mozilla/layers/VideoBridgeParent.h"
13 #include "mozilla/webrender/RenderTextureHostWrapper.h"
14 #include "mozilla/webrender/RenderThread.h"
15
16 namespace mozilla {
17 namespace layers {
18
GPUVideoTextureHost(TextureFlags aFlags,const SurfaceDescriptorGPUVideo & aDescriptor)19 GPUVideoTextureHost::GPUVideoTextureHost(
20 TextureFlags aFlags, const SurfaceDescriptorGPUVideo& aDescriptor)
21 : TextureHost(aFlags), mDescriptor(aDescriptor) {
22 MOZ_COUNT_CTOR(GPUVideoTextureHost);
23 }
24
~GPUVideoTextureHost()25 GPUVideoTextureHost::~GPUVideoTextureHost() {
26 MOZ_COUNT_DTOR(GPUVideoTextureHost);
27 }
28
CreateFromDescriptor(TextureFlags aFlags,const SurfaceDescriptorGPUVideo & aDescriptor)29 GPUVideoTextureHost* GPUVideoTextureHost::CreateFromDescriptor(
30 TextureFlags aFlags, const SurfaceDescriptorGPUVideo& aDescriptor) {
31 return new GPUVideoTextureHost(aFlags, aDescriptor);
32 }
33
EnsureWrappedTextureHost()34 TextureHost* GPUVideoTextureHost::EnsureWrappedTextureHost() {
35 if (mWrappedTextureHost) {
36 return mWrappedTextureHost;
37 }
38
39 const auto& sd =
40 static_cast<const SurfaceDescriptorRemoteDecoder&>(mDescriptor);
41 VideoBridgeParent* parent = VideoBridgeParent::GetSingleton(sd.source());
42 if (!parent) {
43 // The VideoBridge went away. This can happen if the RDD process
44 // crashes.
45 return nullptr;
46 }
47 mWrappedTextureHost = parent->LookupTexture(sd.handle());
48
49 if (!mWrappedTextureHost) {
50 // The TextureHost hasn't been registered yet. This is due to a race
51 // between the ImageBridge (content) and the VideoBridge (RDD) and the
52 // ImageBridge won. See bug
53 // https://bugzilla.mozilla.org/show_bug.cgi?id=1630733#c14 for more
54 // details.
55 return nullptr;
56 }
57
58 if (mWrappedTextureHost->AsBufferTextureHost()) {
59 // TODO(miko): This code path is taken when WebRenderTextureHost wraps
60 // GPUVideoTextureHost, which wraps BufferTextureHost.
61 // Because this creates additional copies of the texture data, we should not
62 // do this.
63 mWrappedTextureHost->AsBufferTextureHost()->DisableExternalTextures();
64 }
65
66 if (mExternalImageId.isSome()) {
67 // External image id is allocated by mWrappedTextureHost.
68 mWrappedTextureHost->EnsureRenderTexture(Nothing());
69 MOZ_ASSERT(mWrappedTextureHost->mExternalImageId.isSome());
70 auto wrappedId = mWrappedTextureHost->mExternalImageId.ref();
71
72 RefPtr<wr::RenderTextureHost> texture =
73 new wr::RenderTextureHostWrapper(wrappedId);
74 wr::RenderThread::Get()->RegisterExternalImage(
75 wr::AsUint64(mExternalImageId.ref()), texture.forget());
76 }
77
78 if (mPendingSourceProvider) {
79 RefPtr<TextureSourceProvider> provider = mPendingSourceProvider.forget();
80 mWrappedTextureHost->SetTextureSourceProvider(provider);
81 }
82 if (mPendingUpdatedInternal) {
83 mWrappedTextureHost->UpdatedInternal(mPendingIntRegion.ptrOr(nullptr));
84 mPendingIntRegion.reset();
85 mPendingUpdatedInternal = false;
86 }
87 if (mPendingPrepareTextureSource) {
88 mWrappedTextureHost->PrepareTextureSource(*mPendingPrepareTextureSource);
89 mPendingPrepareTextureSource.reset();
90 }
91
92 return mWrappedTextureHost;
93 }
94
IsValid()95 bool GPUVideoTextureHost::IsValid() { return !!EnsureWrappedTextureHost(); }
96
Lock()97 bool GPUVideoTextureHost::Lock() {
98 if (!EnsureWrappedTextureHost()) {
99 return false;
100 }
101 return EnsureWrappedTextureHost()->Lock();
102 }
103
Unlock()104 void GPUVideoTextureHost::Unlock() {
105 if (!EnsureWrappedTextureHost()) {
106 return;
107 }
108 EnsureWrappedTextureHost()->Unlock();
109 }
110
PrepareTextureSource(CompositableTextureSourceRef & aTexture)111 void GPUVideoTextureHost::PrepareTextureSource(
112 CompositableTextureSourceRef& aTexture) {
113 if (!EnsureWrappedTextureHost()) {
114 mPendingPrepareTextureSource = Some(aTexture);
115 return;
116 }
117 EnsureWrappedTextureHost()->PrepareTextureSource(aTexture);
118 }
119
BindTextureSource(CompositableTextureSourceRef & aTexture)120 bool GPUVideoTextureHost::BindTextureSource(
121 CompositableTextureSourceRef& aTexture) {
122 MOZ_ASSERT(EnsureWrappedTextureHost(), "Image isn't valid yet");
123 if (!EnsureWrappedTextureHost()) {
124 return false;
125 }
126 return EnsureWrappedTextureHost()->BindTextureSource(aTexture);
127 }
128
AcquireTextureSource(CompositableTextureSourceRef & aTexture)129 bool GPUVideoTextureHost::AcquireTextureSource(
130 CompositableTextureSourceRef& aTexture) {
131 MOZ_ASSERT(EnsureWrappedTextureHost(), "Image isn't valid yet");
132 if (!EnsureWrappedTextureHost()) {
133 return false;
134 }
135 return EnsureWrappedTextureHost()->AcquireTextureSource(aTexture);
136 }
137
SetTextureSourceProvider(TextureSourceProvider * aProvider)138 void GPUVideoTextureHost::SetTextureSourceProvider(
139 TextureSourceProvider* aProvider) {
140 if (!EnsureWrappedTextureHost()) {
141 mPendingSourceProvider = aProvider;
142 return;
143 }
144 EnsureWrappedTextureHost()->SetTextureSourceProvider(aProvider);
145 }
146
GetYUVColorSpace() const147 gfx::YUVColorSpace GPUVideoTextureHost::GetYUVColorSpace() const {
148 MOZ_ASSERT(mWrappedTextureHost, "Image isn't valid yet");
149 if (!mWrappedTextureHost) {
150 return TextureHost::GetYUVColorSpace();
151 }
152 return mWrappedTextureHost->GetYUVColorSpace();
153 }
154
GetColorDepth() const155 gfx::ColorDepth GPUVideoTextureHost::GetColorDepth() const {
156 MOZ_ASSERT(mWrappedTextureHost, "Image isn't valid yet");
157 if (!mWrappedTextureHost) {
158 return TextureHost::GetColorDepth();
159 }
160 return mWrappedTextureHost->GetColorDepth();
161 }
162
GetColorRange() const163 gfx::ColorRange GPUVideoTextureHost::GetColorRange() const {
164 MOZ_ASSERT(mWrappedTextureHost, "Image isn't valid yet");
165 if (!mWrappedTextureHost) {
166 return TextureHost::GetColorRange();
167 }
168 return mWrappedTextureHost->GetColorRange();
169 }
170
GetSize() const171 gfx::IntSize GPUVideoTextureHost::GetSize() const {
172 MOZ_ASSERT(mWrappedTextureHost, "Image isn't valid yet");
173 if (!mWrappedTextureHost) {
174 return gfx::IntSize();
175 }
176 return mWrappedTextureHost->GetSize();
177 }
178
GetFormat() const179 gfx::SurfaceFormat GPUVideoTextureHost::GetFormat() const {
180 MOZ_ASSERT(mWrappedTextureHost, "Image isn't valid yet");
181 if (!mWrappedTextureHost) {
182 return gfx::SurfaceFormat::UNKNOWN;
183 }
184 return mWrappedTextureHost->GetFormat();
185 }
186
HasIntermediateBuffer() const187 bool GPUVideoTextureHost::HasIntermediateBuffer() const {
188 MOZ_ASSERT(mWrappedTextureHost, "Image isn't valid yet");
189 if (!mWrappedTextureHost) {
190 return false;
191 }
192 return mWrappedTextureHost->HasIntermediateBuffer();
193 }
194
UpdatedInternal(const nsIntRegion * Region)195 void GPUVideoTextureHost::UpdatedInternal(const nsIntRegion* Region) {
196 if (!EnsureWrappedTextureHost()) {
197 mPendingUpdatedInternal = true;
198 if (Region) {
199 mPendingIntRegion = Some(*Region);
200 } else {
201 mPendingIntRegion.reset();
202 }
203 return;
204 }
205 EnsureWrappedTextureHost()->UpdatedInternal(Region);
206 }
207
CreateRenderTexture(const wr::ExternalImageId & aExternalImageId)208 void GPUVideoTextureHost::CreateRenderTexture(
209 const wr::ExternalImageId& aExternalImageId) {
210 MOZ_ASSERT(mExternalImageId.isSome());
211
212 // When mWrappedTextureHost already exist, call CreateRenderTexture() here.
213 // In other cases, EnsureWrappedTextureHost() handles CreateRenderTexture().
214
215 if (mWrappedTextureHost) {
216 // External image id is allocated by mWrappedTextureHost.
217 mWrappedTextureHost->EnsureRenderTexture(Nothing());
218 MOZ_ASSERT(mWrappedTextureHost->mExternalImageId.isSome());
219 auto wrappedId = mWrappedTextureHost->mExternalImageId.ref();
220
221 RefPtr<wr::RenderTextureHost> texture =
222 new wr::RenderTextureHostWrapper(wrappedId);
223 wr::RenderThread::Get()->RegisterExternalImage(
224 wr::AsUint64(mExternalImageId.ref()), texture.forget());
225 return;
226 }
227
228 EnsureWrappedTextureHost();
229 }
230
MaybeDestroyRenderTexture()231 void GPUVideoTextureHost::MaybeDestroyRenderTexture() {
232 if (mExternalImageId.isNothing() || !mWrappedTextureHost) {
233 // RenderTextureHost was not created
234 return;
235 }
236 // When GPUVideoTextureHost created RenderTextureHost, delete it here.
237 TextureHost::DestroyRenderTexture(mExternalImageId.ref());
238 }
239
NumSubTextures()240 uint32_t GPUVideoTextureHost::NumSubTextures() {
241 if (!EnsureWrappedTextureHost()) {
242 return 0;
243 }
244 return EnsureWrappedTextureHost()->NumSubTextures();
245 }
246
PushResourceUpdates(wr::TransactionBuilder & aResources,ResourceUpdateOp aOp,const Range<wr::ImageKey> & aImageKeys,const wr::ExternalImageId & aExtID)247 void GPUVideoTextureHost::PushResourceUpdates(
248 wr::TransactionBuilder& aResources, ResourceUpdateOp aOp,
249 const Range<wr::ImageKey>& aImageKeys, const wr::ExternalImageId& aExtID) {
250 MOZ_ASSERT(EnsureWrappedTextureHost(), "Image isn't valid yet");
251 if (!EnsureWrappedTextureHost()) {
252 return;
253 }
254 EnsureWrappedTextureHost()->PushResourceUpdates(aResources, aOp, aImageKeys,
255 aExtID);
256 }
257
PushDisplayItems(wr::DisplayListBuilder & aBuilder,const wr::LayoutRect & aBounds,const wr::LayoutRect & aClip,wr::ImageRendering aFilter,const Range<wr::ImageKey> & aImageKeys,PushDisplayItemFlagSet aFlags)258 void GPUVideoTextureHost::PushDisplayItems(
259 wr::DisplayListBuilder& aBuilder, const wr::LayoutRect& aBounds,
260 const wr::LayoutRect& aClip, wr::ImageRendering aFilter,
261 const Range<wr::ImageKey>& aImageKeys, PushDisplayItemFlagSet aFlags) {
262 MOZ_ASSERT(EnsureWrappedTextureHost(), "Image isn't valid yet");
263 MOZ_ASSERT(aImageKeys.length() > 0);
264 if (!EnsureWrappedTextureHost()) {
265 return;
266 }
267
268 EnsureWrappedTextureHost()->PushDisplayItems(aBuilder, aBounds, aClip,
269 aFilter, aImageKeys, aFlags);
270 }
271
SupportsExternalCompositing(WebRenderBackend aBackend)272 bool GPUVideoTextureHost::SupportsExternalCompositing(
273 WebRenderBackend aBackend) {
274 if (!EnsureWrappedTextureHost()) {
275 return false;
276 }
277 return EnsureWrappedTextureHost()->SupportsExternalCompositing(aBackend);
278 }
279
UnbindTextureSource()280 void GPUVideoTextureHost::UnbindTextureSource() {
281 if (EnsureWrappedTextureHost()) {
282 EnsureWrappedTextureHost()->UnbindTextureSource();
283 }
284 // Handle read unlock
285 TextureHost::UnbindTextureSource();
286 }
287
NotifyNotUsed()288 void GPUVideoTextureHost::NotifyNotUsed() {
289 if (EnsureWrappedTextureHost()) {
290 EnsureWrappedTextureHost()->NotifyNotUsed();
291 }
292 TextureHost::NotifyNotUsed();
293 }
294
295 } // namespace layers
296 } // namespace mozilla
297