Line data Source code
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/. */
5 :
6 : #include "TextureHost.h"
7 :
8 : #include "CompositableHost.h" // for CompositableHost
9 : #include "LayerScope.h"
10 : #include "LayersLogging.h" // for AppendToString
11 : #include "mozilla/gfx/2D.h" // for DataSourceSurface, Factory
12 : #include "mozilla/gfx/gfxVars.h"
13 : #include "mozilla/ipc/Shmem.h" // for Shmem
14 : #include "mozilla/layers/CompositableTransactionParent.h" // for CompositableParentManager
15 : #include "mozilla/layers/CompositorBridgeParent.h"
16 : #include "mozilla/layers/Compositor.h" // for Compositor
17 : #include "mozilla/layers/ISurfaceAllocator.h" // for ISurfaceAllocator
18 : #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc
19 : #include "mozilla/layers/TextureHostBasic.h"
20 : #include "mozilla/layers/TextureHostOGL.h" // for TextureHostOGL
21 : #include "mozilla/layers/ImageDataSerializer.h"
22 : #include "mozilla/layers/TextureClient.h"
23 : #include "mozilla/layers/GPUVideoTextureHost.h"
24 : #include "mozilla/layers/WebRenderTextureHost.h"
25 : #include "mozilla/webrender/RenderBufferTextureHost.h"
26 : #include "mozilla/webrender/RenderThread.h"
27 : #include "mozilla/webrender/WebRenderAPI.h"
28 : #include "nsAString.h"
29 : #include "mozilla/RefPtr.h" // for nsRefPtr
30 : #include "nsPrintfCString.h" // for nsPrintfCString
31 : #include "mozilla/layers/PTextureParent.h"
32 : #include "mozilla/Unused.h"
33 : #include <limits>
34 : #include "../opengl/CompositorOGL.h"
35 : #include "gfxPrefs.h"
36 : #include "gfxUtils.h"
37 : #include "IPDLActor.h"
38 :
39 : #ifdef MOZ_ENABLE_D3D10_LAYER
40 : #include "../d3d11/CompositorD3D11.h"
41 : #endif
42 :
43 : #ifdef MOZ_X11
44 : #include "mozilla/layers/X11TextureHost.h"
45 : #endif
46 :
47 : #ifdef XP_MACOSX
48 : #include "../opengl/MacIOSurfaceTextureHostOGL.h"
49 : #endif
50 :
51 : #ifdef XP_WIN
52 : #include "mozilla/layers/TextureDIB.h"
53 : #endif
54 :
55 : #if 0
56 : #define RECYCLE_LOG(...) printf_stderr(__VA_ARGS__)
57 : #else
58 : #define RECYCLE_LOG(...) do { } while (0)
59 : #endif
60 :
61 : namespace mozilla {
62 : namespace layers {
63 :
64 : /**
65 : * TextureParent is the host-side IPDL glue between TextureClient and TextureHost.
66 : * It is an IPDL actor just like LayerParent, CompositableParent, etc.
67 : */
68 : class TextureParent : public ParentActor<PTextureParent>
69 : {
70 : public:
71 : explicit TextureParent(HostIPCAllocator* aAllocator, uint64_t aSerial, const wr::MaybeExternalImageId& aExternalImageId);
72 :
73 : ~TextureParent();
74 :
75 : bool Init(const SurfaceDescriptor& aSharedData,
76 : const LayersBackend& aLayersBackend,
77 : const TextureFlags& aFlags);
78 :
79 : void NotifyNotUsed(uint64_t aTransactionId);
80 :
81 : virtual mozilla::ipc::IPCResult RecvRecycleTexture(const TextureFlags& aTextureFlags) override;
82 :
83 : TextureHost* GetTextureHost() { return mTextureHost; }
84 :
85 : virtual void Destroy() override;
86 :
87 : uint64_t GetSerial() const { return mSerial; }
88 :
89 : HostIPCAllocator* mSurfaceAllocator;
90 : RefPtr<TextureHost> mTextureHost;
91 : // mSerial is unique in TextureClient's process.
92 : const uint64_t mSerial;
93 : wr::MaybeExternalImageId mExternalImageId;
94 : };
95 :
96 : static bool
97 9 : WrapWithWebRenderTextureHost(ISurfaceAllocator* aDeallocator,
98 : LayersBackend aBackend,
99 : TextureFlags aFlags)
100 : {
101 36 : if (!gfxVars::UseWebRender() ||
102 9 : (aFlags & TextureFlags::SNAPSHOT) ||
103 27 : (aBackend != LayersBackend::LAYERS_WR) ||
104 0 : (!aDeallocator->UsesImageBridge() && !aDeallocator->AsCompositorBridgeParentBase())) {
105 9 : return false;
106 : }
107 0 : return true;
108 : }
109 :
110 : ////////////////////////////////////////////////////////////////////////////////
111 : PTextureParent*
112 9 : TextureHost::CreateIPDLActor(HostIPCAllocator* aAllocator,
113 : const SurfaceDescriptor& aSharedData,
114 : LayersBackend aLayersBackend,
115 : TextureFlags aFlags,
116 : uint64_t aSerial,
117 : const wr::MaybeExternalImageId& aExternalImageId)
118 : {
119 27 : if (aSharedData.type() == SurfaceDescriptor::TSurfaceDescriptorBuffer &&
120 17 : aSharedData.get_SurfaceDescriptorBuffer().data().type() == MemoryOrShmem::Tuintptr_t &&
121 8 : !aAllocator->IsSameProcess())
122 : {
123 0 : NS_ERROR("A client process is trying to peek at our address space using a MemoryTexture!");
124 0 : return nullptr;
125 : }
126 9 : TextureParent* actor = new TextureParent(aAllocator, aSerial, aExternalImageId);
127 9 : if (!actor->Init(aSharedData, aLayersBackend, aFlags)) {
128 0 : delete actor;
129 0 : return nullptr;
130 : }
131 9 : return actor;
132 : }
133 :
134 : // static
135 : bool
136 6 : TextureHost::DestroyIPDLActor(PTextureParent* actor)
137 : {
138 6 : delete actor;
139 6 : return true;
140 : }
141 :
142 : // static
143 : bool
144 0 : TextureHost::SendDeleteIPDLActor(PTextureParent* actor)
145 : {
146 0 : return PTextureParent::Send__delete__(actor);
147 : }
148 :
149 : // static
150 : TextureHost*
151 66 : TextureHost::AsTextureHost(PTextureParent* actor)
152 : {
153 66 : if (!actor) {
154 0 : return nullptr;
155 : }
156 66 : return static_cast<TextureParent*>(actor)->mTextureHost;
157 : }
158 :
159 : // static
160 : uint64_t
161 0 : TextureHost::GetTextureSerial(PTextureParent* actor)
162 : {
163 0 : if (!actor) {
164 0 : return UINT64_MAX;
165 : }
166 0 : return static_cast<TextureParent*>(actor)->mSerial;
167 : }
168 :
169 : PTextureParent*
170 0 : TextureHost::GetIPDLActor()
171 : {
172 0 : return mActor;
173 : }
174 :
175 : void
176 33 : TextureHost::SetLastFwdTransactionId(uint64_t aTransactionId)
177 : {
178 33 : MOZ_ASSERT(mFwdTransactionId <= aTransactionId);
179 33 : mFwdTransactionId = aTransactionId;
180 33 : }
181 :
182 : // implemented in TextureHostOGL.cpp
183 : already_AddRefed<TextureHost> CreateTextureHostOGL(const SurfaceDescriptor& aDesc,
184 : ISurfaceAllocator* aDeallocator,
185 : LayersBackend aBackend,
186 : TextureFlags aFlags);
187 :
188 : // implemented in TextureHostBasic.cpp
189 : already_AddRefed<TextureHost> CreateTextureHostBasic(const SurfaceDescriptor& aDesc,
190 : ISurfaceAllocator* aDeallocator,
191 : LayersBackend aBackend,
192 : TextureFlags aFlags);
193 :
194 : // implemented in TextureD3D11.cpp
195 : already_AddRefed<TextureHost> CreateTextureHostD3D11(const SurfaceDescriptor& aDesc,
196 : ISurfaceAllocator* aDeallocator,
197 : LayersBackend aBackend,
198 : TextureFlags aFlags);
199 :
200 : already_AddRefed<TextureHost>
201 9 : TextureHost::Create(const SurfaceDescriptor& aDesc,
202 : ISurfaceAllocator* aDeallocator,
203 : LayersBackend aBackend,
204 : TextureFlags aFlags,
205 : wr::MaybeExternalImageId& aExternalImageId)
206 : {
207 18 : RefPtr<TextureHost> result;
208 :
209 9 : switch (aDesc.type()) {
210 : case SurfaceDescriptor::TSurfaceDescriptorBuffer:
211 : case SurfaceDescriptor::TSurfaceDescriptorDIB:
212 : case SurfaceDescriptor::TSurfaceDescriptorFileMapping:
213 : case SurfaceDescriptor::TSurfaceDescriptorGPUVideo:
214 9 : result = CreateBackendIndependentTextureHost(aDesc, aDeallocator, aBackend, aFlags);
215 9 : break;
216 :
217 : case SurfaceDescriptor::TEGLImageDescriptor:
218 : case SurfaceDescriptor::TSurfaceTextureDescriptor:
219 : case SurfaceDescriptor::TSurfaceDescriptorSharedGLTexture:
220 0 : result = CreateTextureHostOGL(aDesc, aDeallocator, aBackend, aFlags);
221 0 : break;
222 :
223 : case SurfaceDescriptor::TSurfaceDescriptorMacIOSurface:
224 0 : if (aBackend == LayersBackend::LAYERS_OPENGL ||
225 : aBackend == LayersBackend::LAYERS_WR) {
226 0 : result = CreateTextureHostOGL(aDesc, aDeallocator, aBackend, aFlags);
227 0 : break;
228 : } else {
229 0 : result = CreateTextureHostBasic(aDesc, aDeallocator, aBackend, aFlags);
230 0 : break;
231 : }
232 :
233 : #ifdef MOZ_X11
234 : case SurfaceDescriptor::TSurfaceDescriptorX11: {
235 0 : const SurfaceDescriptorX11& desc = aDesc.get_SurfaceDescriptorX11();
236 0 : result = MakeAndAddRef<X11TextureHost>(aFlags, desc);
237 0 : break;
238 : }
239 : #endif
240 :
241 : #ifdef XP_WIN
242 : case SurfaceDescriptor::TSurfaceDescriptorD3D10:
243 : case SurfaceDescriptor::TSurfaceDescriptorDXGIYCbCr:
244 : result = CreateTextureHostD3D11(aDesc, aDeallocator, aBackend, aFlags);
245 : break;
246 : #endif
247 : default:
248 0 : MOZ_CRASH("GFX: Unsupported Surface type host");
249 : }
250 :
251 9 : if (WrapWithWebRenderTextureHost(aDeallocator, aBackend, aFlags)) {
252 0 : MOZ_ASSERT(aExternalImageId.isSome());
253 0 : result = new WebRenderTextureHost(aDesc, aFlags, result, aExternalImageId.ref());
254 : }
255 :
256 18 : return result.forget();
257 : }
258 :
259 : already_AddRefed<TextureHost>
260 9 : CreateBackendIndependentTextureHost(const SurfaceDescriptor& aDesc,
261 : ISurfaceAllocator* aDeallocator,
262 : LayersBackend aBackend,
263 : TextureFlags aFlags)
264 : {
265 18 : RefPtr<TextureHost> result;
266 9 : switch (aDesc.type()) {
267 : case SurfaceDescriptor::TSurfaceDescriptorBuffer: {
268 9 : const SurfaceDescriptorBuffer& bufferDesc = aDesc.get_SurfaceDescriptorBuffer();
269 9 : const MemoryOrShmem& data = bufferDesc.data();
270 9 : switch (data.type()) {
271 : case MemoryOrShmem::TShmem: {
272 : result = new ShmemTextureHost(data.get_Shmem(),
273 : bufferDesc.desc(),
274 : aDeallocator,
275 2 : aFlags);
276 1 : break;
277 : }
278 : case MemoryOrShmem::Tuintptr_t: {
279 8 : result = new MemoryTextureHost(reinterpret_cast<uint8_t*>(data.get_uintptr_t()),
280 : bufferDesc.desc(),
281 16 : aFlags);
282 8 : break;
283 : }
284 : default:
285 0 : gfxCriticalError() << "Failed texture host for backend " << (int)data.type();
286 0 : MOZ_CRASH("GFX: No texture host for backend");
287 : }
288 9 : break;
289 : }
290 : case SurfaceDescriptor::TSurfaceDescriptorGPUVideo: {
291 0 : result = new GPUVideoTextureHost(aFlags, aDesc.get_SurfaceDescriptorGPUVideo());
292 0 : break;
293 : }
294 : #ifdef XP_WIN
295 : case SurfaceDescriptor::TSurfaceDescriptorDIB: {
296 : result = new DIBTextureHost(aFlags, aDesc);
297 : break;
298 : }
299 : case SurfaceDescriptor::TSurfaceDescriptorFileMapping: {
300 : result = new TextureHostFileMapping(aFlags, aDesc);
301 : break;
302 : }
303 : #endif
304 : default: {
305 0 : NS_WARNING("No backend independent TextureHost for this descriptor type");
306 : }
307 : }
308 18 : return result.forget();
309 : }
310 :
311 9 : TextureHost::TextureHost(TextureFlags aFlags)
312 : : AtomicRefCountedWithFinalize("TextureHost")
313 : , mActor(nullptr)
314 : , mFlags(aFlags)
315 : , mCompositableCount(0)
316 9 : , mFwdTransactionId(0)
317 : {
318 9 : }
319 :
320 12 : TextureHost::~TextureHost()
321 : {
322 : // If we still have a ReadLock, unlock it. At this point we don't care about
323 : // the texture client being written into on the other side since it should be
324 : // destroyed by now. But we will hit assertions if we don't ReadUnlock before
325 : // destroying the lock itself.
326 6 : ReadUnlock();
327 6 : }
328 :
329 6 : void TextureHost::Finalize()
330 : {
331 6 : if (!(GetFlags() & TextureFlags::DEALLOCATE_CLIENT)) {
332 6 : DeallocateSharedData();
333 6 : DeallocateDeviceData();
334 : }
335 6 : }
336 :
337 : void
338 0 : TextureHost::UnbindTextureSource()
339 : {
340 0 : if (mReadLock) {
341 : // This TextureHost is not used anymore. Since most compositor backends are
342 : // working asynchronously under the hood a compositor could still be using
343 : // this texture, so it is generally best to wait until the end of the next
344 : // composition before calling ReadUnlock. We ask the compositor to take care
345 : // of that for us.
346 0 : if (mProvider) {
347 0 : mProvider->UnlockAfterComposition(this);
348 : } else {
349 : // GetCompositor returned null which means no compositor can be using this
350 : // texture. We can ReadUnlock right away.
351 0 : ReadUnlock();
352 : }
353 : }
354 0 : }
355 :
356 : void
357 0 : TextureHost::RecycleTexture(TextureFlags aFlags)
358 : {
359 0 : MOZ_ASSERT(GetFlags() & TextureFlags::RECYCLE);
360 0 : MOZ_ASSERT(aFlags & TextureFlags::RECYCLE);
361 0 : mFlags = aFlags;
362 0 : }
363 :
364 : void
365 31 : TextureHost::NotifyNotUsed()
366 : {
367 31 : if (!mActor) {
368 2 : return;
369 : }
370 :
371 : // Do not need to call NotifyNotUsed() if TextureHost does not have
372 : // TextureFlags::RECYCLE flag.
373 29 : if (!(GetFlags() & TextureFlags::RECYCLE)) {
374 29 : return;
375 : }
376 :
377 : // The following cases do not need to defer NotifyNotUsed until next Composite.
378 : // - TextureHost does not have Compositor.
379 : // - Compositor is BasicCompositor.
380 : // - TextureHost has intermediate buffer.
381 : // end of buffer usage.
382 0 : if (!mProvider ||
383 0 : HasIntermediateBuffer() ||
384 0 : !mProvider->NotifyNotUsedAfterComposition(this))
385 : {
386 0 : static_cast<TextureParent*>(mActor)->NotifyNotUsed(mFwdTransactionId);
387 0 : return;
388 : }
389 : }
390 :
391 : void
392 0 : TextureHost::CallNotifyNotUsed()
393 : {
394 0 : if (!mActor) {
395 0 : return;
396 : }
397 0 : static_cast<TextureParent*>(mActor)->NotifyNotUsed(mFwdTransactionId);
398 : }
399 :
400 : void
401 0 : TextureHost::PrintInfo(std::stringstream& aStream, const char* aPrefix)
402 : {
403 0 : aStream << aPrefix;
404 0 : aStream << nsPrintfCString("%s (0x%p)", Name(), this).get();
405 : // Note: the TextureHost needs to be locked before it is safe to call
406 : // GetSize() and GetFormat() on it.
407 0 : if (Lock()) {
408 0 : AppendToString(aStream, GetSize(), " [size=", "]");
409 0 : AppendToString(aStream, GetFormat(), " [format=", "]");
410 0 : Unlock();
411 : }
412 0 : AppendToString(aStream, mFlags, " [flags=", "]");
413 : #ifdef MOZ_DUMP_PAINTING
414 0 : if (gfxPrefs::LayersDumpTexture() ||
415 0 : profiler_feature_active(ProfilerFeature::LayersDump)) {
416 0 : nsAutoCString pfx(aPrefix);
417 0 : pfx += " ";
418 :
419 0 : aStream << "\n" << pfx.get() << "Surface: ";
420 0 : RefPtr<gfx::DataSourceSurface> dSurf = GetAsSurface();
421 0 : if (dSurf) {
422 0 : aStream << gfxUtils::GetAsLZ4Base64Str(dSurf).get();
423 : }
424 : }
425 : #endif
426 0 : }
427 :
428 : void
429 33 : TextureHost::Updated(const nsIntRegion* aRegion)
430 : {
431 33 : LayerScope::ContentChanged(this);
432 33 : UpdatedInternal(aRegion);
433 33 : }
434 :
435 36 : TextureSource::TextureSource()
436 36 : : mCompositableCount(0)
437 : {
438 36 : }
439 :
440 33 : TextureSource::~TextureSource()
441 : {
442 33 : }
443 :
444 : const char*
445 0 : TextureSource::Name() const
446 : {
447 0 : MOZ_CRASH("GFX: TextureSource without class name");
448 : return "TextureSource";
449 : }
450 :
451 9 : BufferTextureHost::BufferTextureHost(const BufferDescriptor& aDesc,
452 9 : TextureFlags aFlags)
453 : : TextureHost(aFlags)
454 : , mUpdateSerial(1)
455 : , mLocked(false)
456 9 : , mNeedsFullUpdate(false)
457 : {
458 9 : mDescriptor = aDesc;
459 9 : switch (mDescriptor.type()) {
460 : case BufferDescriptor::TYCbCrDescriptor: {
461 0 : const YCbCrDescriptor& ycbcr = mDescriptor.get_YCbCrDescriptor();
462 0 : mSize = ycbcr.ySize();
463 0 : mFormat = gfx::SurfaceFormat::YUV;
464 0 : mHasIntermediateBuffer = ycbcr.hasIntermediateBuffer();
465 0 : break;
466 : }
467 : case BufferDescriptor::TRGBDescriptor: {
468 9 : const RGBDescriptor& rgb = mDescriptor.get_RGBDescriptor();
469 9 : mSize = rgb.size();
470 9 : mFormat = rgb.format();
471 9 : mHasIntermediateBuffer = rgb.hasIntermediateBuffer();
472 9 : break;
473 : }
474 : default:
475 0 : gfxCriticalError() << "Bad buffer host descriptor " << (int)mDescriptor.type();
476 0 : MOZ_CRASH("GFX: Bad descriptor");
477 : }
478 9 : if (aFlags & TextureFlags::COMPONENT_ALPHA) {
479 : // One texture of a component alpha texture pair will start out all white.
480 : // This hack allows us to easily make sure that white will be uploaded.
481 : // See bug 1138934
482 0 : mNeedsFullUpdate = true;
483 : }
484 9 : }
485 :
486 6 : BufferTextureHost::~BufferTextureHost()
487 6 : {}
488 :
489 : void
490 33 : BufferTextureHost::UpdatedInternal(const nsIntRegion* aRegion)
491 : {
492 33 : ++mUpdateSerial;
493 : // If the last frame wasn't uploaded yet, and we -don't- have a partial update,
494 : // we still need to update the full surface.
495 33 : if (aRegion && !mNeedsFullUpdate) {
496 0 : mMaybeUpdatedRegion.OrWith(*aRegion);
497 : } else {
498 33 : mNeedsFullUpdate = true;
499 : }
500 33 : if (GetFlags() & TextureFlags::IMMEDIATE_UPLOAD) {
501 66 : DebugOnly<bool> result = MaybeUpload(!mNeedsFullUpdate ? &mMaybeUpdatedRegion : nullptr);
502 33 : NS_WARNING_ASSERTION(result, "Failed to upload a texture");
503 : }
504 33 : }
505 :
506 : void
507 33 : BufferTextureHost::SetTextureSourceProvider(TextureSourceProvider* aProvider)
508 : {
509 33 : if (mProvider == aProvider) {
510 24 : return;
511 : }
512 9 : if (mFirstSource && mFirstSource->IsOwnedBy(this)) {
513 0 : mFirstSource->SetOwner(nullptr);
514 : }
515 9 : if (mFirstSource) {
516 0 : mFirstSource = nullptr;
517 0 : mNeedsFullUpdate = true;
518 : }
519 9 : mProvider = aProvider;
520 : }
521 :
522 : void
523 12 : BufferTextureHost::DeallocateDeviceData()
524 : {
525 12 : if (mFirstSource && mFirstSource->NumCompositableRefs() > 0) {
526 6 : return;
527 : }
528 :
529 12 : if (!mFirstSource || !mFirstSource->IsOwnedBy(this)) {
530 6 : mFirstSource = nullptr;
531 6 : return;
532 : }
533 :
534 6 : mFirstSource->SetOwner(nullptr);
535 :
536 12 : RefPtr<TextureSource> it = mFirstSource;
537 18 : while (it) {
538 6 : it->DeallocateDeviceData();
539 6 : it = it->GetNextSibling();
540 : }
541 : }
542 :
543 : bool
544 56 : BufferTextureHost::Lock()
545 : {
546 56 : MOZ_ASSERT(!mLocked);
547 56 : if (!UploadIfNeeded()) {
548 0 : return false;
549 : }
550 56 : mLocked = !!mFirstSource;
551 56 : return mLocked;
552 : }
553 :
554 : void
555 56 : BufferTextureHost::Unlock()
556 : {
557 56 : MOZ_ASSERT(mLocked);
558 56 : mLocked = false;
559 56 : }
560 :
561 : void
562 0 : BufferTextureHost::CreateRenderTexture(const wr::ExternalImageId& aExternalImageId)
563 : {
564 : RefPtr<wr::RenderTextureHost> texture =
565 0 : new wr::RenderBufferTextureHost(GetBuffer(), GetBufferDescriptor());
566 :
567 0 : wr::RenderThread::Get()->RegisterExternalImage(wr::AsUint64(aExternalImageId), texture.forget());
568 0 : }
569 :
570 : void
571 0 : BufferTextureHost::GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys,
572 : const std::function<wr::ImageKey()>& aImageKeyAllocator)
573 : {
574 0 : MOZ_ASSERT(aImageKeys.IsEmpty());
575 :
576 0 : if (GetFormat() != gfx::SurfaceFormat::YUV) {
577 : // 1 image key
578 0 : aImageKeys.AppendElement(aImageKeyAllocator());
579 0 : MOZ_ASSERT(aImageKeys.Length() == 1);
580 : } else {
581 : // 3 image key
582 0 : aImageKeys.AppendElement(aImageKeyAllocator());
583 0 : aImageKeys.AppendElement(aImageKeyAllocator());
584 0 : aImageKeys.AppendElement(aImageKeyAllocator());
585 0 : MOZ_ASSERT(aImageKeys.Length() == 3);
586 : }
587 0 : }
588 :
589 : void
590 0 : BufferTextureHost::AddWRImage(wr::WebRenderAPI* aAPI,
591 : Range<const wr::ImageKey>& aImageKeys,
592 : const wr::ExternalImageId& aExtID)
593 : {
594 0 : if (GetFormat() != gfx::SurfaceFormat::YUV) {
595 0 : MOZ_ASSERT(aImageKeys.length() == 1);
596 :
597 0 : wr::ImageDescriptor descriptor(GetSize(),
598 0 : ImageDataSerializer::ComputeRGBStride(GetFormat(), GetSize().width),
599 0 : GetFormat());
600 0 : aAPI->AddExternalImageBuffer(aImageKeys[0], descriptor, aExtID);
601 : } else {
602 0 : MOZ_ASSERT(aImageKeys.length() == 3);
603 :
604 0 : const layers::YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor();
605 0 : wr::ImageDescriptor yDescriptor(desc.ySize(), desc.ySize().width, gfx::SurfaceFormat::A8);
606 0 : wr::ImageDescriptor cbcrDescriptor(desc.cbCrSize(), desc.cbCrSize().width, gfx::SurfaceFormat::A8);
607 0 : aAPI->AddExternalImage(aImageKeys[0],
608 : yDescriptor,
609 : aExtID,
610 : WrExternalImageBufferType::ExternalBuffer,
611 0 : 0);
612 0 : aAPI->AddExternalImage(aImageKeys[1],
613 : cbcrDescriptor,
614 : aExtID,
615 : WrExternalImageBufferType::ExternalBuffer,
616 0 : 1);
617 0 : aAPI->AddExternalImage(aImageKeys[2],
618 : cbcrDescriptor,
619 : aExtID,
620 : WrExternalImageBufferType::ExternalBuffer,
621 0 : 2);
622 : }
623 0 : }
624 :
625 : void
626 0 : BufferTextureHost::PushExternalImage(wr::DisplayListBuilder& aBuilder,
627 : const WrRect& aBounds,
628 : const WrRect& aClip,
629 : wr::ImageRendering aFilter,
630 : Range<const wr::ImageKey>& aImageKeys)
631 : {
632 0 : if (GetFormat() != gfx::SurfaceFormat::YUV) {
633 0 : MOZ_ASSERT(aImageKeys.length() == 1);
634 0 : aBuilder.PushImage(aBounds, aClip, aFilter, aImageKeys[0]);
635 : } else {
636 0 : MOZ_ASSERT(aImageKeys.length() == 3);
637 : aBuilder.PushYCbCrPlanarImage(aBounds,
638 : aClip,
639 0 : aImageKeys[0],
640 0 : aImageKeys[1],
641 0 : aImageKeys[2],
642 : WrYuvColorSpace::Rec601,
643 0 : aFilter);
644 : }
645 0 : }
646 :
647 : void
648 0 : TextureHost::DeserializeReadLock(const ReadLockDescriptor& aDesc,
649 : ISurfaceAllocator* aAllocator)
650 : {
651 0 : RefPtr<TextureReadLock> lock = TextureReadLock::Deserialize(aDesc, aAllocator);
652 0 : if (!lock) {
653 0 : return;
654 : }
655 :
656 : // If mReadLock is not null it means we haven't unlocked it yet and the content
657 : // side should not have been able to write into this texture and send a new lock!
658 0 : MOZ_ASSERT(!mReadLock);
659 0 : mReadLock = lock.forget();
660 : }
661 :
662 : void
663 33 : TextureHost::SetReadLock(TextureReadLock* aReadLock)
664 : {
665 33 : if (!aReadLock) {
666 0 : return;
667 : }
668 : // If mReadLock is not null it means we haven't unlocked it yet and the content
669 : // side should not have been able to write into this texture and send a new lock!
670 33 : MOZ_ASSERT(!mReadLock);
671 33 : mReadLock = aReadLock;
672 : }
673 :
674 : void
675 43 : TextureHost::ReadUnlock()
676 : {
677 43 : if (mReadLock) {
678 31 : mReadLock->ReadUnlock();
679 31 : mReadLock = nullptr;
680 : }
681 43 : }
682 :
683 : bool
684 66 : BufferTextureHost::EnsureWrappingTextureSource()
685 : {
686 66 : MOZ_ASSERT(!mHasIntermediateBuffer);
687 :
688 66 : if (mFirstSource && mFirstSource->IsOwnedBy(this)) {
689 57 : return true;
690 : }
691 : // We don't own it, apparently.
692 9 : if (mFirstSource) {
693 0 : mNeedsFullUpdate = true;
694 0 : mFirstSource = nullptr;
695 : }
696 :
697 9 : if (!mProvider) {
698 0 : return false;
699 : }
700 :
701 9 : if (mFormat == gfx::SurfaceFormat::YUV) {
702 0 : mFirstSource = mProvider->CreateDataTextureSourceAroundYCbCr(this);
703 : } else {
704 : RefPtr<gfx::DataSourceSurface> surf =
705 18 : gfx::Factory::CreateWrappingDataSourceSurface(GetBuffer(),
706 18 : ImageDataSerializer::ComputeRGBStride(mFormat, mSize.width), mSize, mFormat);
707 9 : if (!surf) {
708 0 : return false;
709 : }
710 9 : mFirstSource = mProvider->CreateDataTextureSourceAround(surf);
711 : }
712 :
713 9 : if (!mFirstSource) {
714 : // BasicCompositor::CreateDataTextureSourceAround never returns null
715 : // and we don't expect to take this branch if we are using another backend.
716 : // Returning false is fine but if we get into this situation it probably
717 : // means something fishy is going on, like a texture being used with
718 : // several compositor backends.
719 0 : NS_WARNING("Failed to use a BufferTextureHost without intermediate buffer");
720 0 : return false;
721 : }
722 :
723 9 : mFirstSource->SetUpdateSerial(mUpdateSerial);
724 9 : mFirstSource->SetOwner(this);
725 :
726 9 : return true;
727 : }
728 :
729 : static
730 0 : bool IsCompatibleTextureSource(TextureSource* aTexture,
731 : const BufferDescriptor& aDescriptor,
732 : TextureSourceProvider* aProvider)
733 : {
734 0 : if (!aProvider) {
735 0 : return false;
736 : }
737 :
738 0 : switch (aDescriptor.type()) {
739 : case BufferDescriptor::TYCbCrDescriptor: {
740 0 : const YCbCrDescriptor& ycbcr = aDescriptor.get_YCbCrDescriptor();
741 :
742 0 : if (!aProvider->SupportsEffect(EffectTypes::YCBCR)) {
743 0 : return aTexture->GetFormat() == gfx::SurfaceFormat::B8G8R8X8
744 0 : && aTexture->GetSize() == ycbcr.ySize();
745 : }
746 :
747 0 : if (aTexture->GetFormat() != gfx::SurfaceFormat::A8
748 0 : || aTexture->GetSize() != ycbcr.ySize()) {
749 0 : return false;
750 : }
751 :
752 0 : auto cbTexture = aTexture->GetSubSource(1);
753 0 : if (!cbTexture
754 0 : || cbTexture->GetFormat() != gfx::SurfaceFormat::A8
755 0 : || cbTexture->GetSize() != ycbcr.cbCrSize()) {
756 0 : return false;
757 : }
758 :
759 0 : auto crTexture = aTexture->GetSubSource(2);
760 0 : if (!crTexture
761 0 : || crTexture->GetFormat() != gfx::SurfaceFormat::A8
762 0 : || crTexture->GetSize() != ycbcr.cbCrSize()) {
763 0 : return false;
764 : }
765 :
766 0 : return true;
767 : }
768 : case BufferDescriptor::TRGBDescriptor: {
769 0 : const RGBDescriptor& rgb = aDescriptor.get_RGBDescriptor();
770 0 : return aTexture->GetFormat() == rgb.format()
771 0 : && aTexture->GetSize() == rgb.size();
772 : }
773 : default: {
774 0 : return false;
775 : }
776 : }
777 : }
778 :
779 : void
780 33 : BufferTextureHost::PrepareTextureSource(CompositableTextureSourceRef& aTexture)
781 : {
782 : // Reuse WrappingTextureSourceYCbCrBasic to reduce memory consumption.
783 132 : if (mFormat == gfx::SurfaceFormat::YUV &&
784 0 : !mHasIntermediateBuffer &&
785 0 : aTexture.get() &&
786 0 : aTexture->AsWrappingTextureSourceYCbCrBasic() &&
787 66 : aTexture->NumCompositableRefs() <= 1 &&
788 33 : aTexture->GetSize() == GetSize()) {
789 0 : aTexture->AsSourceBasic()->SetBufferTextureHost(this);
790 0 : aTexture->AsDataTextureSource()->SetOwner(this);
791 0 : mFirstSource = aTexture->AsDataTextureSource();
792 0 : mNeedsFullUpdate = true;
793 : }
794 :
795 33 : if (!mHasIntermediateBuffer) {
796 33 : EnsureWrappingTextureSource();
797 : }
798 :
799 33 : if (mFirstSource && mFirstSource->IsOwnedBy(this)) {
800 : // We are already attached to a TextureSource, nothing to do except tell
801 : // the compositable to use it.
802 33 : aTexture = mFirstSource.get();
803 33 : return;
804 : }
805 :
806 : // We don't own it, apparently.
807 0 : if (mFirstSource) {
808 0 : mNeedsFullUpdate = true;
809 0 : mFirstSource = nullptr;
810 : }
811 :
812 0 : DataTextureSource* texture = aTexture.get() ? aTexture->AsDataTextureSource() : nullptr;
813 :
814 0 : bool compatibleFormats = texture && IsCompatibleTextureSource(texture,
815 : mDescriptor,
816 0 : mProvider);
817 :
818 0 : bool shouldCreateTexture = !compatibleFormats
819 0 : || texture->NumCompositableRefs() > 1
820 0 : || texture->HasOwner();
821 :
822 0 : if (!shouldCreateTexture) {
823 0 : mFirstSource = texture;
824 0 : mFirstSource->SetOwner(this);
825 0 : mNeedsFullUpdate = true;
826 :
827 : // It's possible that texture belonged to a different compositor,
828 : // so make sure we update it (and all of its siblings) to the
829 : // current one.
830 0 : RefPtr<TextureSource> it = mFirstSource;
831 0 : while (it) {
832 0 : it->SetTextureSourceProvider(mProvider);
833 0 : it = it->GetNextSibling();
834 : }
835 : }
836 : }
837 :
838 : bool
839 56 : BufferTextureHost::BindTextureSource(CompositableTextureSourceRef& aTexture)
840 : {
841 56 : MOZ_ASSERT(mLocked);
842 56 : MOZ_ASSERT(mFirstSource);
843 56 : aTexture = mFirstSource;
844 56 : return !!aTexture;
845 : }
846 :
847 : bool
848 0 : BufferTextureHost::AcquireTextureSource(CompositableTextureSourceRef& aTexture)
849 : {
850 0 : if (!UploadIfNeeded()) {
851 0 : return false;
852 : }
853 0 : aTexture = mFirstSource;
854 0 : return !!mFirstSource;
855 : }
856 :
857 : void
858 31 : BufferTextureHost::UnbindTextureSource()
859 : {
860 31 : if (mFirstSource && mFirstSource->IsOwnedBy(this)) {
861 31 : mFirstSource->Unbind();
862 : }
863 : // This texture is not used by any layer anymore.
864 : // If the texture doesn't have an intermediate buffer, it means we are
865 : // compositing synchronously on the CPU, so we don't need to wait until
866 : // the end of the next composition to ReadUnlock (which other textures do
867 : // by default).
868 : // If the texture has an intermediate buffer we don't care either because
869 : // texture uploads are also performed synchronously for BufferTextureHost.
870 31 : ReadUnlock();
871 31 : }
872 :
873 : gfx::SurfaceFormat
874 0 : BufferTextureHost::GetFormat() const
875 : {
876 : // mFormat is the format of the data that we share with the content process.
877 : // GetFormat, on the other hand, expects the format that we present to the
878 : // Compositor (it is used to choose the effect type).
879 : // if the compositor does not support YCbCr effects, we give it a RGBX texture
880 : // instead (see BufferTextureHost::Upload)
881 0 : if (mFormat == gfx::SurfaceFormat::YUV &&
882 0 : mProvider &&
883 0 : !mProvider->SupportsEffect(EffectTypes::YCBCR)) {
884 0 : return gfx::SurfaceFormat::R8G8B8X8;
885 : }
886 0 : return mFormat;
887 : }
888 :
889 : YUVColorSpace
890 0 : BufferTextureHost::GetYUVColorSpace() const
891 : {
892 0 : if (mFormat == gfx::SurfaceFormat::YUV) {
893 0 : const YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor();
894 0 : return desc.yUVColorSpace();
895 : }
896 0 : return YUVColorSpace::UNKNOWN;
897 : }
898 :
899 : bool
900 56 : BufferTextureHost::UploadIfNeeded()
901 : {
902 56 : return MaybeUpload(!mNeedsFullUpdate ? &mMaybeUpdatedRegion : nullptr);
903 : }
904 :
905 : bool
906 89 : BufferTextureHost::MaybeUpload(nsIntRegion *aRegion)
907 : {
908 89 : auto serial = mFirstSource ? mFirstSource->GetUpdateSerial() : 0;
909 :
910 89 : if (serial == mUpdateSerial) {
911 56 : return true;
912 : }
913 :
914 33 : if (serial == 0) {
915 : // 0 means the source has no valid content
916 9 : aRegion = nullptr;
917 : }
918 :
919 33 : if (!Upload(aRegion)) {
920 0 : return false;
921 : }
922 :
923 33 : if (mHasIntermediateBuffer) {
924 : // We just did the texture upload, the content side can now freely write
925 : // into the shared buffer.
926 0 : ReadUnlock();
927 : }
928 :
929 : // We no longer have an invalid region.
930 33 : mNeedsFullUpdate = false;
931 33 : mMaybeUpdatedRegion.SetEmpty();
932 :
933 : // If upload returns true we know mFirstSource is not null
934 33 : mFirstSource->SetUpdateSerial(mUpdateSerial);
935 33 : return true;
936 : }
937 :
938 : bool
939 33 : BufferTextureHost::Upload(nsIntRegion *aRegion)
940 : {
941 33 : uint8_t* buf = GetBuffer();
942 33 : if (!buf) {
943 : // We don't have a buffer; a possible cause is that the IPDL actor
944 : // is already dead. This inevitably happens as IPDL actors can die
945 : // at any time, so we want to silently return in this case.
946 : // another possible cause is that IPDL failed to map the shmem when
947 : // deserializing it.
948 0 : return false;
949 : }
950 33 : if (!mProvider) {
951 : // This can happen if we send textures to a compositable that isn't yet
952 : // attached to a layer.
953 0 : return false;
954 : }
955 33 : if (!mHasIntermediateBuffer && EnsureWrappingTextureSource()) {
956 33 : return true;
957 : }
958 :
959 0 : if (mFormat == gfx::SurfaceFormat::UNKNOWN) {
960 0 : NS_WARNING("BufferTextureHost: unsupported format!");
961 0 : return false;
962 0 : } else if (mFormat == gfx::SurfaceFormat::YUV) {
963 0 : const YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor();
964 :
965 0 : if (!mProvider->SupportsEffect(EffectTypes::YCBCR)) {
966 : RefPtr<gfx::DataSourceSurface> surf =
967 0 : ImageDataSerializer::DataSourceSurfaceFromYCbCrDescriptor(buf, mDescriptor.get_YCbCrDescriptor());
968 0 : if (NS_WARN_IF(!surf)) {
969 0 : return false;
970 : }
971 0 : if (!mFirstSource) {
972 0 : mFirstSource = mProvider->CreateDataTextureSource(mFlags|TextureFlags::RGB_FROM_YCBCR);
973 0 : mFirstSource->SetOwner(this);
974 : }
975 0 : mFirstSource->Update(surf, aRegion);
976 0 : return true;
977 : }
978 :
979 0 : RefPtr<DataTextureSource> srcY;
980 0 : RefPtr<DataTextureSource> srcU;
981 0 : RefPtr<DataTextureSource> srcV;
982 0 : if (!mFirstSource) {
983 : // We don't support BigImages for YCbCr compositing.
984 0 : srcY = mProvider->CreateDataTextureSource(mFlags|TextureFlags::DISALLOW_BIGIMAGE);
985 0 : srcU = mProvider->CreateDataTextureSource(mFlags|TextureFlags::DISALLOW_BIGIMAGE);
986 0 : srcV = mProvider->CreateDataTextureSource(mFlags|TextureFlags::DISALLOW_BIGIMAGE);
987 0 : mFirstSource = srcY;
988 0 : mFirstSource->SetOwner(this);
989 0 : srcY->SetNextSibling(srcU);
990 0 : srcU->SetNextSibling(srcV);
991 : } else {
992 : // mFormat never changes so if this was created as a YCbCr host and already
993 : // contains a source it should already have 3 sources.
994 : // BufferTextureHost only uses DataTextureSources so it is safe to assume
995 : // all 3 sources are DataTextureSource.
996 0 : MOZ_ASSERT(mFirstSource->GetNextSibling());
997 0 : MOZ_ASSERT(mFirstSource->GetNextSibling()->GetNextSibling());
998 0 : srcY = mFirstSource;
999 0 : srcU = mFirstSource->GetNextSibling()->AsDataTextureSource();
1000 0 : srcV = mFirstSource->GetNextSibling()->GetNextSibling()->AsDataTextureSource();
1001 : }
1002 :
1003 : RefPtr<gfx::DataSourceSurface> tempY =
1004 0 : gfx::Factory::CreateWrappingDataSourceSurface(ImageDataSerializer::GetYChannel(buf, desc),
1005 0 : desc.ySize().width,
1006 0 : desc.ySize(),
1007 0 : gfx::SurfaceFormat::A8);
1008 : RefPtr<gfx::DataSourceSurface> tempCb =
1009 0 : gfx::Factory::CreateWrappingDataSourceSurface(ImageDataSerializer::GetCbChannel(buf, desc),
1010 0 : desc.cbCrSize().width,
1011 0 : desc.cbCrSize(),
1012 0 : gfx::SurfaceFormat::A8);
1013 : RefPtr<gfx::DataSourceSurface> tempCr =
1014 0 : gfx::Factory::CreateWrappingDataSourceSurface(ImageDataSerializer::GetCrChannel(buf, desc),
1015 0 : desc.cbCrSize().width,
1016 0 : desc.cbCrSize(),
1017 0 : gfx::SurfaceFormat::A8);
1018 : // We don't support partial updates for Y U V textures
1019 0 : NS_ASSERTION(!aRegion, "Unsupported partial updates for YCbCr textures");
1020 0 : if (!tempY ||
1021 0 : !tempCb ||
1022 0 : !tempCr ||
1023 0 : !srcY->Update(tempY) ||
1024 0 : !srcU->Update(tempCb) ||
1025 0 : !srcV->Update(tempCr)) {
1026 0 : NS_WARNING("failed to update the DataTextureSource");
1027 0 : return false;
1028 : }
1029 : } else {
1030 : // non-YCbCr case
1031 0 : nsIntRegion* regionToUpdate = aRegion;
1032 0 : if (!mFirstSource) {
1033 0 : mFirstSource = mProvider->CreateDataTextureSource(mFlags);
1034 0 : mFirstSource->SetOwner(this);
1035 0 : if (mFlags & TextureFlags::COMPONENT_ALPHA) {
1036 : // Update the full region the first time for component alpha textures.
1037 0 : regionToUpdate = nullptr;
1038 : }
1039 : }
1040 :
1041 : RefPtr<gfx::DataSourceSurface> surf =
1042 0 : gfx::Factory::CreateWrappingDataSourceSurface(GetBuffer(),
1043 0 : ImageDataSerializer::ComputeRGBStride(mFormat, mSize.width), mSize, mFormat);
1044 0 : if (!surf) {
1045 0 : return false;
1046 : }
1047 :
1048 0 : if (!mFirstSource->Update(surf.get(), regionToUpdate)) {
1049 0 : NS_WARNING("failed to update the DataTextureSource");
1050 0 : return false;
1051 : }
1052 : }
1053 0 : MOZ_ASSERT(mFirstSource);
1054 0 : return true;
1055 : }
1056 :
1057 : already_AddRefed<gfx::DataSourceSurface>
1058 0 : BufferTextureHost::GetAsSurface()
1059 : {
1060 0 : RefPtr<gfx::DataSourceSurface> result;
1061 0 : if (mFormat == gfx::SurfaceFormat::UNKNOWN) {
1062 0 : NS_WARNING("BufferTextureHost: unsupported format!");
1063 0 : return nullptr;
1064 0 : } else if (mFormat == gfx::SurfaceFormat::YUV) {
1065 0 : result = ImageDataSerializer::DataSourceSurfaceFromYCbCrDescriptor(
1066 0 : GetBuffer(), mDescriptor.get_YCbCrDescriptor());
1067 0 : if (NS_WARN_IF(!result)) {
1068 0 : return nullptr;
1069 : }
1070 : } else {
1071 : result =
1072 0 : gfx::Factory::CreateWrappingDataSourceSurface(GetBuffer(),
1073 0 : ImageDataSerializer::GetRGBStride(mDescriptor.get_RGBDescriptor()),
1074 0 : mSize, mFormat);
1075 : }
1076 0 : return result.forget();
1077 : }
1078 :
1079 1 : ShmemTextureHost::ShmemTextureHost(const ipc::Shmem& aShmem,
1080 : const BufferDescriptor& aDesc,
1081 : ISurfaceAllocator* aDeallocator,
1082 1 : TextureFlags aFlags)
1083 : : BufferTextureHost(aDesc, aFlags)
1084 1 : , mDeallocator(aDeallocator)
1085 : {
1086 1 : if (aShmem.IsReadable()) {
1087 1 : mShmem = MakeUnique<ipc::Shmem>(aShmem);
1088 : } else {
1089 : // This can happen if we failed to map the shmem on this process, perhaps
1090 : // because it was big and we didn't have enough contiguous address space
1091 : // available, even though we did on the child process.
1092 : // As a result this texture will be in an invalid state and Lock will
1093 : // always fail.
1094 :
1095 0 : gfxCriticalNote << "Failed to create a valid ShmemTextureHost";
1096 : }
1097 :
1098 1 : MOZ_COUNT_CTOR(ShmemTextureHost);
1099 1 : }
1100 :
1101 0 : ShmemTextureHost::~ShmemTextureHost()
1102 : {
1103 0 : MOZ_ASSERT(!mShmem || (mFlags & TextureFlags::DEALLOCATE_CLIENT),
1104 : "Leaking our buffer");
1105 0 : DeallocateDeviceData();
1106 0 : MOZ_COUNT_DTOR(ShmemTextureHost);
1107 0 : }
1108 :
1109 : void
1110 0 : ShmemTextureHost::DeallocateSharedData()
1111 : {
1112 0 : if (mShmem) {
1113 0 : MOZ_ASSERT(mDeallocator,
1114 : "Shared memory would leak without a ISurfaceAllocator");
1115 0 : mDeallocator->AsShmemAllocator()->DeallocShmem(*mShmem);
1116 0 : mShmem = nullptr;
1117 : }
1118 0 : }
1119 :
1120 : void
1121 0 : ShmemTextureHost::ForgetSharedData()
1122 : {
1123 0 : if (mShmem) {
1124 0 : mShmem = nullptr;
1125 : }
1126 0 : }
1127 :
1128 : void
1129 0 : ShmemTextureHost::OnShutdown()
1130 : {
1131 0 : mShmem = nullptr;
1132 0 : }
1133 :
1134 2 : uint8_t* ShmemTextureHost::GetBuffer()
1135 : {
1136 2 : return mShmem ? mShmem->get<uint8_t>() : nullptr;
1137 : }
1138 :
1139 0 : size_t ShmemTextureHost::GetBufferSize()
1140 : {
1141 0 : return mShmem ? mShmem->Size<uint8_t>() : 0;
1142 : }
1143 :
1144 8 : MemoryTextureHost::MemoryTextureHost(uint8_t* aBuffer,
1145 : const BufferDescriptor& aDesc,
1146 8 : TextureFlags aFlags)
1147 : : BufferTextureHost(aDesc, aFlags)
1148 8 : , mBuffer(aBuffer)
1149 : {
1150 8 : MOZ_COUNT_CTOR(MemoryTextureHost);
1151 8 : }
1152 :
1153 18 : MemoryTextureHost::~MemoryTextureHost()
1154 : {
1155 6 : MOZ_ASSERT(!mBuffer || (mFlags & TextureFlags::DEALLOCATE_CLIENT),
1156 : "Leaking our buffer");
1157 6 : DeallocateDeviceData();
1158 6 : MOZ_COUNT_DTOR(MemoryTextureHost);
1159 18 : }
1160 :
1161 : void
1162 6 : MemoryTextureHost::DeallocateSharedData()
1163 : {
1164 6 : if (mBuffer) {
1165 6 : GfxMemoryImageReporter::WillFree(mBuffer);
1166 : }
1167 6 : delete[] mBuffer;
1168 6 : mBuffer = nullptr;
1169 6 : }
1170 :
1171 : void
1172 0 : MemoryTextureHost::ForgetSharedData()
1173 : {
1174 0 : mBuffer = nullptr;
1175 0 : }
1176 :
1177 40 : uint8_t* MemoryTextureHost::GetBuffer()
1178 : {
1179 40 : return mBuffer;
1180 : }
1181 :
1182 0 : size_t MemoryTextureHost::GetBufferSize()
1183 : {
1184 : // MemoryTextureHost just trusts that the buffer size is large enough to read
1185 : // anything we need to. That's because MemoryTextureHost has to trust the buffer
1186 : // pointer anyway, so the security model here is just that MemoryTexture's
1187 : // are restricted to same-process clients.
1188 0 : return std::numeric_limits<size_t>::max();
1189 : }
1190 :
1191 9 : TextureParent::TextureParent(HostIPCAllocator* aSurfaceAllocator, uint64_t aSerial, const wr::MaybeExternalImageId& aExternalImageId)
1192 : : mSurfaceAllocator(aSurfaceAllocator)
1193 : , mSerial(aSerial)
1194 9 : , mExternalImageId(aExternalImageId)
1195 : {
1196 9 : MOZ_COUNT_CTOR(TextureParent);
1197 9 : }
1198 :
1199 18 : TextureParent::~TextureParent()
1200 : {
1201 6 : MOZ_COUNT_DTOR(TextureParent);
1202 18 : }
1203 :
1204 : void
1205 0 : TextureParent::NotifyNotUsed(uint64_t aTransactionId)
1206 : {
1207 0 : if (!mTextureHost) {
1208 0 : return;
1209 : }
1210 0 : mSurfaceAllocator->NotifyNotUsed(this, aTransactionId);
1211 : }
1212 :
1213 : bool
1214 9 : TextureParent::Init(const SurfaceDescriptor& aSharedData,
1215 : const LayersBackend& aBackend,
1216 : const TextureFlags& aFlags)
1217 : {
1218 27 : mTextureHost = TextureHost::Create(aSharedData,
1219 9 : mSurfaceAllocator,
1220 : aBackend,
1221 : aFlags,
1222 9 : mExternalImageId);
1223 9 : if (mTextureHost) {
1224 9 : mTextureHost->mActor = this;
1225 : }
1226 :
1227 9 : return !!mTextureHost;
1228 : }
1229 :
1230 : void
1231 6 : TextureParent::Destroy()
1232 : {
1233 6 : if (!mTextureHost) {
1234 0 : return;
1235 : }
1236 :
1237 : // ReadUnlock here to make sure the ReadLock's shmem does not outlive the
1238 : // protocol that created it.
1239 6 : mTextureHost->ReadUnlock();
1240 :
1241 6 : if (mTextureHost->GetFlags() & TextureFlags::DEALLOCATE_CLIENT) {
1242 0 : mTextureHost->ForgetSharedData();
1243 : }
1244 :
1245 6 : mTextureHost->mActor = nullptr;
1246 6 : mTextureHost = nullptr;
1247 : }
1248 :
1249 : void
1250 2 : TextureHost::ReceivedDestroy(PTextureParent* aActor)
1251 : {
1252 2 : static_cast<TextureParent*>(aActor)->RecvDestroy();
1253 2 : }
1254 :
1255 : mozilla::ipc::IPCResult
1256 0 : TextureParent::RecvRecycleTexture(const TextureFlags& aTextureFlags)
1257 : {
1258 0 : if (!mTextureHost) {
1259 0 : return IPC_OK();
1260 : }
1261 0 : mTextureHost->RecycleTexture(aTextureFlags);
1262 0 : return IPC_OK();
1263 : }
1264 :
1265 : ////////////////////////////////////////////////////////////////////////////////
1266 :
1267 : } // namespace layers
1268 9 : } // namespace mozilla
|