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/. */
7 #include "TextureHost.h"
9 #include "CompositableHost.h" // for CompositableHost
10 #include "mozilla/gfx/2D.h" // for DataSourceSurface, Factory
11 #include "mozilla/gfx/CanvasManagerParent.h"
12 #include "mozilla/gfx/gfxVars.h"
13 #include "mozilla/ipc/Shmem.h" // for Shmem
14 #include "mozilla/layers/AsyncImagePipelineManager.h"
15 #include "mozilla/layers/BufferTexture.h"
16 #include "mozilla/layers/CompositableTransactionParent.h" // for CompositableParentManager
17 #include "mozilla/layers/CompositorBridgeParent.h"
18 #include "mozilla/layers/Compositor.h" // for Compositor
19 #include "mozilla/layers/ISurfaceAllocator.h" // for ISurfaceAllocator
20 #include "mozilla/layers/ImageBridgeParent.h" // for ImageBridgeParent
21 #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor, etc
22 #include "mozilla/layers/RemoteTextureMap.h"
23 #include "mozilla/layers/TextureHostOGL.h" // for TextureHostOGL
24 #include "mozilla/layers/ImageDataSerializer.h"
25 #include "mozilla/layers/TextureClient.h"
26 #include "mozilla/layers/GPUVideoTextureHost.h"
27 #include "mozilla/layers/WebRenderTextureHost.h"
28 #include "mozilla/StaticPrefs_layers.h"
29 #include "mozilla/StaticPrefs_gfx.h"
30 #include "mozilla/webrender/RenderBufferTextureHost.h"
31 #include "mozilla/webrender/RenderExternalTextureHost.h"
32 #include "mozilla/webrender/RenderThread.h"
33 #include "mozilla/webrender/WebRenderAPI.h"
34 #include "nsAString.h"
35 #include "mozilla/RefPtr.h" // for nsRefPtr
36 #include "nsPrintfCString.h" // for nsPrintfCString
37 #include "mozilla/layers/PTextureParent.h"
38 #include "mozilla/Unused.h"
40 #include "../opengl/CompositorOGL.h"
43 #include "IPDLActor.h"
46 # include "../opengl/MacIOSurfaceTextureHostOGL.h"
50 # include "../d3d11/CompositorD3D11.h"
51 # include "mozilla/layers/TextureD3D11.h"
52 # ifdef MOZ_WMF_MEDIA_ENGINE
53 # include "mozilla/layers/DcompSurfaceImage.h"
58 # define RECYCLE_LOG(...) printf_stderr(__VA_ARGS__)
60 # define RECYCLE_LOG(...) \
69 * TextureParent is the host-side IPDL glue between TextureClient and
70 * TextureHost. It is an IPDL actor just like LayerParent, CompositableParent,
73 class TextureParent
: public ParentActor
<PTextureParent
> {
75 TextureParent(HostIPCAllocator
* aAllocator
,
76 const dom::ContentParentId
& aContentId
, uint64_t aSerial
,
77 const wr::MaybeExternalImageId
& aExternalImageId
);
79 virtual ~TextureParent();
81 bool Init(const SurfaceDescriptor
& aSharedData
,
82 ReadLockDescriptor
&& aReadLock
, const LayersBackend
& aLayersBackend
,
83 const TextureFlags
& aFlags
);
85 void NotifyNotUsed(uint64_t aTransactionId
);
87 mozilla::ipc::IPCResult
RecvRecycleTexture(
88 const TextureFlags
& aTextureFlags
) final
;
90 TextureHost
* GetTextureHost() { return mTextureHost
; }
92 void Destroy() override
;
94 const dom::ContentParentId
& GetContentId() const { return mContentId
; }
96 uint64_t GetSerial() const { return mSerial
; }
98 HostIPCAllocator
* mSurfaceAllocator
;
99 RefPtr
<TextureHost
> mTextureHost
;
100 dom::ContentParentId mContentId
;
101 // mSerial is unique in TextureClient's process.
102 const uint64_t mSerial
;
103 wr::MaybeExternalImageId mExternalImageId
;
106 static bool WrapWithWebRenderTextureHost(ISurfaceAllocator
* aDeallocator
,
107 LayersBackend aBackend
,
108 TextureFlags aFlags
) {
112 if ((aFlags
& TextureFlags::SNAPSHOT
) ||
113 (!aDeallocator
->UsesImageBridge() &&
114 !aDeallocator
->AsCompositorBridgeParentBase())) {
120 ////////////////////////////////////////////////////////////////////////////////
121 PTextureParent
* TextureHost::CreateIPDLActor(
122 HostIPCAllocator
* aAllocator
, const SurfaceDescriptor
& aSharedData
,
123 ReadLockDescriptor
&& aReadLock
, LayersBackend aLayersBackend
,
124 TextureFlags aFlags
, const dom::ContentParentId
& aContentId
,
125 uint64_t aSerial
, const wr::MaybeExternalImageId
& aExternalImageId
) {
126 TextureParent
* actor
=
127 new TextureParent(aAllocator
, aContentId
, aSerial
, aExternalImageId
);
128 if (!actor
->Init(aSharedData
, std::move(aReadLock
), aLayersBackend
, aFlags
)) {
129 actor
->ActorDestroy(ipc::IProtocol::ActorDestroyReason::FailedConstructor
);
137 bool TextureHost::DestroyIPDLActor(PTextureParent
* actor
) {
143 bool TextureHost::SendDeleteIPDLActor(PTextureParent
* actor
) {
144 return PTextureParent::Send__delete__(actor
);
148 TextureHost
* TextureHost::AsTextureHost(PTextureParent
* actor
) {
152 return static_cast<TextureParent
*>(actor
)->mTextureHost
;
156 uint64_t TextureHost::GetTextureSerial(PTextureParent
* actor
) {
160 return static_cast<TextureParent
*>(actor
)->mSerial
;
164 dom::ContentParentId
TextureHost::GetTextureContentId(PTextureParent
* actor
) {
166 return dom::ContentParentId();
168 return static_cast<TextureParent
*>(actor
)->mContentId
;
171 PTextureParent
* TextureHost::GetIPDLActor() { return mActor
; }
173 void TextureHost::SetLastFwdTransactionId(uint64_t aTransactionId
) {
174 MOZ_ASSERT(mFwdTransactionId
<= aTransactionId
);
175 mFwdTransactionId
= aTransactionId
;
178 already_AddRefed
<TextureHost
> CreateDummyBufferTextureHost(
179 mozilla::layers::LayersBackend aBackend
,
180 mozilla::layers::TextureFlags aFlags
) {
181 // Ensure that the host will delete the memory.
182 aFlags
&= ~TextureFlags::DEALLOCATE_CLIENT
;
183 aFlags
|= TextureFlags::DUMMY_TEXTURE
;
184 UniquePtr
<TextureData
> textureData(BufferTextureData::Create(
185 gfx::IntSize(1, 1), gfx::SurfaceFormat::B8G8R8A8
, gfx::BackendType::SKIA
,
186 aBackend
, aFlags
, TextureAllocationFlags::ALLOC_DEFAULT
, nullptr));
187 SurfaceDescriptor surfDesc
;
188 textureData
->Serialize(surfDesc
);
189 const SurfaceDescriptorBuffer
& bufferDesc
=
190 surfDesc
.get_SurfaceDescriptorBuffer();
191 const MemoryOrShmem
& data
= bufferDesc
.data();
192 RefPtr
<TextureHost
> host
=
193 new MemoryTextureHost(reinterpret_cast<uint8_t*>(data
.get_uintptr_t()),
194 bufferDesc
.desc(), aFlags
);
195 return host
.forget();
198 already_AddRefed
<TextureHost
> TextureHost::Create(
199 const SurfaceDescriptor
& aDesc
, ReadLockDescriptor
&& aReadLock
,
200 HostIPCAllocator
* aDeallocator
, LayersBackend aBackend
, TextureFlags aFlags
,
201 wr::MaybeExternalImageId
& aExternalImageId
) {
202 RefPtr
<TextureHost
> result
;
204 switch (aDesc
.type()) {
205 case SurfaceDescriptor::TSurfaceDescriptorBuffer
:
206 case SurfaceDescriptor::TSurfaceDescriptorGPUVideo
:
207 result
= CreateBackendIndependentTextureHost(aDesc
, aDeallocator
,
211 case SurfaceDescriptor::TEGLImageDescriptor
:
212 case SurfaceDescriptor::TSurfaceTextureDescriptor
:
213 case SurfaceDescriptor::TSurfaceDescriptorAndroidHardwareBuffer
:
214 case SurfaceDescriptor::TSurfaceDescriptorSharedGLTexture
:
215 case SurfaceDescriptor::TSurfaceDescriptorDMABuf
:
216 result
= CreateTextureHostOGL(aDesc
, aDeallocator
, aBackend
, aFlags
);
219 case SurfaceDescriptor::TSurfaceDescriptorMacIOSurface
:
220 result
= CreateTextureHostOGL(aDesc
, aDeallocator
, aBackend
, aFlags
);
224 case SurfaceDescriptor::TSurfaceDescriptorD3D10
:
225 case SurfaceDescriptor::TSurfaceDescriptorDXGIYCbCr
:
226 result
= CreateTextureHostD3D11(aDesc
, aDeallocator
, aBackend
, aFlags
);
228 # ifdef MOZ_WMF_MEDIA_ENGINE
229 case SurfaceDescriptor::TSurfaceDescriptorDcompSurface
:
231 CreateTextureHostDcompSurface(aDesc
, aDeallocator
, aBackend
, aFlags
);
236 MOZ_CRASH("GFX: Unsupported Surface type host");
240 gfxCriticalNote
<< "TextureHost creation failure type=" << aDesc
.type();
243 if (result
&& WrapWithWebRenderTextureHost(aDeallocator
, aBackend
, aFlags
)) {
244 MOZ_ASSERT(aExternalImageId
.isSome());
245 result
= new WebRenderTextureHost(aFlags
, result
, aExternalImageId
.ref());
249 result
->DeserializeReadLock(std::move(aReadLock
), aDeallocator
);
252 return result
.forget();
255 already_AddRefed
<TextureHost
> CreateBackendIndependentTextureHost(
256 const SurfaceDescriptor
& aDesc
, ISurfaceAllocator
* aDeallocator
,
257 LayersBackend aBackend
, TextureFlags aFlags
) {
258 RefPtr
<TextureHost
> result
;
259 switch (aDesc
.type()) {
260 case SurfaceDescriptor::TSurfaceDescriptorBuffer
: {
261 const SurfaceDescriptorBuffer
& bufferDesc
=
262 aDesc
.get_SurfaceDescriptorBuffer();
263 const MemoryOrShmem
& data
= bufferDesc
.data();
264 switch (data
.type()) {
265 case MemoryOrShmem::TShmem
: {
266 const ipc::Shmem
& shmem
= data
.get_Shmem();
267 const BufferDescriptor
& desc
= bufferDesc
.desc();
268 if (!shmem
.IsReadable()) {
269 // We failed to map the shmem so we can't verify its size. This
270 // should not be a fatal error, so just create the texture with
271 // nothing backing it.
272 result
= new ShmemTextureHost(shmem
, desc
, aDeallocator
, aFlags
);
276 size_t bufSize
= shmem
.Size
<char>();
277 size_t reqSize
= SIZE_MAX
;
278 switch (desc
.type()) {
279 case BufferDescriptor::TYCbCrDescriptor
: {
280 const YCbCrDescriptor
& ycbcr
= desc
.get_YCbCrDescriptor();
281 reqSize
= ImageDataSerializer::ComputeYCbCrBufferSize(
282 ycbcr
.ySize(), ycbcr
.yStride(), ycbcr
.cbCrSize(),
283 ycbcr
.cbCrStride(), ycbcr
.yOffset(), ycbcr
.cbOffset(),
287 case BufferDescriptor::TRGBDescriptor
: {
288 const RGBDescriptor
& rgb
= desc
.get_RGBDescriptor();
289 reqSize
= ImageDataSerializer::ComputeRGBBufferSize(rgb
.size(),
295 << "Bad buffer host descriptor " << (int)desc
.type();
296 MOZ_CRASH("GFX: Bad descriptor");
299 if (reqSize
== 0 || bufSize
< reqSize
) {
301 "A client process gave a shmem too small to fit for its "
306 result
= new ShmemTextureHost(shmem
, desc
, aDeallocator
, aFlags
);
309 case MemoryOrShmem::Tuintptr_t
: {
310 if (aDeallocator
&& !aDeallocator
->IsSameProcess()) {
312 "A client process is trying to peek at our address space using "
317 result
= new MemoryTextureHost(
318 reinterpret_cast<uint8_t*>(data
.get_uintptr_t()),
319 bufferDesc
.desc(), aFlags
);
324 << "Failed texture host for backend " << (int)data
.type();
325 MOZ_CRASH("GFX: No texture host for backend");
329 case SurfaceDescriptor::TSurfaceDescriptorGPUVideo
: {
330 MOZ_ASSERT(aDesc
.get_SurfaceDescriptorGPUVideo().type() ==
331 SurfaceDescriptorGPUVideo::TSurfaceDescriptorRemoteDecoder
);
332 result
= GPUVideoTextureHost::CreateFromDescriptor(
333 aDeallocator
->GetContentId(), aFlags
,
334 aDesc
.get_SurfaceDescriptorGPUVideo());
338 NS_WARNING("No backend independent TextureHost for this descriptor type");
341 return result
.forget();
344 TextureHost::TextureHost(TextureHostType aType
, TextureFlags aFlags
)
345 : AtomicRefCountedWithFinalize("TextureHost"),
346 mTextureHostType(aType
),
349 mCompositableCount(0),
350 mFwdTransactionId(0),
351 mReadLocked(false) {}
353 TextureHost::~TextureHost() {
354 MOZ_ASSERT(mExternalImageId
.isNothing());
357 // If we still have a ReadLock, unlock it. At this point we don't care about
358 // the texture client being written into on the other side since it should
359 // be destroyed by now. But we will hit assertions if we don't ReadUnlock
360 // before destroying the lock itself.
363 if (mDestroyedCallback
) {
364 mDestroyedCallback();
368 void TextureHost::Finalize() {
369 MaybeDestroyRenderTexture();
371 if (!(GetFlags() & TextureFlags::DEALLOCATE_CLIENT
)) {
372 DeallocateSharedData();
373 DeallocateDeviceData();
377 void TextureHost::UnbindTextureSource() {
383 void TextureHost::RecycleTexture(TextureFlags aFlags
) {
384 MOZ_ASSERT(GetFlags() & TextureFlags::RECYCLE
);
385 MOZ_ASSERT(aFlags
& TextureFlags::RECYCLE
);
389 void TextureHost::PrepareForUse() {}
391 void TextureHost::NotifyNotUsed() {
393 if ((mFlags
& TextureFlags::REMOTE_TEXTURE
) && AsSurfaceTextureHost()) {
394 MOZ_ASSERT(mExternalImageId
.isSome());
395 wr::RenderThread::Get()->NotifyNotUsed(*mExternalImageId
);
400 // Do not need to call NotifyNotUsed() if TextureHost does not have
401 // TextureFlags::RECYCLE flag nor TextureFlags::WAIT_HOST_USAGE_END flag.
402 if (!(GetFlags() & TextureFlags::RECYCLE
) &&
403 !(GetFlags() & TextureFlags::WAIT_HOST_USAGE_END
)) {
407 static_cast<TextureParent
*>(mActor
)->NotifyNotUsed(mFwdTransactionId
);
410 void TextureHost::CallNotifyNotUsed() {
414 static_cast<TextureParent
*>(mActor
)->NotifyNotUsed(mFwdTransactionId
);
417 void TextureHost::MaybeDestroyRenderTexture() {
418 if (mExternalImageId
.isNothing()) {
419 // RenderTextureHost was not created
422 // When TextureHost created RenderTextureHost, delete it here.
423 TextureHost::DestroyRenderTexture(mExternalImageId
.ref());
424 mExternalImageId
= Nothing();
427 void TextureHost::DestroyRenderTexture(
428 const wr::ExternalImageId
& aExternalImageId
) {
429 wr::RenderThread::Get()->UnregisterExternalImage(aExternalImageId
);
432 void TextureHost::EnsureRenderTexture(
433 const wr::MaybeExternalImageId
& aExternalImageId
) {
434 if (aExternalImageId
.isNothing()) {
435 // TextureHost is wrapped by GPUVideoTextureHost.
436 if (mExternalImageId
.isSome()) {
437 // RenderTextureHost was already created.
441 Some(AsyncImagePipelineManager::GetNextExternalImageId());
443 // TextureHost is wrapped by WebRenderTextureHost.
444 if (aExternalImageId
== mExternalImageId
) {
445 // The texture has already been created.
448 MOZ_ASSERT(mExternalImageId
.isNothing());
449 mExternalImageId
= aExternalImageId
;
451 CreateRenderTexture(mExternalImageId
.ref());
454 TextureSource::TextureSource() : mCompositableCount(0) {}
456 TextureSource::~TextureSource() = default;
457 BufferTextureHost::BufferTextureHost(const BufferDescriptor
& aDesc
,
459 : TextureHost(TextureHostType::Buffer
, aFlags
), mLocked(false) {
461 switch (mDescriptor
.type()) {
462 case BufferDescriptor::TYCbCrDescriptor
: {
463 const YCbCrDescriptor
& ycbcr
= mDescriptor
.get_YCbCrDescriptor();
464 mSize
= ycbcr
.display().Size();
465 mFormat
= gfx::SurfaceFormat::YUV420
;
468 case BufferDescriptor::TRGBDescriptor
: {
469 const RGBDescriptor
& rgb
= mDescriptor
.get_RGBDescriptor();
471 mFormat
= rgb
.format();
475 gfxCriticalError() << "Bad buffer host descriptor "
476 << (int)mDescriptor
.type();
477 MOZ_CRASH("GFX: Bad descriptor");
481 const int kMinSize
= 1024;
482 const int kMaxSize
= 4096;
483 mUseExternalTextures
=
484 kMaxSize
>= mSize
.width
&& mSize
.width
>= kMinSize
&&
485 kMaxSize
>= mSize
.height
&& mSize
.height
>= kMinSize
&&
486 StaticPrefs::gfx_webrender_enable_client_storage_AtStartup();
488 mUseExternalTextures
= false;
492 BufferTextureHost::~BufferTextureHost() = default;
494 void BufferTextureHost::DeallocateDeviceData() {}
496 void BufferTextureHost::CreateRenderTexture(
497 const wr::ExternalImageId
& aExternalImageId
) {
498 MOZ_ASSERT(mExternalImageId
.isSome());
500 RefPtr
<wr::RenderTextureHost
> texture
;
502 if (UseExternalTextures()) {
504 new wr::RenderExternalTextureHost(GetBuffer(), GetBufferDescriptor());
507 new wr::RenderBufferTextureHost(GetBuffer(), GetBufferDescriptor());
510 wr::RenderThread::Get()->RegisterExternalImage(aExternalImageId
,
514 uint32_t BufferTextureHost::NumSubTextures() {
515 if (GetFormat() == gfx::SurfaceFormat::YUV420
) {
522 void BufferTextureHost::PushResourceUpdates(
523 wr::TransactionBuilder
& aResources
, ResourceUpdateOp aOp
,
524 const Range
<wr::ImageKey
>& aImageKeys
, const wr::ExternalImageId
& aExtID
) {
525 auto method
= aOp
== TextureHost::ADD_IMAGE
526 ? &wr::TransactionBuilder::AddExternalImage
527 : &wr::TransactionBuilder::UpdateExternalImage
;
529 // Use native textures if our backend requires it, or if our backend doesn't
530 // forbid it and we want to use them.
531 NativeTexturePolicy policy
=
532 BackendNativeTexturePolicy(aResources
.GetBackendType(), GetSize());
533 bool useNativeTexture
=
534 (policy
== REQUIRE
) || (policy
!= FORBID
&& UseExternalTextures());
535 auto imageType
= useNativeTexture
? wr::ExternalImageType::TextureHandle(
536 wr::ImageBufferKind::TextureRect
)
537 : wr::ExternalImageType::Buffer();
539 if (GetFormat() != gfx::SurfaceFormat::YUV420
) {
540 MOZ_ASSERT(aImageKeys
.length() == 1);
542 wr::ImageDescriptor
descriptor(
544 ImageDataSerializer::ComputeRGBStride(GetFormat(), GetSize().width
),
546 (aResources
.*method
)(aImageKeys
[0], descriptor
, aExtID
, imageType
, 0,
547 /* aNormalizedUvs */ false);
549 MOZ_ASSERT(aImageKeys
.length() == 3);
551 const layers::YCbCrDescriptor
& desc
= mDescriptor
.get_YCbCrDescriptor();
552 gfx::IntSize ySize
= desc
.display().Size();
553 gfx::IntSize cbcrSize
= ImageDataSerializer::GetCroppedCbCrSize(desc
);
554 wr::ImageDescriptor
yDescriptor(
555 ySize
, desc
.yStride(), SurfaceFormatForColorDepth(desc
.colorDepth()));
556 wr::ImageDescriptor
cbcrDescriptor(
557 cbcrSize
, desc
.cbCrStride(),
558 SurfaceFormatForColorDepth(desc
.colorDepth()));
559 (aResources
.*method
)(aImageKeys
[0], yDescriptor
, aExtID
, imageType
, 0,
560 /* aNormalizedUvs */ false);
561 (aResources
.*method
)(aImageKeys
[1], cbcrDescriptor
, aExtID
, imageType
, 1,
562 /* aNormalizedUvs */ false);
563 (aResources
.*method
)(aImageKeys
[2], cbcrDescriptor
, aExtID
, imageType
, 2,
564 /* aNormalizedUvs */ false);
568 void BufferTextureHost::PushDisplayItems(wr::DisplayListBuilder
& aBuilder
,
569 const wr::LayoutRect
& aBounds
,
570 const wr::LayoutRect
& aClip
,
571 wr::ImageRendering aFilter
,
572 const Range
<wr::ImageKey
>& aImageKeys
,
573 PushDisplayItemFlagSet aFlags
) {
574 // SWGL should always try to bypass shaders and composite directly.
575 bool preferCompositorSurface
=
576 aFlags
.contains(PushDisplayItemFlag::PREFER_COMPOSITOR_SURFACE
);
577 bool useExternalSurface
=
578 aFlags
.contains(PushDisplayItemFlag::SUPPORTS_EXTERNAL_BUFFER_TEXTURES
);
579 if (GetFormat() != gfx::SurfaceFormat::YUV420
) {
580 MOZ_ASSERT(aImageKeys
.length() == 1);
581 aBuilder
.PushImage(aBounds
, aClip
, true, false, aFilter
, aImageKeys
[0],
582 !(mFlags
& TextureFlags::NON_PREMULTIPLIED
),
583 wr::ColorF
{1.0f
, 1.0f
, 1.0f
, 1.0f
},
584 preferCompositorSurface
, useExternalSurface
);
586 MOZ_ASSERT(aImageKeys
.length() == 3);
587 const YCbCrDescriptor
& desc
= mDescriptor
.get_YCbCrDescriptor();
588 aBuilder
.PushYCbCrPlanarImage(
589 aBounds
, aClip
, true, aImageKeys
[0], aImageKeys
[1], aImageKeys
[2],
590 wr::ToWrColorDepth(desc
.colorDepth()),
591 wr::ToWrYuvColorSpace(desc
.yUVColorSpace()),
592 wr::ToWrColorRange(desc
.colorRange()), aFilter
, preferCompositorSurface
,
597 void TextureHost::DeserializeReadLock(ReadLockDescriptor
&& aDesc
,
598 ISurfaceAllocator
* aAllocator
) {
603 mReadLock
= TextureReadLock::Deserialize(std::move(aDesc
), aAllocator
);
606 void TextureHost::SetReadLocked() {
610 // If mReadLocked is true it means we haven't read unlocked yet and the
611 // content side should not have been able to write into this texture and read
613 MOZ_ASSERT(!mReadLocked
);
617 void TextureHost::ReadUnlock() {
618 if (mReadLock
&& mReadLocked
) {
619 mReadLock
->ReadUnlock();
624 bool TextureHost::NeedsYFlip() const {
625 return bool(mFlags
& TextureFlags::ORIGIN_BOTTOM_LEFT
);
628 void BufferTextureHost::UnbindTextureSource() {
629 // This texture is not used by any layer anymore.
630 // If the texture has an intermediate buffer we don't care either because
631 // texture uploads are also performed synchronously for BufferTextureHost.
635 gfx::SurfaceFormat
BufferTextureHost::GetFormat() const { return mFormat
; }
637 gfx::YUVColorSpace
BufferTextureHost::GetYUVColorSpace() const {
638 if (mFormat
== gfx::SurfaceFormat::YUV420
) {
639 const YCbCrDescriptor
& desc
= mDescriptor
.get_YCbCrDescriptor();
640 return desc
.yUVColorSpace();
642 return gfx::YUVColorSpace::Identity
;
645 gfx::ColorDepth
BufferTextureHost::GetColorDepth() const {
646 if (mFormat
== gfx::SurfaceFormat::YUV420
) {
647 const YCbCrDescriptor
& desc
= mDescriptor
.get_YCbCrDescriptor();
648 return desc
.colorDepth();
650 return gfx::ColorDepth::COLOR_8
;
653 gfx::ColorRange
BufferTextureHost::GetColorRange() const {
654 if (mFormat
== gfx::SurfaceFormat::YUV420
) {
655 const YCbCrDescriptor
& desc
= mDescriptor
.get_YCbCrDescriptor();
656 return desc
.colorRange();
658 return TextureHost::GetColorRange();
661 gfx::ChromaSubsampling
BufferTextureHost::GetChromaSubsampling() const {
662 if (mFormat
== gfx::SurfaceFormat::YUV420
) {
663 const YCbCrDescriptor
& desc
= mDescriptor
.get_YCbCrDescriptor();
664 return desc
.chromaSubsampling();
666 return gfx::ChromaSubsampling::FULL
;
669 uint8_t* BufferTextureHost::GetYChannel() {
670 if (mFormat
== gfx::SurfaceFormat::YUV420
) {
671 const YCbCrDescriptor
& desc
= mDescriptor
.get_YCbCrDescriptor();
672 return ImageDataSerializer::GetYChannel(GetBuffer(), desc
);
677 uint8_t* BufferTextureHost::GetCbChannel() {
678 if (mFormat
== gfx::SurfaceFormat::YUV420
) {
679 const YCbCrDescriptor
& desc
= mDescriptor
.get_YCbCrDescriptor();
680 return ImageDataSerializer::GetCbChannel(GetBuffer(), desc
);
685 uint8_t* BufferTextureHost::GetCrChannel() {
686 if (mFormat
== gfx::SurfaceFormat::YUV420
) {
687 const YCbCrDescriptor
& desc
= mDescriptor
.get_YCbCrDescriptor();
688 return ImageDataSerializer::GetCrChannel(GetBuffer(), desc
);
693 int32_t BufferTextureHost::GetYStride() const {
694 if (mFormat
== gfx::SurfaceFormat::YUV420
) {
695 const YCbCrDescriptor
& desc
= mDescriptor
.get_YCbCrDescriptor();
696 return desc
.yStride();
701 int32_t BufferTextureHost::GetCbCrStride() const {
702 if (mFormat
== gfx::SurfaceFormat::YUV420
) {
703 const YCbCrDescriptor
& desc
= mDescriptor
.get_YCbCrDescriptor();
704 return desc
.cbCrStride();
709 already_AddRefed
<gfx::DataSourceSurface
> BufferTextureHost::GetAsSurface(
710 gfx::DataSourceSurface
* aSurface
) {
711 RefPtr
<gfx::DataSourceSurface
> result
;
712 if (mFormat
== gfx::SurfaceFormat::UNKNOWN
) {
713 NS_WARNING("BufferTextureHost: unsupported format!");
716 if (mFormat
== gfx::SurfaceFormat::YUV420
) {
717 result
= ImageDataSerializer::DataSourceSurfaceFromYCbCrDescriptor(
718 GetBuffer(), mDescriptor
.get_YCbCrDescriptor(), aSurface
);
719 if (NS_WARN_IF(!result
)) {
723 result
= gfx::Factory::CreateWrappingDataSourceSurface(
725 ImageDataSerializer::GetRGBStride(mDescriptor
.get_RGBDescriptor()),
728 return result
.forget();
731 ShmemTextureHost::ShmemTextureHost(const ipc::Shmem
& aShmem
,
732 const BufferDescriptor
& aDesc
,
733 ISurfaceAllocator
* aDeallocator
,
735 : BufferTextureHost(aDesc
, aFlags
), mDeallocator(aDeallocator
) {
736 if (aShmem
.IsReadable()) {
737 mShmem
= MakeUnique
<ipc::Shmem
>(aShmem
);
739 // This can happen if we failed to map the shmem on this process, perhaps
740 // because it was big and we didn't have enough contiguous address space
741 // available, even though we did on the child process.
742 // As a result this texture will be in an invalid state and Lock will
745 gfxCriticalNote
<< "Failed to create a valid ShmemTextureHost";
748 MOZ_COUNT_CTOR(ShmemTextureHost
);
751 ShmemTextureHost::~ShmemTextureHost() {
752 MOZ_ASSERT(!mShmem
|| (mFlags
& TextureFlags::DEALLOCATE_CLIENT
),
753 "Leaking our buffer");
754 DeallocateDeviceData();
755 MOZ_COUNT_DTOR(ShmemTextureHost
);
758 void ShmemTextureHost::DeallocateSharedData() {
760 MOZ_ASSERT(mDeallocator
,
761 "Shared memory would leak without a ISurfaceAllocator");
762 mDeallocator
->AsShmemAllocator()->DeallocShmem(*mShmem
);
767 void ShmemTextureHost::ForgetSharedData() {
773 void ShmemTextureHost::OnShutdown() { mShmem
= nullptr; }
775 uint8_t* ShmemTextureHost::GetBuffer() {
776 return mShmem
? mShmem
->get
<uint8_t>() : nullptr;
779 size_t ShmemTextureHost::GetBufferSize() {
780 return mShmem
? mShmem
->Size
<uint8_t>() : 0;
783 MemoryTextureHost::MemoryTextureHost(uint8_t* aBuffer
,
784 const BufferDescriptor
& aDesc
,
786 : BufferTextureHost(aDesc
, aFlags
), mBuffer(aBuffer
) {
787 MOZ_COUNT_CTOR(MemoryTextureHost
);
790 MemoryTextureHost::~MemoryTextureHost() {
791 MOZ_ASSERT(!mBuffer
|| (mFlags
& TextureFlags::DEALLOCATE_CLIENT
),
792 "Leaking our buffer");
793 DeallocateDeviceData();
794 MOZ_COUNT_DTOR(MemoryTextureHost
);
797 void MemoryTextureHost::DeallocateSharedData() {
799 GfxMemoryImageReporter::WillFree(mBuffer
);
805 void MemoryTextureHost::ForgetSharedData() { mBuffer
= nullptr; }
807 uint8_t* MemoryTextureHost::GetBuffer() { return mBuffer
; }
809 size_t MemoryTextureHost::GetBufferSize() {
810 // MemoryTextureHost just trusts that the buffer size is large enough to read
811 // anything we need to. That's because MemoryTextureHost has to trust the
812 // buffer pointer anyway, so the security model here is just that
813 // MemoryTexture's are restricted to same-process clients.
814 return std::numeric_limits
<size_t>::max();
817 TextureParent::TextureParent(HostIPCAllocator
* aSurfaceAllocator
,
818 const dom::ContentParentId
& aContentId
,
820 const wr::MaybeExternalImageId
& aExternalImageId
)
821 : mSurfaceAllocator(aSurfaceAllocator
),
822 mContentId(aContentId
),
824 mExternalImageId(aExternalImageId
) {
825 MOZ_COUNT_CTOR(TextureParent
);
828 TextureParent::~TextureParent() { MOZ_COUNT_DTOR(TextureParent
); }
830 void TextureParent::NotifyNotUsed(uint64_t aTransactionId
) {
834 mSurfaceAllocator
->NotifyNotUsed(this, aTransactionId
);
837 bool TextureParent::Init(const SurfaceDescriptor
& aSharedData
,
838 ReadLockDescriptor
&& aReadLock
,
839 const LayersBackend
& aBackend
,
840 const TextureFlags
& aFlags
) {
842 TextureHost::Create(aSharedData
, std::move(aReadLock
), mSurfaceAllocator
,
843 aBackend
, aFlags
, mExternalImageId
);
845 mTextureHost
->mActor
= this;
848 return !!mTextureHost
;
851 void TextureParent::Destroy() {
856 if (mTextureHost
->mReadLocked
) {
857 // ReadUnlock here to make sure the ReadLock's shmem does not outlive the
858 // protocol that created it.
859 mTextureHost
->ReadUnlock();
862 if (mTextureHost
->GetFlags() & TextureFlags::DEALLOCATE_CLIENT
) {
863 mTextureHost
->ForgetSharedData();
866 mTextureHost
->mActor
= nullptr;
867 mTextureHost
= nullptr;
870 void TextureHost::ReceivedDestroy(PTextureParent
* aActor
) {
871 static_cast<TextureParent
*>(aActor
)->RecvDestroy();
874 mozilla::ipc::IPCResult
TextureParent::RecvRecycleTexture(
875 const TextureFlags
& aTextureFlags
) {
879 mTextureHost
->RecycleTexture(aTextureFlags
);
883 ////////////////////////////////////////////////////////////////////////////////
885 } // namespace layers
886 } // namespace mozilla