Bug Summary

File:root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/RefPtr.h
Warning:line 287, column 12
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name TextureClient.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/gfx/layers -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/gfx/layers -resource-dir /usr/lib/llvm-21/lib/clang/21 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D _GLIBCXX_ASSERTIONS -D DEBUG=1 -D GOOGLE_PROTOBUF_NO_RTTI -D GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER -D MOZ_APP_VERSION=142.0a1 -D D3D_DEBUG_INFO -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /root/firefox-clang/gfx/layers -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/gfx/layers -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /root/firefox-clang/ipc/chromium/src -I /root/firefox-clang/docshell/base -I /root/firefox-clang/dom/canvas -I /root/firefox-clang/gfx/cairo/cairo/src -I /root/firefox-clang/layout/base -I /root/firefox-clang/layout/generic -I /root/firefox-clang/media/libyuv/libyuv/include -I /root/firefox-clang/gfx/skia -I /root/firefox-clang/gfx/skia/skia -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/sysprof-6 -I /usr/include/harfbuzz -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/x86_64-linux-gnu -I /usr/include/webp -I /usr/include/gio-unix-2.0 -I /usr/include/cloudproviders -I /usr/include/atk-1.0 -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/gtk-3.0/unix-print -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -internal-isystem /usr/lib/llvm-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-error=pessimizing-move -Wno-error=large-by-value-copy=128 -Wno-error=implicit-int-float-conversion -Wno-error=thread-safety-analysis -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-deprecated-this-capture -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2025-06-24-230228-2656624-1 -x c++ /root/firefox-clang/gfx/layers/client/TextureClient.cpp

/root/firefox-clang/gfx/layers/client/TextureClient.cpp

