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