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=158.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-12-101221-999933-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;
528 {
529 MutexAutoLock lock(mMutex);
530 data = mData;
531 mData = nullptr;
532 }
533
534 if (data || actor || readLock) {
535 TextureDeallocParams params;
536 params.actor = std::move(actor);
537 params.readLock = std::move(readLock);
538 params.allocator = mAllocator;
539 params.clientDeallocation = !!(mFlags & TextureFlags::DEALLOCATE_CLIENT);
540 params.data = data;
541 // At the moment we always deallocate synchronously when deallocating on the
542 // client side, but having asynchronous deallocate in some of the cases will
543 // be a worthwhile optimization.
544 params.syncDeallocation = !!(mFlags & TextureFlags::DEALLOCATE_CLIENT);
545
546 // Release the lock before calling DeallocateTextureClient because the
547 // latter may wait for the main thread which could create a dead-lock.
548
549 if (params.actor) {
550 params.actor->Unlock();
551 }
552
553 DeallocateTextureClient(params);
554 }
555}
556
557void TextureClient::LockActor() const {
558 if (mActor) {
559 mActor->Lock();
560 }
561}
562
563void TextureClient::UnlockActor() const {
564 if (mActor) {
565 mActor->Unlock();
566 }
567}
568
569void TextureClient::EnsureHasReadLock() {
570 if (mFlags & TextureFlags::NON_BLOCKING_READ_LOCK) {
571 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", 571
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(mFlags & TextureFlags::BLOCKING_READ_LOCK)"
")"); do { MOZ_CrashSequence(__null, 571); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
572 EnableReadLock();
573 } else if (mFlags & TextureFlags::BLOCKING_READ_LOCK) {
574 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"
, 574); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!(mFlags & TextureFlags::NON_BLOCKING_READ_LOCK)"
")"); do { MOZ_CrashSequence(__null, 574); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
575 EnableBlockingReadLock();
576 }
577}
578
579bool TextureClient::IsReadLocked() {
580 if (!ShouldReadLock()) {
581 return false;
582 }
583
584 nsCOMPtr<nsISerialEventTarget> thread;
585
586 {
587 MutexAutoLock lock(mMutex);
588 if (mReadLock) {
589 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"
, 590); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mReadLock->AsNonBlockingLock()"
") (" "Can only check locked for non-blocking locks!" ")"); do
{ MOZ_CrashSequence(__null, 590); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
590 "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"
, 590); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mReadLock->AsNonBlockingLock()"
") (" "Can only check locked for non-blocking locks!" ")"); do
{ MOZ_CrashSequence(__null, 590); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
591 return mReadLock->AsNonBlockingLock()->GetReadCount() > 1;
592 }
593
594 thread = mAllocator->GetThread();
595 if (!thread) {
596 // We must be in the process of shutting down.
597 return false;
598 }
599
600 if (thread->IsOnCurrentThread()) {
601 EnsureHasReadLock();
602 if (NS_WARN_IF(!mReadLock)NS_warn_if_impl(!mReadLock, "!mReadLock", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 602)
) {
603 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", 603
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mAllocator->IPCOpen()"
")"); do { MOZ_CrashSequence(__null, 603); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
604 return false;
605 }
606 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"
, 607); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mReadLock->AsNonBlockingLock()"
") (" "Can only check locked for non-blocking locks!" ")"); do
{ MOZ_CrashSequence(__null, 607); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
607 "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"
, 607); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mReadLock->AsNonBlockingLock()"
") (" "Can only check locked for non-blocking locks!" ")"); do
{ MOZ_CrashSequence(__null, 607); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
608 return mReadLock->AsNonBlockingLock()->GetReadCount() > 1;
609 }
610 }
611
612 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"
, 612); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAllocator->UsesImageBridge()"
")"); do { MOZ_CrashSequence(__null, 612); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
613
614 bool result = false;
615 SynchronousTask task("TextureClient::IsReadLocked");
616 thread->Dispatch(NS_NewRunnableFunction("TextureClient::IsReadLocked", [&]() {
617 AutoCompleteTask complete(&task);
618 result = IsReadLocked();
619 }));
620 task.Wait();
621
622 return result;
623}
624
625bool TextureClient::TryReadLock() {
626 if (!ShouldReadLock()) {
627 return true;
628 }
629
630 nsCOMPtr<nsISerialEventTarget> thread;
631
632 {
633 MutexAutoLock lock(mMutex);
634 if (mIsReadLocked) {
635 return true;
636 }
637
638 if (mReadLock) {
639 if (mReadLock->AsNonBlockingLock() &&
640 mReadLock->AsNonBlockingLock()->GetReadCount() > 1) {
641 return false;
642 }
643
644 if (!mReadLock->TryReadLock(TimeDuration::FromMilliseconds(500))) {
645 return false;
646 }
647
648 mIsReadLocked = true;
649 return true;
650 }
651
652 thread = mAllocator->GetThread();
653 if (!thread) {
654 // We must be in the process of shutting down.
655 return false;
656 }
657
658 if (thread->IsOnCurrentThread()) {
659 EnsureHasReadLock();
660
661 if (NS_WARN_IF(!mReadLock)NS_warn_if_impl(!mReadLock, "!mReadLock", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 661)
) {
662 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", 662
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mAllocator->IPCOpen()"
")"); do { MOZ_CrashSequence(__null, 662); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
663 return false;
664 }
665
666 if (mReadLock->AsNonBlockingLock() &&
667 mReadLock->AsNonBlockingLock()->GetReadCount() > 1) {
668 return false;
669 }
670
671 if (!mReadLock->TryReadLock(TimeDuration::FromMilliseconds(500))) {
672 return false;
673 }
674
675 mIsReadLocked = true;
676 return true;
677 }
678 }
679
680 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"
, 680); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAllocator->UsesImageBridge()"
")"); do { MOZ_CrashSequence(__null, 680); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
681
682 bool result = false;
683 SynchronousTask task("TextureClient::TryReadLock");
684 thread->Dispatch(NS_NewRunnableFunction("TextureClient::TryReadLock", [&]() {
685 AutoCompleteTask complete(&task);
686 result = TryReadLock();
687 }));
688 task.Wait();
689
690 return result;
691}
692
693void TextureClient::ReadUnlock() {
694 if (!ShouldReadLock()) {
695 return;
696 }
697
698 MutexAutoLock lock(mMutex);
699
700 if (!mIsReadLocked) {
701 return;
702 }
703
704 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"
, 704); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mReadLock" ")"
); do { MOZ_CrashSequence(__null, 704); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
705 mReadLock->ReadUnlock();
706 mIsReadLocked = false;
707}
708
709bool TextureClient::Lock(OpenMode aMode) {
710 if (NS_WARN_IF(!IsValid())NS_warn_if_impl(!IsValid(), "!IsValid()", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 710)
) {
711 return false;
712 }
713 if (NS_WARN_IF(mIsLocked)NS_warn_if_impl(mIsLocked, "mIsLocked", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 713)
) {
714 return mOpenMode == aMode;
715 }
716
717 if ((aMode & OpenMode::OPEN_WRITE || !mInfo.canConcurrentlyReadLock) &&
718 !TryReadLock()) {
719 // Only warn if attempting to write. Attempting to read is acceptable usage.
720 if (aMode & OpenMode::OPEN_WRITE) {
721 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"
, 722)
722 "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"
, 722)
;
723 }
724 return false;
725 }
726
727 LockActor();
728
729 mIsLocked = mData->Lock(aMode);
730 mOpenMode = aMode;
731
732 auto format = GetFormat();
733 if (mIsLocked && CanExposeDrawTarget() &&
734 (aMode & OpenMode::OPEN_READ_WRITE) == OpenMode::OPEN_READ_WRITE &&
735 NS_IsMainThread() &&
736 // the formats that we apparently expect, in the cairo backend. Any other
737 // format will trigger an assertion in GfxFormatToCairoFormat.
738 (format == SurfaceFormat::A8R8G8B8_UINT32 ||
739 format == SurfaceFormat::X8R8G8B8_UINT32 ||
740 format == SurfaceFormat::A8 || format == SurfaceFormat::R5G6B5_UINT16)) {
741 if (!BorrowDrawTarget()) {
742 // Failed to get a DrawTarget, means we won't be able to write into the
743 // texture, might as well fail now.
744 Unlock();
745 return false;
746 }
747 }
748
749 if (!mIsLocked) {
750 UnlockActor();
751 ReadUnlock();
752 }
753
754 return mIsLocked;
755}
756
757void TextureClient::Unlock() {
758 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"
, 758); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsValid()" ")"
); do { MOZ_CrashSequence(__null, 758); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
759 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"
, 759); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIsLocked" ")"
); do { MOZ_CrashSequence(__null, 759); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
760 if (!IsValid() || !mIsLocked) {
761 return;
762 }
763
764 if (mBorrowedDrawTarget) {
765 if (mOpenMode & OpenMode::OPEN_WRITE) {
766 mBorrowedDrawTarget->Flush();
767 }
768
769 mData->ReturnDrawTarget(mBorrowedDrawTarget.forget());
770 }
771 mBorrowedSnapshot = false;
772
773 if (mOpenMode & OpenMode::OPEN_WRITE) {
774 mUpdated = true;
775 }
776
777 if (mData) {
778 mData->Unlock();
779 }
780 mIsLocked = false;
781 mOpenMode = OpenMode::OPEN_NONE;
782
783 UnlockActor();
784 ReadUnlock();
785}
786
787void TextureClient::EnableReadLock() {
788 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", 788
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ShouldReadLock()"
")"); do { MOZ_CrashSequence(__null, 788); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
789 if (!mReadLock && mAllocator->GetTileLockAllocator()) {
790 mReadLock = NonBlockingTextureReadLock::Create(mAllocator);
791 }
792}
793
794void TextureClient::OnPrepareForwardToHost() {
795 if (!ShouldReadLock()) {
796 return;
797 }
798
799 MutexAutoLock lock(mMutex);
800 if (NS_WARN_IF(!mReadLock)NS_warn_if_impl(!mReadLock, "!mReadLock", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 800)
) {
801 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"
, 801); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mAllocator->IPCOpen()"
") (" "Should have created readlock already!" ")"); do { MOZ_CrashSequence
(__null, 801); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
802 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"
, 802); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsPendingForwardReadLocked"
")"); do { MOZ_CrashSequence(__null, 802); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
803 return;
804 }
805
806 if (mIsPendingForwardReadLocked) {
807 return;
808 }
809
810 mReadLock->ReadLock();
811 mIsPendingForwardReadLocked = true;
812}
813
814void TextureClient::OnAbandonForwardToHost() {
815 if (!ShouldReadLock()) {
816 return;
817 }
818
819 MutexAutoLock lock(mMutex);
820 if (!mReadLock || !mIsPendingForwardReadLocked) {
821 return;
822 }
823
824 mReadLock->ReadUnlock();
825 mIsPendingForwardReadLocked = false;
826}
827
828bool TextureClient::OnForwardedToHost() {
829 if (mData) {
830 mData->OnForwardedToHost();
831 }
832
833 if (!ShouldReadLock()) {
834 return false;
835 }
836
837 MutexAutoLock lock(mMutex);
838 EnsureHasReadLock();
839
840 if (NS_WARN_IF(!mReadLock)NS_warn_if_impl(!mReadLock, "!mReadLock", "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 840)
) {
841 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", 841
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mAllocator->IPCOpen()"
")"); do { MOZ_CrashSequence(__null, 841); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
842 return false;
843 }
844
845 if (!mUpdated) {
846 if (mIsPendingForwardReadLocked) {
847 mIsPendingForwardReadLocked = false;
848 mReadLock->ReadUnlock();
849 }
850 return false;
851 }
852
853 mUpdated = false;
854
855 if (mIsPendingForwardReadLocked) {
856 // We have successfully forwarded, just clear the flag and let the
857 // TextureHost be responsible for unlocking.
858 mIsPendingForwardReadLocked = false;
859 } else {
860 // Otherwise we did not need to readlock in advance, so do so now. We do
861 // this on behalf of the TextureHost.
862 mReadLock->ReadLock();
863 }
864
865 return true;
866}
867
868TextureClient::~TextureClient() {
869 // TextureClients should be kept alive while there are references on the
870 // paint thread.
871 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", 871
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mPaintThreadRefs == 0"
")"); do { MOZ_CrashSequence(__null, 871); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
872 mReadLock = nullptr;
873 Destroy();
874}
875
876void TextureClient::UpdateFromSurface(gfx::SourceSurface* aSurface) {
877 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"
, 877); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsValid()" ")"
); do { MOZ_CrashSequence(__null, 877); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
878 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"
, 878); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIsLocked" ")"
); do { MOZ_CrashSequence(__null, 878); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
879 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"
, 879); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aSurface" ")"
); do { MOZ_CrashSequence(__null, 879); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
880 // If you run into this assertion, make sure the texture was locked write-only
881 // rather than read-write.
882 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", 882
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mBorrowedDrawTarget"
")"); do { MOZ_CrashSequence(__null, 882); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
883
884 // XXX - It would be better to first try the DrawTarget approach and fallback
885 // to the backend-specific implementation because the latter will usually do
886 // an expensive read-back + cpu-side copy if the texture is on the gpu.
887 // There is a bug with the DrawTarget approach, though specific to reading
888 // back from WebGL (where R and B channel end up inverted) to figure out
889 // first.
890 if (mData->UpdateFromSurface(aSurface)) {
891 return;
892 }
893 if (CanExposeDrawTarget() && NS_IsMainThread()) {
894 RefPtr<DrawTarget> dt = BorrowDrawTarget();
895
896 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"
, 896); AnnotateMozCrashReason("MOZ_ASSERT" "(" "dt" ")"); do
{ MOZ_CrashSequence(__null, 896); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
897 if (dt) {
898 dt->CopySurface(aSurface,
899 gfx::IntRect(gfx::IntPoint(0, 0), aSurface->GetSize()),
900 gfx::IntPoint(0, 0));
901 return;
902 }
903 }
904 NS_WARNING("TextureClient::UpdateFromSurface failed")NS_DebugBreak(NS_DEBUG_WARNING, "TextureClient::UpdateFromSurface failed"
, nullptr, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp"
, 904)
;
905}
906
907already_AddRefed<TextureClient> TextureClient::CreateSimilar(
908 LayersBackend aLayersBackend, TextureFlags aFlags,
909 TextureAllocationFlags aAllocFlags) const {
910 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"
, 910); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsValid()" ")"
); do { MOZ_CrashSequence(__null, 910); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
911
912 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"
, 912); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsLocked" ")"
); do { MOZ_CrashSequence(__null, 912); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
913 if (mIsLocked) {
914 return nullptr;
915 }
916
917 LockActor();
918 TextureData* data =
919 mData->CreateSimilar(mAllocator, aLayersBackend, aFlags, aAllocFlags);
920 UnlockActor();
921
922 if (!data) {
923 return nullptr;
924 }
925
926 return MakeAndAddRef<TextureClient>(data, aFlags, mAllocator);
927}
928
929gfx::DrawTarget* TextureClient::BorrowDrawTarget() {
930 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"
, 930); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsValid()" ")"
); do { MOZ_CrashSequence(__null, 930); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
931 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"
, 931); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIsLocked" ")"
); do { MOZ_CrashSequence(__null, 931); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
932 // TODO- We can't really assert that at the moment because there is code that
933 // Borrows the DrawTarget, just to get a snapshot, which is legit in term of
934 // OpenMode but we should have a way to get a SourceSurface directly instead.
935 // MOZ_ASSERT(mOpenMode & OpenMode::OPEN_WRITE);
936
937 if (!IsValid() || !mIsLocked) {
938 return nullptr;
939 }
940
941 if (!mBorrowedDrawTarget) {
942 mBorrowedDrawTarget = mData->BorrowDrawTarget();
943 }
944
945 return mBorrowedDrawTarget;
946}
947
948void TextureClient::EndDraw() {
949 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", 949
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mOpenMode & OpenMode::OPEN_READ_WRITE"
")"); do { MOZ_CrashSequence(__null, 949); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
950
951 // Because EndDraw is used when we are not unlocking this TextureClient at the
952 // end of a transaction, we need to Flush and DetachAllSnapshots to ensure any
953 // dependents are updated.
954 mBorrowedDrawTarget->Flush();
955 mData->ReturnDrawTarget(mBorrowedDrawTarget.forget());
956
957 mBorrowedSnapshot = false;
958 mData->EndDraw();
959}
960
961void TextureData::ReturnDrawTarget(already_AddRefed<gfx::DrawTarget> aDT) {
962 RefPtr<gfx::DrawTarget> dt(aDT);
963 dt->DetachAllSnapshots();
964}
965
966already_AddRefed<gfx::SourceSurface> TextureClient::BorrowSnapshot() {
967 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"
, 967); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mIsLocked" ")"
); do { MOZ_CrashSequence(__null, 967); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
968
969 RefPtr<gfx::SourceSurface> surface = mData->BorrowSnapshot();
970 if (surface) {
971 mBorrowedSnapshot = true;
972 } else {
973 RefPtr<gfx::DrawTarget> drawTarget = BorrowDrawTarget();
974 if (!drawTarget) {
975 return nullptr;
976 }
977 surface = drawTarget->Snapshot();
978 }
979
980 return surface.forget();
981}
982
983void TextureData::ReturnSnapshot(
984 already_AddRefed<gfx::SourceSurface> aSnapshot) {
985 RefPtr<gfx::SourceSurface> snapshot(aSnapshot);
986}
987
988void TextureClient::ReturnSnapshot(
989 already_AddRefed<gfx::SourceSurface> aSnapshot) {
990 RefPtr<gfx::SourceSurface> snapshot = aSnapshot;
991 if (mBorrowedSnapshot) {
992 mData->ReturnSnapshot(snapshot.forget());
993 mBorrowedSnapshot = false;
994 }
995}
996
997bool TextureClient::BorrowMappedData(MappedTextureData& aMap) {
998 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"
, 998); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsValid()" ")"
); do { MOZ_CrashSequence(__null, 998); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
999
1000 // TODO - SharedRGBImage just accesses the buffer without properly locking
1001 // the texture. It's bad.
1002 // MOZ_ASSERT(mIsLocked);
1003 // if (!mIsLocked) {
1004 // return nullptr;
1005 //}
1006
1007 return mData ? mData->BorrowMappedData(aMap) : false;
1008}
1009
1010bool TextureClient::BorrowMappedYCbCrData(MappedYCbCrTextureData& aMap) {
1011 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"
, 1011); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsValid()" ")"
); do { MOZ_CrashSequence(__null, 1011); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1012
1013 return mData ? mData->BorrowMappedYCbCrData(aMap) : false;
1014}
1015
1016bool TextureClient::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) {
1017 MutexAutoLock lock(mMutex);
1018 return mData ? mData->Serialize(aOutDescriptor) : false;
1019}
1020
1021// static
1022already_AddRefed<PTextureChild> TextureClient::CreateIPDLActor() {
1023 return MakeAndAddRef<TextureChild>();
1024}
1025
1026// static
1027already_AddRefed<TextureClient> TextureClient::AsTextureClient(
1028 PTextureChild* actor) {
1029 if (!actor) {
1030 return nullptr;
1031 }
1032
1033 TextureChild* tc = static_cast<TextureChild*>(actor);
1034
1035 tc->Lock();
1036
1037 // Since TextureClient may be destroyed asynchronously with respect to its
1038 // IPDL actor, we must acquire a reference within a lock. The mDestroyed bit
1039 // tells us whether or not the main thread has disconnected the TextureClient
1040 // from its actor.
1041 if (tc->mDestroyed) {
1042 tc->Unlock();
1043 return nullptr;
1044 }
1045
1046 RefPtr<TextureClient> texture = tc->mTextureClient;
1047 tc->Unlock();
1048
1049 return texture.forget();
1050}
1051
1052bool TextureClient::IsSharedWithCompositor() const {
1053 return mActor && mActor->CanSend();
1054}
1055
1056void TextureClient::AddFlags(TextureFlags aFlags) {
1057 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", 1059
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsSharedWithCompositor() || ((GetFlags() & TextureFlags::RECYCLE) && !IsAddedToCompositableClient())"
")"); do { MOZ_CrashSequence(__null, 1059); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1058 !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", 1059
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsSharedWithCompositor() || ((GetFlags() & TextureFlags::RECYCLE) && !IsAddedToCompositableClient())"
")"); do { MOZ_CrashSequence(__null, 1059); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1059 ((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", 1059
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsSharedWithCompositor() || ((GetFlags() & TextureFlags::RECYCLE) && !IsAddedToCompositableClient())"
")"); do { MOZ_CrashSequence(__null, 1059); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1060 mFlags |= aFlags;
1061}
1062
1063void TextureClient::RemoveFlags(TextureFlags aFlags) {
1064 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", 1066
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsSharedWithCompositor() || ((GetFlags() & TextureFlags::RECYCLE) && !IsAddedToCompositableClient())"
")"); do { MOZ_CrashSequence(__null, 1066); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1065 !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", 1066
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsSharedWithCompositor() || ((GetFlags() & TextureFlags::RECYCLE) && !IsAddedToCompositableClient())"
")"); do { MOZ_CrashSequence(__null, 1066); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1066 ((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", 1066
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsSharedWithCompositor() || ((GetFlags() & TextureFlags::RECYCLE) && !IsAddedToCompositableClient())"
")"); do { MOZ_CrashSequence(__null, 1066); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1067 mFlags &= ~aFlags;
1068}
1069
1070void TextureClient::RecycleTexture(TextureFlags aFlags) {
1071 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", 1071
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "GetFlags() & TextureFlags::RECYCLE"
")"); do { MOZ_CrashSequence(__null, 1071); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1072 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"
, 1072); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsLocked"
")"); do { MOZ_CrashSequence(__null, 1072); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1073
1074 mAddedToCompositableClient = false;
1075 if (mFlags != aFlags) {
1076 mFlags = aFlags;
1077 }
1078}
1079
1080void TextureClient::SetAddedToCompositableClient() {
1081 if (!mAddedToCompositableClient) {
1082 mAddedToCompositableClient = true;
1083 if (!(GetFlags() & TextureFlags::RECYCLE)) {
1084 return;
1085 }
1086 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"
, 1086); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIsLocked"
")"); do { MOZ_CrashSequence(__null, 1086); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1087 LockActor();
1088 if (IsValid() && mActor && !mActor->mDestroyed && mActor->CanSend()) {
1089 mActor->SendRecycleTexture(mFlags);
1090 }
1091 UnlockActor();
1092 }
1093}
1094
1095static void CancelTextureClientNotifyNotUsed(uint64_t aTextureId,
1096 LayersIPCChannel* aAllocator) {
1097 if (!aAllocator) {
1098 return;
1099 }
1100 nsCOMPtr<nsISerialEventTarget> thread = aAllocator->GetThread();
1101 if (!thread) {
1102 return;
1103 }
1104 if (thread->IsOnCurrentThread()) {
1105 aAllocator->CancelWaitForNotifyNotUsed(aTextureId);
1106 } else {
1107 thread->Dispatch(NewRunnableFunction(
1108 "CancelTextureClientNotifyNotUsedRunnable",
1109 CancelTextureClientNotifyNotUsed, aTextureId, aAllocator));
1110 }
1111}
1112
1113void TextureClient::CancelWaitForNotifyNotUsed() {
1114 if (GetFlags() & TextureFlags::RECYCLE) {
1115 CancelTextureClientNotifyNotUsed(mSerial, GetAllocator());
1116 return;
1117 }
1118}
1119
1120/* static */
1121void TextureClient::TextureClientRecycleCallback(TextureClient* aClient,
1122 void* aClosure) {
1123 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"
, 1123); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aClient->GetRecycleAllocator()"
")"); do { MOZ_CrashSequence(__null, 1123); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1124 aClient->GetRecycleAllocator()->RecycleTextureClient(aClient);
1125}
1126
1127void TextureClient::SetRecycleAllocator(
1128 ITextureClientRecycleAllocator* aAllocator) {
1129 mRecycleAllocator = aAllocator;
1130 if (aAllocator) {
1131 SetRecycleCallback(TextureClientRecycleCallback, nullptr);
1132 } else {
1133 ClearRecycleCallback();
1134 }
1135}
1136
1137bool TextureClient::InitIPDLActor(CompositableForwarder* aForwarder) {
1138 RefPtr<TextureForwarder> textureFwd = aForwarder->GetTextureForwarder();
1139 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", 1139
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aForwarder && textureFwd->GetThread() == mAllocator->GetThread()"
")"); do { MOZ_CrashSequence(__null, 1139); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1140
1141 if (mActor && !mActor->CanSend()) {
1142 return false;
1143 }
1144
1145 if (mActor && !mActor->mDestroyed) {
1146 CompositableForwarder* currentFwd = mActor->mCompositableForwarder;
1147 if (currentFwd != aForwarder) {
1148 // It's a bit iffy but right now ShadowLayerForwarder inherits
1149 // TextureForwarder even though it should not.
1150 // ShadowLayerForwarder::GetTextureForwarder actually returns a pointer to
1151 // the CompositorBridgeChild. It's Ok for a texture to move from a
1152 // ShadowLayerForwarder to another, but not form a CompositorBridgeChild
1153 // to another (they use different channels).
1154 if (mActor->mTextureForwarder &&
1155 mActor->mTextureForwarder != textureFwd) {
1156 gfxCriticalErrormozilla::gfx::CriticalLog()
1157 << "Attempt to move a texture to a different channel CF.";
1158 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"
, 1158); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "unexpected to be called" ")"); do
{ MOZ_CrashSequence(__null, 1158); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
1159 return false;
1160 }
1161 if (currentFwd && currentFwd->GetCompositorBackendType() !=
1162 aForwarder->GetCompositorBackendType()) {
1163 gfxCriticalErrormozilla::gfx::CriticalLog()
1164 << "Attempt to move a texture to different compositor backend.";
1165 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"
, 1165); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "unexpected to be called" ")"); do
{ MOZ_CrashSequence(__null, 1165); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
1166 return false;
1167 }
1168 mActor->mCompositableForwarder = aForwarder;
1169 mActor->mUsesImageBridge = textureFwd->UsesImageBridge();
1170 }
1171 return true;
1172 }
1173 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"
, 1174); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mActor || mActor->mDestroyed"
") (" "Cannot use a texture on several IPC channels." ")"); do
{ MOZ_CrashSequence(__null, 1174); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
1174 "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"
, 1174); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mActor || mActor->mDestroyed"
") (" "Cannot use a texture on several IPC channels." ")"); do
{ MOZ_CrashSequence(__null, 1174); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
1175
1176 SurfaceDescriptor desc;
1177 if (!ToSurfaceDescriptor(desc)) {
1178 return false;
1179 }
1180
1181 // Try external image id allocation.
1182 mExternalImageId = textureFwd->GetNextExternalImageId();
1183
1184 ReadLockDescriptor readLockDescriptor = null_t();
1185
1186 {
1187 MutexAutoLock lock(mMutex);
1188 EnsureHasReadLock();
1189 if (mReadLock) {
1190 mReadLock->Serialize(readLockDescriptor, GetAllocator()->GetParentPid());
1191 }
1192 }
1193
1194 RefPtr actor = textureFwd->CreateTexture(
1195 desc, std::move(readLockDescriptor),
1196 aForwarder->GetCompositorBackendType(), GetFlags(),
1197 dom::ContentParentId(), mSerial, mExternalImageId);
1198
1199 if (!actor) {
1200 gfxCriticalNotemozilla::gfx::CriticalLog(mozilla::gfx::CriticalLog::DefaultOptions
(false))
<< static_cast<int32_t>(desc.type()) << ", "
1201 << static_cast<int32_t>(
1202 aForwarder->GetCompositorBackendType())
1203 << ", " << static_cast<uint32_t>(GetFlags()) << ", "
1204 << mSerial;
1205 return false;
1206 }
1207
1208 mActor = actor.forget().downcast<TextureChild>();
1209 mActor->mCompositableForwarder = aForwarder;
1210 mActor->mTextureForwarder = textureFwd;
1211 mActor->mTextureClient = this;
1212
1213 // If the TextureClient is already locked, we have to lock TextureChild's
1214 // mutex since it will be unlocked in TextureClient::Unlock.
1215 if (mIsLocked) {
1216 LockActor();
1217 }
1218
1219 return mActor->CanSend();
1220}
1221
1222bool TextureClient::InitIPDLActor(KnowsCompositor* aKnowsCompositor,
1223 const dom::ContentParentId& aContentId) {
1224 RefPtr<TextureForwarder> textureFwd = aKnowsCompositor->GetTextureForwarder();
1225 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", 1226
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aKnowsCompositor && textureFwd->GetThread() == mAllocator->GetThread()"
")"); do { MOZ_CrashSequence(__null, 1226); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1226 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", 1226
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aKnowsCompositor && textureFwd->GetThread() == mAllocator->GetThread()"
")"); do { MOZ_CrashSequence(__null, 1226); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1227 if (mActor && !mActor->mDestroyed) {
1228 CompositableForwarder* currentFwd = mActor->mCompositableForwarder;
1229
1230 if (currentFwd) {
1231 gfxCriticalErrormozilla::gfx::CriticalLog()
1232 << "Attempt to remove a texture from a CompositableForwarder.";
1233 return false;
1234 }
1235
1236 if (mActor->mTextureForwarder && mActor->mTextureForwarder != textureFwd) {
1237 gfxCriticalErrormozilla::gfx::CriticalLog()
1238 << "Attempt to move a texture to a different channel TF.";
1239 return false;
1240 }
1241 mActor->mTextureForwarder = textureFwd;
1242 return true;
1243 }
1244 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"
, 1245); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mActor || mActor->mDestroyed"
") (" "Cannot use a texture on several IPC channels." ")"); do
{ MOZ_CrashSequence(__null, 1245); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
1245 "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"
, 1245); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mActor || mActor->mDestroyed"
") (" "Cannot use a texture on several IPC channels." ")"); do
{ MOZ_CrashSequence(__null, 1245); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
1246
1247 SurfaceDescriptor desc;
1248 if (!ToSurfaceDescriptor(desc)) {
1249 return false;
1250 }
1251
1252 // Try external image id allocation.
1253 mExternalImageId = textureFwd->GetNextExternalImageId();
1254
1255 ReadLockDescriptor readLockDescriptor = null_t();
1256 {
1257 MutexAutoLock lock(mMutex);
1258 EnsureHasReadLock();
1259 if (mReadLock) {
1260 mReadLock->Serialize(readLockDescriptor, GetAllocator()->GetParentPid());
1261 }
1262 }
1263
1264 RefPtr actor = textureFwd->CreateTexture(
1265 desc, std::move(readLockDescriptor),
1266 aKnowsCompositor->GetCompositorBackendType(), GetFlags(), aContentId,
1267 mSerial, mExternalImageId);
1268 if (!actor) {
1269 gfxCriticalNotemozilla::gfx::CriticalLog(mozilla::gfx::CriticalLog::DefaultOptions
(false))
<< static_cast<int32_t>(desc.type()) << ", "
1270 << static_cast<int32_t>(
1271 aKnowsCompositor->GetCompositorBackendType())
1272 << ", " << static_cast<uint32_t>(GetFlags()) << ", "
1273 << mSerial;
1274 return false;
1275 }
1276
1277 mActor = actor.forget().downcast<TextureChild>();
1278 mActor->mTextureForwarder = textureFwd;
1279 mActor->mTextureClient = this;
1280
1281 // If the TextureClient is already locked, we have to lock TextureChild's
1282 // mutex since it will be unlocked in TextureClient::Unlock.
1283 if (mIsLocked) {
1284 LockActor();
1285 }
1286
1287 return mActor->CanSend();
1288}
1289
1290PTextureChild* TextureClient::GetIPDLActor() { return mActor; }
1291
1292// static
1293already_AddRefed<TextureClient> TextureClient::CreateForDrawing(
1294 KnowsCompositor* aAllocator, gfx::SurfaceFormat aFormat, gfx::IntSize aSize,
1295 BackendSelector aSelector, TextureFlags aTextureFlags,
1296 TextureAllocationFlags aAllocFlags) {
1297 return TextureClient::CreateForDrawing(
1298 aAllocator->GetTextureForwarder().get(), aFormat, aSize, aAllocator,
1299 aSelector, aTextureFlags, aAllocFlags);
1300}
1301
1302// static
1303already_AddRefed<TextureClient> TextureClient::CreateForDrawing(
1304 TextureForwarder* aAllocator, gfx::SurfaceFormat aFormat,
1305 gfx::IntSize aSize, KnowsCompositor* aKnowsCompositor,
1306 BackendSelector aSelector, TextureFlags aTextureFlags,
1307 TextureAllocationFlags aAllocFlags) {
1308 LayersBackend layersBackend = aKnowsCompositor->GetCompositorBackendType();
1309 gfx::BackendType moz2DBackend =
1310 BackendTypeForBackendSelector(layersBackend, aSelector);
1311
1312 // also test the validity of aAllocator
1313 if (!aAllocator || !aAllocator->IPCOpen()) {
1314 return nullptr;
1315 }
1316
1317 if (!gfx::Factory::AllowedSurfaceSize(aSize)) {
1318 return nullptr;
1319 }
1320
1321 TextureData* data =
1322 TextureData::Create(aAllocator, aFormat, aSize, aKnowsCompositor,
1323 aSelector, aTextureFlags, aAllocFlags);
1324
1325 if (data) {
1326 return MakeAndAddRef<TextureClient>(data, aTextureFlags, aAllocator);
1327 }
1328 if (aAllocFlags & ALLOC_FORCE_REMOTE) {
1329 // If we must be remote, but allocation failed, then don't fall back.
1330 return nullptr;
1331 }
1332
1333 // Can't do any better than a buffer texture client.
1334 return TextureClient::CreateForRawBufferAccess(aAllocator, aFormat, aSize,
1335 moz2DBackend, layersBackend,
1336 aTextureFlags, aAllocFlags);
1337}
1338
1339// static
1340already_AddRefed<TextureClient> TextureClient::CreateFromSurface(
1341 KnowsCompositor* aAllocator, gfx::SourceSurface* aSurface,
1342 BackendSelector aSelector, TextureFlags aTextureFlags,
1343 TextureAllocationFlags aAllocFlags) {
1344 // also test the validity of aAllocator
1345 if (!aAllocator || !aAllocator->GetTextureForwarder()->IPCOpen()) {
1346 return nullptr;
1347 }
1348
1349 gfx::IntSize size = aSurface->GetSize();
1350
1351 if (!gfx::Factory::AllowedSurfaceSize(size)) {
1352 return nullptr;
1353 }
1354
1355 // Fall back to using UpdateFromSurface
1356
1357 TextureAllocationFlags allocFlags =
1358 TextureAllocationFlags(aAllocFlags | ALLOC_UPDATE_FROM_SURFACE);
1359 RefPtr<TextureClient> client =
1360 CreateForDrawing(aAllocator, aSurface->GetFormat(), size, aSelector,
1361 aTextureFlags, allocFlags);
1362 if (!client) {
1363 return nullptr;
1364 }
1365
1366 TextureClientAutoLock autoLock(client, OpenMode::OPEN_WRITE_ONLY);
1367 if (!autoLock.Succeeded()) {
1368 return nullptr;
1369 }
1370
1371 client->UpdateFromSurface(aSurface);
1372 return client.forget();
1373}
1374
1375// static
1376already_AddRefed<TextureClient> TextureClient::CreateForRawBufferAccess(
1377 KnowsCompositor* aAllocator, gfx::SurfaceFormat aFormat, gfx::IntSize aSize,
1378 gfx::BackendType aMoz2DBackend, TextureFlags aTextureFlags,
1379 TextureAllocationFlags aAllocFlags) {
1380 return CreateForRawBufferAccess(
1381 aAllocator->GetTextureForwarder().get(), aFormat, aSize, aMoz2DBackend,
1382 aAllocator->GetCompositorBackendType(), aTextureFlags, aAllocFlags);
1383}
1384
1385// static
1386already_AddRefed<TextureClient> TextureClient::CreateForRawBufferAccess(
1387 LayersIPCChannel* aAllocator, gfx::SurfaceFormat aFormat,
1388 gfx::IntSize aSize, gfx::BackendType aMoz2DBackend,
1389 LayersBackend aLayersBackend, TextureFlags aTextureFlags,
1390 TextureAllocationFlags aAllocFlags) {
1391 // also test the validity of aAllocator
1392 if (!aAllocator || !aAllocator->IPCOpen()) {
1393 return nullptr;
1394 }
1395
1396 if (!gfx::Factory::AllowedSurfaceSize(aSize)) {
1397 return nullptr;
1398 }
1399
1400 if (aFormat == SurfaceFormat::B8G8R8X8) {
1401 // Skia doesn't support RGBX, so ensure we clear the buffer for the proper
1402 // alpha values.
1403 aAllocFlags = TextureAllocationFlags(aAllocFlags | ALLOC_CLEAR_BUFFER);
1404 }
1405
1406 // We ignore the backend type if we get here. It should only be Skia.
1407 // Therefore it is safe to force the buffer to be Skia.
1408 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", 1409
); } } while (false)
1409 "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", 1409
); } } while (false)
;
1410
1411 // For future changes, check aAllocFlags aAllocFlags & ALLOC_DO_NOT_ACCELERATE
1412 TextureData* texData = BufferTextureData::Create(
1413 aSize, aFormat, gfx::ColorSpace2::SRGB, gfx::TransferFunction::SRGB,
1414 gfx::BackendType::SKIA, aLayersBackend, aTextureFlags, aAllocFlags,
1415 aAllocator);
1416 if (!texData) {
1417 return nullptr;
1418 }
1419
1420 return MakeAndAddRef<TextureClient>(texData, aTextureFlags, aAllocator);
1421}
1422
1423// static
1424already_AddRefed<TextureClient> TextureClient::CreateForYCbCr(
1425 KnowsCompositor* aAllocator, const gfx::IntRect& aDisplay,
1426 const gfx::IntSize& aYSize, uint32_t aYStride,
1427 const gfx::IntSize& aCbCrSize, uint32_t aCbCrStride, StereoMode aStereoMode,
1428 gfx::ColorDepth aColorDepth, gfx::YUVColorSpace aYUVColorSpace,
1429 gfx::ColorRange aColorRange, gfx::TransferFunction aTransferFunction,
1430 gfx::ChromaSubsampling aSubsampling, TextureFlags aTextureFlags,
1431 const Maybe<gfx::HDRMetadata>& aHDRMetadata) {
1432 if (!aAllocator || !aAllocator->GetLayersIPCActor()->IPCOpen()) {
1433 return nullptr;
1434 }
1435
1436 if (!gfx::Factory::AllowedSurfaceSize(aYSize)) {
1437 return nullptr;
1438 }
1439
1440 TextureData* data = BufferTextureData::CreateForYCbCr(
1441 aAllocator, aDisplay, aYSize, aYStride, aCbCrSize, aCbCrStride,
1442 aStereoMode, aColorDepth, aYUVColorSpace, aColorRange, aTransferFunction,
1443 aSubsampling, aTextureFlags, aHDRMetadata);
1444 if (!data) {
1445 return nullptr;
1446 }
1447
1448 return MakeAndAddRef<TextureClient>(data, aTextureFlags,
1449 aAllocator->GetTextureForwarder().get());
1450}
1451
1452TextureClient::TextureClient(TextureData* aData, TextureFlags aFlags,
1453 LayersIPCChannel* aAllocator)
1454 : AtomicRefCountedWithFinalize("TextureClient"),
1455 mMutex("TextureClient::mMutex"),
1456 mAllocator(aAllocator),
1457 mActor(nullptr),
1458 mData(aData),
1459 mFlags(aFlags),
1460 mOpenMode(OpenMode::OPEN_NONE),
1461 mIsLocked(false),
1462 mIsReadLocked(false),
1463 mUpdated(false),
1464 mAddedToCompositableClient(false),
1465 mFwdTransactionId(0),
1466 mSerial(++sSerialCounter) {
1467 mData->FillInfo(mInfo);
1468 mFlags |= mData->GetTextureFlags();
1469}
1470
1471bool TextureClient::CopyToTextureClient(TextureClient* aTarget,
1472 const gfx::IntRect* aRect,
1473 const gfx::IntPoint* aPoint) {
1474 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"
, 1474); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsLocked()"
")"); do { MOZ_CrashSequence(__null, 1474); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1475 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", 1475
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTarget->IsLocked()"
")"); do { MOZ_CrashSequence(__null, 1475); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1476
1477 if (!aTarget->CanExposeDrawTarget() || !CanExposeDrawTarget()) {
1478 return false;
1479 }
1480
1481 RefPtr<DrawTarget> destinationTarget = aTarget->BorrowDrawTarget();
1482 if (!destinationTarget) {
1483 gfxWarningmozilla::gfx::WarningLog() << "TextureClient::CopyToTextureClient (dest) failed in "
1484 "BorrowDrawTarget";
1485 return false;
1486 }
1487
1488 RefPtr<DrawTarget> sourceTarget = BorrowDrawTarget();
1489 if (!sourceTarget) {
1490 gfxWarningmozilla::gfx::WarningLog() << "TextureClient::CopyToTextureClient (src) failed in "
1491 "BorrowDrawTarget";
1492 return false;
1493 }
1494
1495 RefPtr<gfx::SourceSurface> source = sourceTarget->Snapshot();
1496 destinationTarget->CopySurface(
1497 source, aRect ? *aRect : gfx::IntRect(gfx::IntPoint(0, 0), GetSize()),
1498 aPoint ? *aPoint : gfx::IntPoint(0, 0));
1499 return true;
1500}
1501
1502already_AddRefed<gfx::DataSourceSurface> TextureClient::GetAsSurface() {
1503 if (!Lock(OpenMode::OPEN_READ)) {
1504 return nullptr;
1505 }
1506 RefPtr<gfx::DataSourceSurface> data;
1507 { // scope so that the DrawTarget is destroyed before Unlock()
1508 RefPtr<gfx::DrawTarget> dt = BorrowDrawTarget();
1509 if (dt) {
1510 RefPtr<gfx::SourceSurface> surf = dt->Snapshot();
1511 if (surf) {
1512 data = surf->GetDataSurface();
1513 }
1514 }
1515 }
1516 Unlock();
1517 return data.forget();
1518}
1519
1520void TextureClient::GetSurfaceDescriptorRemoteDecoder(
1521 SurfaceDescriptorRemoteDecoder* const aOutDesc) {
1522 const auto handle = GetSerial();
1523
1524 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"
, 1524); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "mData"
")"); do { MOZ_CrashSequence(__null, 1524); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1525
1526 auto videoType = mData->GetRemoteDecoderVideoType();
1527
1528 *aOutDesc = SurfaceDescriptorRemoteDecoder(
1529 handle, videoType, Nothing(),
1530 SurfaceDescriptorRemoteDecoderId::GetNext());
1531}
1532
1533class MemoryTextureReadLock : public NonBlockingTextureReadLock {
1534 public:
1535 MemoryTextureReadLock();
1536
1537 virtual ~MemoryTextureReadLock();
1538
1539 bool ReadLock() override;
1540
1541 int32_t ReadUnlock() override;
1542
1543 int32_t GetReadCount() override;
1544
1545 LockType GetType() override { return TYPE_NONBLOCKING_MEMORY; }
1546
1547 bool IsValid() const override { return true; };
1548
1549 bool Serialize(ReadLockDescriptor& aOutput, base::ProcessId aOther) override;
1550
1551 Atomic<int32_t> mReadCount;
1552};
1553
1554// The cross-prcess implementation of TextureReadLock.
1555//
1556// Since we don't use cross-process reference counting for the ReadLock objects,
1557// we use the lock's internal counter as a way to know when to deallocate the
1558// underlying shmem section: when the counter is equal to 1, it means that the
1559// lock is not "held" (the texture is writable), when the counter is equal to 0
1560// it means that we can safely deallocate the shmem section without causing a
1561// race condition with the other process.
1562class ShmemTextureReadLock : public NonBlockingTextureReadLock {
1563 public:
1564 struct ShmReadLockInfo {
1565 int32_t readCount;
1566 };
1567
1568 explicit ShmemTextureReadLock(LayersIPCChannel* aAllocator);
1569
1570 virtual ~ShmemTextureReadLock();
1571
1572 bool ReadLock() override;
1573
1574 int32_t ReadUnlock() override;
1575
1576 int32_t GetReadCount() override;
1577
1578 bool IsValid() const override { return mAllocSuccess; };
1579
1580 LockType GetType() override { return TYPE_NONBLOCKING_SHMEM; }
1581
1582 bool Serialize(ReadLockDescriptor& aOutput, base::ProcessId aOther) override;
1583
1584 mozilla::layers::ShmemSection& GetShmemSection() { return mShmemSection; }
1585
1586 explicit ShmemTextureReadLock(
1587 const mozilla::layers::ShmemSection& aShmemSection)
1588 : mShmemSection(aShmemSection), mAllocSuccess(true) {
1589 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)
;
1590 }
1591
1592 ShmReadLockInfo* GetShmReadLockInfoPtr() {
1593 return reinterpret_cast<ShmReadLockInfo*>(
1594 mShmemSection.shmem().get<char>() + mShmemSection.offset());
1595 }
1596
1597 RefPtr<LayersIPCChannel> mClientAllocator;
1598 mozilla::layers::ShmemSection mShmemSection;
1599 bool mAllocSuccess;
1600};
1601
1602class CrossProcessSemaphoreReadLock : public TextureReadLock {
1603 public:
1604 CrossProcessSemaphoreReadLock()
1605 : mSemaphore(CrossProcessSemaphore::Create("TextureReadLock", 1)),
1606 mShared(false) {}
1607 explicit CrossProcessSemaphoreReadLock(CrossProcessSemaphoreHandle aHandle)
1608 : mSemaphore(CrossProcessSemaphore::Create(std::move(aHandle))),
1609 mShared(false) {}
1610
1611 bool ReadLock() override {
1612 if (!IsValid()) {
1613 return false;
1614 }
1615 return mSemaphore->Wait();
1616 }
1617 bool TryReadLock(TimeDuration aTimeout) override {
1618 if (!IsValid()) {
1619 return false;
1620 }
1621 return mSemaphore->Wait(Some(aTimeout));
1622 }
1623 int32_t ReadUnlock() override {
1624 if (!IsValid()) {
1625 return 1;
1626 }
1627 mSemaphore->Signal();
1628 return 1;
1629 }
1630 bool IsValid() const override { return !!mSemaphore; }
1631
1632 bool Serialize(ReadLockDescriptor& aOutput, base::ProcessId aOther) override;
1633
1634 LockType GetType() override { return TYPE_CROSS_PROCESS_SEMAPHORE; }
1635
1636 UniquePtr<CrossProcessSemaphore> mSemaphore;
1637 bool mShared;
1638};
1639
1640// static
1641already_AddRefed<TextureReadLock> TextureReadLock::Deserialize(
1642 ReadLockDescriptor&& aDescriptor, ISurfaceAllocator* aAllocator) {
1643 switch (aDescriptor.type()) {
1
Control jumps to 'case Tuintptr_t:' at line 1655
1644 case ReadLockDescriptor::TUntrustedShmemSection: {
1645 const UntrustedShmemSection& untrusted =
1646 aDescriptor.get_UntrustedShmemSection();
1647 size_t minSize = sizeof(ShmemTextureReadLock::ShmReadLockInfo);
1648 Maybe<ShmemSection> section =
1649 ShmemSection::FromUntrusted(untrusted, minSize);
1650 if (section.isNothing()) {
1651 return nullptr;
1652 }
1653 return MakeAndAddRef<ShmemTextureReadLock>(section.value());
1654 }
1655 case ReadLockDescriptor::Tuintptr_t: {
1656 if (!aAllocator->IsSameProcess()) {
2
Assuming the condition is false
3
Taking false branch
1657 // Trying to use a memory based lock instead of a shmem based one in
1658 // the cross-process case is a bad security violation.
1659 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"
, 1661); MOZ_PretendNoReturn(); } while (0)
1660 "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"
, 1661); MOZ_PretendNoReturn(); } while (0)
1661 "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"
, 1661); MOZ_PretendNoReturn(); } while (0)
;
1662 return nullptr;
1663 }
1664 RefPtr<TextureReadLock> lock =
1665 reinterpret_cast<MemoryTextureReadLock*>(aDescriptor.get_uintptr_t());
4
Calling constructor for 'RefPtr<mozilla::layers::TextureReadLock>'
7
Returning from constructor for 'RefPtr<mozilla::layers::TextureReadLock>'
1666
1667 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"
, 1667); AnnotateMozCrashReason("MOZ_ASSERT" "(" "lock" ")");
do { MOZ_CrashSequence(__null, 1667); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8
Taking false branch
9
Loop condition is false. Exiting loop
1668 if (lock) {
10
Taking true branch
1669 // The corresponding AddRef is in MemoryTextureReadLock::Serialize
1670 lock.get()->Release();
11
Calling 'TextureReadLock::Release'
19
Returning; memory was released
1671 }
1672
1673 return lock.forget();
20
Calling 'RefPtr::forget'
1674 }
1675 case ReadLockDescriptor::TCrossProcessSemaphoreDescriptor: {
1676 return MakeAndAddRef<CrossProcessSemaphoreReadLock>(
1677 std::move(aDescriptor.get_CrossProcessSemaphoreDescriptor().sem()));
1678 }
1679 case ReadLockDescriptor::Tnull_t: {
1680 return nullptr;
1681 }
1682 default: {
1683 MOZ_DIAGNOSTIC_CRASH(do { do { } while (false); MOZ_ReportCrash("" "Invalid descriptor in TextureReadLock::Deserialize"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 1684
); AnnotateMozCrashReason("MOZ_CRASH(" "Invalid descriptor in TextureReadLock::Deserialize"
")"); do { MOZ_CrashSequence(__null, 1684); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
1684 "Invalid descriptor in TextureReadLock::Deserialize")do { do { } while (false); MOZ_ReportCrash("" "Invalid descriptor in TextureReadLock::Deserialize"
, "/root/firefox-clang/gfx/layers/client/TextureClient.cpp", 1684
); AnnotateMozCrashReason("MOZ_CRASH(" "Invalid descriptor in TextureReadLock::Deserialize"
")"); do { MOZ_CrashSequence(__null, 1684); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
1685 }
1686 }
1687 return nullptr;
1688}
1689// static
1690already_AddRefed<TextureReadLock> NonBlockingTextureReadLock::Create(
1691 LayersIPCChannel* aAllocator) {
1692 if (aAllocator->IsSameProcess()) {
1693 // If our compositor is in the same process, we can save some cycles by not
1694 // using shared memory.
1695 return MakeAndAddRef<MemoryTextureReadLock>();
1696 }
1697
1698 return MakeAndAddRef<ShmemTextureReadLock>(aAllocator);
1699}
1700
1701MemoryTextureReadLock::MemoryTextureReadLock() : mReadCount(1) {
1702 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)
;
1703}
1704
1705MemoryTextureReadLock::~MemoryTextureReadLock() {
1706 // One read count that is added in constructor.
1707 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", 1707
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mReadCount == 1" ")"
); do { MOZ_CrashSequence(__null, 1707); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1708 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)
;
1709}
1710
1711bool MemoryTextureReadLock::Serialize(ReadLockDescriptor& aOutput,
1712 base::ProcessId aOther) {
1713 // AddRef here and Release when receiving on the host side to make sure the
1714 // reference count doesn't go to zero before the host receives the message.
1715 // see TextureReadLock::Deserialize
1716 this->AddRef();
1717 aOutput = ReadLockDescriptor(uintptr_t(this));
1718 return true;
1719}
1720
1721bool MemoryTextureReadLock::ReadLock() {
1722 ++mReadCount;
1723 return true;
1724}
1725
1726int32_t MemoryTextureReadLock::ReadUnlock() {
1727 int32_t readCount = --mReadCount;
1728 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", 1728
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "readCount >= 0"
")"); do { MOZ_CrashSequence(__null, 1728); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1729
1730 return readCount;
1731}
1732
1733int32_t MemoryTextureReadLock::GetReadCount() { return mReadCount; }
1734
1735ShmemTextureReadLock::ShmemTextureReadLock(LayersIPCChannel* aAllocator)
1736 : mClientAllocator(aAllocator), mAllocSuccess(false) {
1737 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)
;
1738 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", 1738
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mClientAllocator"
")"); do { MOZ_CrashSequence(__null, 1738); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1739 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", 1739
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mClientAllocator->GetTileLockAllocator()"
")"); do { MOZ_CrashSequence(__null, 1739); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1740#define MOZ_ALIGN_WORD(x)(((x) + 3) & ~3) (((x) + 3) & ~3)
1741 if (mClientAllocator->GetTileLockAllocator()->AllocShmemSection(
1742 MOZ_ALIGN_WORD(sizeof(ShmReadLockInfo))(((sizeof(ShmReadLockInfo)) + 3) & ~3), &mShmemSection)) {
1743 ShmReadLockInfo* info = GetShmReadLockInfoPtr();
1744 info->readCount = 1;
1745 mAllocSuccess = true;
1746 }
1747}
1748
1749ShmemTextureReadLock::~ShmemTextureReadLock() {
1750 if (mClientAllocator) {
1751 // Release one read count that is added in constructor.
1752 // The count is kept for calling GetReadCount() by TextureClientPool.
1753 ReadUnlock();
1754 }
1755 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)
;
1756}
1757
1758bool ShmemTextureReadLock::Serialize(ReadLockDescriptor& aOutput,
1759 base::ProcessId aOther) {
1760 aOutput = ReadLockDescriptor(UntrustedShmemSection(
1761 Shmem(mShmemSection.shmem()), std::move(mShmemSection.offset()),
1762 std::move(mShmemSection.size())));
1763 return true;
1764}
1765
1766bool ShmemTextureReadLock::ReadLock() {
1767 if (!mAllocSuccess) {
1768 return false;
1769 }
1770 ShmReadLockInfo* info = GetShmReadLockInfoPtr();
1771 PR_ATOMIC_INCREMENT(&info->readCount)__sync_add_and_fetch(&info->readCount, 1);
1772 return true;
1773}
1774
1775int32_t ShmemTextureReadLock::ReadUnlock() {
1776 if (!mAllocSuccess) {
1777 return 0;
1778 }
1779 ShmReadLockInfo* info = GetShmReadLockInfoPtr();
1780 int32_t readCount = PR_ATOMIC_DECREMENT(&info->readCount)__sync_sub_and_fetch(&info->readCount, 1);
1781 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", 1781
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "readCount >= 0"
")"); do { MOZ_CrashSequence(__null, 1781); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1782 if (readCount > 0) {
1783 return readCount;
1784 }
1785 if (mClientAllocator) {
1786 if (nsCOMPtr<nsISerialEventTarget> thread = mClientAllocator->GetThread()) {
1787 if (thread->IsOnCurrentThread()) {
1788 if (auto* tileLockAllocator =
1789 mClientAllocator->GetTileLockAllocator()) {
1790 tileLockAllocator->DeallocShmemSection(mShmemSection);
1791 return readCount;
1792 }
1793 } else {
1794 thread->Dispatch(NS_NewRunnableFunction(
1795 __func__,
1796 [shmemSection = std::move(mShmemSection),
1797 clientAllocator = std::move(mClientAllocator)]() mutable {
1798 if (auto* tileLockAllocator =
1799 clientAllocator->GetTileLockAllocator()) {
1800 tileLockAllocator->DeallocShmemSection(shmemSection);
1801 } else {
1802 // we are on the compositor process, or IPC is down.
1803 FixedSizeSmallShmemSectionAllocator::FreeShmemSection(
1804 shmemSection);
1805 }
1806 }));
1807 return readCount;
1808 }
1809 }
1810 }
1811 // we are on the compositor process, or IPC is down.
1812 FixedSizeSmallShmemSectionAllocator::FreeShmemSection(mShmemSection);
1813 return readCount;
1814}
1815
1816int32_t ShmemTextureReadLock::GetReadCount() {
1817 if (!mAllocSuccess) {
1818 return 0;
1819 }
1820 ShmReadLockInfo* info = GetShmReadLockInfoPtr();
1821 return info->readCount;
1822}
1823
1824bool CrossProcessSemaphoreReadLock::Serialize(ReadLockDescriptor& aOutput,
1825 base::ProcessId aOther) {
1826 if (!mShared && IsValid()) {
1827 aOutput = ReadLockDescriptor(
1828 CrossProcessSemaphoreDescriptor(mSemaphore->CloneHandle()));
1829 mSemaphore->CloseHandle();
1830 mShared = true;
1831 return true;
1832 } else {
1833 return mShared;
1834 }
1835}
1836
1837void TextureClient::EnableBlockingReadLock() {
1838 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", 1838
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ShouldReadLock()"
")"); do { MOZ_CrashSequence(__null, 1838); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1839 if (!mReadLock) {
1840 mReadLock = new CrossProcessSemaphoreReadLock();
1841 }
1842}
1843
1844bool UpdateYCbCrTextureClient(TextureClient* aTexture,
1845 const PlanarYCbCrData& aData) {
1846 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"
, 1846); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTexture" ")"
); do { MOZ_CrashSequence(__null, 1846); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1847 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", 1847
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTexture->IsLocked()"
")"); do { MOZ_CrashSequence(__null, 1847); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1848 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"
, 1849); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTexture->GetFormat() == gfx::SurfaceFormat::YUV420"
") (" "This textureClient can only use YCbCr data" ")"); do {
MOZ_CrashSequence(__null, 1849); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
1849 "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"
, 1849); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTexture->GetFormat() == gfx::SurfaceFormat::YUV420"
") (" "This textureClient can only use YCbCr data" ")"); do {
MOZ_CrashSequence(__null, 1849); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
1850 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", 1850
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aTexture->IsImmutable()"
")"); do { MOZ_CrashSequence(__null, 1850); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1851 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", 1851
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aTexture->IsValid()"
")"); do { MOZ_CrashSequence(__null, 1851); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1852 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"
, 1852); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aData.mCbSkip == aData.mCrSkip"
")"); do { MOZ_CrashSequence(__null, 1852); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1853
1854 MappedYCbCrTextureData mapped;
1855 if (!aTexture->BorrowMappedYCbCrData(mapped)) {
1856 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"
, 1856)
;
1857 return false;
1858 }
1859
1860 uint32_t bytesPerPixel =
1861 BytesPerPixel(SurfaceFormatForColorDepth(aData.mColorDepth));
1862 MappedYCbCrTextureData srcData;
1863 srcData.y.data = aData.mYChannel;
1864 srcData.y.size = aData.YDataSize();
1865 srcData.y.stride = aData.mYStride;
1866 srcData.y.skip = aData.mYSkip;
1867 srcData.y.bytesPerPixel = bytesPerPixel;
1868 srcData.cb.data = aData.mCbChannel;
1869 srcData.cb.size = aData.CbCrDataSize();
1870 srcData.cb.stride = aData.mCbCrStride;
1871 srcData.cb.skip = aData.mCbSkip;
1872 srcData.cb.bytesPerPixel = bytesPerPixel;
1873 srcData.cr.data = aData.mCrChannel;
1874 srcData.cr.size = aData.CbCrDataSize();
1875 srcData.cr.stride = aData.mCbCrStride;
1876 srcData.cr.skip = aData.mCrSkip;
1877 srcData.cr.bytesPerPixel = bytesPerPixel;
1878 srcData.metadata = nullptr;
1879
1880 if (!srcData.CopyInto(mapped)) {
1881 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"
, 1881)
;
1882 return false;
1883 }
1884
1885 if (TextureRequiresLocking(aTexture->GetFlags())) {
1886 // We don't have support for proper locking yet, so we'll
1887 // have to be immutable instead.
1888 aTexture->MarkImmutable();
1889 }
1890 return true;
1891}
1892
1893already_AddRefed<TextureClient> TextureClient::CreateWithData(
1894 TextureData* aData, TextureFlags aFlags, LayersIPCChannel* aAllocator) {
1895 if (!aData) {
1896 return nullptr;
1897 }
1898 return MakeAndAddRef<TextureClient>(aData, aFlags, aAllocator);
1899}
1900
1901template <class PixelDataType>
1902static void copyData(PixelDataType* aDst,
1903 const MappedYCbCrChannelData& aChannelDst,
1904 PixelDataType* aSrc,
1905 const MappedYCbCrChannelData& aChannelSrc) {
1906 uint8_t* srcByte = reinterpret_cast<uint8_t*>(aSrc);
1907 const int32_t srcSkip = aChannelSrc.skip + 1;
1908 uint8_t* dstByte = reinterpret_cast<uint8_t*>(aDst);
1909 const int32_t dstSkip = aChannelDst.skip + 1;
1910 for (int32_t i = 0; i < aChannelSrc.size.height; ++i) {
1911 for (int32_t j = 0; j < aChannelSrc.size.width; ++j) {
1912 *aDst = *aSrc;
1913 aSrc += srcSkip;
1914 aDst += dstSkip;
1915 }
1916 srcByte += aChannelSrc.stride;
1917 aSrc = reinterpret_cast<PixelDataType*>(srcByte);
1918 dstByte += aChannelDst.stride;
1919 aDst = reinterpret_cast<PixelDataType*>(dstByte);
1920 }
1921}
1922
1923bool MappedYCbCrChannelData::CopyInto(MappedYCbCrChannelData& aDst) {
1924 if (!data || !aDst.data || size != aDst.size) {
1925 return false;
1926 }
1927
1928 if (stride == aDst.stride && skip == aDst.skip) {
1929 // fast path!
1930 // We assume that the padding in the destination is there for alignment
1931 // purposes and doesn't contain useful data.
1932 memcpy(aDst.data, data, stride * size.height);
1933 return true;
1934 }
1935
1936 if (aDst.skip == 0 && skip == 0) {
1937 // fast-ish path
1938 for (int32_t i = 0; i < size.height; ++i) {
1939 memcpy(aDst.data + i * aDst.stride, data + i * stride,
1940 size.width * bytesPerPixel);
1941 }
1942 return true;
1943 }
1944
1945 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", 1945
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytesPerPixel == 1 || bytesPerPixel == 2"
")"); do { MOZ_CrashSequence(__null, 1945); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1946 // slow path
1947 if (bytesPerPixel == 1) {
1948 copyData(aDst.data, aDst, data, *this);
1949 } else if (bytesPerPixel == 2) {
1950 copyData(reinterpret_cast<uint16_t*>(aDst.data), aDst,
1951 reinterpret_cast<uint16_t*>(data), *this);
1952 }
1953 return true;
1954}
1955
1956} // 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 RemoteDecoderVideoType GetRemoteDecoderVideoType() {
280 return RemoteDecoderVideoType::TypeNone;
281 }
282
283 virtual void OnForwardedToHost() {}
284
285 virtual TextureData* CreateSimilar(
286 LayersIPCChannel* aAllocator, LayersBackend aLayersBackend,
287 TextureFlags aFlags = TextureFlags::DEFAULT,
288 TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const {
289 return nullptr;
290 }
291
292 virtual bool UpdateFromSurface(gfx::SourceSurface* aSurface) {
293 return false;
294 };
295
296 virtual void SyncWithObject(RefPtr<SyncObjectClient> aSyncObject) {};
297
298 virtual TextureFlags GetTextureFlags() const {
299 return TextureFlags::NO_FLAGS;
300 }
301
302#ifdef XP_WIN
303 virtual D3D11TextureData* AsD3D11TextureData() { return nullptr; }
304 virtual DXGIYCbCrTextureData* AsDXGIYCbCrTextureData() { return nullptr; }
305#endif
306
307 virtual BufferTextureData* AsBufferTextureData() { return nullptr; }
308
309 virtual GPUVideoTextureData* AsGPUVideoTextureData() { return nullptr; }
310
311 virtual AndroidHardwareBufferTextureData*
312 AsAndroidHardwareBufferTextureData() {
313 return nullptr;
314 }
315
316 virtual RecordedTextureData* AsRecordedTextureData() { return nullptr; }
317
318 // It is used by AndroidHardwareBufferTextureData and
319 // SharedSurfaceTextureData. Returns buffer id when it owns
320 // AndroidHardwareBuffer. It is used only on android.
321 virtual Maybe<uint64_t> GetBufferId() const { return Nothing(); }
322
323 // The acquire fence is a fence that is used for waiting until rendering to
324 // its AHardwareBuffer is completed.
325 // It is used only on android.
326 virtual UniqueFileHandle GetAcquireFence() { return UniqueFileHandle(); }
327
328 virtual bool RequiresRefresh() const { return false; }
329
330 virtual already_AddRefed<FwdTransactionTracker> UseCompositableForwarder(
331 CompositableForwarder* aForwarder) {
332 return nullptr;
333 }
334
335 protected:
336 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); }
337};
338
339/**
340 * TextureClient is a thin abstraction over texture data that need to be shared
341 * between the content process and the compositor process. It is the
342 * content-side half of a TextureClient/TextureHost pair. A corresponding
343 * TextureHost lives on the compositor-side.
344 *
345 * TextureClient's primary purpose is to present texture data in a way that is
346 * understood by the IPC system. There are two ways to use it:
347 * - Use it to serialize image data that is not IPC-friendly (most likely
348 * involving a copy into shared memory)
349 * - preallocate it and paint directly into it, which avoids copy but requires
350 * the painting code to be aware of TextureClient (or at least the underlying
351 * shared memory).
352 *
353 * There is always one and only one TextureClient per TextureHost, and the
354 * TextureClient/Host pair only owns one buffer of image data through its
355 * lifetime. This means that the lifetime of the underlying shared data
356 * matches the lifetime of the TextureClient/Host pair. It also means
357 * TextureClient/Host do not implement double buffering, which is the
358 * responsibility of the compositable (which would use pairs of Textures).
359 * In order to send several different buffers to the compositor side, use
360 * several TextureClients.
361 */
362class TextureClient : public AtomicRefCountedWithFinalize<TextureClient> {
363 public:
364 TextureClient(TextureData* aData, TextureFlags aFlags,
365 LayersIPCChannel* aAllocator);
366
367 virtual ~TextureClient();
368
369 static already_AddRefed<TextureClient> CreateWithData(
370 TextureData* aData, TextureFlags aFlags, LayersIPCChannel* aAllocator);
371
372 // Creates and allocates a TextureClient usable with Moz2D.
373 static already_AddRefed<TextureClient> CreateForDrawing(
374 KnowsCompositor* aAllocator, gfx::SurfaceFormat aFormat,
375 gfx::IntSize aSize, BackendSelector aSelector, TextureFlags aTextureFlags,
376 TextureAllocationFlags flags = ALLOC_DEFAULT);
377
378 static already_AddRefed<TextureClient> CreateFromSurface(
379 KnowsCompositor* aAllocator, gfx::SourceSurface* aSurface,
380 BackendSelector aSelector, TextureFlags aTextureFlags,
381 TextureAllocationFlags aAllocFlags);
382
383 // Creates and allocates a TextureClient supporting the YCbCr format.
384 static already_AddRefed<TextureClient> CreateForYCbCr(
385 KnowsCompositor* aAllocator, const gfx::IntRect& aDisplay,
386 const gfx::IntSize& aYSize, uint32_t aYStride,
387 const gfx::IntSize& aCbCrSize, uint32_t aCbCrStride,
388 StereoMode aStereoMode, gfx::ColorDepth aColorDepth,
389 gfx::YUVColorSpace aYUVColorSpace, gfx::ColorRange aColorRange,
390 gfx::TransferFunction aTransferFunction,
391 gfx::ChromaSubsampling aSubsampling, TextureFlags aTextureFlags,
392 const Maybe<gfx::HDRMetadata>& aHDRMetadata = Nothing());
393
394 // Creates and allocates a TextureClient (can be accessed through raw
395 // pointers).
396 static already_AddRefed<TextureClient> CreateForRawBufferAccess(
397 KnowsCompositor* aAllocator, gfx::SurfaceFormat aFormat,
398 gfx::IntSize aSize, gfx::BackendType aMoz2dBackend,
399 TextureFlags aTextureFlags, TextureAllocationFlags flags = ALLOC_DEFAULT);
400
401 // Creates and allocates a TextureClient of the same type.
402 already_AddRefed<TextureClient> CreateSimilar(
403 LayersBackend aLayersBackend = LayersBackend::LAYERS_NONE,
404 TextureFlags aFlags = TextureFlags::DEFAULT,
405 TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const;
406
407 /**
408 * Locks the shared data, allowing the caller to get access to it.
409 *
410 * Please always lock/unlock when accessing the shared data.
411 * If Lock() returns false, you should not attempt to access the shared data.
412 */
413 bool Lock(OpenMode aMode);
414
415 void Unlock();
416
417 bool IsLocked() const { return mIsLocked; }
418
419 gfx::IntSize GetSize() const { return mInfo.size; }
420
421 gfx::SurfaceFormat GetFormat() const { return mInfo.format; }
422
423 /**
424 * Returns true if this texture has a synchronization mechanism (mutex, fence,
425 * etc.). Textures that do not implement synchronization should be immutable
426 * or should use immediate uploads (see TextureFlags in CompositorTypes.h)
427 * Even if a texture does not implement synchronization, Lock and Unlock need
428 * to be used appropriately since the latter are also there to map/numap data.
429 */
430 bool HasSynchronization() const { return mInfo.hasSynchronization; }
431
432 bool CanExposeDrawTarget() const { return mInfo.supportsMoz2D; }
433
434 bool CanExposeMappedData() const { return mInfo.canExposeMappedData; }
435
436 /**
437 * Returns a DrawTarget to draw into the TextureClient.
438 * This function should never be called when not on the main thread!
439 *
440 * This must never be called on a TextureClient that is not sucessfully
441 * locked. When called several times within one Lock/Unlock pair, this method
442 * should return the same DrawTarget. The DrawTarget is automatically flushed
443 * by the TextureClient when the latter is unlocked, and the DrawTarget that
444 * will be returned within the next lock/unlock pair may or may not be the
445 * same object. Do not keep references to the DrawTarget outside of the
446 * lock/unlock pair.
447 *
448 * This is typically used as follows:
449 *
450 * if (!texture->Lock(OpenMode::OPEN_READ_WRITE)) {
451 * return false;
452 * }
453 * {
454 * // Restrict this code's scope to ensure all references to dt are gone
455 * // when Unlock is called.
456 * DrawTarget* dt = texture->BorrowDrawTarget();
457 * // use the draw target ...
458 * }
459 * texture->Unlock();
460 *
461 */
462 gfx::DrawTarget* BorrowDrawTarget();
463
464 /**
465 * When the TextureClient is not being Unlocked, this can be used to inform it
466 * that drawing has finished until the next BorrowDrawTarget.
467 */
468 void EndDraw();
469
470 already_AddRefed<gfx::SourceSurface> BorrowSnapshot();
471
472 void ReturnSnapshot(already_AddRefed<gfx::SourceSurface> aSnapshot);
473
474 /**
475 * Similar to BorrowDrawTarget but provides direct access to the texture's
476 * bits instead of a DrawTarget.
477 */
478 bool BorrowMappedData(MappedTextureData&);
479 bool BorrowMappedYCbCrData(MappedYCbCrTextureData&);
480
481 /**
482 * This function can be used to update the contents of the TextureClient
483 * off the main thread.
484 */
485 void UpdateFromSurface(gfx::SourceSurface* aSurface);
486
487 /**
488 * This method is strictly for debugging. It causes locking and
489 * needless copies.
490 */
491 already_AddRefed<gfx::DataSourceSurface> GetAsSurface();
492
493 /**
494 * Copies a rectangle from this texture client to a position in aTarget.
495 * It is assumed that the necessary locks are in place; so this should at
496 * least have a read lock and aTarget should at least have a write lock.
497 */
498 bool CopyToTextureClient(TextureClient* aTarget, const gfx::IntRect* aRect,
499 const gfx::IntPoint* aPoint);
500
501 /**
502 * Allocate a TextureChild actor.
503 *
504 * TextureChild is an implementation detail of TextureClient that is not
505 * exposed to the rest of the code base.
506 */
507 static already_AddRefed<PTextureChild> CreateIPDLActor();
508
509 /**
510 * Get the TextureClient corresponding to the actor passed in parameter.
511 */
512 static already_AddRefed<TextureClient> AsTextureClient(PTextureChild* actor);
513
514 /**
515 * TextureFlags contain important information about various aspects
516 * of the texture, like how its liferime is managed, and how it
517 * should be displayed.
518 * See TextureFlags in CompositorTypes.h.
519 */
520 TextureFlags GetFlags() const { return mFlags; }
521
522 bool HasFlags(TextureFlags aFlags) const {
523 return (mFlags & aFlags) == aFlags;
524 }
525
526 void AddFlags(TextureFlags aFlags);
527
528 void RemoveFlags(TextureFlags aFlags);
529
530 // Must not be called when TextureClient is in use by CompositableClient.
531 void RecycleTexture(TextureFlags aFlags);
532
533 /**
534 * After being shared with the compositor side, an immutable texture is never
535 * modified, it can only be read. It is safe to not Lock/Unlock immutable
536 * textures.
537 */
538 bool IsImmutable() const { return !!(mFlags & TextureFlags::IMMUTABLE); }
539
540 void MarkImmutable() { AddFlags(TextureFlags::IMMUTABLE); }
541
542 bool IsSharedWithCompositor() const;
543
544 /**
545 * If this method returns false users of TextureClient are not allowed
546 * to access the shared data.
547 */
548 bool IsValid() const { return !!mData; }
549
550 /**
551 * Called when TextureClient is added to CompositableClient.
552 */
553 void SetAddedToCompositableClient();
554
555 /**
556 * If this method retuns false, TextureClient is already added to
557 * CompositableClient, since its creation or recycling.
558 */
559 bool IsAddedToCompositableClient() const {
560 return mAddedToCompositableClient;
561 }
562
563 /**
564 * Create and init the TextureChild/Parent IPDL actor pair
565 * with a CompositableForwarder.
566 *
567 * Should be called only once per TextureClient.
568 * The TextureClient must not be locked when calling this method.
569 */
570 bool InitIPDLActor(CompositableForwarder* aForwarder);
571
572 /**
573 * Create and init the TextureChild/Parent IPDL actor pair
574 * with a TextureForwarder.
575 *
576 * Should be called only once per TextureClient.
577 * The TextureClient must not be locked when calling this method.
578 */
579 bool InitIPDLActor(KnowsCompositor* aKnowsCompositor,
580 const dom::ContentParentId& aContentId);
581
582 /**
583 * Return a pointer to the IPDLActor.
584 *
585 * This is to be used with IPDL messages only. Do not store the returned
586 * pointer.
587 */
588 PTextureChild* GetIPDLActor();
589
590 /**
591 * Triggers the destruction of the shared data and the corresponding
592 * TextureHost.
593 *
594 * If the texture flags contain TextureFlags::DEALLOCATE_CLIENT, the
595 * destruction will be synchronously coordinated with the compositor side,
596 * otherwise it will be done asynchronously.
597 */
598 void Destroy();
599
600 /**
601 * Track how much of this texture is wasted.
602 * For example we might allocate a 256x256 tile but only use 10x10.
603 */
604 void SetWaste(int aWasteArea) {
605 mWasteTracker.Update(aWasteArea, BytesPerPixel(GetFormat()));
606 }
607
608 void SyncWithObject(RefPtr<SyncObjectClient> aSyncObject) {
609 mData->SyncWithObject(aSyncObject);
610 }
611
612 LayersIPCChannel* GetAllocator() { return mAllocator; }
613
614 ITextureClientRecycleAllocator* GetRecycleAllocator() {
615 return mRecycleAllocator;
616 }
617 void SetRecycleAllocator(ITextureClientRecycleAllocator* aAllocator);
618
619 /// If you add new code that uses this method, you are probably doing
620 /// something wrong.
621 TextureData* GetInternalData() { return mData; }
622 const TextureData* GetInternalData() const { return mData; }
623
624 /**
625 * Serializes the underlying TextureData into aDescriptor. Returns false if
626 * the TextureData has already been destroyed. Safe to call from any thread
627 * concurrently with Destroy().
628 */
629 bool ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor);
630
631 uint64_t GetSerial() const { return mSerial; }
632 void GetSurfaceDescriptorRemoteDecoder(
633 SurfaceDescriptorRemoteDecoder* aOutDesc);
634
635 void CancelWaitForNotifyNotUsed();
636
637 /**
638 * Set last transaction id of CompositableForwarder.
639 *
640 * Called when TextureClient has TextureFlags::RECYCLE flag.
641 * When CompositableForwarder forwards the TextureClient with
642 * TextureFlags::RECYCLE, it holds TextureClient's ref until host side
643 * releases it. The host side sends TextureClient release message.
644 * The id is used to check if the message is for the last TextureClient
645 * forwarding.
646 */
647 void SetLastFwdTransactionId(uint64_t aTransactionId) {
648 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"
, 648); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mFwdTransactionId <= aTransactionId"
")"); do { MOZ_CrashSequence(__null, 648); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
649 mFwdTransactionId = aTransactionId;
650 }
651
652 uint64_t GetLastFwdTransactionId() { return mFwdTransactionId; }
653
654 bool HasReadLock() const {
655 MutexAutoLock lock(mMutex);
656 return !!mReadLock;
657 }
658
659 int32_t GetNonBlockingReadLockCount() {
660 MutexAutoLock lock(mMutex);
661 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"
, 661)
) {
662 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"
, 662); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "No read lock created yet?" ")");
do { MOZ_CrashSequence(__null, 662); __attribute__((nomerge)
) ::abort(); } while (false); } } while (false)
;
663 return 0;
664 }
665 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"
, 666); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mReadLock->AsNonBlockingLock()"
") (" "Can only check locked for non-blocking locks!" ")"); do
{ MOZ_CrashSequence(__null, 666); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
666 "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"
, 666); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mReadLock->AsNonBlockingLock()"
") (" "Can only check locked for non-blocking locks!" ")"); do
{ MOZ_CrashSequence(__null, 666); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
667 return mReadLock->AsNonBlockingLock()->GetReadCount();
668 }
669
670 bool IsReadLocked();
671
672 bool ShouldReadLock() const {
673 return bool(mFlags & (TextureFlags::NON_BLOCKING_READ_LOCK |
674 TextureFlags::BLOCKING_READ_LOCK));
675 }
676
677 bool TryReadLock();
678 void ReadUnlock();
679
680 void SetUpdated() { mUpdated = true; }
681
682 void OnPrepareForwardToHost();
683 void OnAbandonForwardToHost();
684 bool OnForwardedToHost();
685
686 // Mark that the TextureClient will be used by the paint thread, and should
687 // not free its underlying texture data. This must only be called from the
688 // main thread.
689 void AddPaintThreadRef();
690
691 // Mark that the TextureClient is no longer in use by the PaintThread. This
692 // must only be called from the PaintThread.
693 void DropPaintThreadRef();
694
695 wr::MaybeExternalImageId GetExternalImageKey() { return mExternalImageId; }
696
697 private:
698 static void TextureClientRecycleCallback(TextureClient* aClient,
699 void* aClosure);
700
701 static already_AddRefed<TextureClient> CreateForDrawing(
702 TextureForwarder* aAllocator, gfx::SurfaceFormat aFormat,
703 gfx::IntSize aSize, KnowsCompositor* aKnowsCompositor,
704 BackendSelector aSelector, TextureFlags aTextureFlags,
705 TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT);
706
707 static already_AddRefed<TextureClient> CreateForRawBufferAccess(
708 LayersIPCChannel* aAllocator, gfx::SurfaceFormat aFormat,
709 gfx::IntSize aSize, gfx::BackendType aMoz2dBackend,
710 LayersBackend aLayersBackend, TextureFlags aTextureFlags,
711 TextureAllocationFlags flags = ALLOC_DEFAULT);
712
713 void EnsureHasReadLock() MOZ_REQUIRES(mMutex)__attribute__((exclusive_locks_required(mMutex)));
714 void EnableReadLock() MOZ_REQUIRES(mMutex)__attribute__((exclusive_locks_required(mMutex)));
715 void EnableBlockingReadLock() MOZ_REQUIRES(mMutex)__attribute__((exclusive_locks_required(mMutex)));
716
717 /**
718 * Called once, during the destruction of the Texture, on the thread in which
719 * texture's reference count reaches 0 (could be any thread).
720 *
721 * Here goes the shut-down code that uses virtual methods.
722 * Must only be called by Release().
723 */
724 void Finalize() {}
725
726 friend class AtomicRefCountedWithFinalize<TextureClient>;
727
728 protected:
729 void LockActor() const;
730 void UnlockActor() const;
731
732 TextureData::Info mInfo;
733 mutable Mutex mMutex;
734
735 RefPtr<LayersIPCChannel> mAllocator;
736 RefPtr<TextureChild> mActor;
737 RefPtr<ITextureClientRecycleAllocator> mRecycleAllocator;
738 RefPtr<TextureReadLock> mReadLock MOZ_GUARDED_BY(mMutex)__attribute__((guarded_by(mMutex)));
739
740 TextureData* mData;
741 RefPtr<gfx::DrawTarget> mBorrowedDrawTarget;
742 bool mBorrowedSnapshot = false;
743
744 TextureFlags mFlags;
745
746 gl::GfxTextureWasteTracker mWasteTracker;
747
748 OpenMode mOpenMode;
749 bool mIsLocked;
750 bool mIsReadLocked MOZ_GUARDED_BY(mMutex)__attribute__((guarded_by(mMutex)));
751 bool mIsPendingForwardReadLocked MOZ_GUARDED_BY(mMutex)__attribute__((guarded_by(mMutex))) = false;
752 // This member tracks that the texture was written into until the update
753 // is sent to the compositor. We need this remember to lock mReadLock on
754 // behalf of the compositor just before sending the notification.
755 bool mUpdated;
756
757 // Used when TextureClient is recycled with TextureFlags::RECYCLE flag.
758 bool mAddedToCompositableClient;
759
760 uint64_t mFwdTransactionId;
761
762 // Serial id of TextureClient. It is unique in current process.
763 const uint64_t mSerial;
764
765 // When non-zero, texture data must not be freed.
766 mozilla::Atomic<uintptr_t> mPaintThreadRefs;
767
768 // External image id. It is unique if it is allocated.
769 // The id is allocated in TextureClient::InitIPDLActor().
770 // Its allocation is supported by
771 // CompositorBridgeChild and ImageBridgeChild for now.
772 wr::MaybeExternalImageId mExternalImageId;
773
774 // Used to assign serial ids of TextureClient.
775 static mozilla::Atomic<uint64_t> sSerialCounter;
776
777 friend class TextureChild;
778 friend void TestTextureClientSurface(TextureClient*, gfxImageSurface*);
779 friend void TestTextureClientYCbCr(TextureClient*, PlanarYCbCrData&);
780 friend void TestYCbCrDescriptorTransferFunction(gfx::TransferFunction,
781 Maybe<gfx::HDRMetadata>,
782 RefPtr<ImageBridgeChild>);
783 friend already_AddRefed<TextureHost> CreateTextureHostWithBackend(
784 TextureClient*, ISurfaceAllocator*, LayersBackend&);
785};
786
787/**
788 * Task that releases TextureClient pointer on a specified thread.
789 */
790class TextureClientReleaseTask : public Runnable {
791 public:
792 explicit TextureClientReleaseTask(TextureClient* aClient)
793 : Runnable("layers::TextureClientReleaseTask"), mTextureClient(aClient) {}
794
795 NS_IMETHODvirtual nsresult Run() override {
796 mTextureClient = nullptr;
797 return NS_OK;
798 }
799
800 private:
801 RefPtr<TextureClient> mTextureClient;
802};
803
804// Automatically lock and unlock a texture. Since texture locking is fallible,
805// Succeeded() must be checked on the guard object before proceeding.
806class MOZ_RAII TextureClientAutoLock {
807 public:
808 TextureClientAutoLock(TextureClient* aTexture, OpenMode aMode)
809 : mTexture(aTexture), mSucceeded(false) {
810 mSucceeded = mTexture->Lock(aMode);
811#ifdef DEBUG1
812 mChecked = false;
813#endif
814 }
815 ~TextureClientAutoLock() {
816 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"
, 816); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mChecked" ")"
); do { MOZ_CrashSequence(__null, 816); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
817 if (mSucceeded) {
818 mTexture->Unlock();
819 }
820 }
821
822 bool Succeeded() {
823#ifdef DEBUG1
824 mChecked = true;
825#endif
826 return mSucceeded;
827 }
828
829 private:
830 TextureClient* mTexture;
831#ifdef DEBUG1
832 bool mChecked;
833#endif
834 bool mSucceeded;
835};
836
837/// Convenience function to set the content of ycbcr texture.
838bool UpdateYCbCrTextureClient(TextureClient* aTexture,
839 const PlanarYCbCrData& aData);
840
841TextureType PreferredCanvasTextureType(KnowsCompositor* aKnowsCompositor);
842
843} // namespace layers
844} // namespace mozilla
845
846#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 */