1/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3/* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7#include "mozilla/layers/TextureClient.h"
8
9#include <stdint.h> // for uint8_t, uint32_t, etc
10
11#include "BufferTexture.h"
12#include "IPDLActor.h"
13#include "ImageContainer.h" // for PlanarYCbCrData, etc
14#include "MainThreadUtils.h"
15#include "gfx2DGlue.h"
16#include "gfxPlatform.h" // for gfxPlatform
17#include "gfxUtils.h" // for gfxUtils::GetAsLZ4Base64Str
18#include "mozilla/Atomics.h"
19#include "mozilla/Mutex.h"
20#include "mozilla/ProfilerLabels.h"
21#include "mozilla/SchedulerGroup.h"
22#include "mozilla/StaticPrefs_gfx.h"
23#include "mozilla/StaticPrefs_layers.h"
24#include "mozilla/gfx/2D.h"
25#include "mozilla/gfx/DataSurfaceHelpers.h" // for CreateDataSourceSurfaceByCloning
26#include "mozilla/gfx/Logging.h" // for gfxDebug
27#include "mozilla/gfx/gfxVars.h"
28#include "mozilla/ipc/CrossProcessSemaphore.h"
29#include "mozilla/layers/CanvasRenderer.h"
30#include "mozilla/layers/CompositableForwarder.h"
31#include "mozilla/layers/ISurfaceAllocator.h"
32#include "mozilla/layers/ImageBridgeChild.h"
33#include "mozilla/layers/ImageDataSerializer.h"
34#include "mozilla/layers/PTextureChild.h"
35#include "mozilla/layers/SynchronousTask.h"
36#include "mozilla/layers/TextureClientOGL.h"
37#include "mozilla/layers/TextureClientRecycleAllocator.h"
38#include "mozilla/layers/TextureRecorded.h"
39#include "nsDebug.h" // for NS_ASSERTION, NS_WARNING, etc
40#include "nsISerialEventTarget.h"
41#include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc
42#include "nsPrintfCString.h" // for nsPrintfCString
43
44#ifdef XP_WIN
45# include "gfx2DGlue.h"
46# include "gfxWindowsPlatform.h"
47# include "mozilla/gfx/DeviceManagerDx.h"
48# include "mozilla/layers/TextureD3D11.h"
49#endif
50#ifdef MOZ_WIDGET_GTK1
51# include <gtk/gtkx.h>
52# include "gfxPlatformGtk.h"
53#endif
54#ifdef MOZ_WAYLAND1
55# include "mozilla/widget/nsWaylandDisplay.h"
56#endif
57
58#ifdef XP_MACOSX
59# include "mozilla/layers/MacIOSurfaceTextureClientOGL.h"
60#endif
61
62#if 0
63# define RECYCLE_LOG(...)do { } while (0) printf_stderr(__VA_ARGS__)
64#else
65# define RECYCLE_LOG(...)do { } while (0) \
66 do { \
67 } while (0)
68#endif
69
70namespace mozilla::layers {
71
72using namespace mozilla::ipc;
73using namespace mozilla::gl;
74using namespace mozilla::gfx;
75
76struct TextureDeallocParams {
77 TextureData* data = nullptr;
78 RefPtr<TextureChild> actor;
79 RefPtr<TextureReadLock> readLock;
80 RefPtr<LayersIPCChannel> allocator;
81 bool clientDeallocation = false;
82 bool syncDeallocation = false;
83
84 TextureDeallocParams() = default;
85 TextureDeallocParams(const TextureDeallocParams&) = delete;
86 TextureDeallocParams& operator=(const TextureDeallocParams&) = delete;
87
88 TextureDeallocParams(TextureDeallocParams&& aOther)
89 : data(aOther.data),
90 actor(std::move(aOther.actor)),
91 readLock(std::move(aOther.readLock)),
92 allocator(std::move(aOther.allocator)),
93 clientDeallocation(aOther.clientDeallocation),
94 syncDeallocation(aOther.syncDeallocation) {
95 aOther.data = nullptr;
96 }
97
98 TextureDeallocParams& operator=(TextureDeallocParams&& aOther) {
99 data = aOther.data;
100 aOther.data = nullptr;
101 actor = std::move(aOther.actor);
102 readLock = std::move(aOther.readLock);
103 allocator = std::move(aOther.allocator);
104 clientDeallocation = aOther.clientDeallocation;
105 syncDeallocation = aOther.syncDeallocation;
106 return *this;
107 }
108};
109
110void DeallocateTextureClient(TextureDeallocParams& params);
111
112/**
113 * TextureChild is the content-side incarnation of the PTexture IPDL actor.
114 *
115 * TextureChild is used to synchronize a texture client and its corresponding
116 * TextureHost if needed (a TextureClient that is not shared with the compositor
117 * does not have a TextureChild)
118 *
119 * During the deallocation phase, a TextureChild may hold its recently destroyed
120 * TextureClient's data until the compositor side confirmed that it is safe to
121 * deallocte or recycle the it.
122 */
123class TextureChild final : PTextureChild {
124 ~TextureChild() {
125 // We should have deallocated mTextureData in ActorDestroy
126 MOZ_ASSERT(!mTextureData)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mTextureData)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mTextureData))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!mTextureData",
"/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 126
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mTextureData" ")"
); do { MOZ_CrashSequence(__null, 126); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
127 MOZ_ASSERT_IF(!mOwnerCalledDestroy, !mTextureClient)do { if (!mOwnerCalledDestroy) { do { static_assert( mozilla::
detail::AssertionConditionType<decltype(!mTextureClient)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!mTextureClient))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mTextureClient", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 127); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mTextureClient"
")"); do { MOZ_CrashSequence(__null, 127); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
128 }
129
130 public:
131 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TextureChild)public: MozExternalRefCountType AddRef(void) { static_assert(
!std::is_destructible_v<TextureChild>, "Reference-counted class "
"TextureChild" " should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 131); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 131
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count
), ("TextureChild"), (uint32_t)(sizeof(*this))); return (nsrefcnt
)count; } MozExternalRefCountType Release(void) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(int32_t
(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 131); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 131
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); nsrefcnt count = --mRefCnt; NS_LogRelease((this), (
count), ("TextureChild")); if (count == 0) { delete (this); return
0; } return count; } using HasThreadSafeRefCnt = std::true_type
; protected: ::mozilla::ThreadSafeAutoRefCnt mRefCnt; public:
132
133 TextureChild()
134 : mCompositableForwarder(nullptr),
135 mTextureForwarder(nullptr),
136 mTextureClient(nullptr),
137 mTextureData(nullptr),
138 mDestroyed(false),
139 mIPCOpen(false),
140 mOwnsTextureData(false),
141 mOwnerCalledDestroy(false),
142 mUsesImageBridge(false) {}
143
144 mozilla::ipc::IPCResult Recv__delete__() override { return IPC_OK()mozilla::ipc::IPCResult::Ok(); }
145
146 LayersIPCChannel* GetAllocator() { return mTextureForwarder; }
147
148 void ActorDestroy(ActorDestroyReason why) override;
149
150 bool IPCOpen() const { return mIPCOpen; }
151
152 void Lock() const {
153 if (mUsesImageBridge) {
154 mLock.Enter();
155 }
156 }
157
158 void Unlock() const {
159 if (mUsesImageBridge) {
160 mLock.Leave();
161 }
162 }
163
164 private:
165 // AddIPDLReference and ReleaseIPDLReference are only to be called by
166 // CreateIPDLActor and DestroyIPDLActor, respectively. We intentionally make
167 // them private to prevent misuse. The purpose of these methods is to be aware
168 // of when the IPC system around this actor goes down: mIPCOpen is then set to
169 // false.
170 void AddIPDLReference() {
171 MOZ_ASSERT(mIPCOpen == false)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mIPCOpen == false)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mIPCOpen == false))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mIPCOpen == false"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 171
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIPCOpen == false"
")"); do { MOZ_CrashSequence(__null, 171); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
172 mIPCOpen = true;
173 AddRef();
174 }
175 void ReleaseIPDLReference() {
176 MOZ_ASSERT(mIPCOpen == false)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mIPCOpen == false)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mIPCOpen == false))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mIPCOpen == false"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 176
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIPCOpen == false"
")"); do { MOZ_CrashSequence(__null, 176); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
177 Release();
178 }
179
180 /// The normal way to destroy the actor.
181 ///
182 /// This will asynchronously send a Destroy message to the parent actor, whom
183 /// will send the delete message.
184 void Destroy(const TextureDeallocParams& aParams);
185
186 // This lock is used order to prevent several threads to access the
187 // TextureClient's data concurrently. In particular, it prevents shutdown
188 // code to destroy a texture while another thread is reading or writing into
189 // it.
190 // In most places, the lock is held in short and bounded scopes in which we
191 // don't block on any other resource. There are few exceptions to this, which
192 // are discussed below.
193 //
194 // The locking pattern of TextureClient may in some case upset deadlock
195 // detection tools such as TSan. Typically our tile rendering code will lock
196 // all of its tiles, render into them and unlock them all right after that,
197 // which looks something like:
198 //
199 // Lock tile A
200 // Lock tile B
201 // Lock tile C
202 // Apply drawing commands to tiles A, B and C
203 // Unlock tile A
204 // Unlock tile B
205 // Unlock tile C
206 //
207 // And later, we may end up rendering a tile buffer that has the same tiles,
208 // in a different order, for example:
209 //
210 // Lock tile B
211 // Lock tile A
212 // Lock tile D
213 // Apply drawing commands to tiles A, B and D
214 // Unlock tile B
215 // Unlock tile A
216 // Unlock tile D
217 //
218 // This is because textures being expensive to create, we recycle them as much
219 // as possible and they may reappear in the tile buffer in a different order.
220 //
221 // Unfortunately this is not very friendly to TSan's analysis, which will see
222 // that B was once locked while A was locked, and then A locked while B was
223 // locked. TSan identifies this as a potential dead-lock which would be the
224 // case if this kind of inconsistent and dependent locking order was happening
225 // concurrently.
226 // In the case of TextureClient, dependent locking only ever happens on the
227 // thread that draws into the texture (let's call it the producer thread).
228 // Other threads may call into a method that can lock the texture in a short
229 // and bounded scope inside of which it is not allowed to do anything that
230 // could cause the thread to block. A given texture can only have one producer
231 // thread.
232 //
233 // Another example of TSan-unfriendly locking pattern is when copying a
234 // texture into another, which also never happens outside of the producer
235 // thread. Copying A into B looks like this:
236 //
237 // Lock texture B
238 // Lock texture A
239 // Copy A into B
240 // Unlock A
241 // Unlock B
242 //
243 // In a given frame we may need to copy A into B and in another frame copy
244 // B into A. For example A and B can be the Front and Back buffers,
245 // alternating roles and the copy is needed to avoid the cost of re-drawing
246 // the valid region.
247 //
248 // The important rule is that all of the dependent locking must occur only
249 // in the texture's producer thread to avoid deadlocks.
250 mutable gfx::CriticalSection mLock;
251
252 RefPtr<CompositableForwarder> mCompositableForwarder;
253 RefPtr<TextureForwarder> mTextureForwarder;
254
255 TextureClient* mTextureClient;
256 TextureData* mTextureData;
257 Atomic<bool> mDestroyed;
258 bool mIPCOpen;
259 bool mOwnsTextureData;
260 bool mOwnerCalledDestroy;
261 bool mUsesImageBridge;
262
263 friend class TextureClient;
264 friend void DeallocateTextureClient(TextureDeallocParams& params);
265};
266
267static inline gfx::BackendType BackendTypeForBackendSelector(
268 LayersBackend aLayersBackend, BackendSelector aSelector) {
269 switch (aSelector) {
270 case BackendSelector::Canvas:
271 return gfxPlatform::GetPlatform()->GetPreferredCanvasBackend();
272 case BackendSelector::Content:
273 return gfxPlatform::GetPlatform()->GetContentBackendFor(aLayersBackend);
274 default:
275 MOZ_ASSERT_UNREACHABLE("Unknown backend selector")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Unknown backend selector" ")", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 275); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Unknown backend selector" ")"); do
{ MOZ_CrashSequence(__null, 275); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
276 return gfx::BackendType::NONE;
277 }
278};
279
280static TextureType ChooseTextureType(gfx::SurfaceFormat aFormat,
281 gfx::IntSize aSize,
282 KnowsCompositor* aKnowsCompositor,
283 BackendSelector aSelector,
284 TextureAllocationFlags aAllocFlags) {
285 LayersBackend layersBackend = aKnowsCompositor->GetCompositorBackendType();
286 gfx::BackendType moz2DBackend =
287 BackendTypeForBackendSelector(layersBackend, aSelector);
288 Unused << moz2DBackend;
289
290#ifdef XP_WIN
291 int32_t maxTextureSize = aKnowsCompositor->GetMaxTextureSize();
292 if ((layersBackend == LayersBackend::LAYERS_WR &&
293 !aKnowsCompositor->UsingSoftwareWebRender()) &&
294 (moz2DBackend == gfx::BackendType::DIRECT2D ||
295 moz2DBackend == gfx::BackendType::DIRECT2D1_1) &&
296 aSize.width <= maxTextureSize && aSize.height <= maxTextureSize &&
297 !(aAllocFlags & (ALLOC_UPDATE_FROM_SURFACE | ALLOC_DO_NOT_ACCELERATE))) {
298 return TextureType::D3D11;
299 }
300#endif
301
302#ifdef XP_MACOSX
303 if (StaticPrefs::gfx_use_iosurface_textures_AtStartup() &&
304 !aKnowsCompositor->UsingSoftwareWebRender()) {
305 return TextureType::MacIOSurface;
306 }
307#endif
308
309#ifdef MOZ_WIDGET_ANDROID
310 if (StaticPrefs::gfx_use_surfacetexture_textures_AtStartup() &&
311 !aKnowsCompositor->UsingSoftwareWebRender()) {
312 return TextureType::AndroidNativeWindow;
313 }
314#endif
315
316 return TextureType::Unknown;
317}
318
319TextureType PreferredCanvasTextureType(KnowsCompositor* aKnowsCompositor) {
320 return ChooseTextureType(gfx::SurfaceFormat::R8G8B8A8, {1, 1},
321 aKnowsCompositor, BackendSelector::Canvas,
322 TextureAllocationFlags::ALLOC_DEFAULT);
323}
324
325/* static */
326TextureData* TextureData::Create(TextureType aTextureType,
327 gfx::SurfaceFormat aFormat,
328 const gfx::IntSize& aSize,
329 TextureAllocationFlags aAllocFlags,
330 gfx::BackendType aBackendType) {
331 switch (aTextureType) {
332#ifdef XP_WIN
333 case TextureType::D3D11:
334 return D3D11TextureData::Create(aSize, aFormat, aAllocFlags);
335#endif
336
337#ifdef XP_MACOSX
338 case TextureType::MacIOSurface:
339 return MacIOSurfaceTextureData::Create(aSize, aFormat, aBackendType);
340#endif
341#ifdef MOZ_WIDGET_ANDROID
342 case TextureType::AndroidNativeWindow:
343 return AndroidNativeWindowTextureData::Create(aSize, aFormat);
344#endif
345 default:
346 return nullptr;
347 }
348}
349
350/* static */
351TextureData* TextureData::Create(TextureForwarder* aAllocator,
352 gfx::SurfaceFormat aFormat, gfx::IntSize aSize,
353 KnowsCompositor* aKnowsCompositor,
354 BackendSelector aSelector,
355 TextureFlags aTextureFlags,
356 TextureAllocationFlags aAllocFlags) {
357 TextureType textureType = ChooseTextureType(aFormat, aSize, aKnowsCompositor,
358 aSelector, aAllocFlags);
359
360 if (aAllocFlags & ALLOC_FORCE_REMOTE) {
361 RefPtr<CanvasChild> canvasChild = aAllocator->GetCanvasChild();
362 if (canvasChild) {
363 TextureType webglTextureType =
364 TexTypeForWebgl(aKnowsCompositor, /* aIsWebglOop */ true);
365 if (canvasChild->EnsureRecorder(aSize, aFormat, textureType,
366 webglTextureType)) {
367 return new RecordedTextureData(canvasChild.forget(), aSize, aFormat,
368 textureType, webglTextureType);
369 }
370 }
371 // If we must be remote, but there is no canvas child, then falling back
372 // is not possible.
373 return nullptr;
374 }
375
376 gfx::BackendType moz2DBackend = gfx::BackendType::NONE;
377
378#if defined(XP_MACOSX) || defined(MOZ_WIDGET_GTK1)
379 moz2DBackend = BackendTypeForBackendSelector(
380 aKnowsCompositor->GetCompositorBackendType(), aSelector);
381#endif
382
383 return TextureData::Create(textureType, aFormat, aSize, aAllocFlags,
384 moz2DBackend);
385}
386
387/* static */
388bool TextureData::IsRemote(KnowsCompositor* aKnowsCompositor,
389 BackendSelector aSelector,
390 gfx::SurfaceFormat aFormat, gfx::IntSize aSize) {
391 if (aSelector != BackendSelector::Canvas || !gfxPlatform::UseRemoteCanvas()) {
392 return false;
393 }
394
395 TextureType textureType =
396 ChooseTextureType(aFormat, aSize, aKnowsCompositor, aSelector,
397 TextureAllocationFlags::ALLOC_DEFAULT);
398
399 switch (textureType) {
400 case TextureType::D3D11:
401 return true;
402 default:
403 return false;
404 }
405}
406
407static void DestroyTextureData(TextureData* aTextureData,
408 LayersIPCChannel* aAllocator, bool aDeallocate) {
409 if (!aTextureData) {
410 return;
411 }
412
413 if (aDeallocate) {
414 aTextureData->Deallocate(aAllocator);
415 } else {
416 aTextureData->Forget(aAllocator);
417 }
418 delete aTextureData;
419}
420
421void TextureChild::ActorDestroy(ActorDestroyReason why) {
422 AUTO_PROFILER_LABEL("TextureChild::ActorDestroy", GRAPHICS)mozilla::AutoProfilerLabel raiiObject422( "TextureChild::ActorDestroy"
, nullptr, JS::ProfilingCategoryPair::GRAPHICS)
;
423 MOZ_ASSERT(mIPCOpen)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mIPCOpen)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mIPCOpen))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mIPCOpen", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 423); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIPCOpen" ")"
); do { MOZ_CrashSequence(__null, 423); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
424 mIPCOpen = false;
425
426 if (mTextureData) {
427 DestroyTextureData(mTextureData, GetAllocator(), mOwnsTextureData);
428 mTextureData = nullptr;
429 }
430}
431
432void TextureChild::Destroy(const TextureDeallocParams& aParams) {
433 MOZ_ASSERT(!mOwnerCalledDestroy)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mOwnerCalledDestroy)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mOwnerCalledDestroy))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("!mOwnerCalledDestroy"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 433
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mOwnerCalledDestroy"
")"); do { MOZ_CrashSequence(__null, 433); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
434 if (mOwnerCalledDestroy) {
435 return;
436 }
437
438 mOwnerCalledDestroy = true;
439
440 if (!IPCOpen()) {
441 DestroyTextureData(aParams.data, aParams.allocator,
442 aParams.clientDeallocation);
443 return;
444 }
445
446 // DestroyTextureData will be called by TextureChild::ActorDestroy
447 mTextureData = aParams.data;
448 mOwnsTextureData = aParams.clientDeallocation;
449
450 if (!mCompositableForwarder ||
451 !mCompositableForwarder->DestroyInTransaction(this)) {
452 this->SendDestroy();
453 }
454}
455
456/* static */
457Atomic<uint64_t> TextureClient::sSerialCounter(0);
458
459/// The logic for synchronizing a TextureClient's deallocation goes here.
460///
461/// This funciton takes care of dispatching work to the right thread using
462/// a synchronous proxy if needed, and handles client/host deallocation.
463void DeallocateTextureClient(TextureDeallocParams& params) {
464 if (!params.actor && !params.readLock && !params.data) {
465 // Nothing to do
466 return;
467 }
468
469 TextureChild* actor = params.actor;
470 nsCOMPtr<nsISerialEventTarget> ipdlThread;
471
472 if (params.allocator) {
473 ipdlThread = params.allocator->GetThread();
474 if (!ipdlThread) {
475 // An allocator with no thread means we are too late in the shutdown
476 // sequence.
477 gfxCriticalErrormozilla::gfx::CriticalLog() << "Texture deallocated too late during shutdown";
478 return;
479 }
480 }
481
482 // First make sure that the work is happening on the IPDL thread.
483 if (ipdlThread && !ipdlThread->IsOnCurrentThread()) {
484 if (params.syncDeallocation) {
485 bool done = false;
486 ReentrantMonitor barrier MOZ_UNANNOTATED("DeallocateTextureClient");
487 ReentrantMonitorAutoEnter autoMon(barrier);
488 ipdlThread->Dispatch(NS_NewRunnableFunction(
489 "DeallocateTextureClientSyncProxyRunnable", [&]() {
490 DeallocateTextureClient(params);
491 ReentrantMonitorAutoEnter autoMonInner(barrier);
492 done = true;
493 barrier.NotifyAll();
494 }));
495 while (!done) {
496 barrier.Wait();
497 }
498 } else {
499 ipdlThread->Dispatch(
500 NS_NewRunnableFunction("DeallocateTextureClientRunnable",
501 [params = std::move(params)]() mutable {
502 DeallocateTextureClient(params);
503 }));
504 }
505 // The work has been forwarded to the IPDL thread, we are done.
506 return;
507 }
508
509 // Below this line, we are either in the IPDL thread or ther is no IPDL
510 // thread anymore.
511
512 if (!ipdlThread) {
513 // If we don't have a thread we can't know for sure that we are in
514 // the IPDL thread and use the LayersIPCChannel.
515 // This should ideally not happen outside of gtest, but some shutdown
516 // raciness could put us in this situation.
517 params.allocator = nullptr;
518 }
519
520 if (params.readLock) {
521 // This should be the last reference to the object, which will destroy it.
522 params.readLock = nullptr;
523 }
524
525 if (!actor) {
526 // We don't have an IPDL actor, probably because we destroyed the
527 // TextureClient before sharing it with the compositor. It means the data
528 // cannot be owned by the TextureHost since we never created the
529 // TextureHost...
530 DestroyTextureData(params.data, params.allocator, /* aDeallocate */ true);
531 return;
532 }
533
534 actor->Destroy(params);
535}
536
537void TextureClient::Destroy() {
538 // Async paints should have been flushed by now.
539 MOZ_RELEASE_ASSERT(mPaintThreadRefs == 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mPaintThreadRefs == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mPaintThreadRefs == 0))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("mPaintThreadRefs == 0"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 539
); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "mPaintThreadRefs == 0"
")"); do { MOZ_CrashSequence(__null, 539); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
540
541 if (mActor && !mIsLocked) {
542 mActor->Lock();
543 }
544
545 mBorrowedDrawTarget = nullptr;
546 mBorrowedSnapshot = false;
547
548 RefPtr<TextureChild> actor = std::move(mActor);
549
550 RefPtr<TextureReadLock> readLock;
551 {
552 MutexAutoLock lock(mMutex);
553 readLock = std::move(mReadLock);
554 }
555
556 if (actor && !actor->mDestroyed.compareExchange(false, true)) {
557 actor->Unlock();
558 actor = nullptr;
559 }
560
561 TextureData* data = mData;
562 mData = nullptr;
563
564 if (data || actor || readLock) {
565 TextureDeallocParams params;
566 params.actor = std::move(actor);
567 params.readLock = std::move(readLock);
568 params.allocator = mAllocator;
569 params.clientDeallocation = !!(mFlags & TextureFlags::DEALLOCATE_CLIENT);
570 params.data = data;
571 // At the moment we always deallocate synchronously when deallocating on the
572 // client side, but having asynchronous deallocate in some of the cases will
573 // be a worthwhile optimization.
574 params.syncDeallocation = !!(mFlags & TextureFlags::DEALLOCATE_CLIENT);
575
576 // Release the lock before calling DeallocateTextureClient because the
577 // latter may wait for the main thread which could create a dead-lock.
578
579 if (params.actor) {
580 params.actor->Unlock();
581 }
582
583 DeallocateTextureClient(params);
584 }
585}
586
587void TextureClient::LockActor() const {
588 if (mActor) {
589 mActor->Lock();
590 }
591}
592
593void TextureClient::UnlockActor() const {
594 if (mActor) {
595 mActor->Unlock();
596 }
597}
598
599void TextureClient::EnsureHasReadLock() {
600 if (mFlags & TextureFlags::NON_BLOCKING_READ_LOCK) {
601 MOZ_ASSERT(!(mFlags & TextureFlags::BLOCKING_READ_LOCK))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(mFlags & TextureFlags::BLOCKING_READ_LOCK))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!(mFlags & TextureFlags::BLOCKING_READ_LOCK)))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("!(mFlags & TextureFlags::BLOCKING_READ_LOCK)"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 601
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(mFlags & TextureFlags::BLOCKING_READ_LOCK)"
")"); do { MOZ_CrashSequence(__null, 601); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
602 EnableReadLock();
603 } else if (mFlags & TextureFlags::BLOCKING_READ_LOCK) {
604 MOZ_ASSERT(!(mFlags & TextureFlags::NON_BLOCKING_READ_LOCK))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!(mFlags & TextureFlags::NON_BLOCKING_READ_LOCK)
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!(mFlags & TextureFlags::NON_BLOCKING_READ_LOCK)
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!(mFlags & TextureFlags::NON_BLOCKING_READ_LOCK)", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 604); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(mFlags & TextureFlags::NON_BLOCKING_READ_LOCK)"
")"); do { MOZ_CrashSequence(__null, 604); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
605 EnableBlockingReadLock();
606 }
607}
608
609bool TextureClient::IsReadLocked() {
610 if (!ShouldReadLock()) {
611 return false;
612 }
613
614 nsCOMPtr<nsISerialEventTarget> thread;
615
616 {
617 MutexAutoLock lock(mMutex);
618 if (mReadLock) {
619 MOZ_ASSERT(mReadLock->AsNonBlockingLock(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mReadLock->AsNonBlockingLock())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mReadLock->AsNonBlockingLock
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mReadLock->AsNonBlockingLock()" " (" "Can only check locked for non-blocking locks!"
")", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 620); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mReadLock->AsNonBlockingLock()"
") (" "Can only check locked for non-blocking locks!" ")"); do
{ MOZ_CrashSequence(__null, 620); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
620 "Can only check locked for non-blocking locks!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mReadLock->AsNonBlockingLock())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mReadLock->AsNonBlockingLock
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mReadLock->AsNonBlockingLock()" " (" "Can only check locked for non-blocking locks!"
")", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 620); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mReadLock->AsNonBlockingLock()"
") (" "Can only check locked for non-blocking locks!" ")"); do
{ MOZ_CrashSequence(__null, 620); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
621 return mReadLock->AsNonBlockingLock()->GetReadCount() > 1;
622 }
623
624 thread = mAllocator->GetThread();
625 if (!thread) {
626 // We must be in the process of shutting down.
627 return false;
628 }
629
630 if (thread->IsOnCurrentThread()) {
631 EnsureHasReadLock();
632 if (NS_WARN_IF(!mReadLock)NS_warn_if_impl(!mReadLock, "!mReadLock", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 632)
) {
633 MOZ_ASSERT(!mAllocator->IPCOpen())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mAllocator->IPCOpen())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mAllocator->IPCOpen())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mAllocator->IPCOpen()"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 633
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mAllocator->IPCOpen()"
")"); do { MOZ_CrashSequence(__null, 633); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
634 return false;
635 }
636 MOZ_ASSERT(mReadLock->AsNonBlockingLock(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mReadLock->AsNonBlockingLock())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mReadLock->AsNonBlockingLock
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mReadLock->AsNonBlockingLock()" " (" "Can only check locked for non-blocking locks!"
")", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 637); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mReadLock->AsNonBlockingLock()"
") (" "Can only check locked for non-blocking locks!" ")"); do
{ MOZ_CrashSequence(__null, 637); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
637 "Can only check locked for non-blocking locks!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mReadLock->AsNonBlockingLock())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mReadLock->AsNonBlockingLock
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mReadLock->AsNonBlockingLock()" " (" "Can only check locked for non-blocking locks!"
")", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 637); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mReadLock->AsNonBlockingLock()"
") (" "Can only check locked for non-blocking locks!" ")"); do
{ MOZ_CrashSequence(__null, 637); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
638 return mReadLock->AsNonBlockingLock()->GetReadCount() > 1;
639 }
640 }
641
642 MOZ_ASSERT(mAllocator->UsesImageBridge())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mAllocator->UsesImageBridge())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mAllocator->UsesImageBridge
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mAllocator->UsesImageBridge()", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 642); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAllocator->UsesImageBridge()"
")"); do { MOZ_CrashSequence(__null, 642); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
643
644 bool result = false;
645 SynchronousTask task("TextureClient::IsReadLocked");
646 thread->Dispatch(NS_NewRunnableFunction("TextureClient::IsReadLocked", [&]() {
647 AutoCompleteTask complete(&task);
648 result = IsReadLocked();
649 }));
650 task.Wait();
651
652 return result;
653}
654
655bool TextureClient::TryReadLock() {
656 if (!ShouldReadLock()) {
657 return true;
658 }
659
660 nsCOMPtr<nsISerialEventTarget> thread;
661
662 {
663 MutexAutoLock lock(mMutex);
664 if (mIsReadLocked) {
665 return true;
666 }
667
668 if (mReadLock) {
669 if (mReadLock->AsNonBlockingLock() &&
670 mReadLock->AsNonBlockingLock()->GetReadCount() > 1) {
671 return false;
672 }
673
674 if (!mReadLock->TryReadLock(TimeDuration::FromMilliseconds(500))) {
675 return false;
676 }
677
678 mIsReadLocked = true;
679 return true;
680 }
681
682 thread = mAllocator->GetThread();
683 if (!thread) {
684 // We must be in the process of shutting down.
685 return false;
686 }
687
688 if (thread->IsOnCurrentThread()) {
689 EnsureHasReadLock();
690
691 if (NS_WARN_IF(!mReadLock)NS_warn_if_impl(!mReadLock, "!mReadLock", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 691)
) {
692 MOZ_ASSERT(!mAllocator->IPCOpen())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mAllocator->IPCOpen())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mAllocator->IPCOpen())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mAllocator->IPCOpen()"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 692
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mAllocator->IPCOpen()"
")"); do { MOZ_CrashSequence(__null, 692); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
693 return false;
694 }
695
696 if (mReadLock->AsNonBlockingLock() &&
697 mReadLock->AsNonBlockingLock()->GetReadCount() > 1) {
698 return false;
699 }
700
701 if (!mReadLock->TryReadLock(TimeDuration::FromMilliseconds(500))) {
702 return false;
703 }
704
705 mIsReadLocked = true;
706 return true;
707 }
708 }
709
710 MOZ_ASSERT(mAllocator->UsesImageBridge())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mAllocator->UsesImageBridge())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mAllocator->UsesImageBridge
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mAllocator->UsesImageBridge()", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 710); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAllocator->UsesImageBridge()"
")"); do { MOZ_CrashSequence(__null, 710); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
711
712 bool result = false;
713 SynchronousTask task("TextureClient::TryReadLock");
714 thread->Dispatch(NS_NewRunnableFunction("TextureClient::TryReadLock", [&]() {
715 AutoCompleteTask complete(&task);
716 result = TryReadLock();
717 }));
718 task.Wait();
719
720 return result;
721}
722
723void TextureClient::ReadUnlock() {
724 if (!ShouldReadLock()) {
725 return;
726 }
727
728 MutexAutoLock lock(mMutex);
729
730 if (!mIsReadLocked) {
731 return;
732 }
733
734 MOZ_ASSERT(mReadLock)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mReadLock)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mReadLock))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mReadLock", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 734); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mReadLock" ")"
); do { MOZ_CrashSequence(__null, 734); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
735 mReadLock->ReadUnlock();
736 mIsReadLocked = false;
737}
738
739bool TextureClient::Lock(OpenMode aMode) {
740 if (NS_WARN_IF(!IsValid())NS_warn_if_impl(!IsValid(), "!IsValid()", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 740)
) {
741 return false;
742 }
743 if (NS_WARN_IF(mIsLocked)NS_warn_if_impl(mIsLocked, "mIsLocked", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 743)
) {
744 return mOpenMode == aMode;
745 }
746
747 if ((aMode & OpenMode::OPEN_WRITE || !mInfo.canConcurrentlyReadLock) &&
748 !TryReadLock()) {
749 // Only warn if attempting to write. Attempting to read is acceptable usage.
750 if (aMode & OpenMode::OPEN_WRITE) {
751 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "Attempt to Lock a texture that is being read by the compositor!"
, nullptr, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 752)
752 "Attempt to Lock a texture that is being read by the compositor!")NS_DebugBreak(NS_DEBUG_WARNING, "Attempt to Lock a texture that is being read by the compositor!"
, nullptr, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 752)
;
753 }
754 return false;
755 }
756
757 LockActor();
758
759 mIsLocked = mData->Lock(aMode);
760 mOpenMode = aMode;
761
762 auto format = GetFormat();
763 if (mIsLocked && CanExposeDrawTarget() &&
764 (aMode & OpenMode::OPEN_READ_WRITE) == OpenMode::OPEN_READ_WRITE &&
765 NS_IsMainThread() &&
766 // the formats that we apparently expect, in the cairo backend. Any other
767 // format will trigger an assertion in GfxFormatToCairoFormat.
768 (format == SurfaceFormat::A8R8G8B8_UINT32 ||
769 format == SurfaceFormat::X8R8G8B8_UINT32 ||
770 format == SurfaceFormat::A8 || format == SurfaceFormat::R5G6B5_UINT16)) {
771 if (!BorrowDrawTarget()) {
772 // Failed to get a DrawTarget, means we won't be able to write into the
773 // texture, might as well fail now.
774 Unlock();
775 return false;
776 }
777 }
778
779 if (!mIsLocked) {
780 UnlockActor();
781 ReadUnlock();
782 }
783
784 return mIsLocked;
785}
786
787void TextureClient::Unlock() {
788 MOZ_ASSERT(IsValid())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsValid())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsValid()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("IsValid()", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 788); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsValid()" ")"
); do { MOZ_CrashSequence(__null, 788); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
789 MOZ_ASSERT(mIsLocked)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mIsLocked)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mIsLocked))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mIsLocked", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 789); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIsLocked" ")"
); do { MOZ_CrashSequence(__null, 789); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
790 if (!IsValid() || !mIsLocked) {
791 return;
792 }
793
794 if (mBorrowedDrawTarget) {
795 if (!(mOpenMode & OpenMode::OPEN_ASYNC)) {
796 if (mOpenMode & OpenMode::OPEN_WRITE) {
797 mBorrowedDrawTarget->Flush();
798 }
799
800 mBorrowedDrawTarget->DetachAllSnapshots();
801 // If this assertion is hit, it means something is holding a strong
802 // reference to our DrawTarget externally, which is not allowed.
803 MOZ_ASSERT(mBorrowedDrawTarget->refCount() <= mExpectedDtRefs)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mBorrowedDrawTarget->refCount() <= mExpectedDtRefs
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mBorrowedDrawTarget->refCount() <= mExpectedDtRefs
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mBorrowedDrawTarget->refCount() <= mExpectedDtRefs", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 803); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBorrowedDrawTarget->refCount() <= mExpectedDtRefs"
")"); do { MOZ_CrashSequence(__null, 803); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
804 }
805
806 mBorrowedDrawTarget = nullptr;
807 }
808 mBorrowedSnapshot = false;
809
810 if (mOpenMode & OpenMode::OPEN_WRITE) {
811 mUpdated = true;
812 }
813
814 if (mData) {
815 mData->Unlock();
816 }
817 mIsLocked = false;
818 mOpenMode = OpenMode::OPEN_NONE;
819
820 UnlockActor();
821 ReadUnlock();
822}
823
824void TextureClient::EnableReadLock() {
825 MOZ_ASSERT(ShouldReadLock())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(ShouldReadLock())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(ShouldReadLock()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("ShouldReadLock()"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 825
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ShouldReadLock()"
")"); do { MOZ_CrashSequence(__null, 825); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
826 if (!mReadLock && mAllocator->GetTileLockAllocator()) {
827 mReadLock = NonBlockingTextureReadLock::Create(mAllocator);
828 }
829}
830
831void TextureClient::OnPrepareForwardToHost() {
832 if (!ShouldReadLock()) {
833 return;
834 }
835
836 MutexAutoLock lock(mMutex);
837 if (NS_WARN_IF(!mReadLock)NS_warn_if_impl(!mReadLock, "!mReadLock", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 837)
) {
838 MOZ_ASSERT(!mAllocator->IPCOpen(), "Should have created readlock already!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mAllocator->IPCOpen())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mAllocator->IPCOpen())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mAllocator->IPCOpen()"
" (" "Should have created readlock already!" ")", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 838); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mAllocator->IPCOpen()"
") (" "Should have created readlock already!" ")"); do { MOZ_CrashSequence
(__null, 838); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
839 MOZ_ASSERT(!mIsPendingForwardReadLocked)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIsPendingForwardReadLocked)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mIsPendingForwardReadLocked
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!mIsPendingForwardReadLocked", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 839); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsPendingForwardReadLocked"
")"); do { MOZ_CrashSequence(__null, 839); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
840 return;
841 }
842
843 if (mIsPendingForwardReadLocked) {
844 return;
845 }
846
847 mReadLock->ReadLock();
848 mIsPendingForwardReadLocked = true;
849}
850
851void TextureClient::OnAbandonForwardToHost() {
852 if (!ShouldReadLock()) {
853 return;
854 }
855
856 MutexAutoLock lock(mMutex);
857 if (!mReadLock || !mIsPendingForwardReadLocked) {
858 return;
859 }
860
861 mReadLock->ReadUnlock();
862 mIsPendingForwardReadLocked = false;
863}
864
865bool TextureClient::OnForwardedToHost() {
866 if (mData) {
867 mData->OnForwardedToHost();
868 }
869
870 if (!ShouldReadLock()) {
871 return false;
872 }
873
874 MutexAutoLock lock(mMutex);
875 EnsureHasReadLock();
876
877 if (NS_WARN_IF(!mReadLock)NS_warn_if_impl(!mReadLock, "!mReadLock", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 877)
) {
878 MOZ_ASSERT(!mAllocator->IPCOpen())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mAllocator->IPCOpen())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mAllocator->IPCOpen())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("!mAllocator->IPCOpen()"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 878
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mAllocator->IPCOpen()"
")"); do { MOZ_CrashSequence(__null, 878); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
879 return false;
880 }
881
882 if (!mUpdated) {
883 if (mIsPendingForwardReadLocked) {
884 mIsPendingForwardReadLocked = false;
885 mReadLock->ReadUnlock();
886 }
887 return false;
888 }
889
890 mUpdated = false;
891
892 if (mIsPendingForwardReadLocked) {
893 // We have successfully forwarded, just clear the flag and let the
894 // TextureHost be responsible for unlocking.
895 mIsPendingForwardReadLocked = false;
896 } else {
897 // Otherwise we did not need to readlock in advance, so do so now. We do
898 // this on behalf of the TextureHost.
899 mReadLock->ReadLock();
900 }
901
902 return true;
903}
904
905TextureClient::~TextureClient() {
906 // TextureClients should be kept alive while there are references on the
907 // paint thread.
908 MOZ_ASSERT(mPaintThreadRefs == 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mPaintThreadRefs == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mPaintThreadRefs == 0))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("mPaintThreadRefs == 0"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 908
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPaintThreadRefs == 0"
")"); do { MOZ_CrashSequence(__null, 908); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
909 mReadLock = nullptr;
910 Destroy();
911}
912
913void TextureClient::UpdateFromSurface(gfx::SourceSurface* aSurface) {
914 MOZ_ASSERT(IsValid())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsValid())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsValid()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("IsValid()", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 914); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsValid()" ")"
); do { MOZ_CrashSequence(__null, 914); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
915 MOZ_ASSERT(mIsLocked)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mIsLocked)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mIsLocked))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mIsLocked", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 915); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIsLocked" ")"
); do { MOZ_CrashSequence(__null, 915); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
916 MOZ_ASSERT(aSurface)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aSurface)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aSurface))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aSurface", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 916); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSurface" ")"
); do { MOZ_CrashSequence(__null, 916); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
917 // If you run into this assertion, make sure the texture was locked write-only
918 // rather than read-write.
919 MOZ_ASSERT(!mBorrowedDrawTarget)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mBorrowedDrawTarget)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mBorrowedDrawTarget))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("!mBorrowedDrawTarget"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 919
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mBorrowedDrawTarget"
")"); do { MOZ_CrashSequence(__null, 919); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
920
921 // XXX - It would be better to first try the DrawTarget approach and fallback
922 // to the backend-specific implementation because the latter will usually do
923 // an expensive read-back + cpu-side copy if the texture is on the gpu.
924 // There is a bug with the DrawTarget approach, though specific to reading
925 // back from WebGL (where R and B channel end up inverted) to figure out
926 // first.
927 if (mData->UpdateFromSurface(aSurface)) {
928 return;
929 }
930 if (CanExposeDrawTarget() && NS_IsMainThread()) {
931 RefPtr<DrawTarget> dt = BorrowDrawTarget();
932
933 MOZ_ASSERT(dt)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(dt)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(dt))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("dt", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 933); AnnotateMozCrashReason("MOZ_ASSERT" "(" "dt" ")"); do
{ MOZ_CrashSequence(__null, 933); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
934 if (dt) {
935 dt->CopySurface(aSurface,
936 gfx::IntRect(gfx::IntPoint(0, 0), aSurface->GetSize()),
937 gfx::IntPoint(0, 0));
938 return;
939 }
940 }
941 NS_WARNING("TextureClient::UpdateFromSurface failed")NS_DebugBreak(NS_DEBUG_WARNING, "TextureClient::UpdateFromSurface failed"
, nullptr, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 941)
;
942}
943
944already_AddRefed<TextureClient> TextureClient::CreateSimilar(
945 LayersBackend aLayersBackend, TextureFlags aFlags,
946 TextureAllocationFlags aAllocFlags) const {
947 MOZ_ASSERT(IsValid())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsValid())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsValid()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("IsValid()", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 947); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsValid()" ")"
); do { MOZ_CrashSequence(__null, 947); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
948
949 MOZ_ASSERT(!mIsLocked)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIsLocked)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mIsLocked))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("!mIsLocked", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 949); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsLocked" ")"
); do { MOZ_CrashSequence(__null, 949); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
950 if (mIsLocked) {
951 return nullptr;
952 }
953
954 LockActor();
955 TextureData* data =
956 mData->CreateSimilar(mAllocator, aLayersBackend, aFlags, aAllocFlags);
957 UnlockActor();
958
959 if (!data) {
960 return nullptr;
961 }
962
963 return MakeAndAddRef<TextureClient>(data, aFlags, mAllocator);
964}
965
966gfx::DrawTarget* TextureClient::BorrowDrawTarget() {
967 MOZ_ASSERT(IsValid())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsValid())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsValid()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("IsValid()", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 967); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsValid()" ")"
); do { MOZ_CrashSequence(__null, 967); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
968 MOZ_ASSERT(mIsLocked)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mIsLocked)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mIsLocked))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mIsLocked", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 968); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIsLocked" ")"
); do { MOZ_CrashSequence(__null, 968); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
969 // TODO- We can't really assert that at the moment because there is code that
970 // Borrows the DrawTarget, just to get a snapshot, which is legit in term of
971 // OpenMode but we should have a way to get a SourceSurface directly instead.
972 // MOZ_ASSERT(mOpenMode & OpenMode::OPEN_WRITE);
973
974 if (!IsValid() || !mIsLocked) {
975 return nullptr;
976 }
977
978 if (!mBorrowedDrawTarget) {
979 mBorrowedDrawTarget = mData->BorrowDrawTarget();
980#ifdef DEBUG1
981 mExpectedDtRefs = mBorrowedDrawTarget ? mBorrowedDrawTarget->refCount() : 0;
982#endif
983 }
984
985 return mBorrowedDrawTarget;
986}
987
988void TextureClient::EndDraw() {
989 MOZ_ASSERT(mOpenMode & OpenMode::OPEN_READ_WRITE)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mOpenMode & OpenMode::OPEN_READ_WRITE)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mOpenMode & OpenMode::OPEN_READ_WRITE))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("mOpenMode & OpenMode::OPEN_READ_WRITE"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 989
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mOpenMode & OpenMode::OPEN_READ_WRITE"
")"); do { MOZ_CrashSequence(__null, 989); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
990
991 // Because EndDraw is used when we are not unlocking this TextureClient at the
992 // end of a transaction, we need to Flush and DetachAllSnapshots to ensure any
993 // dependents are updated.
994 mBorrowedDrawTarget->Flush();
995 mBorrowedDrawTarget->DetachAllSnapshots();
996 MOZ_ASSERT(mBorrowedDrawTarget->refCount() <= mExpectedDtRefs)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mBorrowedDrawTarget->refCount() <= mExpectedDtRefs
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(mBorrowedDrawTarget->refCount() <= mExpectedDtRefs
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mBorrowedDrawTarget->refCount() <= mExpectedDtRefs", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 996); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mBorrowedDrawTarget->refCount() <= mExpectedDtRefs"
")"); do { MOZ_CrashSequence(__null, 996); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
997
998 mBorrowedDrawTarget = nullptr;
999 mBorrowedSnapshot = false;
1000 mData->EndDraw();
1001}
1002
1003already_AddRefed<gfx::SourceSurface> TextureClient::BorrowSnapshot() {
1004 MOZ_ASSERT(mIsLocked)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mIsLocked)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mIsLocked))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mIsLocked", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 1004); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIsLocked" ")"
); do { MOZ_CrashSequence(__null, 1004); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1005
1006 RefPtr<gfx::SourceSurface> surface = mData->BorrowSnapshot();
1007 if (surface) {
1008 mBorrowedSnapshot = true;
1009 } else {
1010 RefPtr<gfx::DrawTarget> drawTarget = BorrowDrawTarget();
1011 if (!drawTarget) {
1012 return nullptr;
1013 }
1014 surface = drawTarget->Snapshot();
1015 }
1016
1017 return surface.forget();
1018}
1019
1020void TextureClient::ReturnSnapshot(
1021 already_AddRefed<gfx::SourceSurface> aSnapshot) {
1022 RefPtr<gfx::SourceSurface> snapshot = aSnapshot;
1023 if (mBorrowedSnapshot) {
1024 mData->ReturnSnapshot(snapshot.forget());
1025 mBorrowedSnapshot = false;
1026 }
1027}
1028
1029bool TextureClient::BorrowMappedData(MappedTextureData& aMap) {
1030 MOZ_ASSERT(IsValid())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsValid())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsValid()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("IsValid()", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 1030); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsValid()" ")"
); do { MOZ_CrashSequence(__null, 1030); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1031
1032 // TODO - SharedRGBImage just accesses the buffer without properly locking
1033 // the texture. It's bad.
1034 // MOZ_ASSERT(mIsLocked);
1035 // if (!mIsLocked) {
1036 // return nullptr;
1037 //}
1038
1039 return mData ? mData->BorrowMappedData(aMap) : false;
1040}
1041
1042bool TextureClient::BorrowMappedYCbCrData(MappedYCbCrTextureData& aMap) {
1043 MOZ_ASSERT(IsValid())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsValid())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsValid()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("IsValid()", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 1043); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsValid()" ")"
); do { MOZ_CrashSequence(__null, 1043); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1044
1045 return mData ? mData->BorrowMappedYCbCrData(aMap) : false;
1046}
1047
1048bool TextureClient::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) {
1049 MOZ_ASSERT(IsValid())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsValid())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsValid()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("IsValid()", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 1049); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsValid()" ")"
); do { MOZ_CrashSequence(__null, 1049); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1050
1051 return mData ? mData->Serialize(aOutDescriptor) : false;
1052}
1053
1054// static
1055PTextureChild* TextureClient::CreateIPDLActor() {
1056 TextureChild* c = new TextureChild();
1057 c->AddIPDLReference();
1058 return c;
1059}
1060
1061// static
1062bool TextureClient::DestroyIPDLActor(PTextureChild* actor) {
1063 static_cast<TextureChild*>(actor)->ReleaseIPDLReference();
1064 return true;
1065}
1066
1067// static
1068already_AddRefed<TextureClient> TextureClient::AsTextureClient(
1069 PTextureChild* actor) {
1070 if (!actor) {
1071 return nullptr;
1072 }
1073
1074 TextureChild* tc = static_cast<TextureChild*>(actor);
1075
1076 tc->Lock();
1077
1078 // Since TextureClient may be destroyed asynchronously with respect to its
1079 // IPDL actor, we must acquire a reference within a lock. The mDestroyed bit
1080 // tells us whether or not the main thread has disconnected the TextureClient
1081 // from its actor.
1082 if (tc->mDestroyed) {
1083 tc->Unlock();
1084 return nullptr;
1085 }
1086
1087 RefPtr<TextureClient> texture = tc->mTextureClient;
1088 tc->Unlock();
1089
1090 return texture.forget();
1091}
1092
1093bool TextureClient::IsSharedWithCompositor() const {
1094 return mActor && mActor->IPCOpen();
1095}
1096
1097void TextureClient::AddFlags(TextureFlags aFlags) {
1098 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsSharedWithCompositor() || ((GetFlags() & TextureFlags
::RECYCLE) && !IsAddedToCompositableClient()))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!IsSharedWithCompositor() || ((GetFlags() & TextureFlags
::RECYCLE) && !IsAddedToCompositableClient())))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("!IsSharedWithCompositor() || ((GetFlags() & TextureFlags::RECYCLE) && !IsAddedToCompositableClient())"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 1100
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsSharedWithCompositor() || ((GetFlags() & TextureFlags::RECYCLE) && !IsAddedToCompositableClient())"
")"); do { MOZ_CrashSequence(__null, 1100); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1099 !IsSharedWithCompositor() ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsSharedWithCompositor() || ((GetFlags() & TextureFlags
::RECYCLE) && !IsAddedToCompositableClient()))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!IsSharedWithCompositor() || ((GetFlags() & TextureFlags
::RECYCLE) && !IsAddedToCompositableClient())))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("!IsSharedWithCompositor() || ((GetFlags() & TextureFlags::RECYCLE) && !IsAddedToCompositableClient())"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 1100
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsSharedWithCompositor() || ((GetFlags() & TextureFlags::RECYCLE) && !IsAddedToCompositableClient())"
")"); do { MOZ_CrashSequence(__null, 1100); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1100 ((GetFlags() & TextureFlags::RECYCLE) && !IsAddedToCompositableClient()))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsSharedWithCompositor() || ((GetFlags() & TextureFlags
::RECYCLE) && !IsAddedToCompositableClient()))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!IsSharedWithCompositor() || ((GetFlags() & TextureFlags
::RECYCLE) && !IsAddedToCompositableClient())))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("!IsSharedWithCompositor() || ((GetFlags() & TextureFlags::RECYCLE) && !IsAddedToCompositableClient())"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 1100
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsSharedWithCompositor() || ((GetFlags() & TextureFlags::RECYCLE) && !IsAddedToCompositableClient())"
")"); do { MOZ_CrashSequence(__null, 1100); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1101 mFlags |= aFlags;
1102}
1103
1104void TextureClient::RemoveFlags(TextureFlags aFlags) {
1105 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsSharedWithCompositor() || ((GetFlags() & TextureFlags
::RECYCLE) && !IsAddedToCompositableClient()))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!IsSharedWithCompositor() || ((GetFlags() & TextureFlags
::RECYCLE) && !IsAddedToCompositableClient())))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("!IsSharedWithCompositor() || ((GetFlags() & TextureFlags::RECYCLE) && !IsAddedToCompositableClient())"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 1107
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsSharedWithCompositor() || ((GetFlags() & TextureFlags::RECYCLE) && !IsAddedToCompositableClient())"
")"); do { MOZ_CrashSequence(__null, 1107); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1106 !IsSharedWithCompositor() ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsSharedWithCompositor() || ((GetFlags() & TextureFlags
::RECYCLE) && !IsAddedToCompositableClient()))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!IsSharedWithCompositor() || ((GetFlags() & TextureFlags
::RECYCLE) && !IsAddedToCompositableClient())))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("!IsSharedWithCompositor() || ((GetFlags() & TextureFlags::RECYCLE) && !IsAddedToCompositableClient())"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 1107
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsSharedWithCompositor() || ((GetFlags() & TextureFlags::RECYCLE) && !IsAddedToCompositableClient())"
")"); do { MOZ_CrashSequence(__null, 1107); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1107 ((GetFlags() & TextureFlags::RECYCLE) && !IsAddedToCompositableClient()))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsSharedWithCompositor() || ((GetFlags() & TextureFlags
::RECYCLE) && !IsAddedToCompositableClient()))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!IsSharedWithCompositor() || ((GetFlags() & TextureFlags
::RECYCLE) && !IsAddedToCompositableClient())))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("!IsSharedWithCompositor() || ((GetFlags() & TextureFlags::RECYCLE) && !IsAddedToCompositableClient())"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 1107
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsSharedWithCompositor() || ((GetFlags() & TextureFlags::RECYCLE) && !IsAddedToCompositableClient())"
")"); do { MOZ_CrashSequence(__null, 1107); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1108 mFlags &= ~aFlags;
1109}
1110
1111void TextureClient::RecycleTexture(TextureFlags aFlags) {
1112 MOZ_ASSERT(GetFlags() & TextureFlags::RECYCLE)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(GetFlags() & TextureFlags::RECYCLE)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(GetFlags() & TextureFlags::RECYCLE))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("GetFlags() & TextureFlags::RECYCLE"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 1112
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetFlags() & TextureFlags::RECYCLE"
")"); do { MOZ_CrashSequence(__null, 1112); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1113 MOZ_ASSERT(!mIsLocked)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIsLocked)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mIsLocked))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("!mIsLocked", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 1113); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsLocked"
")"); do { MOZ_CrashSequence(__null, 1113); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1114
1115 mAddedToCompositableClient = false;
1116 if (mFlags != aFlags) {
1117 mFlags = aFlags;
1118 }
1119}
1120
1121void TextureClient::SetAddedToCompositableClient() {
1122 if (!mAddedToCompositableClient) {
1123 mAddedToCompositableClient = true;
1124 if (!(GetFlags() & TextureFlags::RECYCLE)) {
1125 return;
1126 }
1127 MOZ_ASSERT(!mIsLocked)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIsLocked)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mIsLocked))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("!mIsLocked", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 1127); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsLocked"
")"); do { MOZ_CrashSequence(__null, 1127); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1128 LockActor();
1129 if (IsValid() && mActor && !mActor->mDestroyed && mActor->IPCOpen()) {
1130 mActor->SendRecycleTexture(mFlags);
1131 }
1132 UnlockActor();
1133 }
1134}
1135
1136static void CancelTextureClientNotifyNotUsed(uint64_t aTextureId,
1137 LayersIPCChannel* aAllocator) {
1138 if (!aAllocator) {
1139 return;
1140 }
1141 nsCOMPtr<nsISerialEventTarget> thread = aAllocator->GetThread();
1142 if (!thread) {
1143 return;
1144 }
1145 if (thread->IsOnCurrentThread()) {
1146 aAllocator->CancelWaitForNotifyNotUsed(aTextureId);
1147 } else {
1148 thread->Dispatch(NewRunnableFunction(
1149 "CancelTextureClientNotifyNotUsedRunnable",
1150 CancelTextureClientNotifyNotUsed, aTextureId, aAllocator));
1151 }
1152}
1153
1154void TextureClient::CancelWaitForNotifyNotUsed() {
1155 if (GetFlags() & TextureFlags::RECYCLE) {
1156 CancelTextureClientNotifyNotUsed(mSerial, GetAllocator());
1157 return;
1158 }
1159}
1160
1161/* static */
1162void TextureClient::TextureClientRecycleCallback(TextureClient* aClient,
1163 void* aClosure) {
1164 MOZ_ASSERT(aClient->GetRecycleAllocator())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aClient->GetRecycleAllocator())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aClient->GetRecycleAllocator
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("aClient->GetRecycleAllocator()", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 1164); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aClient->GetRecycleAllocator()"
")"); do { MOZ_CrashSequence(__null, 1164); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1165 aClient->GetRecycleAllocator()->RecycleTextureClient(aClient);
1166}
1167
1168void TextureClient::SetRecycleAllocator(
1169 ITextureClientRecycleAllocator* aAllocator) {
1170 mRecycleAllocator = aAllocator;
1171 if (aAllocator) {
1172 SetRecycleCallback(TextureClientRecycleCallback, nullptr);
1173 } else {
1174 ClearRecycleCallback();
1175 }
1176}
1177
1178bool TextureClient::InitIPDLActor(CompositableForwarder* aForwarder) {
1179 MOZ_ASSERT(aForwarder && aForwarder->GetTextureForwarder()->GetThread() ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aForwarder && aForwarder->GetTextureForwarder
()->GetThread() == mAllocator->GetThread())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aForwarder && aForwarder->GetTextureForwarder()
->GetThread() == mAllocator->GetThread()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aForwarder && aForwarder->GetTextureForwarder()->GetThread() == mAllocator->GetThread()"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 1180
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aForwarder && aForwarder->GetTextureForwarder()->GetThread() == mAllocator->GetThread()"
")"); do { MOZ_CrashSequence(__null, 1180); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1180 mAllocator->GetThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aForwarder && aForwarder->GetTextureForwarder
()->GetThread() == mAllocator->GetThread())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aForwarder && aForwarder->GetTextureForwarder()
->GetThread() == mAllocator->GetThread()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("aForwarder && aForwarder->GetTextureForwarder()->GetThread() == mAllocator->GetThread()"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 1180
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aForwarder && aForwarder->GetTextureForwarder()->GetThread() == mAllocator->GetThread()"
")"); do { MOZ_CrashSequence(__null, 1180); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1181
1182 if (mActor && !mActor->IPCOpen()) {
1183 return false;
1184 }
1185
1186 if (mActor && !mActor->mDestroyed) {
1187 CompositableForwarder* currentFwd = mActor->mCompositableForwarder;
1188 TextureForwarder* currentTexFwd = mActor->mTextureForwarder;
1189 if (currentFwd != aForwarder) {
1190 // It's a bit iffy but right now ShadowLayerForwarder inherits
1191 // TextureForwarder even though it should not.
1192 // ShadowLayerForwarder::GetTextureForwarder actually returns a pointer to
1193 // the CompositorBridgeChild. It's Ok for a texture to move from a
1194 // ShadowLayerForwarder to another, but not form a CompositorBridgeChild
1195 // to another (they use different channels).
1196 if (currentTexFwd && currentTexFwd != aForwarder->GetTextureForwarder()) {
1197 gfxCriticalErrormozilla::gfx::CriticalLog()
1198 << "Attempt to move a texture to a different channel CF.";
1199 MOZ_ASSERT_UNREACHABLE("unexpected to be called")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"unexpected to be called" ")", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 1199); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "unexpected to be called" ")"); do
{ MOZ_CrashSequence(__null, 1199); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
1200 return false;
1201 }
1202 if (currentFwd && currentFwd->GetCompositorBackendType() !=
1203 aForwarder->GetCompositorBackendType()) {
1204 gfxCriticalErrormozilla::gfx::CriticalLog()
1205 << "Attempt to move a texture to different compositor backend.";
1206 MOZ_ASSERT_UNREACHABLE("unexpected to be called")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"unexpected to be called" ")", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 1206); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "unexpected to be called" ")"); do
{ MOZ_CrashSequence(__null, 1206); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
1207 return false;
1208 }
1209 mActor->mCompositableForwarder = aForwarder;
1210 mActor->mUsesImageBridge =
1211 aForwarder->GetTextureForwarder()->UsesImageBridge();
1212 }
1213 return true;
1214 }
1215 MOZ_ASSERT(!mActor || mActor->mDestroyed,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mActor || mActor->mDestroyed)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mActor || mActor->mDestroyed
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!mActor || mActor->mDestroyed" " (" "Cannot use a texture on several IPC channels."
")", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 1216); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mActor || mActor->mDestroyed"
") (" "Cannot use a texture on several IPC channels." ")"); do
{ MOZ_CrashSequence(__null, 1216); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
1216 "Cannot use a texture on several IPC channels.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mActor || mActor->mDestroyed)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mActor || mActor->mDestroyed
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!mActor || mActor->mDestroyed" " (" "Cannot use a texture on several IPC channels."
")", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 1216); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mActor || mActor->mDestroyed"
") (" "Cannot use a texture on several IPC channels." ")"); do
{ MOZ_CrashSequence(__null, 1216); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
1217
1218 SurfaceDescriptor desc;
1219 if (!ToSurfaceDescriptor(desc)) {
1220 return false;
1221 }
1222
1223 // Try external image id allocation.
1224 mExternalImageId =
1225 aForwarder->GetTextureForwarder()->GetNextExternalImageId();
1226
1227 ReadLockDescriptor readLockDescriptor = null_t();
1228
1229 {
1230 MutexAutoLock lock(mMutex);
1231 EnsureHasReadLock();
1232 if (mReadLock) {
1233 mReadLock->Serialize(readLockDescriptor, GetAllocator()->GetParentPid());
1234 }
1235 }
1236
1237 PTextureChild* actor = aForwarder->GetTextureForwarder()->CreateTexture(
1238 desc, std::move(readLockDescriptor),
1239 aForwarder->GetCompositorBackendType(), GetFlags(),
1240 dom::ContentParentId(), mSerial, mExternalImageId);
1241
1242 if (!actor) {
1243 gfxCriticalNotemozilla::gfx::CriticalLog(mozilla::gfx::CriticalLog::DefaultOptions
(false))
<< static_cast<int32_t>(desc.type()) << ", "
1244 << static_cast<int32_t>(
1245 aForwarder->GetCompositorBackendType())
1246 << ", " << static_cast<uint32_t>(GetFlags()) << ", "
1247 << mSerial;
1248 return false;
1249 }
1250
1251 mActor = static_cast<TextureChild*>(actor);
1252 mActor->mCompositableForwarder = aForwarder;
1253 mActor->mTextureForwarder = aForwarder->GetTextureForwarder();
1254 mActor->mTextureClient = this;
1255
1256 // If the TextureClient is already locked, we have to lock TextureChild's
1257 // mutex since it will be unlocked in TextureClient::Unlock.
1258 if (mIsLocked) {
1259 LockActor();
1260 }
1261
1262 return mActor->IPCOpen();
1263}
1264
1265bool TextureClient::InitIPDLActor(KnowsCompositor* aKnowsCompositor,
1266 const dom::ContentParentId& aContentId) {
1267 MOZ_ASSERT(aKnowsCompositor &&do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aKnowsCompositor && aKnowsCompositor->GetTextureForwarder
()->GetThread() == mAllocator->GetThread())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aKnowsCompositor && aKnowsCompositor->GetTextureForwarder
()->GetThread() == mAllocator->GetThread()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aKnowsCompositor && aKnowsCompositor->GetTextureForwarder()->GetThread() == mAllocator->GetThread()"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 1269
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aKnowsCompositor && aKnowsCompositor->GetTextureForwarder()->GetThread() == mAllocator->GetThread()"
")"); do { MOZ_CrashSequence(__null, 1269); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1268 aKnowsCompositor->GetTextureForwarder()->GetThread() ==do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aKnowsCompositor && aKnowsCompositor->GetTextureForwarder
()->GetThread() == mAllocator->GetThread())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aKnowsCompositor && aKnowsCompositor->GetTextureForwarder
()->GetThread() == mAllocator->GetThread()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aKnowsCompositor && aKnowsCompositor->GetTextureForwarder()->GetThread() == mAllocator->GetThread()"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 1269
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aKnowsCompositor && aKnowsCompositor->GetTextureForwarder()->GetThread() == mAllocator->GetThread()"
")"); do { MOZ_CrashSequence(__null, 1269); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1269 mAllocator->GetThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aKnowsCompositor && aKnowsCompositor->GetTextureForwarder
()->GetThread() == mAllocator->GetThread())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aKnowsCompositor && aKnowsCompositor->GetTextureForwarder
()->GetThread() == mAllocator->GetThread()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("aKnowsCompositor && aKnowsCompositor->GetTextureForwarder()->GetThread() == mAllocator->GetThread()"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 1269
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aKnowsCompositor && aKnowsCompositor->GetTextureForwarder()->GetThread() == mAllocator->GetThread()"
")"); do { MOZ_CrashSequence(__null, 1269); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1270 TextureForwarder* fwd = aKnowsCompositor->GetTextureForwarder();
1271 if (mActor && !mActor->mDestroyed) {
1272 CompositableForwarder* currentFwd = mActor->mCompositableForwarder;
1273 TextureForwarder* currentTexFwd = mActor->mTextureForwarder;
1274
1275 if (currentFwd) {
1276 gfxCriticalErrormozilla::gfx::CriticalLog()
1277 << "Attempt to remove a texture from a CompositableForwarder.";
1278 return false;
1279 }
1280
1281 if (currentTexFwd && currentTexFwd != fwd) {
1282 gfxCriticalErrormozilla::gfx::CriticalLog()
1283 << "Attempt to move a texture to a different channel TF.";
1284 return false;
1285 }
1286 mActor->mTextureForwarder = fwd;
1287 return true;
1288 }
1289 MOZ_ASSERT(!mActor || mActor->mDestroyed,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mActor || mActor->mDestroyed)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mActor || mActor->mDestroyed
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!mActor || mActor->mDestroyed" " (" "Cannot use a texture on several IPC channels."
")", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 1290); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mActor || mActor->mDestroyed"
") (" "Cannot use a texture on several IPC channels." ")"); do
{ MOZ_CrashSequence(__null, 1290); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
1290 "Cannot use a texture on several IPC channels.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mActor || mActor->mDestroyed)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mActor || mActor->mDestroyed
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"!mActor || mActor->mDestroyed" " (" "Cannot use a texture on several IPC channels."
")", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 1290); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mActor || mActor->mDestroyed"
") (" "Cannot use a texture on several IPC channels." ")"); do
{ MOZ_CrashSequence(__null, 1290); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
1291
1292 SurfaceDescriptor desc;
1293 if (!ToSurfaceDescriptor(desc)) {
1294 return false;
1295 }
1296
1297 // Try external image id allocation.
1298 mExternalImageId =
1299 aKnowsCompositor->GetTextureForwarder()->GetNextExternalImageId();
1300
1301 ReadLockDescriptor readLockDescriptor = null_t();
1302 {
1303 MutexAutoLock lock(mMutex);
1304 EnsureHasReadLock();
1305 if (mReadLock) {
1306 mReadLock->Serialize(readLockDescriptor, GetAllocator()->GetParentPid());
1307 }
1308 }
1309
1310 PTextureChild* actor =
1311 fwd->CreateTexture(desc, std::move(readLockDescriptor),
1312 aKnowsCompositor->GetCompositorBackendType(),
1313 GetFlags(), aContentId, mSerial, mExternalImageId);
1314 if (!actor) {
1315 gfxCriticalNotemozilla::gfx::CriticalLog(mozilla::gfx::CriticalLog::DefaultOptions
(false))
<< static_cast<int32_t>(desc.type()) << ", "
1316 << static_cast<int32_t>(
1317 aKnowsCompositor->GetCompositorBackendType())
1318 << ", " << static_cast<uint32_t>(GetFlags()) << ", "
1319 << mSerial;
1320 return false;
1321 }
1322
1323 mActor = static_cast<TextureChild*>(actor);
1324 mActor->mTextureForwarder = fwd;
1325 mActor->mTextureClient = this;
1326
1327 // If the TextureClient is already locked, we have to lock TextureChild's
1328 // mutex since it will be unlocked in TextureClient::Unlock.
1329 if (mIsLocked) {
1330 LockActor();
1331 }
1332
1333 return mActor->IPCOpen();
1334}
1335
1336PTextureChild* TextureClient::GetIPDLActor() { return mActor; }
1337
1338// static
1339already_AddRefed<TextureClient> TextureClient::CreateForDrawing(
1340 KnowsCompositor* aAllocator, gfx::SurfaceFormat aFormat, gfx::IntSize aSize,
1341 BackendSelector aSelector, TextureFlags aTextureFlags,
1342 TextureAllocationFlags aAllocFlags) {
1343 return TextureClient::CreateForDrawing(aAllocator->GetTextureForwarder(),
1344 aFormat, aSize, aAllocator, aSelector,
1345 aTextureFlags, aAllocFlags);
1346}
1347
1348// static
1349already_AddRefed<TextureClient> TextureClient::CreateForDrawing(
1350 TextureForwarder* aAllocator, gfx::SurfaceFormat aFormat,
1351 gfx::IntSize aSize, KnowsCompositor* aKnowsCompositor,
1352 BackendSelector aSelector, TextureFlags aTextureFlags,
1353 TextureAllocationFlags aAllocFlags) {
1354 LayersBackend layersBackend = aKnowsCompositor->GetCompositorBackendType();
1355 gfx::BackendType moz2DBackend =
1356 BackendTypeForBackendSelector(layersBackend, aSelector);
1357
1358 // also test the validity of aAllocator
1359 if (!aAllocator || !aAllocator->IPCOpen()) {
1360 return nullptr;
1361 }
1362
1363 if (!gfx::Factory::AllowedSurfaceSize(aSize)) {
1364 return nullptr;
1365 }
1366
1367 TextureData* data =
1368 TextureData::Create(aAllocator, aFormat, aSize, aKnowsCompositor,
1369 aSelector, aTextureFlags, aAllocFlags);
1370
1371 if (data) {
1372 return MakeAndAddRef<TextureClient>(data, aTextureFlags, aAllocator);
1373 }
1374 if (aAllocFlags & ALLOC_FORCE_REMOTE) {
1375 // If we must be remote, but allocation failed, then don't fall back.
1376 return nullptr;
1377 }
1378
1379 // Can't do any better than a buffer texture client.
1380 return TextureClient::CreateForRawBufferAccess(aAllocator, aFormat, aSize,
1381 moz2DBackend, layersBackend,
1382 aTextureFlags, aAllocFlags);
1383}
1384
1385// static
1386already_AddRefed<TextureClient> TextureClient::CreateFromSurface(
1387 KnowsCompositor* aAllocator, gfx::SourceSurface* aSurface,
1388 BackendSelector aSelector, TextureFlags aTextureFlags,
1389 TextureAllocationFlags aAllocFlags) {
1390 // also test the validity of aAllocator
1391 if (!aAllocator || !aAllocator->GetTextureForwarder()->IPCOpen()) {
1392 return nullptr;
1393 }
1394
1395 gfx::IntSize size = aSurface->GetSize();
1396
1397 if (!gfx::Factory::AllowedSurfaceSize(size)) {
1398 return nullptr;
1399 }
1400
1401 TextureData* data = nullptr;
1402#if defined(XP_WIN)
1403 LayersBackend layersBackend = aAllocator->GetCompositorBackendType();
1404 gfx::BackendType moz2DBackend =
1405 BackendTypeForBackendSelector(layersBackend, aSelector);
1406
1407 int32_t maxTextureSize = aAllocator->GetMaxTextureSize();
1408
1409 if (layersBackend == LayersBackend::LAYERS_WR &&
1410 (moz2DBackend == gfx::BackendType::DIRECT2D ||
1411 moz2DBackend == gfx::BackendType::DIRECT2D1_1) &&
1412 size.width <= maxTextureSize && size.height <= maxTextureSize) {
1413 data = D3D11TextureData::Create(aSurface, aAllocFlags);
1414 }
1415#endif
1416
1417 if (data) {
1418 return MakeAndAddRef<TextureClient>(data, aTextureFlags,
1419 aAllocator->GetTextureForwarder());
1420 }
1421
1422 // Fall back to using UpdateFromSurface
1423
1424 TextureAllocationFlags allocFlags =
1425 TextureAllocationFlags(aAllocFlags | ALLOC_UPDATE_FROM_SURFACE);
1426 RefPtr<TextureClient> client =
1427 CreateForDrawing(aAllocator, aSurface->GetFormat(), size, aSelector,
1428 aTextureFlags, allocFlags);
1429 if (!client) {
1430 return nullptr;
1431 }
1432
1433 TextureClientAutoLock autoLock(client, OpenMode::OPEN_WRITE_ONLY);
1434 if (!autoLock.Succeeded()) {
1435 return nullptr;
1436 }
1437
1438 client->UpdateFromSurface(aSurface);
1439 return client.forget();
1440}
1441
1442// static
1443already_AddRefed<TextureClient> TextureClient::CreateForRawBufferAccess(
1444 KnowsCompositor* aAllocator, gfx::SurfaceFormat aFormat, gfx::IntSize aSize,
1445 gfx::BackendType aMoz2DBackend, TextureFlags aTextureFlags,
1446 TextureAllocationFlags aAllocFlags) {
1447 return CreateForRawBufferAccess(
1448 aAllocator->GetTextureForwarder(), aFormat, aSize, aMoz2DBackend,
1449 aAllocator->GetCompositorBackendType(), aTextureFlags, aAllocFlags);
1450}
1451
1452// static
1453already_AddRefed<TextureClient> TextureClient::CreateForRawBufferAccess(
1454 LayersIPCChannel* aAllocator, gfx::SurfaceFormat aFormat,
1455 gfx::IntSize aSize, gfx::BackendType aMoz2DBackend,
1456 LayersBackend aLayersBackend, TextureFlags aTextureFlags,
1457 TextureAllocationFlags aAllocFlags) {
1458 // also test the validity of aAllocator
1459 if (!aAllocator || !aAllocator->IPCOpen()) {
1460 return nullptr;
1461 }
1462
1463 if (!gfx::Factory::AllowedSurfaceSize(aSize)) {
1464 return nullptr;
1465 }
1466
1467 if (aFormat == SurfaceFormat::B8G8R8X8) {
1468 // Skia doesn't support RGBX, so ensure we clear the buffer for the proper
1469 // alpha values.
1470 aAllocFlags = TextureAllocationFlags(aAllocFlags | ALLOC_CLEAR_BUFFER);
1471 }
1472
1473 // Note that we ignore the backend type if we get here. It should only be D2D
1474 // or Skia, and D2D does not support data surfaces. Therefore it is safe to
1475 // force the buffer to be Skia.
1476 NS_WARNING_ASSERTION(aMoz2DBackend == gfx::BackendType::SKIA ||do { if (!(aMoz2DBackend == gfx::BackendType::SKIA || aMoz2DBackend
== gfx::BackendType::DIRECT2D || aMoz2DBackend == gfx::BackendType
::DIRECT2D1_1)) { NS_DebugBreak(NS_DEBUG_WARNING, "Unsupported TextureClient backend type"
, "aMoz2DBackend == gfx::BackendType::SKIA || aMoz2DBackend == gfx::BackendType::DIRECT2D || aMoz2DBackend == gfx::BackendType::DIRECT2D1_1"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 1479
); } } while (false)
1477 aMoz2DBackend == gfx::BackendType::DIRECT2D ||do { if (!(aMoz2DBackend == gfx::BackendType::SKIA || aMoz2DBackend
== gfx::BackendType::DIRECT2D || aMoz2DBackend == gfx::BackendType
::DIRECT2D1_1)) { NS_DebugBreak(NS_DEBUG_WARNING, "Unsupported TextureClient backend type"
, "aMoz2DBackend == gfx::BackendType::SKIA || aMoz2DBackend == gfx::BackendType::DIRECT2D || aMoz2DBackend == gfx::BackendType::DIRECT2D1_1"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 1479
); } } while (false)
1478 aMoz2DBackend == gfx::BackendType::DIRECT2D1_1,do { if (!(aMoz2DBackend == gfx::BackendType::SKIA || aMoz2DBackend
== gfx::BackendType::DIRECT2D || aMoz2DBackend == gfx::BackendType
::DIRECT2D1_1)) { NS_DebugBreak(NS_DEBUG_WARNING, "Unsupported TextureClient backend type"
, "aMoz2DBackend == gfx::BackendType::SKIA || aMoz2DBackend == gfx::BackendType::DIRECT2D || aMoz2DBackend == gfx::BackendType::DIRECT2D1_1"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 1479
); } } while (false)
1479 "Unsupported TextureClient backend type")do { if (!(aMoz2DBackend == gfx::BackendType::SKIA || aMoz2DBackend
== gfx::BackendType::DIRECT2D || aMoz2DBackend == gfx::BackendType
::DIRECT2D1_1)) { NS_DebugBreak(NS_DEBUG_WARNING, "Unsupported TextureClient backend type"
, "aMoz2DBackend == gfx::BackendType::SKIA || aMoz2DBackend == gfx::BackendType::DIRECT2D || aMoz2DBackend == gfx::BackendType::DIRECT2D1_1"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 1479
); } } while (false)
;
1480
1481 // For future changes, check aAllocFlags aAllocFlags & ALLOC_DO_NOT_ACCELERATE
1482 TextureData* texData = BufferTextureData::Create(
1483 aSize, aFormat, gfx::BackendType::SKIA, aLayersBackend, aTextureFlags,
1484 aAllocFlags, aAllocator);
1485 if (!texData) {
1486 return nullptr;
1487 }
1488
1489 return MakeAndAddRef<TextureClient>(texData, aTextureFlags, aAllocator);
1490}
1491
1492// static
1493already_AddRefed<TextureClient> TextureClient::CreateForYCbCr(
1494 KnowsCompositor* aAllocator, const gfx::IntRect& aDisplay,
1495 const gfx::IntSize& aYSize, uint32_t aYStride,
1496 const gfx::IntSize& aCbCrSize, uint32_t aCbCrStride, StereoMode aStereoMode,
1497 gfx::ColorDepth aColorDepth, gfx::YUVColorSpace aYUVColorSpace,
1498 gfx::ColorRange aColorRange, gfx::ChromaSubsampling aSubsampling,
1499 TextureFlags aTextureFlags) {
1500 if (!aAllocator || !aAllocator->GetLayersIPCActor()->IPCOpen()) {
1501 return nullptr;
1502 }
1503
1504 if (!gfx::Factory::AllowedSurfaceSize(aYSize)) {
1505 return nullptr;
1506 }
1507
1508 TextureData* data = BufferTextureData::CreateForYCbCr(
1509 aAllocator, aDisplay, aYSize, aYStride, aCbCrSize, aCbCrStride,
1510 aStereoMode, aColorDepth, aYUVColorSpace, aColorRange, aSubsampling,
1511 aTextureFlags);
1512 if (!data) {
1513 return nullptr;
1514 }
1515
1516 return MakeAndAddRef<TextureClient>(data, aTextureFlags,
1517 aAllocator->GetTextureForwarder());
1518}
1519
1520TextureClient::TextureClient(TextureData* aData, TextureFlags aFlags,
1521 LayersIPCChannel* aAllocator)
1522 : AtomicRefCountedWithFinalize("TextureClient"),
1523 mMutex("TextureClient::mMutex"),
1524 mAllocator(aAllocator),
1525 mActor(nullptr),
1526 mData(aData),
1527 mFlags(aFlags),
1528 mOpenMode(OpenMode::OPEN_NONE)
1529#ifdef DEBUG1
1530 ,
1531 mExpectedDtRefs(0)
1532#endif
1533 ,
1534 mIsLocked(false),
1535 mIsReadLocked(false),
1536 mUpdated(false),
1537 mAddedToCompositableClient(false),
1538 mFwdTransactionId(0),
1539 mSerial(++sSerialCounter) {
1540 mData->FillInfo(mInfo);
1541 mFlags |= mData->GetTextureFlags();
1542}
1543
1544bool TextureClient::CopyToTextureClient(TextureClient* aTarget,
1545 const gfx::IntRect* aRect,
1546 const gfx::IntPoint* aPoint) {
1547 MOZ_ASSERT(IsLocked())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsLocked())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsLocked()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("IsLocked()", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 1547); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsLocked()"
")"); do { MOZ_CrashSequence(__null, 1547); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1548 MOZ_ASSERT(aTarget->IsLocked())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aTarget->IsLocked())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aTarget->IsLocked()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aTarget->IsLocked()"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 1548
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTarget->IsLocked()"
")"); do { MOZ_CrashSequence(__null, 1548); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1549
1550 if (!aTarget->CanExposeDrawTarget() || !CanExposeDrawTarget()) {
1551 return false;
1552 }
1553
1554 RefPtr<DrawTarget> destinationTarget = aTarget->BorrowDrawTarget();
1555 if (!destinationTarget) {
1556 gfxWarningmozilla::gfx::WarningLog() << "TextureClient::CopyToTextureClient (dest) failed in "
1557 "BorrowDrawTarget";
1558 return false;
1559 }
1560
1561 RefPtr<DrawTarget> sourceTarget = BorrowDrawTarget();
1562 if (!sourceTarget) {
1563 gfxWarningmozilla::gfx::WarningLog() << "TextureClient::CopyToTextureClient (src) failed in "
1564 "BorrowDrawTarget";
1565 return false;
1566 }
1567
1568 RefPtr<gfx::SourceSurface> source = sourceTarget->Snapshot();
1569 destinationTarget->CopySurface(
1570 source, aRect ? *aRect : gfx::IntRect(gfx::IntPoint(0, 0), GetSize()),
1571 aPoint ? *aPoint : gfx::IntPoint(0, 0));
1572 return true;
1573}
1574
1575already_AddRefed<gfx::DataSourceSurface> TextureClient::GetAsSurface() {
1576 if (!Lock(OpenMode::OPEN_READ)) {
1577 return nullptr;
1578 }
1579 RefPtr<gfx::DataSourceSurface> data;
1580 { // scope so that the DrawTarget is destroyed before Unlock()
1581 RefPtr<gfx::DrawTarget> dt = BorrowDrawTarget();
1582 if (dt) {
1583 RefPtr<gfx::SourceSurface> surf = dt->Snapshot();
1584 if (surf) {
1585 data = surf->GetDataSurface();
1586 }
1587 }
1588 }
1589 Unlock();
1590 return data.forget();
1591}
1592
1593void TextureClient::GetSurfaceDescriptorRemoteDecoder(
1594 SurfaceDescriptorRemoteDecoder* const aOutDesc) {
1595 const auto handle = GetSerial();
1596
1597 RemoteDecoderVideoSubDescriptor subDesc = null_t();
1598 MOZ_RELEASE_ASSERT(mData)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mData)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(mData))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("mData", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 1598); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "mData"
")"); do { MOZ_CrashSequence(__null, 1598); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1599 mData->GetSubDescriptor(&subDesc);
1600
1601 *aOutDesc = SurfaceDescriptorRemoteDecoder(
1602 handle, std::move(subDesc), Nothing(),
1603 SurfaceDescriptorRemoteDecoderId::GetNext());
1604}
1605
1606class MemoryTextureReadLock : public NonBlockingTextureReadLock {
1607 public:
1608 MemoryTextureReadLock();
1609
1610 virtual ~MemoryTextureReadLock();
1611
1612 bool ReadLock() override;
1613
1614 int32_t ReadUnlock() override;
1615
1616 int32_t GetReadCount() override;
1617
1618 LockType GetType() override { return TYPE_NONBLOCKING_MEMORY; }
1619
1620 bool IsValid() const override { return true; };
1621
1622 bool Serialize(ReadLockDescriptor& aOutput, base::ProcessId aOther) override;
1623
1624 Atomic<int32_t> mReadCount;
1625};
1626
1627// The cross-prcess implementation of TextureReadLock.
1628//
1629// Since we don't use cross-process reference counting for the ReadLock objects,
1630// we use the lock's internal counter as a way to know when to deallocate the
1631// underlying shmem section: when the counter is equal to 1, it means that the
1632// lock is not "held" (the texture is writable), when the counter is equal to 0
1633// it means that we can safely deallocate the shmem section without causing a
1634// race condition with the other process.
1635class ShmemTextureReadLock : public NonBlockingTextureReadLock {
1636 public:
1637 struct ShmReadLockInfo {
1638 int32_t readCount;
1639 };
1640
1641 explicit ShmemTextureReadLock(LayersIPCChannel* aAllocator);
1642
1643 virtual ~ShmemTextureReadLock();
1644
1645 bool ReadLock() override;
1646
1647 int32_t ReadUnlock() override;
1648
1649 int32_t GetReadCount() override;
1650
1651 bool IsValid() const override { return mAllocSuccess; };
1652
1653 LockType GetType() override { return TYPE_NONBLOCKING_SHMEM; }
1654
1655 bool Serialize(ReadLockDescriptor& aOutput, base::ProcessId aOther) override;
1656
1657 mozilla::layers::ShmemSection& GetShmemSection() { return mShmemSection; }
1658
1659 explicit ShmemTextureReadLock(
1660 const mozilla::layers::ShmemSection& aShmemSection)
1661 : mShmemSection(aShmemSection), mAllocSuccess(true) {
1662 MOZ_COUNT_CTOR(ShmemTextureReadLock)do { static_assert(std::is_class_v<ShmemTextureReadLock>
, "Token '" "ShmemTextureReadLock" "' is not a class type.");
static_assert(!std::is_base_of<nsISupports, ShmemTextureReadLock
>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or "
"MOZ_COUNT_DTOR");; NS_LogCtor((void*)this, "ShmemTextureReadLock"
, sizeof(*this)); } while (0)
;
1663 }
1664
1665 ShmReadLockInfo* GetShmReadLockInfoPtr() {
1666 return reinterpret_cast<ShmReadLockInfo*>(
1667 mShmemSection.shmem().get<char>() + mShmemSection.offset());
1668 }
1669
1670 RefPtr<LayersIPCChannel> mClientAllocator;
1671 mozilla::layers::ShmemSection mShmemSection;
1672 bool mAllocSuccess;
1673};
1674
1675class CrossProcessSemaphoreReadLock : public TextureReadLock {
1676 public:
1677 CrossProcessSemaphoreReadLock()
1678 : mSemaphore(CrossProcessSemaphore::Create("TextureReadLock", 1)),
1679 mShared(false) {}
1680 explicit CrossProcessSemaphoreReadLock(CrossProcessSemaphoreHandle aHandle)
1681 : mSemaphore(CrossProcessSemaphore::Create(std::move(aHandle))),
1682 mShared(false) {}
1683
1684 bool ReadLock() override {
1685 if (!IsValid()) {
1686 return false;
1687 }
1688 return mSemaphore->Wait();
1689 }
1690 bool TryReadLock(TimeDuration aTimeout) override {
1691 if (!IsValid()) {
1692 return false;
1693 }
1694 return mSemaphore->Wait(Some(aTimeout));
1695 }
1696 int32_t ReadUnlock() override {
1697 if (!IsValid()) {
1698 return 1;
1699 }
1700 mSemaphore->Signal();
1701 return 1;
1702 }
1703 bool IsValid() const override { return !!mSemaphore; }
1704
1705 bool Serialize(ReadLockDescriptor& aOutput, base::ProcessId aOther) override;
1706
1707 LockType GetType() override { return TYPE_CROSS_PROCESS_SEMAPHORE; }
1708
1709 UniquePtr<CrossProcessSemaphore> mSemaphore;
1710 bool mShared;
1711};
1712
1713// static
1714already_AddRefed<TextureReadLock> TextureReadLock::Deserialize(
1715 ReadLockDescriptor&& aDescriptor, ISurfaceAllocator* aAllocator) {
1716 switch (aDescriptor.type()) {
1
Control jumps to 'case Tuintptr_t:' at line 1726
1717 case ReadLockDescriptor::TUntrustedShmemSection: {
1718 const UntrustedShmemSection& untrusted =
1719 aDescriptor.get_UntrustedShmemSection();
1720 Maybe<ShmemSection> section = ShmemSection::FromUntrusted(untrusted);
1721 if (section.isNothing()) {
1722 return nullptr;
1723 }
1724 return MakeAndAddRef<ShmemTextureReadLock>(section.value());
1725 }
1726 case ReadLockDescriptor::Tuintptr_t: {
1727 if (!aAllocator->IsSameProcess()) {
2
Assuming the condition is false
3
Taking false branch
1728 // Trying to use a memory based lock instead of a shmem based one in
1729 // the cross-process case is a bad security violation.
1730 NS_ERROR(do { NS_DebugBreak(NS_DEBUG_ASSERTION, "A client process may be trying to peek at the host's address "
"space!", "Error", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 1732); MOZ_PretendNoReturn(); } while (0)
1731 "A client process may be trying to peek at the host's address "do { NS_DebugBreak(NS_DEBUG_ASSERTION, "A client process may be trying to peek at the host's address "
"space!", "Error", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 1732); MOZ_PretendNoReturn(); } while (0)
1732 "space!")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "A client process may be trying to peek at the host's address "
"space!", "Error", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 1732); MOZ_PretendNoReturn(); } while (0)
;
1733 return nullptr;
1734 }
1735 RefPtr<TextureReadLock> lock =
1736 reinterpret_cast<MemoryTextureReadLock*>(aDescriptor.get_uintptr_t());
4
Calling constructor for 'RefPtr<mozilla::layers::TextureReadLock>'
7
Returning from constructor for 'RefPtr<mozilla::layers::TextureReadLock>'
1737
1738 MOZ_ASSERT(lock)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(lock)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(lock))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("lock", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 1738); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lock" ")");
do { MOZ_CrashSequence(__null, 1738); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8
Taking false branch
9
Loop condition is false. Exiting loop
1739 if (lock) {
10
Taking true branch
1740 // The corresponding AddRef is in MemoryTextureReadLock::Serialize
1741 lock.get()->Release();
11
Calling 'TextureReadLock::Release'
19
Returning; memory was released
1742 }
1743
1744 return lock.forget();
20
Calling 'RefPtr::forget'
1745 }
1746 case ReadLockDescriptor::TCrossProcessSemaphoreDescriptor: {
1747 return MakeAndAddRef<CrossProcessSemaphoreReadLock>(
1748 std::move(aDescriptor.get_CrossProcessSemaphoreDescriptor().sem()));
1749 }
1750 case ReadLockDescriptor::Tnull_t: {
1751 return nullptr;
1752 }
1753 default: {
1754 MOZ_DIAGNOSTIC_CRASH(do { do { } while (false); MOZ_ReportCrash("" "Invalid descriptor in TextureReadLock::Deserialize"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 1755
); AnnotateMozCrashReason("MOZ_CRASH(" "Invalid descriptor in TextureReadLock::Deserialize"
")"); do { MOZ_CrashSequence(__null, 1755); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
1755 "Invalid descriptor in TextureReadLock::Deserialize")do { do { } while (false); MOZ_ReportCrash("" "Invalid descriptor in TextureReadLock::Deserialize"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 1755
); AnnotateMozCrashReason("MOZ_CRASH(" "Invalid descriptor in TextureReadLock::Deserialize"
")"); do { MOZ_CrashSequence(__null, 1755); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1756 }
1757 }
1758 return nullptr;
1759}
1760// static
1761already_AddRefed<TextureReadLock> NonBlockingTextureReadLock::Create(
1762 LayersIPCChannel* aAllocator) {
1763 if (aAllocator->IsSameProcess()) {
1764 // If our compositor is in the same process, we can save some cycles by not
1765 // using shared memory.
1766 return MakeAndAddRef<MemoryTextureReadLock>();
1767 }
1768
1769 return MakeAndAddRef<ShmemTextureReadLock>(aAllocator);
1770}
1771
1772MemoryTextureReadLock::MemoryTextureReadLock() : mReadCount(1) {
1773 MOZ_COUNT_CTOR(MemoryTextureReadLock)do { static_assert(std::is_class_v<MemoryTextureReadLock>
, "Token '" "MemoryTextureReadLock" "' is not a class type.")
; static_assert(!std::is_base_of<nsISupports, MemoryTextureReadLock
>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or "
"MOZ_COUNT_DTOR");; NS_LogCtor((void*)this, "MemoryTextureReadLock"
, sizeof(*this)); } while (0)
;
1774}
1775
1776MemoryTextureReadLock::~MemoryTextureReadLock() {
1777 // One read count that is added in constructor.
1778 MOZ_ASSERT(mReadCount == 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mReadCount == 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mReadCount == 1))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("mReadCount == 1"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 1778
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mReadCount == 1" ")"
); do { MOZ_CrashSequence(__null, 1778); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1779 MOZ_COUNT_DTOR(MemoryTextureReadLock)do { static_assert(std::is_class_v<MemoryTextureReadLock>
, "Token '" "MemoryTextureReadLock" "' is not a class type.")
; static_assert(!std::is_base_of<nsISupports, MemoryTextureReadLock
>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or "
"MOZ_COUNT_DTOR");; NS_LogDtor((void*)this, "MemoryTextureReadLock"
, sizeof(*this)); } while (0)
;
1780}
1781
1782bool MemoryTextureReadLock::Serialize(ReadLockDescriptor& aOutput,
1783 base::ProcessId aOther) {
1784 // AddRef here and Release when receiving on the host side to make sure the
1785 // reference count doesn't go to zero before the host receives the message.
1786 // see TextureReadLock::Deserialize
1787 this->AddRef();
1788 aOutput = ReadLockDescriptor(uintptr_t(this));
1789 return true;
1790}
1791
1792bool MemoryTextureReadLock::ReadLock() {
1793 ++mReadCount;
1794 return true;
1795}
1796
1797int32_t MemoryTextureReadLock::ReadUnlock() {
1798 int32_t readCount = --mReadCount;
1799 MOZ_ASSERT(readCount >= 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(readCount >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(readCount >= 0))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("readCount >= 0"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 1799
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "readCount >= 0"
")"); do { MOZ_CrashSequence(__null, 1799); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1800
1801 return readCount;
1802}
1803
1804int32_t MemoryTextureReadLock::GetReadCount() { return mReadCount; }
1805
1806ShmemTextureReadLock::ShmemTextureReadLock(LayersIPCChannel* aAllocator)
1807 : mClientAllocator(aAllocator), mAllocSuccess(false) {
1808 MOZ_COUNT_CTOR(ShmemTextureReadLock)do { static_assert(std::is_class_v<ShmemTextureReadLock>
, "Token '" "ShmemTextureReadLock" "' is not a class type.");
static_assert(!std::is_base_of<nsISupports, ShmemTextureReadLock
>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or "
"MOZ_COUNT_DTOR");; NS_LogCtor((void*)this, "ShmemTextureReadLock"
, sizeof(*this)); } while (0)
;
1809 MOZ_ASSERT(mClientAllocator)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mClientAllocator)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mClientAllocator))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("mClientAllocator"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 1809
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mClientAllocator"
")"); do { MOZ_CrashSequence(__null, 1809); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1810 MOZ_ASSERT(mClientAllocator->GetTileLockAllocator())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mClientAllocator->GetTileLockAllocator())>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mClientAllocator->GetTileLockAllocator()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("mClientAllocator->GetTileLockAllocator()"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 1810
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mClientAllocator->GetTileLockAllocator()"
")"); do { MOZ_CrashSequence(__null, 1810); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1811#define MOZ_ALIGN_WORD(x)(((x) + 3) & ~3) (((x) + 3) & ~3)
1812 if (mClientAllocator->GetTileLockAllocator()->AllocShmemSection(
1813 MOZ_ALIGN_WORD(sizeof(ShmReadLockInfo))(((sizeof(ShmReadLockInfo)) + 3) & ~3), &mShmemSection)) {
1814 ShmReadLockInfo* info = GetShmReadLockInfoPtr();
1815 info->readCount = 1;
1816 mAllocSuccess = true;
1817 }
1818}
1819
1820ShmemTextureReadLock::~ShmemTextureReadLock() {
1821 if (mClientAllocator) {
1822 // Release one read count that is added in constructor.
1823 // The count is kept for calling GetReadCount() by TextureClientPool.
1824 ReadUnlock();
1825 }
1826 MOZ_COUNT_DTOR(ShmemTextureReadLock)do { static_assert(std::is_class_v<ShmemTextureReadLock>
, "Token '" "ShmemTextureReadLock" "' is not a class type.");
static_assert(!std::is_base_of<nsISupports, ShmemTextureReadLock
>::value, "nsISupports classes don't need to call MOZ_COUNT_CTOR or "
"MOZ_COUNT_DTOR");; NS_LogDtor((void*)this, "ShmemTextureReadLock"
, sizeof(*this)); } while (0)
;
1827}
1828
1829bool ShmemTextureReadLock::Serialize(ReadLockDescriptor& aOutput,
1830 base::ProcessId aOther) {
1831 aOutput = ReadLockDescriptor(GetShmemSection().AsUntrusted());
1832 return true;
1833}
1834
1835bool ShmemTextureReadLock::ReadLock() {
1836 if (!mAllocSuccess) {
1837 return false;
1838 }
1839 ShmReadLockInfo* info = GetShmReadLockInfoPtr();
1840 PR_ATOMIC_INCREMENT(&info->readCount)__sync_add_and_fetch(&info->readCount, 1);
1841 return true;
1842}
1843
1844int32_t ShmemTextureReadLock::ReadUnlock() {
1845 if (!mAllocSuccess) {
1846 return 0;
1847 }
1848 ShmReadLockInfo* info = GetShmReadLockInfoPtr();
1849 int32_t readCount = PR_ATOMIC_DECREMENT(&info->readCount)__sync_sub_and_fetch(&info->readCount, 1);
1850 MOZ_ASSERT(readCount >= 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(readCount >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(readCount >= 0))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("readCount >= 0"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 1850
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "readCount >= 0"
")"); do { MOZ_CrashSequence(__null, 1850); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1851 if (readCount > 0) {
1852 return readCount;
1853 }
1854 if (mClientAllocator) {
1855 if (nsCOMPtr<nsISerialEventTarget> thread = mClientAllocator->GetThread()) {
1856 if (thread->IsOnCurrentThread()) {
1857 if (auto* tileLockAllocator =
1858 mClientAllocator->GetTileLockAllocator()) {
1859 tileLockAllocator->DeallocShmemSection(mShmemSection);
1860 return readCount;
1861 }
1862 } else {
1863 thread->Dispatch(NS_NewRunnableFunction(
1864 __func__,
1865 [shmemSection = std::move(mShmemSection),
1866 clientAllocator = std::move(mClientAllocator)]() mutable {
1867 if (auto* tileLockAllocator =
1868 clientAllocator->GetTileLockAllocator()) {
1869 tileLockAllocator->DeallocShmemSection(shmemSection);
1870 } else {
1871 // we are on the compositor process, or IPC is down.
1872 FixedSizeSmallShmemSectionAllocator::FreeShmemSection(
1873 shmemSection);
1874 }
1875 }));
1876 return readCount;
1877 }
1878 }
1879 }
1880 // we are on the compositor process, or IPC is down.
1881 FixedSizeSmallShmemSectionAllocator::FreeShmemSection(mShmemSection);
1882 return readCount;
1883}
1884
1885int32_t ShmemTextureReadLock::GetReadCount() {
1886 if (!mAllocSuccess) {
1887 return 0;
1888 }
1889 ShmReadLockInfo* info = GetShmReadLockInfoPtr();
1890 return info->readCount;
1891}
1892
1893bool CrossProcessSemaphoreReadLock::Serialize(ReadLockDescriptor& aOutput,
1894 base::ProcessId aOther) {
1895 if (!mShared && IsValid()) {
1896 aOutput = ReadLockDescriptor(
1897 CrossProcessSemaphoreDescriptor(mSemaphore->CloneHandle()));
1898 mSemaphore->CloseHandle();
1899 mShared = true;
1900 return true;
1901 } else {
1902 return mShared;
1903 }
1904}
1905
1906void TextureClient::EnableBlockingReadLock() {
1907 MOZ_ASSERT(ShouldReadLock())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(ShouldReadLock())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(ShouldReadLock()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("ShouldReadLock()"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 1907
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ShouldReadLock()"
")"); do { MOZ_CrashSequence(__null, 1907); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1908 if (!mReadLock) {
1909 mReadLock = new CrossProcessSemaphoreReadLock();
1910 }
1911}
1912
1913bool UpdateYCbCrTextureClient(TextureClient* aTexture,
1914 const PlanarYCbCrData& aData) {
1915 MOZ_ASSERT(aTexture)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aTexture)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aTexture))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aTexture", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 1915); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTexture" ")"
); do { MOZ_CrashSequence(__null, 1915); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1916 MOZ_ASSERT(aTexture->IsLocked())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aTexture->IsLocked())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aTexture->IsLocked()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aTexture->IsLocked()"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 1916
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTexture->IsLocked()"
")"); do { MOZ_CrashSequence(__null, 1916); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1917 MOZ_ASSERT(aTexture->GetFormat() == gfx::SurfaceFormat::YUV420,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aTexture->GetFormat() == gfx::SurfaceFormat::YUV420
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aTexture->GetFormat() == gfx::SurfaceFormat::YUV420
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aTexture->GetFormat() == gfx::SurfaceFormat::YUV420" " ("
"This textureClient can only use YCbCr data" ")", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 1918); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTexture->GetFormat() == gfx::SurfaceFormat::YUV420"
") (" "This textureClient can only use YCbCr data" ")"); do {
MOZ_CrashSequence(__null, 1918); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
1918 "This textureClient can only use YCbCr data")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aTexture->GetFormat() == gfx::SurfaceFormat::YUV420
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aTexture->GetFormat() == gfx::SurfaceFormat::YUV420
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aTexture->GetFormat() == gfx::SurfaceFormat::YUV420" " ("
"This textureClient can only use YCbCr data" ")", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 1918); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTexture->GetFormat() == gfx::SurfaceFormat::YUV420"
") (" "This textureClient can only use YCbCr data" ")"); do {
MOZ_CrashSequence(__null, 1918); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
1919 MOZ_ASSERT(!aTexture->IsImmutable())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aTexture->IsImmutable())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aTexture->IsImmutable())
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!aTexture->IsImmutable()"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 1919
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aTexture->IsImmutable()"
")"); do { MOZ_CrashSequence(__null, 1919); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1920 MOZ_ASSERT(aTexture->IsValid())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aTexture->IsValid())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aTexture->IsValid()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aTexture->IsValid()"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 1920
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTexture->IsValid()"
")"); do { MOZ_CrashSequence(__null, 1920); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1921 MOZ_ASSERT(aData.mCbSkip == aData.mCrSkip)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aData.mCbSkip == aData.mCrSkip)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aData.mCbSkip == aData.mCrSkip
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aData.mCbSkip == aData.mCrSkip", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 1921); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aData.mCbSkip == aData.mCrSkip"
")"); do { MOZ_CrashSequence(__null, 1921); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1922
1923 MappedYCbCrTextureData mapped;
1924 if (!aTexture->BorrowMappedYCbCrData(mapped)) {
1925 NS_WARNING("Failed to extract YCbCr info!")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to extract YCbCr info!"
, nullptr, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 1925)
;
1926 return false;
1927 }
1928
1929 uint32_t bytesPerPixel =
1930 BytesPerPixel(SurfaceFormatForColorDepth(aData.mColorDepth));
1931 MappedYCbCrTextureData srcData;
1932 srcData.y.data = aData.mYChannel;
1933 srcData.y.size = aData.YDataSize();
1934 srcData.y.stride = aData.mYStride;
1935 srcData.y.skip = aData.mYSkip;
1936 srcData.y.bytesPerPixel = bytesPerPixel;
1937 srcData.cb.data = aData.mCbChannel;
1938 srcData.cb.size = aData.CbCrDataSize();
1939 srcData.cb.stride = aData.mCbCrStride;
1940 srcData.cb.skip = aData.mCbSkip;
1941 srcData.cb.bytesPerPixel = bytesPerPixel;
1942 srcData.cr.data = aData.mCrChannel;
1943 srcData.cr.size = aData.CbCrDataSize();
1944 srcData.cr.stride = aData.mCbCrStride;
1945 srcData.cr.skip = aData.mCrSkip;
1946 srcData.cr.bytesPerPixel = bytesPerPixel;
1947 srcData.metadata = nullptr;
1948
1949 if (!srcData.CopyInto(mapped)) {
1950 NS_WARNING("Failed to copy image data!")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to copy image data!",
nullptr, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 1950)
;
1951 return false;
1952 }
1953
1954 if (TextureRequiresLocking(aTexture->GetFlags())) {
1955 // We don't have support for proper locking yet, so we'll
1956 // have to be immutable instead.
1957 aTexture->MarkImmutable();
1958 }
1959 return true;
1960}
1961
1962already_AddRefed<TextureClient> TextureClient::CreateWithData(
1963 TextureData* aData, TextureFlags aFlags, LayersIPCChannel* aAllocator) {
1964 if (!aData) {
1965 return nullptr;
1966 }
1967 return MakeAndAddRef<TextureClient>(aData, aFlags, aAllocator);
1968}
1969
1970template <class PixelDataType>
1971static void copyData(PixelDataType* aDst,
1972 const MappedYCbCrChannelData& aChannelDst,
1973 PixelDataType* aSrc,
1974 const MappedYCbCrChannelData& aChannelSrc) {
1975 uint8_t* srcByte = reinterpret_cast<uint8_t*>(aSrc);
1976 const int32_t srcSkip = aChannelSrc.skip + 1;
1977 uint8_t* dstByte = reinterpret_cast<uint8_t*>(aDst);
1978 const int32_t dstSkip = aChannelDst.skip + 1;
1979 for (int32_t i = 0; i < aChannelSrc.size.height; ++i) {
1980 for (int32_t j = 0; j < aChannelSrc.size.width; ++j) {
1981 *aDst = *aSrc;
1982 aSrc += srcSkip;
1983 aDst += dstSkip;
1984 }
1985 srcByte += aChannelSrc.stride;
1986 aSrc = reinterpret_cast<PixelDataType*>(srcByte);
1987 dstByte += aChannelDst.stride;
1988 aDst = reinterpret_cast<PixelDataType*>(dstByte);
1989 }
1990}
1991
1992bool MappedYCbCrChannelData::CopyInto(MappedYCbCrChannelData& aDst) {
1993 if (!data || !aDst.data || size != aDst.size) {
1994 return false;
1995 }
1996
1997 if (stride == aDst.stride && skip == aDst.skip) {
1998 // fast path!
1999 // We assume that the padding in the destination is there for alignment
2000 // purposes and doesn't contain useful data.
2001 memcpy(aDst.data, data, stride * size.height);
2002 return true;
2003 }
2004
2005 if (aDst.skip == 0 && skip == 0) {
2006 // fast-ish path
2007 for (int32_t i = 0; i < size.height; ++i) {
2008 memcpy(aDst.data + i * aDst.stride, data + i * stride,
2009 size.width * bytesPerPixel);
2010 }
2011 return true;
2012 }
2013
2014 MOZ_ASSERT(bytesPerPixel == 1 || bytesPerPixel == 2)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(bytesPerPixel == 1 || bytesPerPixel == 2)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(bytesPerPixel == 1 || bytesPerPixel == 2))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("bytesPerPixel == 1 || bytesPerPixel == 2"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 2014
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytesPerPixel == 1 || bytesPerPixel == 2"
")"); do { MOZ_CrashSequence(__null, 2014); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2015 // slow path
2016 if (bytesPerPixel == 1) {
2017 copyData(aDst.data, aDst, data, *this);
2018 } else if (bytesPerPixel == 2) {
2019 copyData(reinterpret_cast<uint16_t*>(aDst.data), aDst,
2020 reinterpret_cast<uint16_t*>(data), *this);
2021 }
2022 return true;
2023}
2024
2025} // namespace mozilla::layers

