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 released

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -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-23/lib/clang/23 -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 -D _GLIBCXX_ASSERTIONS=1 -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D GOOGLE_PROTOBUF_NO_RTTI -D GOOGLE_PROTOBUF_NO_STATIC_INITIALIZER -D MOZ_APP_VERSION=157.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/third_party/abseil-cpp -I /root/firefox-clang/toolkit/components/telemetry -I /root/firefox-clang/xpcom/base -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/third_party/drm/drm/include -I /root/firefox-clang/third_party/drm/drm/include/libdrm -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/unix-print -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cloudproviders -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/fribidi -I /usr/include/harfbuzz -I /usr/include/atk-1.0 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/glycin-2 -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/gio-unix-2.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/x86_64-linux-gnu/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16/backward -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -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-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 -Wno-character-conversion -std=gnu++20 -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 -fno-implicit-modules -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-09-01-224014-2642839-1 -x c++ /root/firefox-clang/gfx/layers/client/TextureClient.cpp

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

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

/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/RefPtr.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_RefPtr_h
6#define mozilla_RefPtr_h
7
8#include <fmt/ostream.h>
9
10#include <type_traits>
11
12#include "mozilla/AlreadyAddRefed.h"
13#include "mozilla/Assertions.h"
14#include "mozilla/Attributes.h"
15#include "mozilla/DbgMacro.h" // for mozilla::DebugValue
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 MOZ_NULL_AFTER_MOVE[[clang::annotate("clang-tidy", "bugprone-use-after-move", "null_after_move"
)]]
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 constexpr RefPtr(std::nullptr_t) : 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 released
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
580template <typename T>
581struct fmt::formatter<RefPtr<T>> : fmt::ostream_formatter {};
582
583/*****************************************************************************/
584
585template <class T>
586inline already_AddRefed<T> do_AddRef(T* aObj) {
587 RefPtr<T> ref(aObj);
588 return ref.forget();
589}
590
591template <class T>
592inline already_AddRefed<T> do_AddRef(const RefPtr<T>& aObj) {
593 RefPtr<T> ref(aObj);
594 return ref.forget();
595}
596
597namespace mozilla {
598/**
599 * Helper function to be able to conveniently write things like:
600 *
601 * already_AddRefed<T>
602 * f(...)
603 * {
604 * return MakeAndAddRef<T>(...);
605 * }
606 */
607template <typename T, typename... Args>
608already_AddRefed<T> MakeAndAddRef(Args&&... aArgs) {
609 RefPtr<T> p(new T(std::forward<Args>(aArgs)...));
610 return p.forget();
611}
612
613/**
614 * Helper function to be able to conveniently write things like:
615 *
616 * auto runnable =
617 * MakeRefPtr<ErrorCallbackRunnable<nsIDOMGetUserMediaSuccessCallback>>(
618 * mOnSuccess, mOnFailure, *error, mWindowID);
619 */
620template <typename T, typename... Args>
621RefPtr<T> MakeRefPtr(Args&&... aArgs) {
622 RefPtr<T> p(new T(std::forward<Args>(aArgs)...));
623 return p;
624}
625
626} // namespace mozilla
627
628/**
629 * Deduction guide to allow simple `RefPtr` definitions from an
630 * already_AddRefed<T> without repeating the type, e.g.:
631 *
632 * RefPtr ptr = MakeAndAddRef<SomeType>(...);
633 */
634template <typename T>
635RefPtr(already_AddRefed<T>) -> RefPtr<T>;
636
637#endif /* mozilla_RefPtr_h */

