/work/obj-fuzz/dist/include/mozilla/gfx/Logging.h
Line | Count | Source (jump to first uncovered line) |
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_LOGGING_H_ |
8 | | #define MOZILLA_GFX_LOGGING_H_ |
9 | | |
10 | | #include <string> |
11 | | #include <sstream> |
12 | | #include <stdio.h> |
13 | | #include <vector> |
14 | | |
15 | | #ifdef MOZ_LOGGING |
16 | | #include "mozilla/Logging.h" |
17 | | #endif |
18 | | #include "mozilla/Tuple.h" |
19 | | |
20 | | #if defined(MOZ_WIDGET_ANDROID) |
21 | | #include "nsDebug.h" |
22 | | #endif |
23 | | #include "2D.h" |
24 | | #include "Point.h" |
25 | | #include "BaseRect.h" |
26 | | #include "Matrix.h" |
27 | | #include "LoggingConstants.h" |
28 | | |
29 | | #if defined(MOZ_LOGGING) |
30 | | extern GFX2D_API mozilla::LogModule* GetGFX2DLog(); |
31 | | #endif |
32 | | |
33 | | namespace mozilla { |
34 | | namespace gfx { |
35 | | |
36 | | #if defined(MOZ_LOGGING) |
37 | | inline mozilla::LogLevel PRLogLevelForLevel(int aLevel) { |
38 | | switch (aLevel) { |
39 | | case LOG_CRITICAL: |
40 | | return LogLevel::Error; |
41 | | case LOG_WARNING: |
42 | | return LogLevel::Warning; |
43 | | case LOG_DEBUG: |
44 | | return LogLevel::Debug; |
45 | | case LOG_DEBUG_PRLOG: |
46 | | return LogLevel::Debug; |
47 | | case LOG_EVERYTHING: |
48 | | return LogLevel::Error; |
49 | | } |
50 | | return LogLevel::Debug; |
51 | | } |
52 | | #endif |
53 | | |
54 | | class LoggingPrefs |
55 | | { |
56 | | public: |
57 | | // Used to choose the level of logging we get. The higher the number, |
58 | | // the more logging we get. Value of zero will give you no logging, |
59 | | // 1 just errors, 2 adds warnings and 3 or 4 add debug logging. |
60 | | // In addition to setting the value to 4, you will need to set the |
61 | | // environment variable MOZ_LOG to gfx:4. See mozilla/Logging.h for details. |
62 | | static int32_t sGfxLogLevel; |
63 | | }; |
64 | | |
65 | | /// Graphics logging is available in both debug and release builds and is |
66 | | /// controlled with a gfx.logging.level preference. If not set, the default |
67 | | /// for the preference is 5 in the debug builds, 1 in the release builds. |
68 | | /// |
69 | | /// gfxDebug only works in the debug builds, and is used for information |
70 | | /// level messages, helping with debugging. In addition to only working |
71 | | /// in the debug builds, the value of the above preference of 3 or higher |
72 | | /// is required. |
73 | | /// |
74 | | /// gfxWarning messages are available in both debug and release builds, |
75 | | /// on by default in the debug builds, and off by default in the release builds. |
76 | | /// Setting the preference gfx.logging.level to a value of 2 or higher will |
77 | | /// show the warnings. |
78 | | /// |
79 | | /// gfxCriticalError is available in debug and release builds by default. |
80 | | /// It is only unavailable if gfx.logging.level is set to 0 (or less.) |
81 | | /// It outputs the message to stderr or equivalent, like gfxWarning. |
82 | | /// In the event of a crash, the crash report is annotated with first and |
83 | | /// the last few of these errors, under the key GraphicsCriticalError. |
84 | | /// The total number of errors stored in the crash report is controlled |
85 | | /// by preference gfx.logging.crash.length. |
86 | | /// |
87 | | /// On platforms that support MOZ_LOGGING, the story is slightly more involved. |
88 | | /// In that case, unless gfx.logging.level is set to 4 or higher, the output |
89 | | /// is further controlled by the "gfx2d" logging module. However, in the case |
90 | | /// where such module would disable the output, in all but gfxDebug cases, |
91 | | /// we will still send a printf. |
92 | | |
93 | | // The range is due to the values set in Histograms.json |
94 | | enum class LogReason : int { |
95 | | MustBeMoreThanThis = -1, |
96 | | // Start. Do not insert, always add at end. If you remove items, |
97 | | // make sure the other items retain their values. |
98 | | D3D11InvalidCallDeviceRemoved = 0, |
99 | | D3D11InvalidCall, |
100 | | D3DLockTimeout, |
101 | | D3D10FinalizeFrame, |
102 | | D3D11FinalizeFrame, |
103 | | D3D10SyncLock, |
104 | | D3D11SyncLock, |
105 | | D2D1NoWriteMap, |
106 | | JobStatusError, |
107 | | FilterInputError, |
108 | | FilterInputData, // 10 |
109 | | FilterInputRect, |
110 | | FilterInputSet, |
111 | | FilterInputFormat, |
112 | | FilterNodeD2D1Target, |
113 | | FilterNodeD2D1Backend, |
114 | | SourceSurfaceIncompatible, |
115 | | GlyphAllocFailedCairo, |
116 | | GlyphAllocFailedCG, |
117 | | InvalidRect, |
118 | | CannotDraw3D, // 20 |
119 | | IncompatibleBasicTexturedEffect, |
120 | | InvalidFont, |
121 | | PAllocTextureBackendMismatch, |
122 | | GetFontFileDataFailed, |
123 | | MessageChannelCloseFailure, |
124 | | MessageChannelInvalidHandle, |
125 | | TextureAliveAfterShutdown, |
126 | | InvalidContext, |
127 | | InvalidCommandList, |
128 | | AsyncTransactionTimeout, // 30 |
129 | | TextureCreation, |
130 | | InvalidCacheSurface, |
131 | | AlphaWithBasicClient, |
132 | | UnbalancedClipStack, |
133 | | ProcessingError, |
134 | | InvalidDrawTarget, |
135 | | NativeFontResourceNotFound, |
136 | | UnscaledFontNotFound, |
137 | | ScaledFontNotFound, |
138 | | InvalidLayerType, |
139 | | // End |
140 | | MustBeLessThanThis = 101, |
141 | | }; |
142 | | |
143 | | struct BasicLogger |
144 | | { |
145 | | // For efficiency, this method exists and copies the logic of the |
146 | | // OutputMessage below. If making any changes here, also make it |
147 | | // in the appropriate places in that method. |
148 | | static bool ShouldOutputMessage(int aLevel) { |
149 | | if (LoggingPrefs::sGfxLogLevel >= aLevel) { |
150 | | #if defined(MOZ_WIDGET_ANDROID) |
151 | | return true; |
152 | | #else |
153 | | #if defined(MOZ_LOGGING) |
154 | | if (MOZ_LOG_TEST(GetGFX2DLog(), PRLogLevelForLevel(aLevel))) { |
155 | | return true; |
156 | | } else |
157 | | #endif |
158 | | if ((LoggingPrefs::sGfxLogLevel >= LOG_DEBUG_PRLOG) || |
159 | | (aLevel < LOG_DEBUG)) { |
160 | | return true; |
161 | | } |
162 | | #endif |
163 | | } |
164 | | return false; |
165 | | } |
166 | | |
167 | | // Only for really critical errors. |
168 | | static void CrashAction(LogReason aReason) {} |
169 | | |
170 | | static void OutputMessage(const std::string &aString, |
171 | | int aLevel, |
172 | | bool aNoNewline) { |
173 | | // This behavior (the higher the preference, the more we log) |
174 | | // is consistent with what prlog does in general. Note that if prlog |
175 | | // is in the build, but disabled, we will printf if the preferences |
176 | | // requires us to log something (see sGfxLogLevel for the special |
177 | | // treatment of LOG_DEBUG and LOG_DEBUG_PRLOG) |
178 | | // |
179 | | // If making any logic changes to this method, you should probably |
180 | | // make the corresponding change in the ShouldOutputMessage method |
181 | | // above. |
182 | | if (LoggingPrefs::sGfxLogLevel >= aLevel) { |
183 | | #if defined(MOZ_WIDGET_ANDROID) |
184 | | printf_stderr("%s%s", aString.c_str(), aNoNewline ? "" : "\n"); |
185 | | #else |
186 | | #if defined(MOZ_LOGGING) |
187 | | if (MOZ_LOG_TEST(GetGFX2DLog(), PRLogLevelForLevel(aLevel))) { |
188 | | MOZ_LOG(GetGFX2DLog(), PRLogLevelForLevel(aLevel), ("%s%s", aString.c_str(), aNoNewline ? "" : "\n")); |
189 | | } else |
190 | | #endif |
191 | | if ((LoggingPrefs::sGfxLogLevel >= LOG_DEBUG_PRLOG) || |
192 | | (aLevel < LOG_DEBUG)) { |
193 | | printf("%s%s", aString.c_str(), aNoNewline ? "" : "\n"); |
194 | | } |
195 | | #endif |
196 | | } |
197 | | } |
198 | | }; |
199 | | |
200 | | struct CriticalLogger { |
201 | | static void OutputMessage(const std::string &aString, int aLevel, bool aNoNewline); |
202 | | static void CrashAction(LogReason aReason); |
203 | | }; |
204 | | |
205 | | // The int is the index of the Log call; if the number of logs exceeds some preset |
206 | | // capacity we may not get all of them, so the indices help figure out which |
207 | | // ones we did save. The double is expected to be the "TimeDuration", |
208 | | // time in seconds since the process creation. |
209 | | typedef mozilla::Tuple<int32_t,std::string,double> LoggingRecordEntry; |
210 | | |
211 | | // Implement this interface and init the Factory with an instance to |
212 | | // forward critical logs. |
213 | | typedef std::vector<LoggingRecordEntry> LoggingRecord; |
214 | | class LogForwarder { |
215 | | public: |
216 | 0 | virtual ~LogForwarder() {} |
217 | | virtual void Log(const std::string &aString) = 0; |
218 | | virtual void CrashAction(LogReason aReason) = 0; |
219 | | virtual bool UpdateStringsVector(const std::string& aString) = 0; |
220 | | |
221 | | // Provide a copy of the logs to the caller. |
222 | | virtual LoggingRecord LoggingRecordCopy() = 0; |
223 | | }; |
224 | | |
225 | | class NoLog |
226 | | { |
227 | | public: |
228 | 0 | NoLog() {} |
229 | 0 | ~NoLog() {} |
230 | | |
231 | | // No-op |
232 | 0 | MOZ_IMPLICIT NoLog(const NoLog&) {} |
233 | | |
234 | | template<typename T> |
235 | 0 | NoLog &operator <<(const T &aLogText) { return *this; } Unexecuted instantiation: mozilla::gfx::NoLog& mozilla::gfx::NoLog::operator<< <char [40]>(char const (&) [40]) Unexecuted instantiation: mozilla::gfx::NoLog& mozilla::gfx::NoLog::operator<< <int>(int const&) Unexecuted instantiation: mozilla::gfx::NoLog& mozilla::gfx::NoLog::operator<< <char [2]>(char const (&) [2]) Unexecuted instantiation: mozilla::gfx::NoLog& mozilla::gfx::NoLog::operator<< <char [39]>(char const (&) [39]) Unexecuted instantiation: mozilla::gfx::NoLog& mozilla::gfx::NoLog::operator<< <unsigned long>(unsigned long const&) Unexecuted instantiation: mozilla::gfx::NoLog& mozilla::gfx::NoLog::operator<< <char [7]>(char const (&) [7]) Unexecuted instantiation: mozilla::gfx::NoLog& mozilla::gfx::NoLog::operator<< <char [35]>(char const (&) [35]) Unexecuted instantiation: mozilla::gfx::NoLog& mozilla::gfx::NoLog::operator<< <char [43]>(char const (&) [43]) Unexecuted instantiation: mozilla::gfx::NoLog& mozilla::gfx::NoLog::operator<< <mozilla::dom::CanvasRenderingContext2D::RenderingMode>(mozilla::dom::CanvasRenderingContext2D::RenderingMode const&) |
236 | | }; |
237 | | |
238 | | enum class LogOptions : int { |
239 | | NoNewline = 0x01, |
240 | | AutoPrefix = 0x02, |
241 | | AssertOnCall = 0x04, |
242 | | CrashAction = 0x08, |
243 | | }; |
244 | | |
245 | | template<typename T> |
246 | | struct Hexa { |
247 | 0 | explicit Hexa(T aVal) : mVal(aVal) {} Unexecuted instantiation: mozilla::gfx::Hexa<unsigned long>::Hexa(unsigned long) Unexecuted instantiation: mozilla::gfx::Hexa<mozilla::gfx::ReferencePtr>::Hexa(mozilla::gfx::ReferencePtr) Unexecuted instantiation: mozilla::gfx::Hexa<RefPtr<mozilla::gfx::PrintTarget> >::Hexa(RefPtr<mozilla::gfx::PrintTarget>) Unexecuted instantiation: mozilla::gfx::Hexa<int>::Hexa(int) Unexecuted instantiation: mozilla::gfx::Hexa<unsigned int>::Hexa(unsigned int) Unexecuted instantiation: mozilla::gfx::Hexa<RefPtr<mozilla::gfx::DrawTarget> >::Hexa(RefPtr<mozilla::gfx::DrawTarget>) Unexecuted instantiation: mozilla::gfx::Hexa<mozilla::gfx::SourceSurface*>::Hexa(mozilla::gfx::SourceSurface*) Unexecuted instantiation: mozilla::gfx::Hexa<RefPtr<mozilla::gfx::SourceSurface> >::Hexa(RefPtr<mozilla::gfx::SourceSurface>) Unexecuted instantiation: mozilla::gfx::Hexa<mozilla::gfx::DrawTarget*>::Hexa(mozilla::gfx::DrawTarget*) Unexecuted instantiation: mozilla::gfx::Hexa<mozilla::gl::GLContext*>::Hexa(mozilla::gl::GLContext*) |
248 | | T mVal; |
249 | | }; |
250 | | template<typename T> |
251 | 0 | Hexa<T> hexa(T val) { return Hexa<T>(val); } Unexecuted instantiation: mozilla::gfx::Hexa<unsigned long> mozilla::gfx::hexa<unsigned long>(unsigned long) Unexecuted instantiation: mozilla::gfx::Hexa<mozilla::gfx::ReferencePtr> mozilla::gfx::hexa<mozilla::gfx::ReferencePtr>(mozilla::gfx::ReferencePtr) Unexecuted instantiation: mozilla::gfx::Hexa<RefPtr<mozilla::gfx::PrintTarget> > mozilla::gfx::hexa<RefPtr<mozilla::gfx::PrintTarget> >(RefPtr<mozilla::gfx::PrintTarget>) Unexecuted instantiation: mozilla::gfx::Hexa<int> mozilla::gfx::hexa<int>(int) Unexecuted instantiation: mozilla::gfx::Hexa<unsigned int> mozilla::gfx::hexa<unsigned int>(unsigned int) Unexecuted instantiation: mozilla::gfx::Hexa<RefPtr<mozilla::gfx::DrawTarget> > mozilla::gfx::hexa<RefPtr<mozilla::gfx::DrawTarget> >(RefPtr<mozilla::gfx::DrawTarget>) Unexecuted instantiation: mozilla::gfx::Hexa<mozilla::gfx::SourceSurface*> mozilla::gfx::hexa<mozilla::gfx::SourceSurface*>(mozilla::gfx::SourceSurface*) Unexecuted instantiation: mozilla::gfx::Hexa<RefPtr<mozilla::gfx::SourceSurface> > mozilla::gfx::hexa<RefPtr<mozilla::gfx::SourceSurface> >(RefPtr<mozilla::gfx::SourceSurface>) Unexecuted instantiation: mozilla::gfx::Hexa<mozilla::gfx::DrawTarget*> mozilla::gfx::hexa<mozilla::gfx::DrawTarget*>(mozilla::gfx::DrawTarget*) Unexecuted instantiation: mozilla::gfx::Hexa<mozilla::gl::GLContext*> mozilla::gfx::hexa<mozilla::gl::GLContext*>(mozilla::gl::GLContext*) |
252 | | |
253 | | template<int L, typename Logger = BasicLogger> |
254 | | class Log |
255 | | { |
256 | | public: |
257 | | // The default is to have the prefix, have the new line, and for critical |
258 | | // logs assert on each call. |
259 | | static int DefaultOptions(bool aWithAssert = true) { |
260 | | return (int(LogOptions::AutoPrefix) | |
261 | | (aWithAssert ? int(LogOptions::AssertOnCall) : 0)); |
262 | | } |
263 | | |
264 | | // Note that we're calling BasicLogger::ShouldOutputMessage, rather than |
265 | | // Logger::ShouldOutputMessage. Since we currently don't have a different |
266 | | // version of that method for different loggers, this is OK. Once we do, |
267 | | // change BasicLogger::ShouldOutputMessage to Logger::ShouldOutputMessage. |
268 | | explicit Log(int aOptions = Log::DefaultOptions(L == LOG_CRITICAL), |
269 | | LogReason aReason = LogReason::MustBeMoreThanThis) |
270 | | : mOptions(0) |
271 | | , mLogIt(false) |
272 | | { |
273 | | Init(aOptions, BasicLogger::ShouldOutputMessage(L), aReason); |
274 | | } |
275 | | |
276 | | ~Log() { |
277 | | Flush(); |
278 | | } |
279 | | |
280 | | void Flush() { |
281 | | if (MOZ_LIKELY(!LogIt())) return; |
282 | | |
283 | | std::string str = mMessage.str(); |
284 | | if (!str.empty()) { |
285 | | WriteLog(str); |
286 | | } |
287 | | mMessage.str(""); |
288 | | } |
289 | | |
290 | | Log &operator <<(char aChar) { |
291 | | if (MOZ_UNLIKELY(LogIt())) { |
292 | | mMessage << aChar; |
293 | | } |
294 | | return *this; |
295 | | } |
296 | | Log &operator <<(const std::string &aLogText) { |
297 | | if (MOZ_UNLIKELY(LogIt())) { |
298 | | mMessage << aLogText; |
299 | | } |
300 | | return *this; |
301 | | } |
302 | | Log &operator <<(const char aStr[]) { |
303 | | if (MOZ_UNLIKELY(LogIt())) { |
304 | | mMessage << static_cast<const char*>(aStr); |
305 | | } |
306 | | return *this; |
307 | | } |
308 | | Log &operator <<(bool aBool) { |
309 | | if (MOZ_UNLIKELY(LogIt())) { |
310 | | mMessage << (aBool ? "true" : "false"); |
311 | | } |
312 | | return *this; |
313 | | } |
314 | | Log &operator <<(int aInt) { |
315 | | if (MOZ_UNLIKELY(LogIt())) { |
316 | | mMessage << aInt; |
317 | | } |
318 | | return *this; |
319 | | } |
320 | 0 | Log &operator <<(unsigned int aInt) { |
321 | 0 | if (MOZ_UNLIKELY(LogIt())) { |
322 | 0 | mMessage << aInt; |
323 | 0 | } |
324 | 0 | return *this; |
325 | 0 | } Unexecuted instantiation: mozilla::gfx::Log<1, mozilla::gfx::CriticalLogger>::operator<<(unsigned int) Unexecuted instantiation: mozilla::gfx::Log<3, mozilla::gfx::BasicLogger>::operator<<(unsigned int) |
326 | | Log &operator <<(long aLong) { |
327 | | if (MOZ_UNLIKELY(LogIt())) { |
328 | | mMessage << aLong; |
329 | | } |
330 | | return *this; |
331 | | } |
332 | 0 | Log &operator <<(unsigned long aLong) { |
333 | 0 | if (MOZ_UNLIKELY(LogIt())) { |
334 | 0 | mMessage << aLong; |
335 | 0 | } |
336 | 0 | return *this; |
337 | 0 | } |
338 | | Log &operator <<(long long aLong) { |
339 | | if (MOZ_UNLIKELY(LogIt())) { |
340 | | mMessage << aLong; |
341 | | } |
342 | | return *this; |
343 | | } |
344 | | Log &operator <<(unsigned long long aLong) { |
345 | | if (MOZ_UNLIKELY(LogIt())) { |
346 | | mMessage << aLong; |
347 | | } |
348 | | return *this; |
349 | | } |
350 | | Log &operator <<(Float aFloat) { |
351 | | if (MOZ_UNLIKELY(LogIt())) { |
352 | | mMessage << aFloat; |
353 | | } |
354 | | return *this; |
355 | | } |
356 | | Log &operator <<(double aDouble) { |
357 | | if (MOZ_UNLIKELY(LogIt())) { |
358 | | mMessage << aDouble; |
359 | | } |
360 | | return *this; |
361 | | } |
362 | | Log &operator <<(const Color& aColor) { |
363 | | if (MOZ_UNLIKELY(LogIt())) { |
364 | | mMessage << "Color(" << aColor.r << ", " << aColor.g << ", " << aColor.b << ", " << aColor.a << ")"; |
365 | | } |
366 | | return *this; |
367 | | } |
368 | | template <typename T, typename Sub, typename Coord> |
369 | | Log &operator <<(const BasePoint<T, Sub, Coord>& aPoint) { |
370 | | if (MOZ_UNLIKELY(LogIt())) { |
371 | | mMessage << "Point" << aPoint; |
372 | | } |
373 | | return *this; |
374 | | } |
375 | | template <typename T, typename Sub> |
376 | | Log &operator <<(const BaseSize<T, Sub>& aSize) { |
377 | | if (MOZ_UNLIKELY(LogIt())) { |
378 | | mMessage << "Size(" << aSize.width << "," << aSize.height << ")"; |
379 | | } |
380 | | return *this; |
381 | | } |
382 | | template <typename T, typename Sub, typename Point, typename SizeT, typename Margin> |
383 | 0 | Log &operator <<(const BaseRect<T, Sub, Point, SizeT, Margin>& aRect) { |
384 | 0 | if (MOZ_UNLIKELY(LogIt())) { |
385 | 0 | mMessage << "Rect" << aRect; |
386 | 0 | } |
387 | 0 | return *this; |
388 | 0 | } Unexecuted instantiation: mozilla::gfx::Log<3, mozilla::gfx::BasicLogger>& mozilla::gfx::Log<3, mozilla::gfx::BasicLogger>::operator<< <float, mozilla::gfx::RectTyped<mozilla::ParentLayerPixel, float>, mozilla::gfx::PointTyped<mozilla::ParentLayerPixel, float>, mozilla::gfx::SizeTyped<mozilla::ParentLayerPixel, float>, mozilla::gfx::MarginTyped<mozilla::ParentLayerPixel, float> >(mozilla::gfx::BaseRect<float, mozilla::gfx::RectTyped<mozilla::ParentLayerPixel, float>, mozilla::gfx::PointTyped<mozilla::ParentLayerPixel, float>, mozilla::gfx::SizeTyped<mozilla::ParentLayerPixel, float>, mozilla::gfx::MarginTyped<mozilla::ParentLayerPixel, float> > const&) Unexecuted instantiation: mozilla::gfx::Log<3, mozilla::gfx::BasicLogger>& mozilla::gfx::Log<3, mozilla::gfx::BasicLogger>::operator<< <float, mozilla::gfx::RectTyped<mozilla::CSSPixel, float>, mozilla::gfx::PointTyped<mozilla::CSSPixel, float>, mozilla::gfx::SizeTyped<mozilla::CSSPixel, float>, mozilla::gfx::MarginTyped<mozilla::CSSPixel, float> >(mozilla::gfx::BaseRect<float, mozilla::gfx::RectTyped<mozilla::CSSPixel, float>, mozilla::gfx::PointTyped<mozilla::CSSPixel, float>, mozilla::gfx::SizeTyped<mozilla::CSSPixel, float>, mozilla::gfx::MarginTyped<mozilla::CSSPixel, float> > const&) |
389 | | Log &operator<<(const Matrix& aMatrix) { |
390 | | if (MOZ_UNLIKELY(LogIt())) { |
391 | | mMessage << "Matrix(" << aMatrix._11 << " " << aMatrix._12 << " ; " << aMatrix._21 << " " << aMatrix._22 << " ; " << aMatrix._31 << " " << aMatrix._32 << ")"; |
392 | | } |
393 | | return *this; |
394 | | } |
395 | | template<typename T> |
396 | 0 | Log &operator<<(Hexa<T> aHex) { |
397 | 0 | if (MOZ_UNLIKELY(LogIt())) { |
398 | 0 | mMessage << std::showbase << std::hex |
399 | 0 | << aHex.mVal |
400 | 0 | << std::noshowbase << std::dec; |
401 | 0 | } |
402 | 0 | return *this; |
403 | 0 | } Unexecuted instantiation: mozilla::gfx::Log<1, mozilla::gfx::CriticalLogger>& mozilla::gfx::Log<1, mozilla::gfx::CriticalLogger>::operator<< <unsigned long>(mozilla::gfx::Hexa<unsigned long>) Unexecuted instantiation: mozilla::gfx::Log<1, mozilla::gfx::CriticalLogger>& mozilla::gfx::Log<1, mozilla::gfx::CriticalLogger>::operator<< <mozilla::gfx::ReferencePtr>(mozilla::gfx::Hexa<mozilla::gfx::ReferencePtr>) Unexecuted instantiation: mozilla::gfx::Log<1, mozilla::gfx::CriticalLogger>& mozilla::gfx::Log<1, mozilla::gfx::CriticalLogger>::operator<< <RefPtr<mozilla::gfx::PrintTarget> >(mozilla::gfx::Hexa<RefPtr<mozilla::gfx::PrintTarget> >) Unexecuted instantiation: mozilla::gfx::Log<1, mozilla::gfx::CriticalLogger>& mozilla::gfx::Log<1, mozilla::gfx::CriticalLogger>::operator<< <int>(mozilla::gfx::Hexa<int>) Unexecuted instantiation: mozilla::gfx::Log<1, mozilla::gfx::CriticalLogger>& mozilla::gfx::Log<1, mozilla::gfx::CriticalLogger>::operator<< <unsigned int>(mozilla::gfx::Hexa<unsigned int>) Unexecuted instantiation: mozilla::gfx::Log<1, mozilla::gfx::CriticalLogger>& mozilla::gfx::Log<1, mozilla::gfx::CriticalLogger>::operator<< <RefPtr<mozilla::gfx::DrawTarget> >(mozilla::gfx::Hexa<RefPtr<mozilla::gfx::DrawTarget> >) Unexecuted instantiation: mozilla::gfx::Log<2, mozilla::gfx::BasicLogger>& mozilla::gfx::Log<2, mozilla::gfx::BasicLogger>::operator<< <mozilla::gfx::SourceSurface*>(mozilla::gfx::Hexa<mozilla::gfx::SourceSurface*>) Unexecuted instantiation: mozilla::gfx::Log<1, mozilla::gfx::CriticalLogger>& mozilla::gfx::Log<1, mozilla::gfx::CriticalLogger>::operator<< <RefPtr<mozilla::gfx::SourceSurface> >(mozilla::gfx::Hexa<RefPtr<mozilla::gfx::SourceSurface> >) Unexecuted instantiation: mozilla::gfx::Log<2, mozilla::gfx::BasicLogger>& mozilla::gfx::Log<2, mozilla::gfx::BasicLogger>::operator<< <_cairo_surface*>(mozilla::gfx::Hexa<_cairo_surface*>) Unexecuted instantiation: mozilla::gfx::Log<1, mozilla::gfx::CriticalLogger>& mozilla::gfx::Log<1, mozilla::gfx::CriticalLogger>::operator<< <mozilla::gfx::DrawTarget*>(mozilla::gfx::Hexa<mozilla::gfx::DrawTarget*>) Unexecuted instantiation: mozilla::gfx::Log<1, mozilla::gfx::CriticalLogger>& mozilla::gfx::Log<1, mozilla::gfx::CriticalLogger>::operator<< <mozilla::gl::GLContext*>(mozilla::gfx::Hexa<mozilla::gl::GLContext*>) |
404 | | |
405 | | Log &operator<<(const SourceSurface* aSurface) { |
406 | | if (MOZ_UNLIKELY(LogIt())) { |
407 | | mMessage << "SourceSurface(" << (void*)(aSurface) << ")"; |
408 | | } |
409 | | return *this; |
410 | | } |
411 | | Log &operator<<(const Path* aPath) { |
412 | | if (MOZ_UNLIKELY(LogIt())) { |
413 | | mMessage << "Path(" << (void*)(aPath) << ")"; |
414 | | } |
415 | | return *this; |
416 | | } |
417 | | Log &operator<<(const Pattern* aPattern) { |
418 | | if (MOZ_UNLIKELY(LogIt())) { |
419 | | mMessage << "Pattern(" << (void*)(aPattern) << ")"; |
420 | | } |
421 | | return *this; |
422 | | } |
423 | | Log &operator<<(const ScaledFont* aFont) { |
424 | | if (MOZ_UNLIKELY(LogIt())) { |
425 | | mMessage << "ScaledFont(" << (void*)(aFont) << ")"; |
426 | | } |
427 | | return *this; |
428 | | } |
429 | | Log &operator<<(const FilterNode* aFilter) { |
430 | | if (MOZ_UNLIKELY(LogIt())) { |
431 | | mMessage << "FilterNode(" << (void*)(aFilter) << ")"; |
432 | | } |
433 | | return *this; |
434 | | } |
435 | | Log &operator<<(const DrawOptions& aOptions) { |
436 | | if (MOZ_UNLIKELY(LogIt())) { |
437 | | mMessage << "DrawOptions(" << aOptions.mAlpha << ", "; |
438 | | (*this) << aOptions.mCompositionOp; |
439 | | mMessage << ", "; |
440 | | (*this) << aOptions.mAntialiasMode; |
441 | | mMessage << ")"; |
442 | | } |
443 | | return *this; |
444 | | } |
445 | | Log &operator<<(const DrawSurfaceOptions& aOptions) { |
446 | | if (MOZ_UNLIKELY(LogIt())) { |
447 | | mMessage << "DrawSurfaceOptions("; |
448 | | (*this) << aOptions.mSamplingFilter; |
449 | | mMessage << ", "; |
450 | | (*this) << aOptions.mSamplingBounds; |
451 | | mMessage << ")"; |
452 | | } |
453 | | return *this; |
454 | | } |
455 | | |
456 | | Log& operator<<(SamplingBounds aBounds) { |
457 | | if (MOZ_UNLIKELY(LogIt())) { |
458 | | switch(aBounds) { |
459 | | case SamplingBounds::UNBOUNDED: |
460 | | mMessage << "SamplingBounds::UNBOUNDED"; |
461 | | break; |
462 | | case SamplingBounds::BOUNDED: |
463 | | mMessage << "SamplingBounds::BOUNDED"; |
464 | | break; |
465 | | default: |
466 | | mMessage << "Invalid SamplingBounds (" << (int)aBounds << ")"; |
467 | | break; |
468 | | } |
469 | | } |
470 | | return *this; |
471 | | } |
472 | | Log& operator<<(SamplingFilter aFilter) { |
473 | | if (MOZ_UNLIKELY(LogIt())) { |
474 | | switch(aFilter) { |
475 | | case SamplingFilter::GOOD: |
476 | | mMessage << "SamplingFilter::GOOD"; |
477 | | break; |
478 | | case SamplingFilter::LINEAR: |
479 | | mMessage << "SamplingFilter::LINEAR"; |
480 | | break; |
481 | | case SamplingFilter::POINT: |
482 | | mMessage << "SamplingFilter::POINT"; |
483 | | break; |
484 | | default: |
485 | | mMessage << "Invalid SamplingFilter (" << (int)aFilter << ")"; |
486 | | break; |
487 | | } |
488 | | } |
489 | | return *this; |
490 | | } |
491 | | Log& operator<<(AntialiasMode aMode) { |
492 | | if (MOZ_UNLIKELY(LogIt())) { |
493 | | switch(aMode) { |
494 | | case AntialiasMode::NONE: |
495 | | mMessage << "AntialiasMode::NONE"; |
496 | | break; |
497 | | case AntialiasMode::GRAY: |
498 | | mMessage << "AntialiasMode::GRAY"; |
499 | | break; |
500 | | case AntialiasMode::SUBPIXEL: |
501 | | mMessage << "AntialiasMode::SUBPIXEL"; |
502 | | break; |
503 | | case AntialiasMode::DEFAULT: |
504 | | mMessage << "AntialiasMode::DEFAULT"; |
505 | | break; |
506 | | default: |
507 | | mMessage << "Invalid AntialiasMode (" << (int)aMode << ")"; |
508 | | break; |
509 | | } |
510 | | } |
511 | | return *this; |
512 | | } |
513 | 0 | Log& operator<<(CompositionOp aOp) { |
514 | 0 | if (MOZ_UNLIKELY(LogIt())) { |
515 | 0 | switch(aOp) { |
516 | 0 | case CompositionOp::OP_OVER: |
517 | 0 | mMessage << "CompositionOp::OP_OVER"; |
518 | 0 | break; |
519 | 0 | case CompositionOp::OP_ADD: |
520 | 0 | mMessage << "CompositionOp::OP_ADD"; |
521 | 0 | break; |
522 | 0 | case CompositionOp::OP_ATOP: |
523 | 0 | mMessage << "CompositionOp::OP_ATOP"; |
524 | 0 | break; |
525 | 0 | case CompositionOp::OP_OUT: |
526 | 0 | mMessage << "CompositionOp::OP_OUT"; |
527 | 0 | break; |
528 | 0 | case CompositionOp::OP_IN: |
529 | 0 | mMessage << "CompositionOp::OP_IN"; |
530 | 0 | break; |
531 | 0 | case CompositionOp::OP_SOURCE: |
532 | 0 | mMessage << "CompositionOp::OP_SOURCE"; |
533 | 0 | break; |
534 | 0 | case CompositionOp::OP_DEST_IN: |
535 | 0 | mMessage << "CompositionOp::OP_DEST_IN"; |
536 | 0 | break; |
537 | 0 | case CompositionOp::OP_DEST_OUT: |
538 | 0 | mMessage << "CompositionOp::OP_DEST_OUT"; |
539 | 0 | break; |
540 | 0 | case CompositionOp::OP_DEST_OVER: |
541 | 0 | mMessage << "CompositionOp::OP_DEST_OVER"; |
542 | 0 | break; |
543 | 0 | case CompositionOp::OP_DEST_ATOP: |
544 | 0 | mMessage << "CompositionOp::OP_DEST_ATOP"; |
545 | 0 | break; |
546 | 0 | case CompositionOp::OP_XOR: |
547 | 0 | mMessage << "CompositionOp::OP_XOR"; |
548 | 0 | break; |
549 | 0 | case CompositionOp::OP_MULTIPLY: |
550 | 0 | mMessage << "CompositionOp::OP_MULTIPLY"; |
551 | 0 | break; |
552 | 0 | case CompositionOp::OP_SCREEN: |
553 | 0 | mMessage << "CompositionOp::OP_SCREEN"; |
554 | 0 | break; |
555 | 0 | case CompositionOp::OP_OVERLAY: |
556 | 0 | mMessage << "CompositionOp::OP_OVERLAY"; |
557 | 0 | break; |
558 | 0 | case CompositionOp::OP_DARKEN: |
559 | 0 | mMessage << "CompositionOp::OP_DARKEN"; |
560 | 0 | break; |
561 | 0 | case CompositionOp::OP_LIGHTEN: |
562 | 0 | mMessage << "CompositionOp::OP_LIGHTEN"; |
563 | 0 | break; |
564 | 0 | case CompositionOp::OP_COLOR_DODGE: |
565 | 0 | mMessage << "CompositionOp::OP_COLOR_DODGE"; |
566 | 0 | break; |
567 | 0 | case CompositionOp::OP_COLOR_BURN: |
568 | 0 | mMessage << "CompositionOp::OP_COLOR_BURN"; |
569 | 0 | break; |
570 | 0 | case CompositionOp::OP_HARD_LIGHT: |
571 | 0 | mMessage << "CompositionOp::OP_HARD_LIGHT"; |
572 | 0 | break; |
573 | 0 | case CompositionOp::OP_SOFT_LIGHT: |
574 | 0 | mMessage << "CompositionOp::OP_SOFT_LIGHT"; |
575 | 0 | break; |
576 | 0 | case CompositionOp::OP_DIFFERENCE: |
577 | 0 | mMessage << "CompositionOp::OP_DIFFERENCE"; |
578 | 0 | break; |
579 | 0 | case CompositionOp::OP_EXCLUSION: |
580 | 0 | mMessage << "CompositionOp::OP_EXCLUSION"; |
581 | 0 | break; |
582 | 0 | case CompositionOp::OP_HUE: |
583 | 0 | mMessage << "CompositionOp::OP_HUE"; |
584 | 0 | break; |
585 | 0 | case CompositionOp::OP_SATURATION: |
586 | 0 | mMessage << "CompositionOp::OP_SATURATION"; |
587 | 0 | break; |
588 | 0 | case CompositionOp::OP_COLOR: |
589 | 0 | mMessage << "CompositionOp::OP_COLOR"; |
590 | 0 | break; |
591 | 0 | case CompositionOp::OP_LUMINOSITY: |
592 | 0 | mMessage << "CompositionOp::OP_LUMINOSITY"; |
593 | 0 | break; |
594 | 0 | case CompositionOp::OP_COUNT: |
595 | 0 | mMessage << "CompositionOp::OP_COUNT"; |
596 | 0 | break; |
597 | 0 | default: |
598 | 0 | mMessage << "Invalid CompositionOp (" << (int)aOp << ")"; |
599 | 0 | break; |
600 | 0 | } |
601 | 0 | } |
602 | 0 | return *this; |
603 | 0 | } |
604 | | Log& operator<<(SurfaceFormat aFormat) { |
605 | | if (MOZ_UNLIKELY(LogIt())) { |
606 | | switch(aFormat) { |
607 | | case SurfaceFormat::B8G8R8A8: |
608 | | mMessage << "SurfaceFormat::B8G8R8A8"; |
609 | | break; |
610 | | case SurfaceFormat::B8G8R8X8: |
611 | | mMessage << "SurfaceFormat::B8G8R8X8"; |
612 | | break; |
613 | | case SurfaceFormat::R8G8B8A8: |
614 | | mMessage << "SurfaceFormat::R8G8B8A8"; |
615 | | break; |
616 | | case SurfaceFormat::R8G8B8X8: |
617 | | mMessage << "SurfaceFormat::R8G8B8X8"; |
618 | | break; |
619 | | case SurfaceFormat::R5G6B5_UINT16: |
620 | | mMessage << "SurfaceFormat::R5G6B5_UINT16"; |
621 | | break; |
622 | | case SurfaceFormat::A8: |
623 | | mMessage << "SurfaceFormat::A8"; |
624 | | break; |
625 | | case SurfaceFormat::YUV: |
626 | | mMessage << "SurfaceFormat::YUV"; |
627 | | break; |
628 | | case SurfaceFormat::UNKNOWN: |
629 | | mMessage << "SurfaceFormat::UNKNOWN"; |
630 | | break; |
631 | | default: |
632 | | mMessage << "Invalid SurfaceFormat (" << (int)aFormat << ")"; |
633 | | break; |
634 | | } |
635 | | } |
636 | | return *this; |
637 | | } |
638 | | |
639 | | Log& operator<<(SurfaceType aType) { |
640 | | if (MOZ_UNLIKELY(LogIt())) { |
641 | | switch(aType) { |
642 | | case SurfaceType::DATA: |
643 | | mMessage << "SurfaceType::DATA"; |
644 | | break; |
645 | | case SurfaceType::D2D1_BITMAP: |
646 | | mMessage << "SurfaceType::D2D1_BITMAP"; |
647 | | break; |
648 | | case SurfaceType::D2D1_DRAWTARGET: |
649 | | mMessage << "SurfaceType::D2D1_DRAWTARGET"; |
650 | | break; |
651 | | case SurfaceType::CAIRO: |
652 | | mMessage << "SurfaceType::CAIRO"; |
653 | | break; |
654 | | case SurfaceType::CAIRO_IMAGE: |
655 | | mMessage << "SurfaceType::CAIRO_IMAGE"; |
656 | | break; |
657 | | case SurfaceType::COREGRAPHICS_IMAGE: |
658 | | mMessage << "SurfaceType::COREGRAPHICS_IMAGE"; |
659 | | break; |
660 | | case SurfaceType::COREGRAPHICS_CGCONTEXT: |
661 | | mMessage << "SurfaceType::COREGRAPHICS_CGCONTEXT"; |
662 | | break; |
663 | | case SurfaceType::SKIA: |
664 | | mMessage << "SurfaceType::SKIA"; |
665 | | break; |
666 | | case SurfaceType::DUAL_DT: |
667 | | mMessage << "SurfaceType::DUAL_DT"; |
668 | | break; |
669 | | case SurfaceType::D2D1_1_IMAGE: |
670 | | mMessage << "SurfaceType::D2D1_1_IMAGE"; |
671 | | break; |
672 | | case SurfaceType::RECORDING: |
673 | | mMessage << "SurfaceType::RECORDING"; |
674 | | break; |
675 | | case SurfaceType::TILED: |
676 | | mMessage << "SurfaceType::TILED"; |
677 | | break; |
678 | | case SurfaceType::DATA_SHARED: |
679 | | mMessage << "SurfaceType::DATA_SHARED"; |
680 | | break; |
681 | | default: |
682 | | mMessage << "Invalid SurfaceType (" << (int)aType << ")"; |
683 | | break; |
684 | | } |
685 | | } |
686 | | return *this; |
687 | | } |
688 | | |
689 | | inline bool LogIt() const { return mLogIt; } |
690 | | inline bool NoNewline() const { return mOptions & int(LogOptions::NoNewline); } |
691 | | inline bool AutoPrefix() const { return mOptions & int(LogOptions::AutoPrefix); } |
692 | | inline bool ValidReason() const { return (int)mReason > (int)LogReason::MustBeMoreThanThis && (int)mReason < (int)LogReason::MustBeLessThanThis; } |
693 | | |
694 | | // We do not want this version to do any work, and stringstream can't be |
695 | | // copied anyway. It does come in handy for the "Once" macro defined below. |
696 | 0 | MOZ_IMPLICIT Log(const Log& log) { Init(log.mOptions, false, log.mReason); } Unexecuted instantiation: mozilla::gfx::Log<2, mozilla::gfx::BasicLogger>::Log(mozilla::gfx::Log<2, mozilla::gfx::BasicLogger> const&) Unexecuted instantiation: mozilla::gfx::Log<1, mozilla::gfx::CriticalLogger>::Log(mozilla::gfx::Log<1, mozilla::gfx::CriticalLogger> const&) |
697 | | |
698 | | private: |
699 | | // Initialization common to two constructors |
700 | | void Init(int aOptions, bool aLogIt, LogReason aReason) { |
701 | | mOptions = aOptions; |
702 | | mReason = aReason; |
703 | | mLogIt = aLogIt; |
704 | | if (mLogIt) { |
705 | | if (AutoPrefix()) { |
706 | | if (mOptions & int(LogOptions::AssertOnCall)) { |
707 | | mMessage << "[GFX" << L; |
708 | | } else { |
709 | | mMessage << "[GFX" << L << "-"; |
710 | | } |
711 | | } |
712 | | if ((mOptions & int(LogOptions::CrashAction)) && ValidReason()) { |
713 | | mMessage << " " << (int)mReason; |
714 | | } |
715 | | if (AutoPrefix()) { |
716 | | mMessage << "]: "; |
717 | | } |
718 | | } |
719 | | } |
720 | | |
721 | | void WriteLog(const std::string &aString) { |
722 | | if (MOZ_UNLIKELY(LogIt())) { |
723 | | Logger::OutputMessage(aString, L, NoNewline()); |
724 | | // Assert if required. We don't have a three parameter MOZ_ASSERT |
725 | | // so use the underlying functions instead (see bug 1281702): |
726 | | #ifdef DEBUG |
727 | | if (mOptions & int(LogOptions::AssertOnCall)) { |
728 | | MOZ_ReportAssertionFailure(aString.c_str(), __FILE__, __LINE__); |
729 | | MOZ_CRASH("GFX: An assert from the graphics logger"); |
730 | | } |
731 | | #endif |
732 | | if ((mOptions & int(LogOptions::CrashAction)) && ValidReason()) { |
733 | | Logger::CrashAction(mReason); |
734 | | } |
735 | | } |
736 | | } |
737 | | |
738 | | std::stringstream mMessage; |
739 | | int mOptions; |
740 | | LogReason mReason; |
741 | | bool mLogIt; |
742 | | }; |
743 | | |
744 | | typedef Log<LOG_DEBUG> DebugLog; |
745 | | typedef Log<LOG_WARNING> WarningLog; |
746 | | typedef Log<LOG_CRITICAL, CriticalLogger> CriticalLog; |
747 | | |
748 | | // Macro to glue names to get us less chance of name clashing. |
749 | | #if defined GFX_LOGGING_GLUE1 || defined GFX_LOGGING_GLUE |
750 | | #error "Clash of the macro GFX_LOGGING_GLUE1 or GFX_LOGGING_GLUE" |
751 | | #endif |
752 | | #define GFX_LOGGING_GLUE1(x, y) x##y |
753 | | #define GFX_LOGGING_GLUE(x, y) GFX_LOGGING_GLUE1(x, y) |
754 | | |
755 | | // This log goes into crash reports, use with care. |
756 | 0 | #define gfxCriticalError mozilla::gfx::CriticalLog |
757 | 0 | #define gfxCriticalErrorOnce static gfxCriticalError GFX_LOGGING_GLUE(sOnceAtLine,__LINE__) = gfxCriticalError |
758 | | |
759 | | // This is a shortcut for errors we want logged in crash reports/about support |
760 | | // but we do not want asserting. These are available in all builds, so it is |
761 | | // not worth trying to do magic to avoid matching the syntax of gfxCriticalError. |
762 | | // So, this one is used as |
763 | | // gfxCriticalNote << "Something to report and not assert"; |
764 | | // while the critical error is |
765 | | // gfxCriticalError() << "Something to report and assert"; |
766 | 0 | #define gfxCriticalNote gfxCriticalError(gfxCriticalError::DefaultOptions(false)) |
767 | | #define gfxCriticalNoteOnce static gfxCriticalError GFX_LOGGING_GLUE(sOnceAtLine,__LINE__) = gfxCriticalNote |
768 | | |
769 | | // The "once" versions will only trigger the first time through. You can do this: |
770 | | // gfxCriticalErrorOnce() << "This message only shows up once; |
771 | | // instead of the usual: |
772 | | // static bool firstTime = true; |
773 | | // if (firstTime) { |
774 | | // firstTime = false; |
775 | | // gfxCriticalError() << "This message only shows up once; |
776 | | // } |
777 | | #if defined(DEBUG) |
778 | | #define gfxDebug mozilla::gfx::DebugLog |
779 | | #define gfxDebugOnce static gfxDebug GFX_LOGGING_GLUE(sOnceAtLine,__LINE__) = gfxDebug |
780 | | #else |
781 | 0 | #define gfxDebug if (1) ; else mozilla::gfx::NoLog |
782 | | #define gfxDebugOnce if (1) ; else mozilla::gfx::NoLog |
783 | | #endif |
784 | | |
785 | | // Have gfxWarning available (behind a runtime preference) |
786 | 0 | #define gfxWarning mozilla::gfx::WarningLog |
787 | 0 | #define gfxWarningOnce static gfxWarning GFX_LOGGING_GLUE(sOnceAtLine,__LINE__) = gfxWarning |
788 | | |
789 | | // In the debug build, this is equivalent to the default gfxCriticalError. |
790 | | // In the non-debug build, on nightly and dev edition, it will MOZ_CRASH. |
791 | | // On beta and release versions, it will telemetry count, but proceed. |
792 | | // |
793 | | // You should create a (new) enum in the LogReason and use it for the reason |
794 | | // parameter to ensure uniqueness. |
795 | 0 | #define gfxDevCrash(reason) gfxCriticalError(int(gfx::LogOptions::AutoPrefix) | int(gfx::LogOptions::AssertOnCall) | int(gfx::LogOptions::CrashAction), (reason)) |
796 | | |
797 | | // See nsDebug.h and the NS_WARN_IF macro |
798 | | |
799 | | #ifdef __cplusplus |
800 | | // For now, have MOZ2D_ERROR_IF available in debug and non-debug builds |
801 | | inline bool MOZ2D_error_if_impl(bool aCondition, const char* aExpr, |
802 | | const char* aFile, int32_t aLine) |
803 | 0 | { |
804 | 0 | if (MOZ_UNLIKELY(aCondition)) { |
805 | 0 | gfxCriticalError() << aExpr << " at " << aFile << ":" << aLine; |
806 | 0 | } |
807 | 0 | return aCondition; |
808 | 0 | } |
809 | | #define MOZ2D_ERROR_IF(condition) \ |
810 | | MOZ2D_error_if_impl(condition, #condition, __FILE__, __LINE__) |
811 | | |
812 | | #ifdef DEBUG |
813 | | inline bool MOZ2D_warn_if_impl(bool aCondition, const char* aExpr, |
814 | | const char* aFile, int32_t aLine) |
815 | | { |
816 | | if (MOZ_UNLIKELY(aCondition)) { |
817 | | gfxWarning() << aExpr << " at " << aFile << ":" << aLine; |
818 | | } |
819 | | return aCondition; |
820 | | } |
821 | | #define MOZ2D_WARN_IF(condition) \ |
822 | | MOZ2D_warn_if_impl(condition, #condition, __FILE__, __LINE__) |
823 | | #else |
824 | | #define MOZ2D_WARN_IF(condition) (bool)(condition) |
825 | | #endif |
826 | | #endif |
827 | | |
828 | | const int INDENT_PER_LEVEL = 2; |
829 | | |
830 | | class TreeLog |
831 | | { |
832 | | public: |
833 | | explicit TreeLog(const std::string& aPrefix = "") |
834 | | : mLog(int(LogOptions::NoNewline)), |
835 | | mPrefix(aPrefix), |
836 | | mDepth(0), |
837 | | mStartOfLine(true), |
838 | | mConditionedOnPref(false), |
839 | | mPrefFunction(nullptr) {} |
840 | | |
841 | | template <typename T> |
842 | 0 | TreeLog& operator<<(const T& aObject) { |
843 | 0 | if (mConditionedOnPref && !mPrefFunction()) { |
844 | 0 | return *this; |
845 | 0 | } |
846 | 0 | if (mStartOfLine) { |
847 | 0 | if (!mPrefix.empty()) { |
848 | 0 | mLog << '[' << mPrefix << "] "; |
849 | 0 | } |
850 | 0 | mLog << std::string(mDepth * INDENT_PER_LEVEL, ' '); |
851 | 0 | mStartOfLine = false; |
852 | 0 | } |
853 | 0 | mLog << aObject; |
854 | 0 | if (EndsInNewline(aObject)) { |
855 | 0 | // Don't indent right here as the user may change the indent |
856 | 0 | // between now and the first output to the next line. |
857 | 0 | mLog.Flush(); |
858 | 0 | mStartOfLine = true; |
859 | 0 | } |
860 | 0 | return *this; |
861 | 0 | } Unexecuted instantiation: mozilla::gfx::TreeLog& mozilla::gfx::TreeLog::operator<< <char const*>(char const* const&) Unexecuted instantiation: mozilla::gfx::TreeLog& mozilla::gfx::TreeLog::operator<< <char>(char const&) Unexecuted instantiation: mozilla::gfx::TreeLog& mozilla::gfx::TreeLog::operator<< <mozilla::layers::ScrollableLayerGuid>(mozilla::layers::ScrollableLayerGuid const&) Unexecuted instantiation: mozilla::gfx::TreeLog& mozilla::gfx::TreeLog::operator<< <mozilla::gfx::RectTyped<mozilla::ParentLayerPixel, float> >(mozilla::gfx::RectTyped<mozilla::ParentLayerPixel, float> const&) Unexecuted instantiation: mozilla::gfx::TreeLog& mozilla::gfx::TreeLog::operator<< <mozilla::gfx::RectTyped<mozilla::CSSPixel, float> >(mozilla::gfx::RectTyped<mozilla::CSSPixel, float> const&) |
862 | | |
863 | | void IncreaseIndent() { ++mDepth; } |
864 | | void DecreaseIndent() { |
865 | | MOZ_ASSERT(mDepth > 0); |
866 | | --mDepth; |
867 | | } |
868 | | |
869 | 0 | void ConditionOnPrefFunction(bool(*aPrefFunction)()) { |
870 | 0 | mConditionedOnPref = true; |
871 | 0 | mPrefFunction = aPrefFunction; |
872 | 0 | } |
873 | | private: |
874 | | Log<LOG_DEBUG> mLog; |
875 | | std::string mPrefix; |
876 | | uint32_t mDepth; |
877 | | bool mStartOfLine; |
878 | | bool mConditionedOnPref; |
879 | | bool (*mPrefFunction)(); |
880 | | |
881 | | template <typename T> |
882 | 0 | static bool EndsInNewline(const T& aObject) { |
883 | 0 | return false; |
884 | 0 | } Unexecuted instantiation: bool mozilla::gfx::TreeLog::EndsInNewline<mozilla::layers::ScrollableLayerGuid>(mozilla::layers::ScrollableLayerGuid const&) Unexecuted instantiation: bool mozilla::gfx::TreeLog::EndsInNewline<mozilla::gfx::RectTyped<mozilla::ParentLayerPixel, float> >(mozilla::gfx::RectTyped<mozilla::ParentLayerPixel, float> const&) Unexecuted instantiation: bool mozilla::gfx::TreeLog::EndsInNewline<mozilla::gfx::RectTyped<mozilla::CSSPixel, float> >(mozilla::gfx::RectTyped<mozilla::CSSPixel, float> const&) |
885 | | |
886 | | static bool EndsInNewline(const std::string& aString) { |
887 | | return !aString.empty() && aString[aString.length() - 1] == '\n'; |
888 | | } |
889 | | |
890 | 0 | static bool EndsInNewline(char aChar) { |
891 | 0 | return aChar == '\n'; |
892 | 0 | } |
893 | | |
894 | | static bool EndsInNewline(const char* aString) { |
895 | | return EndsInNewline(std::string(aString)); |
896 | | } |
897 | | }; |
898 | | |
899 | | class TreeAutoIndent |
900 | | { |
901 | | public: |
902 | | explicit TreeAutoIndent(TreeLog& aTreeLog) : mTreeLog(aTreeLog) { |
903 | | mTreeLog.IncreaseIndent(); |
904 | | } |
905 | | |
906 | | TreeAutoIndent(const TreeAutoIndent& aTreeAutoIndent) : |
907 | 0 | mTreeLog(aTreeAutoIndent.mTreeLog) { |
908 | 0 | mTreeLog.IncreaseIndent(); |
909 | 0 | } |
910 | | |
911 | | TreeAutoIndent& operator=(const TreeAutoIndent& aTreeAutoIndent) = delete; |
912 | | |
913 | | ~TreeAutoIndent() { |
914 | | mTreeLog.DecreaseIndent(); |
915 | | } |
916 | | private: |
917 | | TreeLog& mTreeLog; |
918 | | }; |
919 | | |
920 | | } // namespace gfx |
921 | | } // namespace mozilla |
922 | | |
923 | | #endif /* MOZILLA_GFX_LOGGING_H_ */ |