/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/RefPtr.h

1/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3/* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7#ifndef mozilla_RefPtr_h
8#define mozilla_RefPtr_h
9
10#include "mozilla/AlreadyAddRefed.h"
11#include "mozilla/Assertions.h"
12#include "mozilla/Attributes.h"
13#include "mozilla/DbgMacro.h"
14
15#include <type_traits>
16
17/*****************************************************************************/
18
19// template <class T> class RefPtrGetterAddRefs;
20
21class nsQueryReferent;
22class nsCOMPtr_helper;
23class nsISupports;
24
25namespace mozilla {
26template <class T>
27class MovingNotNull;
28template <class T>
29class NotNull;
30template <class T>
31class OwningNonNull;
32template <class T>
33class StaticLocalRefPtr;
34template <class T>
35class StaticRefPtr;
36
37// Traditionally, RefPtr supports automatic refcounting of any pointer type
38// with AddRef() and Release() methods that follow the traditional semantics.
39//
40// This traits class can be specialized to operate on other pointer types. For
41// example, we specialize this trait for opaque FFI types that represent
42// refcounted objects in Rust.
43//
44// Given the use of ConstRemovingRefPtrTraits below, U should not be a const-
45// qualified type.
46template <class U>
47struct RefPtrTraits {
48 static void AddRef(U* aPtr) { aPtr->AddRef(); }
49 static void Release(U* aPtr) { aPtr->Release(); }
50};
51
52} // namespace mozilla
53
54template <class T>
55class MOZ_IS_REFPTR RefPtr {
56 private:
57 void assign_with_AddRef(T* aRawPtr) {
58 if (aRawPtr) {
59 ConstRemovingRefPtrTraits<T>::AddRef(aRawPtr);
60 }
61 assign_assuming_AddRef(aRawPtr);
62 }
63
64 void assign_assuming_AddRef(T* aNewPtr) {
65 T* oldPtr = mRawPtr;
66 mRawPtr = aNewPtr;
67 if (oldPtr) {
68 ConstRemovingRefPtrTraits<T>::Release(oldPtr);
69 }
70 }
71
72 private:
73 T* MOZ_OWNING_REF mRawPtr;
74
75 public:
76 typedef T element_type;
77
78 ~RefPtr() {
79 if (mRawPtr) {
80 ConstRemovingRefPtrTraits<T>::Release(mRawPtr);
81 }
82 }
83
84 // Constructors
85
86 constexpr RefPtr()
87 : mRawPtr(nullptr)
88 // default constructor
89 {}
90
91 RefPtr(const RefPtr<T>& aSmartPtr)
92 : mRawPtr(aSmartPtr.mRawPtr)
93 // copy-constructor
94 {
95 if (mRawPtr) {
96 ConstRemovingRefPtrTraits<T>::AddRef(mRawPtr);
97 }
98 }
99
100 RefPtr(RefPtr<T>&& aRefPtr) noexcept : mRawPtr(aRefPtr.mRawPtr) {
101 aRefPtr.mRawPtr = nullptr;
102 }
103
104 // construct from a raw pointer (of the right type)
105
106 MOZ_IMPLICIT RefPtr(T* aRawPtr) : mRawPtr(aRawPtr) {
107 if (mRawPtr) {
5
Assuming field 'mRawPtr' is non-null
6
Taking true branch
108 ConstRemovingRefPtrTraits<T>::AddRef(mRawPtr);
109 }
110 }
111
112 MOZ_IMPLICIT RefPtr(decltype(nullptr)) : mRawPtr(nullptr) {}
113
114 template <typename I,
115 typename = std::enable_if_t<std::is_convertible_v<I*, T*>>>
116 MOZ_IMPLICIT RefPtr(already_AddRefed<I>& aSmartPtr)
117 : mRawPtr(aSmartPtr.take())
118 // construct from |already_AddRefed|
119 {}
120
121 template <typename I,
122 typename = std::enable_if_t<std::is_convertible_v<I*, T*>>>
123 MOZ_IMPLICIT RefPtr(already_AddRefed<I>&& aSmartPtr)
124 : mRawPtr(aSmartPtr.take())
125 // construct from |otherRefPtr.forget()|
126 {}
127
128 template <typename I,
129 typename = std::enable_if_t<std::is_convertible_v<I*, T*>>>
130 MOZ_IMPLICIT RefPtr(const RefPtr<I>& aSmartPtr)
131 : mRawPtr(aSmartPtr.get())
132 // copy-construct from a smart pointer with a related pointer type
133 {
134 if (mRawPtr) {
135 ConstRemovingRefPtrTraits<T>::AddRef(mRawPtr);
136 }
137 }
138
139 template <typename I,
140 typename = std::enable_if_t<std::is_convertible_v<I*, T*>>>
141 MOZ_IMPLICIT RefPtr(RefPtr<I>&& aSmartPtr)
142 : mRawPtr(aSmartPtr.forget().take())
143 // construct from |Move(RefPtr<SomeSubclassOfT>)|.
144 {}
145
146 template <typename I,
147 typename = std::enable_if_t<!std::is_same_v<I, RefPtr<T>> &&
148 std::is_convertible_v<I, RefPtr<T>>>>
149 MOZ_IMPLICIT RefPtr(const mozilla::NotNull<I>& aSmartPtr)
150 : mRawPtr(RefPtr<T>(aSmartPtr.get()).forget().take())
151 // construct from |mozilla::NotNull|.
152 {}
153
154 template <typename I,
155 typename = std::enable_if_t<!std::is_same_v<I, RefPtr<T>> &&
156 std::is_convertible_v<I, RefPtr<T>>>>
157 MOZ_IMPLICIT RefPtr(mozilla::MovingNotNull<I>&& aSmartPtr)
158 : mRawPtr(RefPtr<T>(std::move(aSmartPtr).unwrapBasePtr()).forget().take())
159 // construct from |mozilla::MovingNotNull|.
160 {}
161
162 MOZ_IMPLICIT RefPtr(const nsQueryReferent& aHelper);
163 MOZ_IMPLICIT RefPtr(const nsCOMPtr_helper& aHelper);
164
165 // Defined in OwningNonNull.h
166 template <class U>
167 MOZ_IMPLICIT RefPtr(const mozilla::OwningNonNull<U>& aOther);
168
169 // Defined in StaticLocalPtr.h
170 template <class U>
171 MOZ_IMPLICIT RefPtr(const mozilla::StaticLocalRefPtr<U>& aOther);
172
173 // Defined in StaticPtr.h
174 template <class U>
175 MOZ_IMPLICIT RefPtr(const mozilla::StaticRefPtr<U>& aOther);
176
177 // Assignment operators
178
179 RefPtr<T>& operator=(decltype(nullptr)) {
180 assign_assuming_AddRef(nullptr);
181 return *this;
182 }
183
184 RefPtr<T>& operator=(const RefPtr<T>& aRhs)
185 // copy assignment operator
186 {
187 assign_with_AddRef(aRhs.mRawPtr);
188 return *this;
189 }
190
191 template <typename I>
192 RefPtr<T>& operator=(const RefPtr<I>& aRhs)
193 // assign from an RefPtr of a related pointer type
194 {
195 assign_with_AddRef(aRhs.get());
196 return *this;
197 }
198
199 RefPtr<T>& operator=(T* aRhs)
200 // assign from a raw pointer (of the right type)
201 {
202 assign_with_AddRef(aRhs);
203 return *this;
204 }
205
206 template <typename I>
207 RefPtr<T>& operator=(already_AddRefed<I>& aRhs)
208 // assign from |already_AddRefed|
209 {
210 assign_assuming_AddRef(aRhs.take());
211 return *this;
212 }
213
214 template <typename I>
215 RefPtr<T>& operator=(already_AddRefed<I>&& aRhs)
216 // assign from |otherRefPtr.forget()|
217 {
218 assign_assuming_AddRef(aRhs.take());
219 return *this;
220 }
221
222 RefPtr<T>& operator=(const nsQueryReferent& aQueryReferent);
223 RefPtr<T>& operator=(const nsCOMPtr_helper& aHelper);
224
225 template <typename I,
226 typename = std::enable_if_t<std::is_convertible_v<I*, T*>>>
227 RefPtr<T>& operator=(RefPtr<I>&& aRefPtr) noexcept {
228 assign_assuming_AddRef(aRefPtr.forget().take());
229 return *this;
230 }
231
232 template <typename I,
233 typename = std::enable_if_t<std::is_convertible_v<I, RefPtr<T>>>>
234 RefPtr<T>& operator=(const mozilla::NotNull<I>& aSmartPtr)
235 // assign from |mozilla::NotNull|.
236 {
237 assign_assuming_AddRef(RefPtr<T>(aSmartPtr.get()).forget().take());
238 return *this;
239 }
240
241 template <typename I,
242 typename = std::enable_if_t<std::is_convertible_v<I, RefPtr<T>>>>
243 RefPtr<T>& operator=(mozilla::MovingNotNull<I>&& aSmartPtr)
244 // assign from |mozilla::MovingNotNull|.
245 {
246 assign_assuming_AddRef(
247 RefPtr<T>(std::move(aSmartPtr).unwrapBasePtr()).forget().take());
248 return *this;
249 }
250
251 // Defined in OwningNonNull.h
252 template <class U>
253 RefPtr<T>& operator=(const mozilla::OwningNonNull<U>& aOther);
254
255 // Defined in StaticLocalPtr.h
256 template <class U>
257 RefPtr<T>& operator=(const mozilla::StaticLocalRefPtr<U>& aOther);
258
259 // Defined in StaticPtr.h
260 template <class U>
261 RefPtr<T>& operator=(const mozilla::StaticRefPtr<U>& aOther);
262
263 // Other pointer operators
264
265 void swap(RefPtr<T>& aRhs)
266 // ...exchange ownership with |aRhs|; can save a pair of refcount operations
267 {
268 T* temp = aRhs.mRawPtr;
269 aRhs.mRawPtr = mRawPtr;
270 mRawPtr = temp;
271 }
272
273 void swap(T*& aRhs)
274 // ...exchange ownership with |aRhs|; can save a pair of refcount operations
275 {
276 T* temp = aRhs;
277 aRhs = mRawPtr;
278 mRawPtr = temp;
279 }
280
281 already_AddRefed<T> MOZ_MAY_CALL_AFTER_MUST_RETURN forget()
282 // return the value of mRawPtr and null out mRawPtr. Useful for
283 // already_AddRefed return values.
284 {
285 T* temp = nullptr;
286 swap(temp);
287 return already_AddRefed<T>(temp);
21
Use of memory after it is freed
288 }
289
290 template <typename I>
291 void forget(I** aRhs)
292 // Set the target of aRhs to the value of mRawPtr and null out mRawPtr.
293 // Useful to avoid unnecessary AddRef/Release pairs with "out"
294 // parameters where aRhs bay be a T** or an I** where I is a base class
295 // of T.
296 {
297 MOZ_ASSERT(aRhs, "Null pointer passed to forget!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRhs)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aRhs))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aRhs" " (" "Null pointer passed to forget!"
")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/RefPtr.h"
, 297); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRhs" ") (" "Null pointer passed to forget!"
")"); do { MOZ_CrashSequence(__null, 297); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
298 *aRhs = mRawPtr;
299 mRawPtr = nullptr;
300 }
301
302 void forget(nsISupports** aRhs) {
303 MOZ_ASSERT(aRhs, "Null pointer passed to forget!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aRhs)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(aRhs))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("aRhs" " (" "Null pointer passed to forget!"
")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/RefPtr.h"
, 303); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aRhs" ") (" "Null pointer passed to forget!"
")"); do { MOZ_CrashSequence(__null, 303); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
304 *aRhs = ToSupports(mRawPtr);
305 mRawPtr = nullptr;
306 }
307
308 T* get() const
309 /*
310 Prefer the implicit conversion provided automatically by |operator T*()
311 const|. Use |get()| to resolve ambiguity or to get a castable pointer.
312 */
313 {
314 return const_cast<T*>(mRawPtr);
315 }
316
317 operator T*() const&
318 /*
319 ...makes an |RefPtr| act like its underlying raw pointer type whenever it
320 is used in a context where a raw pointer is expected. It is this operator
321 that makes an |RefPtr| substitutable for a raw pointer.
322
323 Prefer the implicit use of this operator to calling |get()|, except where
324 necessary to resolve ambiguity.
325 */
326 {
327 return get();
328 }
329
330 // Don't allow implicit conversion of temporary RefPtr to raw pointer,
331 // because the refcount might be one and the pointer will immediately become
332 // invalid.
333 operator T*() const&& = delete;
334
335 // These are needed to avoid the deleted operator above. XXX Why is operator!
336 // needed separately? Shouldn't the compiler prefer using the non-deleted
337 // operator bool instead of the deleted operator T*?
338 explicit operator bool() const { return !!mRawPtr; }
339 bool operator!() const { return !mRawPtr; }
340
341 T* operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN {
342 MOZ_ASSERT(mRawPtr != nullptr,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mRawPtr != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mRawPtr != nullptr))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mRawPtr != nullptr"
" (" "You can't dereference a NULL RefPtr with operator->()."
")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/RefPtr.h"
, 343); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRawPtr != nullptr"
") (" "You can't dereference a NULL RefPtr with operator->()."
")"); do { MOZ_CrashSequence(__null, 343); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
343 "You can't dereference a NULL RefPtr with operator->().")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mRawPtr != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mRawPtr != nullptr))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mRawPtr != nullptr"
" (" "You can't dereference a NULL RefPtr with operator->()."
")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/RefPtr.h"
, 343); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRawPtr != nullptr"
") (" "You can't dereference a NULL RefPtr with operator->()."
")"); do { MOZ_CrashSequence(__null, 343); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
344 return get();
345 }
346
347 template <typename R, typename... Args>
348 class Proxy {
349 typedef R (T::*member_function)(Args...);
350 T* mRawPtr;
351 member_function mFunction;
352
353 public:
354 Proxy(T* aRawPtr, member_function aFunction)
355 : mRawPtr(aRawPtr), mFunction(aFunction) {}
356 template <typename... ActualArgs>
357 R operator()(ActualArgs&&... aArgs) {
358 return ((*mRawPtr).*mFunction)(std::forward<ActualArgs>(aArgs)...);
359 }
360 };
361
362 template <typename R, typename... Args>
363 Proxy<R, Args...> operator->*(R (T::*aFptr)(Args...)) const {
364 MOZ_ASSERT(mRawPtr != nullptr,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mRawPtr != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mRawPtr != nullptr))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mRawPtr != nullptr"
" (" "You can't dereference a NULL RefPtr with operator->*()."
")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/RefPtr.h"
, 365); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRawPtr != nullptr"
") (" "You can't dereference a NULL RefPtr with operator->*()."
")"); do { MOZ_CrashSequence(__null, 365); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
365 "You can't dereference a NULL RefPtr with operator->*().")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mRawPtr != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mRawPtr != nullptr))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mRawPtr != nullptr"
" (" "You can't dereference a NULL RefPtr with operator->*()."
")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/RefPtr.h"
, 365); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRawPtr != nullptr"
") (" "You can't dereference a NULL RefPtr with operator->*()."
")"); do { MOZ_CrashSequence(__null, 365); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
366 return Proxy<R, Args...>(get(), aFptr);
367 }
368
369 RefPtr<T>* get_address()
370 // This is not intended to be used by clients. See |address_of|
371 // below.
372 {
373 return this;
374 }
375
376 const RefPtr<T>* get_address() const
377 // This is not intended to be used by clients. See |address_of|
378 // below.
379 {
380 return this;
381 }
382
383 public:
384 T& operator*() const {
385 MOZ_ASSERT(mRawPtr != nullptr,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mRawPtr != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mRawPtr != nullptr))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mRawPtr != nullptr"
" (" "You can't dereference a NULL RefPtr with operator*()."
")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/RefPtr.h"
, 386); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRawPtr != nullptr"
") (" "You can't dereference a NULL RefPtr with operator*()."
")"); do { MOZ_CrashSequence(__null, 386); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
386 "You can't dereference a NULL RefPtr with operator*().")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mRawPtr != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mRawPtr != nullptr))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("mRawPtr != nullptr"
" (" "You can't dereference a NULL RefPtr with operator*()."
")", "/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/RefPtr.h"
, 386); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mRawPtr != nullptr"
") (" "You can't dereference a NULL RefPtr with operator*()."
")"); do { MOZ_CrashSequence(__null, 386); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
387 return *get();
388 }
389
390 T** StartAssignment() {
391 assign_assuming_AddRef(nullptr);
392 return reinterpret_cast<T**>(&mRawPtr);
393 }
394
395 private:
396 // This helper class makes |RefPtr<const T>| possible by casting away
397 // the constness from the pointer when calling AddRef() and Release().
398 //
399 // This is necessary because AddRef() and Release() implementations can't
400 // generally expected to be const themselves (without heavy use of |mutable|
401 // and |const_cast| in their own implementations).
402 //
403 // This should be sound because while |RefPtr<const T>| provides a
404 // const view of an object, the object itself should not be const (it
405 // would have to be allocated as |new const T| or similar to be const).
406 template <class U>
407 struct ConstRemovingRefPtrTraits {
408 static void AddRef(U* aPtr) { mozilla::RefPtrTraits<U>::AddRef(aPtr); }
409 static void Release(U* aPtr) { mozilla::RefPtrTraits<U>::Release(aPtr); }
410 };
411 template <class U>
412 struct ConstRemovingRefPtrTraits<const U> {
413 static void AddRef(const U* aPtr) {
414 mozilla::RefPtrTraits<U>::AddRef(const_cast<U*>(aPtr));
415 }
416 static void Release(const U* aPtr) {
417 mozilla::RefPtrTraits<U>::Release(const_cast<U*>(aPtr));
418 }
419 };
420};
421
422class nsCycleCollectionTraversalCallback;
423template <typename T>
424void CycleCollectionNoteChild(nsCycleCollectionTraversalCallback& aCallback,
425 T* aChild, const char* aName, uint32_t aFlags);
426
427template <typename T>
428inline void ImplCycleCollectionUnlink(RefPtr<T>& aField) {
429 aField = nullptr;
430}
431
432template <typename T>
433inline void ImplCycleCollectionTraverse(
434 nsCycleCollectionTraversalCallback& aCallback, const RefPtr<T>& aField,
435 const char* aName, uint32_t aFlags = 0) {
436 CycleCollectionNoteChild(aCallback, aField.get(), aName, aFlags);
437}
438
439template <class T>
440inline RefPtr<T>* address_of(RefPtr<T>& aPtr) {
441 return aPtr.get_address();
442}
443
444template <class T>
445inline const RefPtr<T>* address_of(const RefPtr<T>& aPtr) {
446 return aPtr.get_address();
447}
448
449template <class T>
450class RefPtrGetterAddRefs
451/*
452 ...
453
454 This class is designed to be used for anonymous temporary objects in the
455 argument list of calls that return COM interface pointers, e.g.,
456
457 RefPtr<IFoo> fooP;
458 ...->GetAddRefedPointer(getter_AddRefs(fooP))
459
460 DO NOT USE THIS TYPE DIRECTLY IN YOUR CODE. Use |getter_AddRefs()| instead.
461
462 When initialized with a |RefPtr|, as in the example above, it returns
463 a |void**|, a |T**|, or an |nsISupports**| as needed, that the
464 outer call (|GetAddRefedPointer| in this case) can fill in.
465
466 This type should be a nested class inside |RefPtr<T>|.
467*/
468{
469 public:
470 explicit RefPtrGetterAddRefs(RefPtr<T>& aSmartPtr)
471 : mTargetSmartPtr(aSmartPtr) {
472 // nothing else to do
473 }
474
475 operator void**() {
476 return reinterpret_cast<void**>(mTargetSmartPtr.StartAssignment());
477 }
478
479 operator T**() { return mTargetSmartPtr.StartAssignment(); }
480
481 T*& operator*() { return *(mTargetSmartPtr.StartAssignment()); }
482
483 private:
484 RefPtr<T>& mTargetSmartPtr;
485};
486
487template <class T>
488inline RefPtrGetterAddRefs<T> getter_AddRefs(RefPtr<T>& aSmartPtr)
489/*
490 Used around a |RefPtr| when
491 ...makes the class |RefPtrGetterAddRefs<T>| invisible.
492*/
493{
494 return RefPtrGetterAddRefs<T>(aSmartPtr);
495}
496
497// Comparing two |RefPtr|s
498
499template <class T, class U>
500inline bool operator==(const RefPtr<T>& aLhs, const RefPtr<U>& aRhs) {
501 return static_cast<const T*>(aLhs.get()) == static_cast<const U*>(aRhs.get());
502}
503
504template <class T, class U>
505inline bool operator!=(const RefPtr<T>& aLhs, const RefPtr<U>& aRhs) {
506 return static_cast<const T*>(aLhs.get()) != static_cast<const U*>(aRhs.get());
507}
508
509// Comparing an |RefPtr| to a raw pointer
510
511template <class T, class U>
512inline bool operator==(const RefPtr<T>& aLhs, const U* aRhs) {
513 return static_cast<const T*>(aLhs.get()) == static_cast<const U*>(aRhs);
514}
515
516template <class T, class U>
517inline bool operator==(const U* aLhs, const RefPtr<T>& aRhs) {
518 return static_cast<const U*>(aLhs) == static_cast<const T*>(aRhs.get());
519}
520
521template <class T, class U>
522inline bool operator!=(const RefPtr<T>& aLhs, const U* aRhs) {
523 return static_cast<const T*>(aLhs.get()) != static_cast<const U*>(aRhs);
524}
525
526template <class T, class U>
527inline bool operator!=(const U* aLhs, const RefPtr<T>& aRhs) {
528 return static_cast<const U*>(aLhs) != static_cast<const T*>(aRhs.get());
529}
530
531template <class T, class U>
532inline bool operator==(const RefPtr<T>& aLhs, U* aRhs) {
533 return static_cast<const T*>(aLhs.get()) == const_cast<const U*>(aRhs);
534}
535
536template <class T, class U>
537inline bool operator==(U* aLhs, const RefPtr<T>& aRhs) {
538 return const_cast<const U*>(aLhs) == static_cast<const T*>(aRhs.get());
539}
540
541template <class T, class U>
542inline bool operator!=(const RefPtr<T>& aLhs, U* aRhs) {
543 return static_cast<const T*>(aLhs.get()) != const_cast<const U*>(aRhs);
544}
545
546template <class T, class U>
547inline bool operator!=(U* aLhs, const RefPtr<T>& aRhs) {
548 return const_cast<const U*>(aLhs) != static_cast<const T*>(aRhs.get());
549}
550
551// Comparing an |RefPtr| to |nullptr|
552
553template <class T>
554inline bool operator==(const RefPtr<T>& aLhs, decltype(nullptr)) {
555 return aLhs.get() == nullptr;
556}
557
558template <class T>
559inline bool operator==(decltype(nullptr), const RefPtr<T>& aRhs) {
560 return nullptr == aRhs.get();
561}
562
563template <class T>
564inline bool operator!=(const RefPtr<T>& aLhs, decltype(nullptr)) {
565 return aLhs.get() != nullptr;
566}
567
568template <class T>
569inline bool operator!=(decltype(nullptr), const RefPtr<T>& aRhs) {
570 return nullptr != aRhs.get();
571}
572
573// MOZ_DBG support
574
575template <class T>
576std::ostream& operator<<(std::ostream& aOut, const RefPtr<T>& aObj) {
577 return mozilla::DebugValue(aOut, aObj.get());
578}
579
580/*****************************************************************************/
581
582template <class T>
583inline already_AddRefed<T> do_AddRef(T* aObj) {
584 RefPtr<T> ref(aObj);
585 return ref.forget();
586}
587
588template <class T>
589inline already_AddRefed<T> do_AddRef(const RefPtr<T>& aObj) {
590 RefPtr<T> ref(aObj);
591 return ref.forget();
592}
593
594namespace mozilla {
595
596template <typename T>
597class AlignmentFinder;
598
599// Provide a specialization of AlignmentFinder to allow MOZ_ALIGNOF(RefPtr<T>)
600// with an incomplete T.
601template <typename T>
602class AlignmentFinder<RefPtr<T>> {
603 public:
604 static const size_t alignment = alignof(T*);
605};
606
607/**
608 * Helper function to be able to conveniently write things like:
609 *
610 * already_AddRefed<T>
611 * f(...)
612 * {
613 * return MakeAndAddRef<T>(...);
614 * }
615 */
616template <typename T, typename... Args>
617already_AddRefed<T> MakeAndAddRef(Args&&... aArgs) {
618 RefPtr<T> p(new T(std::forward<Args>(aArgs)...));
619 return p.forget();
620}
621
622/**
623 * Helper function to be able to conveniently write things like:
624 *
625 * auto runnable =
626 * MakeRefPtr<ErrorCallbackRunnable<nsIDOMGetUserMediaSuccessCallback>>(
627 * mOnSuccess, mOnFailure, *error, mWindowID);
628 */
629template <typename T, typename... Args>
630RefPtr<T> MakeRefPtr(Args&&... aArgs) {
631 RefPtr<T> p(new T(std::forward<Args>(aArgs)...));
632 return p;
633}
634
635} // namespace mozilla
636
637/**
638 * Deduction guide to allow simple `RefPtr` definitions from an
639 * already_AddRefed<T> without repeating the type, e.g.:
640 *
641 * RefPtr ptr = MakeAndAddRef<SomeType>(...);
642 */
643template <typename T>
644RefPtr(already_AddRefed<T>) -> RefPtr<T>;
645
646#endif /* mozilla_RefPtr_h */