/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/layers/TextureClient.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_GFX_TEXTURECLIENT_H
6#define MOZILLA_GFX_TEXTURECLIENT_H
7
8#include <stddef.h> // for size_t
9#include <stdint.h> // for uint32_t, uint8_t, uint64_t
10
11#include "GLTextureImage.h" // for TextureImage
12#include "GfxTexturesReporter.h"
13#include "ImageTypes.h" // for StereoMode
14#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
15#include "mozilla/Atomics.h"
16#include "mozilla/Attributes.h" // for override
17#include "mozilla/Mutex.h"
18#include "mozilla/RefPtr.h" // for RefPtr, RefCounted
19#include "mozilla/UniquePtrExtensions.h" // for UniqueFileHandle
20#include "mozilla/dom/ipc/IdType.h"
21#include "mozilla/gfx/2D.h" // for DrawTarget
22#include "mozilla/gfx/CriticalSection.h"
23#include "mozilla/gfx/Point.h" // for IntSize
24#include "mozilla/gfx/Types.h" // for SurfaceFormat
25#include "mozilla/ipc/Shmem.h" // for Shmem
26#include "mozilla/layers/AtomicRefCountedWithFinalize.h"
27#include "mozilla/layers/CompositorTypes.h" // for TextureFlags, etc
28#include "mozilla/layers/ISurfaceAllocator.h"
29#include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor
30#include "mozilla/layers/LayersTypes.h"
31#include "mozilla/layers/PTextureChild.h" // for PTextureChild
32#include "mozilla/layers/SyncObject.h"
33#include "mozilla/mozalloc.h" // for operator delete
34#include "mozilla/webrender/WebRenderTypes.h"
35#include "nsCOMPtr.h" // for already_AddRefed
36#include "nsISupportsImpl.h" // for TextureImage::AddRef, etc
37#include "nsThreadUtils.h"
38#include "pratom.h"
39
40class gfxImageSurface;
41struct ID3D11Device;
42
43namespace mozilla {
44
45namespace layers {
46
47class AndroidHardwareBufferTextureData;
48class BufferTextureData;
49class CompositableForwarder;
50class FwdTransactionTracker;
51class KnowsCompositor;
52class LayersIPCChannel;
53class CompositableClient;
54struct PlanarYCbCrData;
55class Image;
56class PTextureChild;
57class TextureChild;
58class TextureData;
59class GPUVideoTextureData;
60class TextureClient;
61class ITextureClientRecycleAllocator;
62class SharedSurfaceTextureData;
63class TextureForwarder;
64class ImageBridgeChild;
65class RecordedTextureData;
66struct RemoteTextureOwnerId;
67
68/**
69 * TextureClient is the abstraction that allows us to share data between the
70 * content and the compositor side.
71 */
72
73enum TextureAllocationFlags {
74 ALLOC_DEFAULT = 0,
75 ALLOC_CLEAR_BUFFER =
76 1 << 1, // Clear the buffer to whatever is best for the draw target
77 ALLOC_CLEAR_BUFFER_WHITE = 1 << 2, // explicit all white
78 ALLOC_CLEAR_BUFFER_BLACK = 1 << 3, // explicit all black
79 ALLOC_DISALLOW_BUFFERTEXTURECLIENT = 1 << 4,
80
81 // Allocate the texture for out-of-band content updates. This is mostly for
82 // TextureClientD3D11, which may otherwise choose D3D10 or non-KeyedMutex
83 // surfaces when used on the main thread.
84 ALLOC_FOR_OUT_OF_BAND_CONTENT = 1 << 5,
85
86 // Disable any cross-device synchronization. This is also for
87 // TextureClientD3D11, and creates a texture without KeyedMutex.
88 ALLOC_MANUAL_SYNCHRONIZATION = 1 << 6,
89
90 // The texture is going to be updated using UpdateFromSurface and needs to
91 // support that call.
92 ALLOC_UPDATE_FROM_SURFACE = 1 << 7,
93
94 // Do not use an accelerated texture type.
95 ALLOC_DO_NOT_ACCELERATE = 1 << 8,
96
97 // Force allocation of remote/recorded texture, or fail if not possible.
98 ALLOC_FORCE_REMOTE = 1 << 9,
99
100 // Prefer to use keyed mutex than D3D11Fence on Windows
101 USE_D3D11_KEYED_MUTEX = 1 << 10,
102};
103
104enum class BackendSelector { Content, Canvas };
105
106/// Temporary object providing direct access to a Texture's memory.
107///
108/// see TextureClient::CanExposeMappedData() and
109/// TextureClient::BorrowMappedData().
110struct MappedTextureData {
111 uint8_t* data;
112 gfx::IntSize size;
113 int32_t stride;
114 gfx::SurfaceFormat format;
115};
116
117struct MappedYCbCrChannelData {
118 uint8_t* data;
119 gfx::IntSize size;
120 int32_t stride;
121 int32_t skip;
122 uint32_t bytesPerPixel;
123
124 bool CopyInto(MappedYCbCrChannelData& aDst);
125};
126
127struct MappedYCbCrTextureData {
128 MappedYCbCrChannelData y;
129 MappedYCbCrChannelData cb;
130 MappedYCbCrChannelData cr;
131 // Sad but because of how SharedPlanarYCbCrData is used we have to expose this
132 // for now.
133 uint8_t* metadata;
134 StereoMode stereoMode;
135
136 bool CopyInto(MappedYCbCrTextureData& aDst) {
137 return y.CopyInto(aDst.y) && cb.CopyInto(aDst.cb) && cr.CopyInto(aDst.cr);
138 }
139};
140
141class ReadLockDescriptor;
142class NonBlockingTextureReadLock;
143
144// A class to help implement copy-on-write semantics for shared textures.
145//
146// A TextureClient/Host pair can opt into using a ReadLock by calling
147// TextureClient::EnableReadLock. This will equip the TextureClient with a
148// ReadLock object that will be automatically ReadLock()'ed by the texture
149// itself when it is written into (see TextureClient::Unlock). A
150// TextureReadLock's counter starts at 1 and is expected to be equal to 1 when
151// the lock is destroyed. See ShmemTextureReadLock for explanations about why we
152// use 1 instead of 0 as the initial state. TextureReadLock is mostly internally
153// managed by the TextureClient/Host pair, and the compositable only has to
154// forward it during updates. If an update message contains a null_t lock, it
155// means that the texture was not written into on the content side, and there is
156// no synchronization required on the compositor side (or it means that the
157// texture pair did not opt into using ReadLocks). On the compositor side, the
158// TextureHost can receive a ReadLock during a transaction, and will both
159// ReadUnlock() it and drop it as soon as the shared data is available again for
160// writing (the texture upload is done, or the compositor not reading the
161// texture anymore). The lock is dropped to make sure it is ReadUnlock()'ed only
162// once.
163class TextureReadLock {
164 protected:
165 virtual ~TextureReadLock() = default;
166
167 public:
168 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"
, 168); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 168
); __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"
, 168); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 168
); __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'
169
170 virtual bool ReadLock() = 0;
171 virtual bool TryReadLock(TimeDuration aTimeout) { return ReadLock(); }
172 virtual int32_t ReadUnlock() = 0;
173 virtual bool IsValid() const = 0;
174
175 static already_AddRefed<TextureReadLock> Deserialize(
176 ReadLockDescriptor&& aDescriptor, ISurfaceAllocator* aAllocator);
177
178 virtual bool Serialize(ReadLockDescriptor& aOutput,
179 base::ProcessId aOther) = 0;
180
181 enum LockType {
182 TYPE_NONBLOCKING_MEMORY,
183 TYPE_NONBLOCKING_SHMEM,
184 TYPE_CROSS_PROCESS_SEMAPHORE
185 };
186 virtual LockType GetType() = 0;
187
188 virtual NonBlockingTextureReadLock* AsNonBlockingLock() { return nullptr; }
189};
190
191class NonBlockingTextureReadLock : public TextureReadLock {
192 public:
193 virtual int32_t GetReadCount() = 0;
194
195 static already_AddRefed<TextureReadLock> Create(LayersIPCChannel* aAllocator);
196
197 NonBlockingTextureReadLock* AsNonBlockingLock() override { return this; }
198};
199
200#ifdef XP_WIN
201class D3D11TextureData;
202class DXGIYCbCrTextureData;
203#endif
204
205class TextureData {
206 public:
207 struct Info {
208 gfx::IntSize size;
209 gfx::SurfaceFormat format;
210 bool hasSynchronization;
211 bool supportsMoz2D;
212 bool canExposeMappedData;
213 bool canConcurrentlyReadLock;
214
215 Info()
216 : format(gfx::SurfaceFormat::UNKNOWN),
217 hasSynchronization(false),
218 supportsMoz2D(false),
219 canExposeMappedData(false),
220 canConcurrentlyReadLock(true) {}
221 };
222
223 static TextureData* Create(
224 TextureType aTextureType, gfx::SurfaceFormat aFormat,
225 const gfx::IntSize& aSize, TextureAllocationFlags aAllocFlags,
226 gfx::BackendType aBackendType = gfx::BackendType::NONE);
227 static TextureData* Create(TextureForwarder* aAllocator,
228 gfx::SurfaceFormat aFormat, gfx::IntSize aSize,
229 KnowsCompositor* aKnowsCompositor,
230 BackendSelector aSelector,
231 TextureFlags aTextureFlags,
232 TextureAllocationFlags aAllocFlags);
233
234 static bool IsRemote(KnowsCompositor* aKnowsCompositor,
235 BackendSelector aSelector,
236 gfx::SurfaceFormat aFormat = gfx::SurfaceFormat::UNKNOWN,
237 gfx::IntSize aSize = gfx::IntSize(1, 1));
238
239 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_v<nsISupports, TextureData
>, "nsISupports classes don't need to call MOZ_COUNT_CTOR or "
"MOZ_COUNT_DTOR");; NS_LogDtor((void*)this, "TextureData", sizeof
(*this)); } while (0); }
240
241 virtual TextureType GetTextureType() const { return TextureType::Last; }
242
243 virtual void FillInfo(TextureData::Info& aInfo) const = 0;
244
245 virtual void InvalidateContents() {}
246
247 virtual bool Lock(OpenMode aMode) = 0;
248
249 virtual void Unlock() = 0;
250
251 virtual already_AddRefed<gfx::DrawTarget> BorrowDrawTarget() {
252 return nullptr;
253 }
254
255 virtual void ReturnDrawTarget(already_AddRefed<gfx::DrawTarget> aDT);
256
257 /**
258 * When the TextureData is not being Unlocked, this can be used to inform a
259 * TextureData that drawing has finished until the next BorrowDrawTarget.
260 */
261 virtual void EndDraw() {}
262
263 virtual already_AddRefed<gfx::SourceSurface> BorrowSnapshot() {
264 return nullptr;
265 }
266
267 virtual void ReturnSnapshot(already_AddRefed<gfx::SourceSurface> aSnapshot);
268
269 virtual bool BorrowMappedData(MappedTextureData&) { return false; }
270
271 virtual bool BorrowMappedYCbCrData(MappedYCbCrTextureData&) { return false; }
272
273 virtual void Deallocate(LayersIPCChannel* aAllocator) = 0;
274
275 /// Depending on the texture's flags either Deallocate or Forget is called.
276 virtual void Forget(LayersIPCChannel* aAllocator) {}
277
278 virtual bool Serialize(SurfaceDescriptor& aDescriptor) = 0;
279 virtual void GetSubDescriptor(RemoteDecoderVideoSubDescriptor* aOutDesc) {}
280
281 virtual void OnForwardedToHost() {}
282
283 virtual TextureData* CreateSimilar(
284 LayersIPCChannel* aAllocator, LayersBackend aLayersBackend,
285 TextureFlags aFlags = TextureFlags::DEFAULT,
286 TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const {
287 return nullptr;
288 }
289
290 virtual bool UpdateFromSurface(gfx::SourceSurface* aSurface) {
291 return false;
292 };
293
294 virtual void SyncWithObject(RefPtr<SyncObjectClient> aSyncObject) {};
295
296 virtual TextureFlags GetTextureFlags() const {
297 return TextureFlags::NO_FLAGS;
298 }
299
300#ifdef XP_WIN
301 virtual D3D11TextureData* AsD3D11TextureData() { return nullptr; }
302 virtual DXGIYCbCrTextureData* AsDXGIYCbCrTextureData() { return nullptr; }
303#endif
304
305 virtual BufferTextureData* AsBufferTextureData() { return nullptr; }
306
307 virtual GPUVideoTextureData* AsGPUVideoTextureData() { return nullptr; }
308
309 virtual AndroidHardwareBufferTextureData*
310 AsAndroidHardwareBufferTextureData() {
311 return nullptr;
312 }
313
314 virtual RecordedTextureData* AsRecordedTextureData() { return nullptr; }
315
316 // It is used by AndroidHardwareBufferTextureData and
317 // SharedSurfaceTextureData. Returns buffer id when it owns
318 // AndroidHardwareBuffer. It is used only on android.
319 virtual Maybe<uint64_t> GetBufferId() const { return Nothing(); }
320
321 // The acquire fence is a fence that is used for waiting until rendering to
322 // its AHardwareBuffer is completed.
323 // It is used only on android.
324 virtual UniqueFileHandle GetAcquireFence() { return UniqueFileHandle(); }
325
326 virtual bool RequiresRefresh() const { return false; }
327
328 virtual already_AddRefed<FwdTransactionTracker> UseCompositableForwarder(
329 CompositableForwarder* aForwarder) {
330 return nullptr;
331 }
332
333 protected:
334 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_v<nsISupports, TextureData>, "nsISupports classes don't need to call MOZ_COUNT_CTOR or "
"MOZ_COUNT_DTOR");; NS_LogCtor((void*)this, "TextureData", sizeof
(*this)); } while (0); }
335};
336
337/**
338 * TextureClient is a thin abstraction over texture data that need to be shared
339 * between the content process and the compositor process. It is the
340 * content-side half of a TextureClient/TextureHost pair. A corresponding
341 * TextureHost lives on the compositor-side.
342 *
343 * TextureClient's primary purpose is to present texture data in a way that is
344 * understood by the IPC system. There are two ways to use it:
345 * - Use it to serialize image data that is not IPC-friendly (most likely
346 * involving a copy into shared memory)
347 * - preallocate it and paint directly into it, which avoids copy but requires
348 * the painting code to be aware of TextureClient (or at least the underlying
349 * shared memory).
350 *
351 * There is always one and only one TextureClient per TextureHost, and the
352 * TextureClient/Host pair only owns one buffer of image data through its
353 * lifetime. This means that the lifetime of the underlying shared data
354 * matches the lifetime of the TextureClient/Host pair. It also means
355 * TextureClient/Host do not implement double buffering, which is the
356 * responsibility of the compositable (which would use pairs of Textures).
357 * In order to send several different buffers to the compositor side, use
358 * several TextureClients.
359 */
360class TextureClient : public AtomicRefCountedWithFinalize<TextureClient> {
361 public:
362 TextureClient(TextureData* aData, TextureFlags aFlags,
363 LayersIPCChannel* aAllocator);
364
365 virtual ~TextureClient();
366
367 static already_AddRefed<TextureClient> CreateWithData(
368 TextureData* aData, TextureFlags aFlags, LayersIPCChannel* aAllocator);
369
370 // Creates and allocates a TextureClient usable with Moz2D.
371 static already_AddRefed<TextureClient> CreateForDrawing(
372 KnowsCompositor* aAllocator, gfx::SurfaceFormat aFormat,
373 gfx::IntSize aSize, BackendSelector aSelector, TextureFlags aTextureFlags,
374 TextureAllocationFlags flags = ALLOC_DEFAULT);
375
376 static already_AddRefed<TextureClient> CreateFromSurface(
377 KnowsCompositor* aAllocator, gfx::SourceSurface* aSurface,
378 BackendSelector aSelector, TextureFlags aTextureFlags,
379 TextureAllocationFlags aAllocFlags);
380
381 // Creates and allocates a TextureClient supporting the YCbCr format.
382 static already_AddRefed<TextureClient> CreateForYCbCr(
383 KnowsCompositor* aAllocator, const gfx::IntRect& aDisplay,
384 const gfx::IntSize& aYSize, uint32_t aYStride,
385 const gfx::IntSize& aCbCrSize, uint32_t aCbCrStride,
386 StereoMode aStereoMode, gfx::ColorDepth aColorDepth,
387 gfx::YUVColorSpace aYUVColorSpace, gfx::ColorRange aColorRange,
388 gfx::TransferFunction aTransferFunction,
389 gfx::ChromaSubsampling aSubsampling, TextureFlags aTextureFlags,
390 const Maybe<gfx::HDRMetadata>& aHDRMetadata = Nothing());
391
392 // Creates and allocates a TextureClient (can be accessed through raw
393 // pointers).
394 static already_AddRefed<TextureClient> CreateForRawBufferAccess(
395 KnowsCompositor* aAllocator, gfx::SurfaceFormat aFormat,
396 gfx::IntSize aSize, gfx::BackendType aMoz2dBackend,
397 TextureFlags aTextureFlags, TextureAllocationFlags flags = ALLOC_DEFAULT);
398
399 // Creates and allocates a TextureClient of the same type.
400 already_AddRefed<TextureClient> CreateSimilar(
401 LayersBackend aLayersBackend = LayersBackend::LAYERS_NONE,
402 TextureFlags aFlags = TextureFlags::DEFAULT,
403 TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const;
404
405 /**
406 * Locks the shared data, allowing the caller to get access to it.
407 *
408 * Please always lock/unlock when accessing the shared data.
409 * If Lock() returns false, you should not attempt to access the shared data.
410 */
411 bool Lock(OpenMode aMode);
412
413 void Unlock();
414
415 bool IsLocked() const { return mIsLocked; }
416
417 gfx::IntSize GetSize() const { return mInfo.size; }
418
419 gfx::SurfaceFormat GetFormat() const { return mInfo.format; }
420
421 /**
422 * Returns true if this texture has a synchronization mechanism (mutex, fence,
423 * etc.). Textures that do not implement synchronization should be immutable
424 * or should use immediate uploads (see TextureFlags in CompositorTypes.h)
425 * Even if a texture does not implement synchronization, Lock and Unlock need
426 * to be used appropriately since the latter are also there to map/numap data.
427 */
428 bool HasSynchronization() const { return mInfo.hasSynchronization; }
429
430 bool CanExposeDrawTarget() const { return mInfo.supportsMoz2D; }
431
432 bool CanExposeMappedData() const { return mInfo.canExposeMappedData; }
433
434 /**
435 * Returns a DrawTarget to draw into the TextureClient.
436 * This function should never be called when not on the main thread!
437 *
438 * This must never be called on a TextureClient that is not sucessfully
439 * locked. When called several times within one Lock/Unlock pair, this method
440 * should return the same DrawTarget. The DrawTarget is automatically flushed
441 * by the TextureClient when the latter is unlocked, and the DrawTarget that
442 * will be returned within the next lock/unlock pair may or may not be the
443 * same object. Do not keep references to the DrawTarget outside of the
444 * lock/unlock pair.
445 *
446 * This is typically used as follows:
447 *
448 * if (!texture->Lock(OpenMode::OPEN_READ_WRITE)) {
449 * return false;
450 * }
451 * {
452 * // Restrict this code's scope to ensure all references to dt are gone
453 * // when Unlock is called.
454 * DrawTarget* dt = texture->BorrowDrawTarget();
455 * // use the draw target ...
456 * }
457 * texture->Unlock();
458 *
459 */
460 gfx::DrawTarget* BorrowDrawTarget();
461
462 /**
463 * When the TextureClient is not being Unlocked, this can be used to inform it
464 * that drawing has finished until the next BorrowDrawTarget.
465 */
466 void EndDraw();
467
468 already_AddRefed<gfx::SourceSurface> BorrowSnapshot();
469
470 void ReturnSnapshot(already_AddRefed<gfx::SourceSurface> aSnapshot);
471
472 /**
473 * Similar to BorrowDrawTarget but provides direct access to the texture's
474 * bits instead of a DrawTarget.
475 */
476 bool BorrowMappedData(MappedTextureData&);
477 bool BorrowMappedYCbCrData(MappedYCbCrTextureData&);
478
479 /**
480 * This function can be used to update the contents of the TextureClient
481 * off the main thread.
482 */
483 void UpdateFromSurface(gfx::SourceSurface* aSurface);
484
485 /**
486 * This method is strictly for debugging. It causes locking and
487 * needless copies.
488 */
489 already_AddRefed<gfx::DataSourceSurface> GetAsSurface();
490
491 /**
492 * Copies a rectangle from this texture client to a position in aTarget.
493 * It is assumed that the necessary locks are in place; so this should at
494 * least have a read lock and aTarget should at least have a write lock.
495 */
496 bool CopyToTextureClient(TextureClient* aTarget, const gfx::IntRect* aRect,
497 const gfx::IntPoint* aPoint);
498
499 /**
500 * Allocate a TextureChild actor.
501 *
502 * TextureChild is an implementation detail of TextureClient that is not
503 * exposed to the rest of the code base.
504 */
505 static already_AddRefed<PTextureChild> CreateIPDLActor();
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 bool mIsLocked;
751 bool mIsReadLocked MOZ_GUARDED_BY(mMutex)__attribute__((guarded_by(mMutex)));
752 bool mIsPendingForwardReadLocked MOZ_GUARDED_BY(mMutex)__attribute__((guarded_by(mMutex))) = false;
753 // This member tracks that the texture was written into until the update
754 // is sent to the compositor. We need this remember to lock mReadLock on
755 // behalf of the compositor just before sending the notification.
756 bool mUpdated;
757
758 // Used when TextureClient is recycled with TextureFlags::RECYCLE flag.
759 bool mAddedToCompositableClient;
760
761 uint64_t mFwdTransactionId;
762
763 // Serial id of TextureClient. It is unique in current process.
764 const uint64_t mSerial;
765
766 // When non-zero, texture data must not be freed.
767 mozilla::Atomic<uintptr_t> mPaintThreadRefs;
768
769 // External image id. It is unique if it is allocated.
770 // The id is allocated in TextureClient::InitIPDLActor().
771 // Its allocation is supported by
772 // CompositorBridgeChild and ImageBridgeChild for now.
773 wr::MaybeExternalImageId mExternalImageId;
774
775 // Used to assign serial ids of TextureClient.
776 static mozilla::Atomic<uint64_t> sSerialCounter;
777
778 friend class TextureChild;
779 friend void TestTextureClientSurface(TextureClient*, gfxImageSurface*);
780 friend void TestTextureClientYCbCr(TextureClient*, PlanarYCbCrData&);
781 friend void TestYCbCrDescriptorTransferFunction(gfx::TransferFunction,
782 Maybe<gfx::HDRMetadata>,
783 RefPtr<ImageBridgeChild>);
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#if defined(__GNUC__4) && !defined(__clang__1)
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#if defined(__GNUC__4) && !defined(__clang__1)
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 */