1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef MOZILLA_GFX_TEXTURECLIENT_H
#define MOZILLA_GFX_TEXTURECLIENT_H
#include <stddef.h> // for size_t
#include <stdint.h> // for uint32_t, uint8_t, uint64_t
#include "GLTextureImage.h" // for TextureImage
#include "GfxTexturesReporter.h"
#include "ImageTypes.h" // for StereoMode
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
#include "mozilla/Atomics.h"
#include "mozilla/Attributes.h" // for override
#include "mozilla/Mutex.h"
#include "mozilla/RefPtr.h" // for RefPtr, RefCounted
#include "mozilla/dom/ipc/IdType.h"
#include "mozilla/gfx/2D.h" // for DrawTarget
#include "mozilla/gfx/CriticalSection.h"
#include "mozilla/gfx/Point.h" // for IntSize
#include "mozilla/gfx/Types.h" // for SurfaceFormat
#include "mozilla/ipc/Shmem.h" // for Shmem
#include "mozilla/layers/AtomicRefCountedWithFinalize.h"
#include "mozilla/layers/CompositorTypes.h" // for TextureFlags, etc
#include "mozilla/layers/ISurfaceAllocator.h"
#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor
#include "mozilla/layers/LayersTypes.h"
#include "mozilla/layers/SyncObject.h"
#include "mozilla/mozalloc.h" // for operator delete
#include "mozilla/UniquePtrExtensions.h" // for UniqueFileHandle
#include "mozilla/webrender/WebRenderTypes.h"
#include "nsCOMPtr.h" // for already_AddRefed
#include "nsISupportsImpl.h" // for TextureImage::AddRef, etc
#include "nsThreadUtils.h"
#include "pratom.h"
class gfxImageSurface;
struct ID3D11Device;
namespace mozilla {
namespace layers {
class AndroidHardwareBufferTextureData;
class BufferTextureData;
class CompositableForwarder;
class FwdTransactionTracker;
class KnowsCompositor;
class LayersIPCChannel;
class CompositableClient;
struct PlanarYCbCrData;
class Image;
class PTextureChild;
class TextureChild;
class TextureData;
class GPUVideoTextureData;
class TextureClient;
class ITextureClientRecycleAllocator;
class SharedSurfaceTextureData;
class TextureForwarder;
class RecordedTextureData;
struct RemoteTextureOwnerId;
/**
* TextureClient is the abstraction that allows us to share data between the
* content and the compositor side.
*/
enum TextureAllocationFlags {
ALLOC_DEFAULT = 0,
ALLOC_CLEAR_BUFFER =
1 << 1, // Clear the buffer to whatever is best for the draw target
ALLOC_CLEAR_BUFFER_WHITE = 1 << 2, // explicit all white
ALLOC_CLEAR_BUFFER_BLACK = 1 << 3, // explicit all black
ALLOC_DISALLOW_BUFFERTEXTURECLIENT = 1 << 4,
// Allocate the texture for out-of-band content updates. This is mostly for
// TextureClientD3D11, which may otherwise choose D3D10 or non-KeyedMutex
// surfaces when used on the main thread.
ALLOC_FOR_OUT_OF_BAND_CONTENT = 1 << 5,
// Disable any cross-device synchronization. This is also for
// TextureClientD3D11, and creates a texture without KeyedMutex.
ALLOC_MANUAL_SYNCHRONIZATION = 1 << 6,
// The texture is going to be updated using UpdateFromSurface and needs to
// support that call.
ALLOC_UPDATE_FROM_SURFACE = 1 << 7,
// Do not use an accelerated texture type.
ALLOC_DO_NOT_ACCELERATE = 1 << 8,
// Force allocation of remote/recorded texture, or fail if not possible.
ALLOC_FORCE_REMOTE = 1 << 9,
// Prefer to use keyed mutex than D3D11Fence on Windows
USE_D3D11_KEYED_MUTEX = 1 << 10,
};
enum class BackendSelector { Content, Canvas };
/// Temporary object providing direct access to a Texture's memory.
///
/// see TextureClient::CanExposeMappedData() and
/// TextureClient::BorrowMappedData().
struct MappedTextureData {
uint8_t* data;
gfx::IntSize size;
int32_t stride;
gfx::SurfaceFormat format;
};
struct MappedYCbCrChannelData {
uint8_t* data;
gfx::IntSize size;
int32_t stride;
int32_t skip;
uint32_t bytesPerPixel;
bool CopyInto(MappedYCbCrChannelData& aDst);
};
struct MappedYCbCrTextureData {
MappedYCbCrChannelData y;
MappedYCbCrChannelData cb;
MappedYCbCrChannelData cr;
// Sad but because of how SharedPlanarYCbCrData is used we have to expose this
// for now.
uint8_t* metadata;
StereoMode stereoMode;
bool CopyInto(MappedYCbCrTextureData& aDst) {
return y.CopyInto(aDst.y) && cb.CopyInto(aDst.cb) && cr.CopyInto(aDst.cr);
}
};
class ReadLockDescriptor;
class NonBlockingTextureReadLock;
// A class to help implement copy-on-write semantics for shared textures.
//
// A TextureClient/Host pair can opt into using a ReadLock by calling
// TextureClient::EnableReadLock. This will equip the TextureClient with a
// ReadLock object that will be automatically ReadLock()'ed by the texture
// itself when it is written into (see TextureClient::Unlock). A
// TextureReadLock's counter starts at 1 and is expected to be equal to 1 when
// the lock is destroyed. See ShmemTextureReadLock for explanations about why we
// use 1 instead of 0 as the initial state. TextureReadLock is mostly internally
// managed by the TextureClient/Host pair, and the compositable only has to
// forward it during updates. If an update message contains a null_t lock, it
// means that the texture was not written into on the content side, and there is
// no synchronization required on the compositor side (or it means that the
// texture pair did not opt into using ReadLocks). On the compositor side, the
// TextureHost can receive a ReadLock during a transaction, and will both
// ReadUnlock() it and drop it as soon as the shared data is available again for
// writing (the texture upload is done, or the compositor not reading the
// texture anymore). The lock is dropped to make sure it is ReadUnlock()'ed only
// once.
class TextureReadLock {
protected:
virtual ~TextureReadLock() = default;
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TextureReadLock)
virtual bool ReadLock() = 0;
virtual bool TryReadLock(TimeDuration aTimeout) { return ReadLock(); }
virtual int32_t ReadUnlock() = 0;
virtual bool IsValid() const = 0;
static already_AddRefed<TextureReadLock> Deserialize(
ReadLockDescriptor&& aDescriptor, ISurfaceAllocator* aAllocator);
virtual bool Serialize(ReadLockDescriptor& aOutput,
base::ProcessId aOther) = 0;
enum LockType {
TYPE_NONBLOCKING_MEMORY,
TYPE_NONBLOCKING_SHMEM,
TYPE_CROSS_PROCESS_SEMAPHORE
};
virtual LockType GetType() = 0;
virtual NonBlockingTextureReadLock* AsNonBlockingLock() { return nullptr; }
};
class NonBlockingTextureReadLock : public TextureReadLock {
public:
virtual int32_t GetReadCount() = 0;
static already_AddRefed<TextureReadLock> Create(LayersIPCChannel* aAllocator);
NonBlockingTextureReadLock* AsNonBlockingLock() override { return this; }
};
#ifdef XP_WIN
class D3D11TextureData;
class DXGIYCbCrTextureData;
#endif
class TextureData {
public:
struct Info {
gfx::IntSize size;
gfx::SurfaceFormat format;
bool hasSynchronization;
bool supportsMoz2D;
bool canExposeMappedData;
bool canConcurrentlyReadLock;
Info()
: format(gfx::SurfaceFormat::UNKNOWN),
hasSynchronization(false),
supportsMoz2D(false),
canExposeMappedData(false),
canConcurrentlyReadLock(true) {}
};
static TextureData* Create(
TextureType aTextureType, gfx::SurfaceFormat aFormat,
const gfx::IntSize& aSize, TextureAllocationFlags aAllocFlags,
gfx::BackendType aBackendType = gfx::BackendType::NONE);
static TextureData* Create(TextureForwarder* aAllocator,
gfx::SurfaceFormat aFormat, gfx::IntSize aSize,
KnowsCompositor* aKnowsCompositor,
BackendSelector aSelector,
TextureFlags aTextureFlags,
TextureAllocationFlags aAllocFlags);
static bool IsRemote(KnowsCompositor* aKnowsCompositor,
BackendSelector aSelector,
gfx::SurfaceFormat aFormat = gfx::SurfaceFormat::UNKNOWN,
gfx::IntSize aSize = gfx::IntSize(1, 1));
MOZ_COUNTED_DTOR_VIRTUAL(TextureData)
virtual TextureType GetTextureType() const { return TextureType::Last; }
virtual void FillInfo(TextureData::Info& aInfo) const = 0;
virtual void InvalidateContents() {}
virtual bool Lock(OpenMode aMode) = 0;
virtual void Unlock() = 0;
virtual already_AddRefed<gfx::DrawTarget> BorrowDrawTarget() {
return nullptr;
}
virtual void ReturnDrawTarget(already_AddRefed<gfx::DrawTarget> aDT);
/**
* When the TextureData is not being Unlocked, this can be used to inform a
* TextureData that drawing has finished until the next BorrowDrawTarget.
*/
virtual void EndDraw() {}
virtual already_AddRefed<gfx::SourceSurface> BorrowSnapshot() {
return nullptr;
}
virtual void ReturnSnapshot(already_AddRefed<gfx::SourceSurface> aSnapshot);
virtual bool BorrowMappedData(MappedTextureData&) { return false; }
virtual bool BorrowMappedYCbCrData(MappedYCbCrTextureData&) { return false; }
virtual void Deallocate(LayersIPCChannel* aAllocator) = 0;
/// Depending on the texture's flags either Deallocate or Forget is called.
virtual void Forget(LayersIPCChannel* aAllocator) {}
virtual bool Serialize(SurfaceDescriptor& aDescriptor) = 0;
virtual void GetSubDescriptor(RemoteDecoderVideoSubDescriptor* aOutDesc) {}
virtual void OnForwardedToHost() {}
virtual TextureData* CreateSimilar(
LayersIPCChannel* aAllocator, LayersBackend aLayersBackend,
TextureFlags aFlags = TextureFlags::DEFAULT,
TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const {
return nullptr;
}
virtual bool UpdateFromSurface(gfx::SourceSurface* aSurface) {
return false;
};
virtual void SyncWithObject(RefPtr<SyncObjectClient> aSyncObject) {};
virtual TextureFlags GetTextureFlags() const {
return TextureFlags::NO_FLAGS;
}
#ifdef XP_WIN
virtual D3D11TextureData* AsD3D11TextureData() { return nullptr; }
virtual DXGIYCbCrTextureData* AsDXGIYCbCrTextureData() { return nullptr; }
#endif
virtual BufferTextureData* AsBufferTextureData() { return nullptr; }
virtual GPUVideoTextureData* AsGPUVideoTextureData() { return nullptr; }
virtual AndroidHardwareBufferTextureData*
AsAndroidHardwareBufferTextureData() {
return nullptr;
}
virtual RecordedTextureData* AsRecordedTextureData() { return nullptr; }
// It is used by AndroidHardwareBufferTextureData and
// SharedSurfaceTextureData. Returns buffer id when it owns
// AndroidHardwareBuffer. It is used only on android.
virtual Maybe<uint64_t> GetBufferId() const { return Nothing(); }
// The acquire fence is a fence that is used for waiting until rendering to
// its AHardwareBuffer is completed.
// It is used only on android.
virtual UniqueFileHandle GetAcquireFence() { return UniqueFileHandle(); }
virtual bool RequiresRefresh() const { return false; }
virtual already_AddRefed<FwdTransactionTracker> UseCompositableForwarder(
CompositableForwarder* aForwarder) {
return nullptr;
}
protected:
MOZ_COUNTED_DEFAULT_CTOR(TextureData)
};
/**
* TextureClient is a thin abstraction over texture data that need to be shared
* between the content process and the compositor process. It is the
* content-side half of a TextureClient/TextureHost pair. A corresponding
* TextureHost lives on the compositor-side.
*
* TextureClient's primary purpose is to present texture data in a way that is
* understood by the IPC system. There are two ways to use it:
* - Use it to serialize image data that is not IPC-friendly (most likely
* involving a copy into shared memory)
* - preallocate it and paint directly into it, which avoids copy but requires
* the painting code to be aware of TextureClient (or at least the underlying
* shared memory).
*
* There is always one and only one TextureClient per TextureHost, and the
* TextureClient/Host pair only owns one buffer of image data through its
* lifetime. This means that the lifetime of the underlying shared data
* matches the lifetime of the TextureClient/Host pair. It also means
* TextureClient/Host do not implement double buffering, which is the
* responsibility of the compositable (which would use pairs of Textures).
* In order to send several different buffers to the compositor side, use
* several TextureClients.
*/
class TextureClient : public AtomicRefCountedWithFinalize<TextureClient> {
public:
TextureClient(TextureData* aData, TextureFlags aFlags,
LayersIPCChannel* aAllocator);
virtual ~TextureClient();
static already_AddRefed<TextureClient> CreateWithData(
TextureData* aData, TextureFlags aFlags, LayersIPCChannel* aAllocator);
// Creates and allocates a TextureClient usable with Moz2D.
static already_AddRefed<TextureClient> CreateForDrawing(
KnowsCompositor* aAllocator, gfx::SurfaceFormat aFormat,
gfx::IntSize aSize, BackendSelector aSelector, TextureFlags aTextureFlags,
TextureAllocationFlags flags = ALLOC_DEFAULT);
static already_AddRefed<TextureClient> CreateFromSurface(
KnowsCompositor* aAllocator, gfx::SourceSurface* aSurface,
BackendSelector aSelector, TextureFlags aTextureFlags,
TextureAllocationFlags aAllocFlags);
// Creates and allocates a TextureClient supporting the YCbCr format.
static already_AddRefed<TextureClient> CreateForYCbCr(
KnowsCompositor* aAllocator, const gfx::IntRect& aDisplay,
const gfx::IntSize& aYSize, uint32_t aYStride,
const gfx::IntSize& aCbCrSize, uint32_t aCbCrStride,
StereoMode aStereoMode, gfx::ColorDepth aColorDepth,
gfx::YUVColorSpace aYUVColorSpace, gfx::ColorRange aColorRange,
gfx::ChromaSubsampling aSubsampling, TextureFlags aTextureFlags);
// Creates and allocates a TextureClient (can be accessed through raw
// pointers).
static already_AddRefed<TextureClient> CreateForRawBufferAccess(
KnowsCompositor* aAllocator, gfx::SurfaceFormat aFormat,
gfx::IntSize aSize, gfx::BackendType aMoz2dBackend,
TextureFlags aTextureFlags, TextureAllocationFlags flags = ALLOC_DEFAULT);
// Creates and allocates a TextureClient of the same type.
already_AddRefed<TextureClient> CreateSimilar(
LayersBackend aLayersBackend = LayersBackend::LAYERS_NONE,
TextureFlags aFlags = TextureFlags::DEFAULT,
TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const;
/**
* Locks the shared data, allowing the caller to get access to it.
*
* Please always lock/unlock when accessing the shared data.
* If Lock() returns false, you should not attempt to access the shared data.
*/
bool Lock(OpenMode aMode);
void Unlock();
bool IsLocked() const { return mIsLocked; }
gfx::IntSize GetSize() const { return mInfo.size; }
gfx::SurfaceFormat GetFormat() const { return mInfo.format; }
/**
* Returns true if this texture has a synchronization mechanism (mutex, fence,
* etc.). Textures that do not implement synchronization should be immutable
* or should use immediate uploads (see TextureFlags in CompositorTypes.h)
* Even if a texture does not implement synchronization, Lock and Unlock need
* to be used appropriately since the latter are also there to map/numap data.
*/
bool HasSynchronization() const { return mInfo.hasSynchronization; }
bool CanExposeDrawTarget() const { return mInfo.supportsMoz2D; }
bool CanExposeMappedData() const { return mInfo.canExposeMappedData; }
/**
* Returns a DrawTarget to draw into the TextureClient.
* This function should never be called when not on the main thread!
*
* This must never be called on a TextureClient that is not sucessfully
* locked. When called several times within one Lock/Unlock pair, this method
* should return the same DrawTarget. The DrawTarget is automatically flushed
* by the TextureClient when the latter is unlocked, and the DrawTarget that
* will be returned within the next lock/unlock pair may or may not be the
* same object. Do not keep references to the DrawTarget outside of the
* lock/unlock pair.
*
* This is typically used as follows:
*
* if (!texture->Lock(OpenMode::OPEN_READ_WRITE)) {
* return false;
* }
* {
* // Restrict this code's scope to ensure all references to dt are gone
* // when Unlock is called.
* DrawTarget* dt = texture->BorrowDrawTarget();
* // use the draw target ...
* }
* texture->Unlock();
*
*/
gfx::DrawTarget* BorrowDrawTarget();
/**
* When the TextureClient is not being Unlocked, this can be used to inform it
* that drawing has finished until the next BorrowDrawTarget.
*/
void EndDraw();
already_AddRefed<gfx::SourceSurface> BorrowSnapshot();
void ReturnSnapshot(already_AddRefed<gfx::SourceSurface> aSnapshot);
/**
* Similar to BorrowDrawTarget but provides direct access to the texture's
* bits instead of a DrawTarget.
*/
bool BorrowMappedData(MappedTextureData&);
bool BorrowMappedYCbCrData(MappedYCbCrTextureData&);
/**
* This function can be used to update the contents of the TextureClient
* off the main thread.
*/
void UpdateFromSurface(gfx::SourceSurface* aSurface);
/**
* This method is strictly for debugging. It causes locking and
* needless copies.
*/
already_AddRefed<gfx::DataSourceSurface> GetAsSurface();
/**
* Copies a rectangle from this texture client to a position in aTarget.
* It is assumed that the necessary locks are in place; so this should at
* least have a read lock and aTarget should at least have a write lock.
*/
bool CopyToTextureClient(TextureClient* aTarget, const gfx::IntRect* aRect,
const gfx::IntPoint* aPoint);
/**
* Allocate and deallocate a TextureChild actor.
*
* TextureChild is an implementation detail of TextureClient that is not
* exposed to the rest of the code base. CreateIPDLActor and DestroyIPDLActor
* are for use with the managing IPDL protocols only (so that they can
* implement AllocPextureChild and DeallocPTextureChild).
*/
static PTextureChild* CreateIPDLActor();
static bool DestroyIPDLActor(PTextureChild* actor);
/**
* Get the TextureClient corresponding to the actor passed in parameter.
*/
static already_AddRefed<TextureClient> AsTextureClient(PTextureChild* actor);
/**
* TextureFlags contain important information about various aspects
* of the texture, like how its liferime is managed, and how it
* should be displayed.
* See TextureFlags in CompositorTypes.h.
*/
TextureFlags GetFlags() const { return mFlags; }
bool HasFlags(TextureFlags aFlags) const {
return (mFlags & aFlags) == aFlags;
}
void AddFlags(TextureFlags aFlags);
void RemoveFlags(TextureFlags aFlags);
// Must not be called when TextureClient is in use by CompositableClient.
void RecycleTexture(TextureFlags aFlags);
/**
* After being shared with the compositor side, an immutable texture is never
* modified, it can only be read. It is safe to not Lock/Unlock immutable
* textures.
*/
bool IsImmutable() const { return !!(mFlags & TextureFlags::IMMUTABLE); }
void MarkImmutable() { AddFlags(TextureFlags::IMMUTABLE); }
bool IsSharedWithCompositor() const;
/**
* If this method returns false users of TextureClient are not allowed
* to access the shared data.
*/
bool IsValid() const { return !!mData; }
/**
* Called when TextureClient is added to CompositableClient.
*/
void SetAddedToCompositableClient();
/**
* If this method retuns false, TextureClient is already added to
* CompositableClient, since its creation or recycling.
*/
bool IsAddedToCompositableClient() const {
return mAddedToCompositableClient;
}
/**
* Create and init the TextureChild/Parent IPDL actor pair
* with a CompositableForwarder.
*
* Should be called only once per TextureClient.
* The TextureClient must not be locked when calling this method.
*/
bool InitIPDLActor(CompositableForwarder* aForwarder);
/**
* Create and init the TextureChild/Parent IPDL actor pair
* with a TextureForwarder.
*
* Should be called only once per TextureClient.
* The TextureClient must not be locked when calling this method.
*/
bool InitIPDLActor(KnowsCompositor* aKnowsCompositor,
const dom::ContentParentId& aContentId);
/**
* Return a pointer to the IPDLActor.
*
* This is to be used with IPDL messages only. Do not store the returned
* pointer.
*/
PTextureChild* GetIPDLActor();
/**
* Triggers the destruction of the shared data and the corresponding
* TextureHost.
*
* If the texture flags contain TextureFlags::DEALLOCATE_CLIENT, the
* destruction will be synchronously coordinated with the compositor side,
* otherwise it will be done asynchronously.
*/
void Destroy();
/**
* Track how much of this texture is wasted.
* For example we might allocate a 256x256 tile but only use 10x10.
*/
void SetWaste(int aWasteArea) {
mWasteTracker.Update(aWasteArea, BytesPerPixel(GetFormat()));
}
void SyncWithObject(RefPtr<SyncObjectClient> aSyncObject) {
mData->SyncWithObject(aSyncObject);
}
LayersIPCChannel* GetAllocator() { return mAllocator; }
ITextureClientRecycleAllocator* GetRecycleAllocator() {
return mRecycleAllocator;
}
void SetRecycleAllocator(ITextureClientRecycleAllocator* aAllocator);
/// If you add new code that uses this method, you are probably doing
/// something wrong.
TextureData* GetInternalData() { return mData; }
const TextureData* GetInternalData() const { return mData; }
uint64_t GetSerial() const { return mSerial; }
void GetSurfaceDescriptorRemoteDecoder(
SurfaceDescriptorRemoteDecoder* aOutDesc);
void CancelWaitForNotifyNotUsed();
/**
* Set last transaction id of CompositableForwarder.
*
* Called when TextureClient has TextureFlags::RECYCLE flag.
* When CompositableForwarder forwards the TextureClient with
* TextureFlags::RECYCLE, it holds TextureClient's ref until host side
* releases it. The host side sends TextureClient release message.
* The id is used to check if the message is for the last TextureClient
* forwarding.
*/
void SetLastFwdTransactionId(uint64_t aTransactionId) {
MOZ_ASSERT(mFwdTransactionId <= aTransactionId);
mFwdTransactionId = aTransactionId;
}
uint64_t GetLastFwdTransactionId() { return mFwdTransactionId; }
bool HasReadLock() const {
MutexAutoLock lock(mMutex);
return !!mReadLock;
}
int32_t GetNonBlockingReadLockCount() {
MutexAutoLock lock(mMutex);
if (NS_WARN_IF(!mReadLock)) {
MOZ_ASSERT_UNREACHABLE("No read lock created yet?");
return 0;
}
MOZ_ASSERT(mReadLock->AsNonBlockingLock(),
"Can only check locked for non-blocking locks!");
return mReadLock->AsNonBlockingLock()->GetReadCount();
}
bool IsReadLocked();
bool ShouldReadLock() const {
return bool(mFlags & (TextureFlags::NON_BLOCKING_READ_LOCK |
TextureFlags::BLOCKING_READ_LOCK));
}
bool TryReadLock();
void ReadUnlock();
void SetUpdated() { mUpdated = true; }
void OnPrepareForwardToHost();
void OnAbandonForwardToHost();
bool OnForwardedToHost();
// Mark that the TextureClient will be used by the paint thread, and should
// not free its underlying texture data. This must only be called from the
// main thread.
void AddPaintThreadRef();
// Mark that the TextureClient is no longer in use by the PaintThread. This
// must only be called from the PaintThread.
void DropPaintThreadRef();
wr::MaybeExternalImageId GetExternalImageKey() { return mExternalImageId; }
private:
static void TextureClientRecycleCallback(TextureClient* aClient,
void* aClosure);
static already_AddRefed<TextureClient> CreateForDrawing(
TextureForwarder* aAllocator, gfx::SurfaceFormat aFormat,
gfx::IntSize aSize, KnowsCompositor* aKnowsCompositor,
BackendSelector aSelector, TextureFlags aTextureFlags,
TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT);
static already_AddRefed<TextureClient> CreateForRawBufferAccess(
LayersIPCChannel* aAllocator, gfx::SurfaceFormat aFormat,
gfx::IntSize aSize, gfx::BackendType aMoz2dBackend,
LayersBackend aLayersBackend, TextureFlags aTextureFlags,
TextureAllocationFlags flags = ALLOC_DEFAULT);
void EnsureHasReadLock() MOZ_REQUIRES(mMutex);
void EnableReadLock() MOZ_REQUIRES(mMutex);
void EnableBlockingReadLock() MOZ_REQUIRES(mMutex);
/**
* Called once, during the destruction of the Texture, on the thread in which
* texture's reference count reaches 0 (could be any thread).
*
* Here goes the shut-down code that uses virtual methods.
* Must only be called by Release().
*/
void Finalize() {}
friend class AtomicRefCountedWithFinalize<TextureClient>;
protected:
/**
* Should only be called *once* per texture, in TextureClient::InitIPDLActor.
* Some texture implementations rely on the fact that the descriptor will be
* deserialized.
* Calling ToSurfaceDescriptor again after it has already returned true,
* or never constructing a TextureHost with aDescriptor may result in a memory
* leak (see TextureClientD3D9 for example).
*/
bool ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor);
void LockActor() const;
void UnlockActor() const;
TextureData::Info mInfo;
mutable Mutex mMutex;
RefPtr<LayersIPCChannel> mAllocator;
RefPtr<TextureChild> mActor;
RefPtr<ITextureClientRecycleAllocator> mRecycleAllocator;
RefPtr<TextureReadLock> mReadLock MOZ_GUARDED_BY(mMutex);
TextureData* mData;
RefPtr<gfx::DrawTarget> mBorrowedDrawTarget;
bool mBorrowedSnapshot = false;
TextureFlags mFlags;
gl::GfxTextureWasteTracker mWasteTracker;
OpenMode mOpenMode;
bool mIsLocked;
bool mIsReadLocked MOZ_GUARDED_BY(mMutex);
bool mIsPendingForwardReadLocked MOZ_GUARDED_BY(mMutex) = false;
// This member tracks that the texture was written into until the update
// is sent to the compositor. We need this remember to lock mReadLock on
// behalf of the compositor just before sending the notification.
bool mUpdated;
// Used when TextureClient is recycled with TextureFlags::RECYCLE flag.
bool mAddedToCompositableClient;
uint64_t mFwdTransactionId;
// Serial id of TextureClient. It is unique in current process.
const uint64_t mSerial;
// When non-zero, texture data must not be freed.
mozilla::Atomic<uintptr_t> mPaintThreadRefs;
// External image id. It is unique if it is allocated.
// The id is allocated in TextureClient::InitIPDLActor().
// Its allocation is supported by
// CompositorBridgeChild and ImageBridgeChild for now.
wr::MaybeExternalImageId mExternalImageId;
// Used to assign serial ids of TextureClient.
static mozilla::Atomic<uint64_t> sSerialCounter;
friend class TextureChild;
friend void TestTextureClientSurface(TextureClient*, gfxImageSurface*);
friend void TestTextureClientYCbCr(TextureClient*, PlanarYCbCrData&);
friend already_AddRefed<TextureHost> CreateTextureHostWithBackend(
TextureClient*, ISurfaceAllocator*, LayersBackend&);
};
/**
* Task that releases TextureClient pointer on a specified thread.
*/
class TextureClientReleaseTask : public Runnable {
public:
explicit TextureClientReleaseTask(TextureClient* aClient)
: Runnable("layers::TextureClientReleaseTask"), mTextureClient(aClient) {}
NS_IMETHOD Run() override {
mTextureClient = nullptr;
return NS_OK;
}
private:
RefPtr<TextureClient> mTextureClient;
};
// Automatically lock and unlock a texture. Since texture locking is fallible,
// Succeeded() must be checked on the guard object before proceeding.
class MOZ_RAII TextureClientAutoLock {
public:
TextureClientAutoLock(TextureClient* aTexture, OpenMode aMode)
: mTexture(aTexture), mSucceeded(false) {
mSucceeded = mTexture->Lock(aMode);
#ifdef DEBUG
mChecked = false;
#endif
}
~TextureClientAutoLock() {
MOZ_ASSERT(mChecked);
if (mSucceeded) {
mTexture->Unlock();
}
}
bool Succeeded() {
#ifdef DEBUG
mChecked = true;
#endif
return mSucceeded;
}
private:
TextureClient* mTexture;
#ifdef DEBUG
bool mChecked;
#endif
bool mSucceeded;
};
/// Convenience function to set the content of ycbcr texture.
bool UpdateYCbCrTextureClient(TextureClient* aTexture,
const PlanarYCbCrData& aData);
TextureType PreferredCanvasTextureType(KnowsCompositor* aKnowsCompositor);
} // namespace layers
} // namespace mozilla
#endif
|