/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/layers/TextureClient.h

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

/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/cxxalloc.h

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5#ifndef mozilla_cxxalloc_h
6#define mozilla_cxxalloc_h
7
8/*
9 * We implement the default operators new/delete as part of
10 * libmozalloc, replacing their definitions in libstdc++. The
11 * operator new* definitions in libmozalloc will never return a NULL
12 * pointer.
13 *
14 * Each operator new immediately below returns a pointer to memory
15 * that can be delete'd by any of
16 *
17 * (1) the matching infallible operator delete immediately below
18 * (2) the matching system |operator delete(void*, std::nothrow)|
19 * (3) the matching system |operator delete(void*) noexcept(false)|
20 *
21 * NB: these are declared |noexcept(false)|, though they will never
22 * throw that exception. This declaration is consistent with the rule
23 * that |::operator new() noexcept(false)| will never return NULL.
24 *
25 * NB: mozilla::fallible can be used instead of std::nothrow.
26 */
27
28#ifndef MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline
29# define MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline MFBT_API__attribute__((weak)) __attribute__((visibility("default")))
30#endif
31
32MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void* operator new(size_t size) noexcept(false) {
33 return moz_xmalloc(size);
34}
35
36MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void* operator new(size_t size,
37 const std::nothrow_t&) noexcept(true) {
38 return malloc_implmalloc(size);
39}
40
41MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void* operator new[](size_t size) noexcept(false) {
42 return moz_xmalloc(size);
43}
44
45// Inlining `new` like this is technically against C++ spec, but we crave perf.
46MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void* operator new[](size_t size,
47 const std::nothrow_t&) noexcept(true) {
48#ifdef __GNUC__4
49// GCC-14 codegen at -O2 causes false positive due to converting
50// `new A[n]` to `malloc(-1)` when `n > PTRDIFF_MAX/sizeof(A)`.
51// (See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85783, WONTFIX'd)
52# pragma GCC diagnostic push
53# pragma GCC diagnostic ignored "-Walloc-size-larger-than="
54#endif
55
56 return malloc_implmalloc(size);
57
58#ifdef __GNUC__4
59# pragma GCC diagnostic pop
60#endif
61}
62
63MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void operator delete(void* ptr) noexcept(true) {
64 return free_implfree(ptr);
17
Memory is released
65}
66
67MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void operator delete(void* ptr,
68 const std::nothrow_t&) noexcept(true) {
69 return free_implfree(ptr);
70}
71
72MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void operator delete[](void* ptr) noexcept(true) {
73 return free_implfree(ptr);
74}
75
76MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void operator delete[](
77 void* ptr, const std::nothrow_t&) noexcept(true) {
78 return free_implfree(ptr);
79}
80
81#if defined(XP_WIN)
82// We provide the global sized delete overloads unconditionally because the
83// MSVC runtime headers do, despite compiling with /Zc:sizedDealloc-
84MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void operator delete(void* ptr,
85 size_t /*size*/) noexcept(true) {
86 return free_implfree(ptr);
87}
88
89MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void operator delete[](void* ptr,
90 size_t /*size*/) noexcept(true) {
91 return free_implfree(ptr);
92}
93#endif
94
95#endif /* mozilla_cxxalloc_h */