Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/mozilla/RefPtr.h
Warning:line 287, column 12
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

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

/var/lib/jenkins/workspace/firefox-scan-build/gfx/layers/client/TextureClient.cpp

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

/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/mozilla/RefPtr.h

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

/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/mozilla/layers/TextureClient.h

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

/var/lib/jenkins/workspace/firefox-scan-build/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
45MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void* operator new[](size_t size,
46 const std::nothrow_t&) noexcept(true) {
47 return malloc_implmalloc(size);
48}
49
50MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void operator delete(void* ptr) noexcept(true) {
51 return free_implfree(ptr);
17
Memory is released
52}
53
54MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void operator delete(void* ptr,
55 const std::nothrow_t&) noexcept(true) {
56 return free_implfree(ptr);
57}
58
59MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void operator delete[](void* ptr) noexcept(true) {
60 return free_implfree(ptr);
61}
62
63MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void operator delete[](
64 void* ptr, const std::nothrow_t&) noexcept(true) {
65 return free_implfree(ptr);
66}
67
68#if defined(XP_WIN)
69// We provide the global sized delete overloads unconditionally because the
70// MSVC runtime headers do, despite compiling with /Zc:sizedDealloc-
71MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void operator delete(void* ptr,
72 size_t /*size*/) noexcept(true) {
73 return free_implfree(ptr);
74}
75
76MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void operator delete[](void* ptr,
77 size_t /*size*/) noexcept(true) {
78 return free_implfree(ptr);
79}
80#endif
81
82#endif /* mozilla_cxxalloc_h */