/src/mozilla-central/gfx/2d/Factory.cpp
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 | | #include "2D.h" |
8 | | #include "Swizzle.h" |
9 | | |
10 | | #ifdef USE_CAIRO |
11 | | #include "DrawTargetCairo.h" |
12 | | #include "SourceSurfaceCairo.h" |
13 | | #endif |
14 | | |
15 | | #ifdef USE_SKIA |
16 | | #include "DrawTargetSkia.h" |
17 | | #include "ScaledFontBase.h" |
18 | | #endif |
19 | | |
20 | | #if defined(WIN32) |
21 | | #include "ScaledFontWin.h" |
22 | | #include "NativeFontResourceGDI.h" |
23 | | #include "UnscaledFontGDI.h" |
24 | | #endif |
25 | | |
26 | | #ifdef XP_DARWIN |
27 | | #include "ScaledFontMac.h" |
28 | | #include "NativeFontResourceMac.h" |
29 | | #endif |
30 | | |
31 | | #ifdef MOZ_WIDGET_GTK |
32 | | #include "ScaledFontFontconfig.h" |
33 | | #include "NativeFontResourceFreeType.h" |
34 | | #include "UnscaledFontFreeType.h" |
35 | | #endif |
36 | | |
37 | | #ifdef MOZ_WIDGET_ANDROID |
38 | | #include "ScaledFontFreeType.h" |
39 | | #include "NativeFontResourceFreeType.h" |
40 | | #endif |
41 | | |
42 | | #ifdef WIN32 |
43 | | #include "DrawTargetD2D1.h" |
44 | | #include "ScaledFontDWrite.h" |
45 | | #include "NativeFontResourceDWrite.h" |
46 | | #include <d3d10_1.h> |
47 | | #include "HelpersD2D.h" |
48 | | #include "HelpersWinFonts.h" |
49 | | #include "mozilla/Mutex.h" |
50 | | #endif |
51 | | |
52 | | #include "DrawTargetCapture.h" |
53 | | #include "DrawTargetDual.h" |
54 | | #include "DrawTargetTiled.h" |
55 | | #include "DrawTargetOffset.h" |
56 | | #include "DrawTargetWrapAndRecord.h" |
57 | | #include "DrawTargetRecording.h" |
58 | | |
59 | | #include "SourceSurfaceRawData.h" |
60 | | |
61 | | #include "DrawEventRecorder.h" |
62 | | |
63 | | #include "Logging.h" |
64 | | |
65 | | #include "mozilla/CheckedInt.h" |
66 | | |
67 | | #ifdef MOZ_ENABLE_FREETYPE |
68 | | #include "ft2build.h" |
69 | | #include FT_FREETYPE_H |
70 | | |
71 | | #include "mozilla/Mutex.h" |
72 | | #endif |
73 | | #include "MainThreadUtils.h" |
74 | | |
75 | | #if defined(MOZ_LOGGING) |
76 | | GFX2D_API mozilla::LogModule* |
77 | | GetGFX2DLog() |
78 | 0 | { |
79 | 0 | static mozilla::LazyLogModule sLog("gfx2d"); |
80 | 0 | return sLog; |
81 | 0 | } |
82 | | #endif |
83 | | |
84 | | // The following code was largely taken from xpcom/glue/SSE.cpp and |
85 | | // made a little simpler. |
86 | | enum CPUIDRegister { eax = 0, ebx = 1, ecx = 2, edx = 3 }; |
87 | | |
88 | | #ifdef HAVE_CPUID_H |
89 | | |
90 | | #if !(defined(__SSE2__) || defined(_M_X64) || \ |
91 | | (defined(_M_IX86_FP) && _M_IX86_FP >= 2)) || \ |
92 | | !defined(__SSE4__) |
93 | | // cpuid.h is available on gcc 4.3 and higher on i386 and x86_64 |
94 | | #include <cpuid.h> |
95 | | |
96 | | static inline bool |
97 | | HasCPUIDBit(unsigned int level, CPUIDRegister reg, unsigned int bit) |
98 | 0 | { |
99 | 0 | unsigned int regs[4]; |
100 | 0 | return __get_cpuid(level, ®s[0], ®s[1], ®s[2], ®s[3]) && |
101 | 0 | (regs[reg] & bit); |
102 | 0 | } |
103 | | #endif |
104 | | |
105 | | #define HAVE_CPU_DETECTION |
106 | | #else |
107 | | |
108 | | #if defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_AMD64)) |
109 | | // MSVC 2005 or later supports __cpuid by intrin.h |
110 | | #include <intrin.h> |
111 | | |
112 | | #define HAVE_CPU_DETECTION |
113 | | #elif defined(__SUNPRO_CC) && (defined(__i386) || defined(__x86_64__)) |
114 | | |
115 | | // Define a function identical to MSVC function. |
116 | | #ifdef __i386 |
117 | | static void |
118 | | __cpuid(int CPUInfo[4], int InfoType) |
119 | | { |
120 | | asm ( |
121 | | "xchg %esi, %ebx\n" |
122 | | "cpuid\n" |
123 | | "movl %eax, (%edi)\n" |
124 | | "movl %ebx, 4(%edi)\n" |
125 | | "movl %ecx, 8(%edi)\n" |
126 | | "movl %edx, 12(%edi)\n" |
127 | | "xchg %esi, %ebx\n" |
128 | | : |
129 | | : "a"(InfoType), // %eax |
130 | | "D"(CPUInfo) // %edi |
131 | | : "%ecx", "%edx", "%esi" |
132 | | ); |
133 | | } |
134 | | #else |
135 | | static void |
136 | | __cpuid(int CPUInfo[4], int InfoType) |
137 | | { |
138 | | asm ( |
139 | | "xchg %rsi, %rbx\n" |
140 | | "cpuid\n" |
141 | | "movl %eax, (%rdi)\n" |
142 | | "movl %ebx, 4(%rdi)\n" |
143 | | "movl %ecx, 8(%rdi)\n" |
144 | | "movl %edx, 12(%rdi)\n" |
145 | | "xchg %rsi, %rbx\n" |
146 | | : |
147 | | : "a"(InfoType), // %eax |
148 | | "D"(CPUInfo) // %rdi |
149 | | : "%ecx", "%edx", "%rsi" |
150 | | ); |
151 | | } |
152 | | |
153 | | #define HAVE_CPU_DETECTION |
154 | | #endif |
155 | | #endif |
156 | | |
157 | | #ifdef HAVE_CPU_DETECTION |
158 | | static inline bool |
159 | | HasCPUIDBit(unsigned int level, CPUIDRegister reg, unsigned int bit) |
160 | | { |
161 | | // Check that the level in question is supported. |
162 | | volatile int regs[4]; |
163 | | __cpuid((int *)regs, level & 0x80000000u); |
164 | | if (unsigned(regs[0]) < level) |
165 | | return false; |
166 | | __cpuid((int *)regs, level); |
167 | | return !!(unsigned(regs[reg]) & bit); |
168 | | } |
169 | | #endif |
170 | | #endif |
171 | | |
172 | | #ifdef MOZ_ENABLE_FREETYPE |
173 | | extern "C" { |
174 | | |
175 | | FT_Face |
176 | | mozilla_NewFTFace(FT_Library aFTLibrary, const char* aFileName, int aFaceIndex) |
177 | 0 | { |
178 | 0 | return mozilla::gfx::Factory::NewFTFace(aFTLibrary, aFileName, aFaceIndex); |
179 | 0 | } |
180 | | |
181 | | FT_Face |
182 | | mozilla_NewFTFaceFromData(FT_Library aFTLibrary, const uint8_t* aData, size_t aDataSize, int aFaceIndex) |
183 | 0 | { |
184 | 0 | return mozilla::gfx::Factory::NewFTFaceFromData(aFTLibrary, aData, aDataSize, aFaceIndex); |
185 | 0 | } |
186 | | |
187 | | void |
188 | | mozilla_ReleaseFTFace(FT_Face aFace) |
189 | 0 | { |
190 | 0 | mozilla::gfx::Factory::ReleaseFTFace(aFace); |
191 | 0 | } |
192 | | |
193 | | FT_Error |
194 | | mozilla_LoadFTGlyph(FT_Face aFace, uint32_t aGlyphIndex, int32_t aFlags) |
195 | 0 | { |
196 | 0 | return mozilla::gfx::Factory::LoadFTGlyph(aFace, aGlyphIndex, aFlags); |
197 | 0 | } |
198 | | |
199 | | void |
200 | | mozilla_LockFTLibrary(FT_Library aFTLibrary) |
201 | 0 | { |
202 | 0 | mozilla::gfx::Factory::LockFTLibrary(aFTLibrary); |
203 | 0 | } |
204 | | |
205 | | void |
206 | | mozilla_UnlockFTLibrary(FT_Library aFTLibrary) |
207 | 0 | { |
208 | 0 | mozilla::gfx::Factory::UnlockFTLibrary(aFTLibrary); |
209 | 0 | } |
210 | | |
211 | | } |
212 | | #endif |
213 | | |
214 | | namespace mozilla { |
215 | | namespace gfx { |
216 | | |
217 | | // In Gecko, this value is managed by gfx.logging.level in gfxPrefs. |
218 | | int32_t LoggingPrefs::sGfxLogLevel = LOG_DEFAULT; |
219 | | |
220 | | #ifdef MOZ_ENABLE_FREETYPE |
221 | | FT_Library Factory::mFTLibrary = nullptr; |
222 | | Mutex* Factory::mFTLock = nullptr; |
223 | | #endif |
224 | | |
225 | | #ifdef WIN32 |
226 | | // Note: mDeviceLock must be held when mutating these values. |
227 | | static uint32_t mDeviceSeq = 0; |
228 | | StaticRefPtr<ID3D11Device> Factory::mD3D11Device; |
229 | | StaticRefPtr<ID2D1Device> Factory::mD2D1Device; |
230 | | StaticRefPtr<IDWriteFactory> Factory::mDWriteFactory; |
231 | | bool Factory::mDWriteFactoryInitialized = false; |
232 | | StaticMutex Factory::mDeviceLock; |
233 | | StaticMutex Factory::mDTDependencyLock; |
234 | | #endif |
235 | | |
236 | | DrawEventRecorder *Factory::mRecorder; |
237 | | |
238 | | mozilla::gfx::Config* Factory::sConfig = nullptr; |
239 | | |
240 | | void |
241 | | Factory::Init(const Config& aConfig) |
242 | 0 | { |
243 | 0 | MOZ_ASSERT(!sConfig); |
244 | 0 | sConfig = new Config(aConfig); |
245 | 0 |
|
246 | 0 | #ifdef MOZ_ENABLE_FREETYPE |
247 | 0 | mFTLock = new Mutex("Factory::mFTLock"); |
248 | 0 | #endif |
249 | 0 | } |
250 | | |
251 | | void |
252 | | Factory::ShutDown() |
253 | 0 | { |
254 | 0 | if (sConfig) { |
255 | 0 | delete sConfig->mLogForwarder; |
256 | 0 | delete sConfig; |
257 | 0 | sConfig = nullptr; |
258 | 0 | } |
259 | 0 |
|
260 | 0 | #ifdef MOZ_ENABLE_FREETYPE |
261 | 0 | mFTLibrary = nullptr; |
262 | 0 | if (mFTLock) { |
263 | 0 | delete mFTLock; |
264 | 0 | mFTLock = nullptr; |
265 | 0 | } |
266 | 0 | #endif |
267 | 0 | } |
268 | | |
269 | | bool |
270 | | Factory::HasSSE2() |
271 | 0 | { |
272 | 0 | #if defined(__SSE2__) || defined(_M_X64) || \ |
273 | 0 | (defined(_M_IX86_FP) && _M_IX86_FP >= 2) |
274 | 0 | // gcc with -msse2 (default on OSX and x86-64) |
275 | 0 | // cl.exe with -arch:SSE2 (default on x64 compiler) |
276 | 0 | return true; |
277 | | #elif defined(HAVE_CPU_DETECTION) |
278 | | static enum { |
279 | | UNINITIALIZED, |
280 | | NO_SSE2, |
281 | | HAS_SSE2 |
282 | | } sDetectionState = UNINITIALIZED; |
283 | | |
284 | | if (sDetectionState == UNINITIALIZED) { |
285 | | sDetectionState = HasCPUIDBit(1u, edx, (1u<<26)) ? HAS_SSE2 : NO_SSE2; |
286 | | } |
287 | | return sDetectionState == HAS_SSE2; |
288 | | #else |
289 | | return false; |
290 | | #endif |
291 | | } |
292 | | |
293 | | bool |
294 | | Factory::HasSSE4() |
295 | 0 | { |
296 | | #if defined(__SSE4__) |
297 | | // gcc with -msse2 (default on OSX and x86-64) |
298 | | // cl.exe with -arch:SSE2 (default on x64 compiler) |
299 | | return true; |
300 | | #elif defined(HAVE_CPU_DETECTION) |
301 | | static enum { |
302 | 0 | UNINITIALIZED, |
303 | 0 | NO_SSE4, |
304 | 0 | HAS_SSE4 |
305 | 0 | } sDetectionState = UNINITIALIZED; |
306 | 0 |
|
307 | 0 | if (sDetectionState == UNINITIALIZED) { |
308 | 0 | sDetectionState = HasCPUIDBit(1u, ecx, (1u << 19)) ? HAS_SSE4 : NO_SSE4; |
309 | 0 | } |
310 | 0 | return sDetectionState == HAS_SSE4; |
311 | | #else |
312 | | return false; |
313 | | #endif |
314 | | } |
315 | | |
316 | | // If the size is "reasonable", we want gfxCriticalError to assert, so |
317 | | // this is the option set up for it. |
318 | | inline int LoggerOptionsBasedOnSize(const IntSize& aSize) |
319 | 0 | { |
320 | 0 | return CriticalLog::DefaultOptions(Factory::ReasonableSurfaceSize(aSize)); |
321 | 0 | } |
322 | | |
323 | | bool |
324 | | Factory::ReasonableSurfaceSize(const IntSize &aSize) |
325 | 0 | { |
326 | 0 | return Factory::CheckSurfaceSize(aSize, 8192); |
327 | 0 | } |
328 | | |
329 | | bool |
330 | | Factory::AllowedSurfaceSize(const IntSize &aSize) |
331 | 0 | { |
332 | 0 | if (sConfig) { |
333 | 0 | return Factory::CheckSurfaceSize(aSize, |
334 | 0 | sConfig->mMaxTextureSize, |
335 | 0 | sConfig->mMaxAllocSize); |
336 | 0 | } |
337 | 0 | |
338 | 0 | return CheckSurfaceSize(aSize); |
339 | 0 | } |
340 | | |
341 | | bool |
342 | | Factory::CheckBufferSize(int32_t bufSize) |
343 | 0 | { |
344 | 0 | return !sConfig || bufSize < sConfig->mMaxAllocSize; |
345 | 0 | } |
346 | | |
347 | | bool |
348 | | Factory::CheckSurfaceSize(const IntSize &sz, |
349 | | int32_t extentLimit, |
350 | | int32_t allocLimit) |
351 | 0 | { |
352 | 0 | if (sz.width <= 0 || sz.height <= 0) { |
353 | 0 | return false; |
354 | 0 | } |
355 | 0 | |
356 | 0 | // reject images with sides bigger than limit |
357 | 0 | if (extentLimit && (sz.width > extentLimit || sz.height > extentLimit)) { |
358 | 0 | gfxDebug() << "Surface size too large (exceeds extent limit)!"; |
359 | 0 | return false; |
360 | 0 | } |
361 | 0 |
|
362 | 0 | // assuming 4 bytes per pixel, make sure the allocation size |
363 | 0 | // doesn't overflow a int32_t either |
364 | 0 | CheckedInt<int32_t> stride = GetAlignedStride<16>(sz.width, 4); |
365 | 0 | if (!stride.isValid() || stride.value() == 0) { |
366 | 0 | gfxDebug() << "Surface size too large (stride overflows int32_t)!"; |
367 | 0 | return false; |
368 | 0 | } |
369 | 0 |
|
370 | 0 | CheckedInt<int32_t> numBytes = stride * sz.height; |
371 | 0 | if (!numBytes.isValid()) { |
372 | 0 | gfxDebug() << "Surface size too large (allocation size would overflow int32_t)!"; |
373 | 0 | return false; |
374 | 0 | } |
375 | 0 |
|
376 | 0 | if (allocLimit && allocLimit < numBytes.value()) { |
377 | 0 | gfxDebug() << "Surface size too large (exceeds allocation limit)!"; |
378 | 0 | return false; |
379 | 0 | } |
380 | 0 |
|
381 | 0 | return true; |
382 | 0 | } |
383 | | |
384 | | already_AddRefed<DrawTarget> |
385 | | Factory::CreateDrawTarget(BackendType aBackend, const IntSize &aSize, SurfaceFormat aFormat) |
386 | 0 | { |
387 | 0 | if (!AllowedSurfaceSize(aSize)) { |
388 | 0 | gfxCriticalError(LoggerOptionsBasedOnSize(aSize)) << "Failed to allocate a surface due to invalid size (CDT) " << aSize; |
389 | 0 | return nullptr; |
390 | 0 | } |
391 | 0 |
|
392 | 0 | RefPtr<DrawTarget> retVal; |
393 | 0 | switch (aBackend) { |
394 | | #ifdef WIN32 |
395 | | case BackendType::DIRECT2D1_1: |
396 | | { |
397 | | RefPtr<DrawTargetD2D1> newTarget; |
398 | | newTarget = new DrawTargetD2D1(); |
399 | | if (newTarget->Init(aSize, aFormat)) { |
400 | | retVal = newTarget; |
401 | | } |
402 | | break; |
403 | | } |
404 | | #endif |
405 | | #ifdef USE_SKIA |
406 | 0 | case BackendType::SKIA: |
407 | 0 | { |
408 | 0 | RefPtr<DrawTargetSkia> newTarget; |
409 | 0 | newTarget = new DrawTargetSkia(); |
410 | 0 | if (newTarget->Init(aSize, aFormat)) { |
411 | 0 | retVal = newTarget; |
412 | 0 | } |
413 | 0 | break; |
414 | 0 | } |
415 | 0 | #endif |
416 | 0 | #ifdef USE_CAIRO |
417 | 0 | case BackendType::CAIRO: |
418 | 0 | { |
419 | 0 | RefPtr<DrawTargetCairo> newTarget; |
420 | 0 | newTarget = new DrawTargetCairo(); |
421 | 0 | if (newTarget->Init(aSize, aFormat)) { |
422 | 0 | retVal = newTarget; |
423 | 0 | } |
424 | 0 | break; |
425 | 0 | } |
426 | 0 | #endif |
427 | 0 | default: |
428 | 0 | return nullptr; |
429 | 0 | } |
430 | 0 | |
431 | 0 | if (mRecorder && retVal) { |
432 | 0 | return MakeAndAddRef<DrawTargetWrapAndRecord>(mRecorder, retVal); |
433 | 0 | } |
434 | 0 | |
435 | 0 | if (!retVal) { |
436 | 0 | // Failed |
437 | 0 | gfxCriticalError(LoggerOptionsBasedOnSize(aSize)) << "Failed to create DrawTarget, Type: " << int(aBackend) << " Size: " << aSize; |
438 | 0 | } |
439 | 0 |
|
440 | 0 | return retVal.forget(); |
441 | 0 | } |
442 | | |
443 | | already_AddRefed<DrawTarget> |
444 | | Factory::CreateWrapAndRecordDrawTarget(DrawEventRecorder *aRecorder, DrawTarget *aDT) |
445 | 0 | { |
446 | 0 | return MakeAndAddRef<DrawTargetWrapAndRecord>(aRecorder, aDT); |
447 | 0 | } |
448 | | |
449 | | already_AddRefed<DrawTarget> |
450 | | Factory::CreateRecordingDrawTarget(DrawEventRecorder *aRecorder, DrawTarget *aDT, IntSize aSize) |
451 | 0 | { |
452 | 0 | return MakeAndAddRef<DrawTargetRecording>(aRecorder, aDT, aSize); |
453 | 0 | } |
454 | | |
455 | | already_AddRefed<DrawTargetCapture> |
456 | | Factory::CreateCaptureDrawTargetForTarget(gfx::DrawTarget* aTarget, size_t aFlushBytes) |
457 | 0 | { |
458 | 0 | return MakeAndAddRef<DrawTargetCaptureImpl>(aTarget, aFlushBytes); |
459 | 0 | } |
460 | | |
461 | | already_AddRefed<DrawTargetCapture> |
462 | | Factory::CreateCaptureDrawTarget(BackendType aBackend, const IntSize& aSize, SurfaceFormat aFormat) |
463 | 0 | { |
464 | 0 | return MakeAndAddRef<DrawTargetCaptureImpl>(aBackend, aSize, aFormat); |
465 | 0 | } |
466 | | |
467 | | already_AddRefed<DrawTargetCapture> |
468 | | Factory::CreateCaptureDrawTargetForData(BackendType aBackend, |
469 | | const IntSize &aSize, |
470 | | SurfaceFormat aFormat, |
471 | | int32_t aStride, |
472 | | size_t aSurfaceAllocationSize) |
473 | 0 | { |
474 | 0 | MOZ_ASSERT(aSurfaceAllocationSize && aStride); |
475 | 0 |
|
476 | 0 | BackendType type = aBackend; |
477 | 0 | if (!Factory::DoesBackendSupportDataDrawtarget(aBackend)) { |
478 | 0 | type = BackendType::SKIA; |
479 | 0 | } |
480 | 0 |
|
481 | 0 | RefPtr<DrawTargetCaptureImpl> dt = new DrawTargetCaptureImpl(type, aSize, aFormat); |
482 | 0 | dt->InitForData(aStride, aSurfaceAllocationSize); |
483 | 0 | return dt.forget(); |
484 | 0 | } |
485 | | |
486 | | already_AddRefed<DrawTarget> |
487 | | Factory::CreateDrawTargetForData(BackendType aBackend, |
488 | | unsigned char *aData, |
489 | | const IntSize &aSize, |
490 | | int32_t aStride, |
491 | | SurfaceFormat aFormat, |
492 | | bool aUninitialized) |
493 | 0 | { |
494 | 0 | MOZ_ASSERT(aData); |
495 | 0 | if (!AllowedSurfaceSize(aSize)) { |
496 | 0 | gfxCriticalError(LoggerOptionsBasedOnSize(aSize)) << "Failed to allocate a surface due to invalid size (DTD) " << aSize; |
497 | 0 | return nullptr; |
498 | 0 | } |
499 | 0 |
|
500 | 0 | RefPtr<DrawTarget> retVal; |
501 | 0 |
|
502 | 0 | switch (aBackend) { |
503 | 0 | #ifdef USE_SKIA |
504 | 0 | case BackendType::SKIA: |
505 | 0 | { |
506 | 0 | RefPtr<DrawTargetSkia> newTarget; |
507 | 0 | newTarget = new DrawTargetSkia(); |
508 | 0 | if (newTarget->Init(aData, aSize, aStride, aFormat, aUninitialized)) { |
509 | 0 | retVal = newTarget; |
510 | 0 | } |
511 | 0 | break; |
512 | 0 | } |
513 | 0 | #endif |
514 | 0 | #ifdef USE_CAIRO |
515 | 0 | case BackendType::CAIRO: |
516 | 0 | { |
517 | 0 | RefPtr<DrawTargetCairo> newTarget; |
518 | 0 | newTarget = new DrawTargetCairo(); |
519 | 0 | if (newTarget->Init(aData, aSize, aStride, aFormat)) { |
520 | 0 | retVal = newTarget.forget(); |
521 | 0 | } |
522 | 0 | break; |
523 | 0 | } |
524 | 0 | #endif |
525 | 0 | default: |
526 | 0 | gfxCriticalNote << "Invalid draw target type specified: " << (int)aBackend; |
527 | 0 | return nullptr; |
528 | 0 | } |
529 | 0 |
|
530 | 0 | if (mRecorder && retVal) { |
531 | 0 | return MakeAndAddRef<DrawTargetWrapAndRecord>(mRecorder, retVal, true); |
532 | 0 | } |
533 | 0 | |
534 | 0 | if (!retVal) { |
535 | 0 | gfxCriticalNote << "Failed to create DrawTarget, Type: " << int(aBackend) << " Size: " << aSize << ", Data: " << hexa((void *)aData) << ", Stride: " << aStride; |
536 | 0 | } |
537 | 0 |
|
538 | 0 | return retVal.forget(); |
539 | 0 | } |
540 | | |
541 | | already_AddRefed<DrawTarget> |
542 | | Factory::CreateTiledDrawTarget(const TileSet& aTileSet) |
543 | 0 | { |
544 | 0 | RefPtr<DrawTargetTiled> dt = new DrawTargetTiled(); |
545 | 0 |
|
546 | 0 | if (!dt->Init(aTileSet)) { |
547 | 0 | return nullptr; |
548 | 0 | } |
549 | 0 | |
550 | 0 | return dt.forget(); |
551 | 0 | } |
552 | | |
553 | | already_AddRefed<DrawTarget> |
554 | | Factory::CreateOffsetDrawTarget(DrawTarget *aDrawTarget, IntPoint aTileOrigin) |
555 | 0 | { |
556 | 0 | RefPtr<DrawTargetOffset> dt = new DrawTargetOffset(); |
557 | 0 |
|
558 | 0 | if (!dt->Init(aDrawTarget, aTileOrigin)) { |
559 | 0 | return nullptr; |
560 | 0 | } |
561 | 0 | |
562 | 0 | return dt.forget(); |
563 | 0 | } |
564 | | |
565 | | |
566 | | bool |
567 | | Factory::DoesBackendSupportDataDrawtarget(BackendType aType) |
568 | 0 | { |
569 | 0 | switch (aType) { |
570 | 0 | case BackendType::DIRECT2D: |
571 | 0 | case BackendType::DIRECT2D1_1: |
572 | 0 | case BackendType::RECORDING: |
573 | 0 | case BackendType::NONE: |
574 | 0 | case BackendType::BACKEND_LAST: |
575 | 0 | case BackendType::WEBRENDER_TEXT: |
576 | 0 | return false; |
577 | 0 | case BackendType::CAIRO: |
578 | 0 | case BackendType::SKIA: |
579 | 0 | return true; |
580 | 0 | } |
581 | 0 | |
582 | 0 | return false; |
583 | 0 | } |
584 | | |
585 | | uint32_t |
586 | | Factory::GetMaxSurfaceSize(BackendType aType) |
587 | 0 | { |
588 | 0 | switch (aType) { |
589 | 0 | case BackendType::CAIRO: |
590 | 0 | return DrawTargetCairo::GetMaxSurfaceSize(); |
591 | 0 | #ifdef USE_SKIA |
592 | 0 | case BackendType::SKIA: |
593 | 0 | return DrawTargetSkia::GetMaxSurfaceSize(); |
594 | 0 | #endif |
595 | | #ifdef WIN32 |
596 | | case BackendType::DIRECT2D1_1: |
597 | | return DrawTargetD2D1::GetMaxSurfaceSize(); |
598 | | #endif |
599 | 0 | default: |
600 | 0 | return 0; |
601 | 0 | } |
602 | 0 | } |
603 | | |
604 | | already_AddRefed<ScaledFont> |
605 | | Factory::CreateScaledFontForNativeFont(const NativeFont &aNativeFont, |
606 | | const RefPtr<UnscaledFont>& aUnscaledFont, |
607 | | Float aSize, |
608 | | cairo_scaled_font_t* aScaledFont) |
609 | 0 | { |
610 | 0 | switch (aNativeFont.mType) { |
611 | | #ifdef WIN32 |
612 | | case NativeFontType::GDI_LOGFONT: |
613 | | { |
614 | | RefPtr<ScaledFontWin> font = MakeAndAddRef<ScaledFontWin>(static_cast<LOGFONT*>(aNativeFont.mFont), aUnscaledFont, aSize); |
615 | | #ifdef USE_CAIRO |
616 | | if (aScaledFont) { |
617 | | font->SetCairoScaledFont(aScaledFont); |
618 | | } else { |
619 | | font->PopulateCairoScaledFont(); |
620 | | } |
621 | | #endif |
622 | | return font.forget(); |
623 | | } |
624 | | #elif defined(MOZ_WIDGET_GTK) |
625 | 0 | case NativeFontType::FONTCONFIG_PATTERN: |
626 | 0 | return MakeAndAddRef<ScaledFontFontconfig>(aScaledFont, static_cast<FcPattern*>(aNativeFont.mFont), aUnscaledFont, aSize); |
627 | | #elif defined(MOZ_WIDGET_ANDROID) |
628 | | case NativeFontType::FREETYPE_FACE: |
629 | | return MakeAndAddRef<ScaledFontFreeType>(aScaledFont, static_cast<FT_Face>(aNativeFont.mFont), aUnscaledFont, aSize); |
630 | | #endif |
631 | 0 | default: |
632 | 0 | gfxWarning() << "Invalid native font type specified."; |
633 | 0 | return nullptr; |
634 | 0 | } |
635 | 0 | } |
636 | | |
637 | | already_AddRefed<NativeFontResource> |
638 | | Factory::CreateNativeFontResource(uint8_t *aData, uint32_t aSize, BackendType aBackendType, FontType aFontType, void* aFontContext) |
639 | 0 | { |
640 | 0 | switch (aFontType) { |
641 | | #ifdef WIN32 |
642 | | case FontType::DWRITE: |
643 | | { |
644 | | bool needsCairo = aBackendType == BackendType::CAIRO; |
645 | | return NativeFontResourceDWrite::Create(aData, aSize, needsCairo); |
646 | | } |
647 | | case FontType::GDI: |
648 | | return NativeFontResourceGDI::Create(aData, aSize); |
649 | | #elif defined(XP_DARWIN) |
650 | | case FontType::MAC: |
651 | | { |
652 | | bool needsCairo = aBackendType == BackendType::CAIRO; |
653 | | return NativeFontResourceMac::Create(aData, aSize, needsCairo); |
654 | | } |
655 | | #elif defined(MOZ_WIDGET_GTK) |
656 | 0 | case FontType::FONTCONFIG: |
657 | 0 | return NativeFontResourceFontconfig::Create(aData, aSize, |
658 | 0 | static_cast<FT_Library>(aFontContext)); |
659 | | #elif defined(MOZ_WIDGET_ANDROID) |
660 | | case FontType::FREETYPE: |
661 | | return NativeFontResourceFreeType::Create(aData, aSize, |
662 | | static_cast<FT_Library>(aFontContext)); |
663 | | #endif |
664 | 0 | default: |
665 | 0 | gfxWarning() << "Unable to create requested font resource from truetype data"; |
666 | 0 | return nullptr; |
667 | 0 | } |
668 | 0 | } |
669 | | |
670 | | already_AddRefed<UnscaledFont> |
671 | | Factory::CreateUnscaledFontFromFontDescriptor(FontType aType, const uint8_t* aData, uint32_t aDataLength, uint32_t aIndex) |
672 | 0 | { |
673 | 0 | switch (aType) { |
674 | | #ifdef WIN32 |
675 | | case FontType::GDI: |
676 | | return UnscaledFontGDI::CreateFromFontDescriptor(aData, aDataLength, aIndex); |
677 | | #endif |
678 | | #ifdef MOZ_WIDGET_GTK |
679 | 0 | case FontType::FONTCONFIG: |
680 | 0 | return UnscaledFontFontconfig::CreateFromFontDescriptor(aData, aDataLength, aIndex); |
681 | 0 | #endif |
682 | 0 | default: |
683 | 0 | gfxWarning() << "Invalid type specified for UnscaledFont font descriptor"; |
684 | 0 | return nullptr; |
685 | 0 | } |
686 | 0 | } |
687 | | |
688 | | #ifdef XP_DARWIN |
689 | | already_AddRefed<ScaledFont> |
690 | | Factory::CreateScaledFontForMacFont(CGFontRef aCGFont, |
691 | | const RefPtr<UnscaledFont>& aUnscaledFont, |
692 | | Float aSize, |
693 | | const Color& aFontSmoothingBackgroundColor, |
694 | | bool aUseFontSmoothing, |
695 | | bool aApplySyntheticBold) |
696 | | { |
697 | | return MakeAndAddRef<ScaledFontMac>( |
698 | | aCGFont, aUnscaledFont, aSize, false, |
699 | | aFontSmoothingBackgroundColor, aUseFontSmoothing, |
700 | | aApplySyntheticBold); |
701 | | } |
702 | | #endif |
703 | | |
704 | | already_AddRefed<DrawTarget> |
705 | | Factory::CreateDualDrawTarget(DrawTarget *targetA, DrawTarget *targetB) |
706 | 0 | { |
707 | 0 | MOZ_ASSERT(targetA && targetB); |
708 | 0 |
|
709 | 0 | RefPtr<DrawTarget> newTarget = |
710 | 0 | new DrawTargetDual(targetA, targetB); |
711 | 0 |
|
712 | 0 | RefPtr<DrawTarget> retVal = newTarget; |
713 | 0 |
|
714 | 0 | if (mRecorder) { |
715 | 0 | retVal = new DrawTargetWrapAndRecord(mRecorder, retVal); |
716 | 0 | } |
717 | 0 |
|
718 | 0 | return retVal.forget(); |
719 | 0 | } |
720 | | |
721 | | already_AddRefed<SourceSurface> |
722 | | Factory::CreateDualSourceSurface(SourceSurface *sourceA, SourceSurface *sourceB) |
723 | 0 | { |
724 | 0 | MOZ_ASSERT(sourceA && sourceB); |
725 | 0 |
|
726 | 0 | RefPtr<SourceSurface> newSource = |
727 | 0 | new SourceSurfaceDual(sourceA, sourceB); |
728 | 0 |
|
729 | 0 | return newSource.forget(); |
730 | 0 | } |
731 | | |
732 | | |
733 | | #ifdef MOZ_ENABLE_FREETYPE |
734 | | void |
735 | | Factory::SetFTLibrary(FT_Library aFTLibrary) |
736 | 0 | { |
737 | 0 | mFTLibrary = aFTLibrary; |
738 | 0 | } |
739 | | |
740 | | FT_Library |
741 | | Factory::GetFTLibrary() |
742 | 0 | { |
743 | 0 | MOZ_ASSERT(mFTLibrary); |
744 | 0 | return mFTLibrary; |
745 | 0 | } |
746 | | |
747 | | FT_Library |
748 | | Factory::NewFTLibrary() |
749 | 0 | { |
750 | 0 | FT_Library library; |
751 | 0 | if (FT_Init_FreeType(&library) != FT_Err_Ok) { |
752 | 0 | return nullptr; |
753 | 0 | } |
754 | 0 | return library; |
755 | 0 | } |
756 | | |
757 | | void |
758 | | Factory::ReleaseFTLibrary(FT_Library aFTLibrary) |
759 | 0 | { |
760 | 0 | FT_Done_FreeType(aFTLibrary); |
761 | 0 | } |
762 | | |
763 | | void |
764 | | Factory::LockFTLibrary(FT_Library aFTLibrary) |
765 | 0 | { |
766 | 0 | MOZ_ASSERT(mFTLock); |
767 | 0 | mFTLock->Lock(); |
768 | 0 | } |
769 | | |
770 | | void |
771 | | Factory::UnlockFTLibrary(FT_Library aFTLibrary) |
772 | 0 | { |
773 | 0 | MOZ_ASSERT(mFTLock); |
774 | 0 | mFTLock->Unlock(); |
775 | 0 | } |
776 | | |
777 | | FT_Face |
778 | | Factory::NewFTFace(FT_Library aFTLibrary, const char* aFileName, int aFaceIndex) |
779 | 0 | { |
780 | 0 | MOZ_ASSERT(mFTLock); |
781 | 0 | MutexAutoLock lock(*mFTLock); |
782 | 0 | if (!aFTLibrary) { |
783 | 0 | aFTLibrary = mFTLibrary; |
784 | 0 | } |
785 | 0 | FT_Face face; |
786 | 0 | if (FT_New_Face(aFTLibrary, aFileName, aFaceIndex, &face) != FT_Err_Ok) { |
787 | 0 | return nullptr; |
788 | 0 | } |
789 | 0 | return face; |
790 | 0 | } |
791 | | |
792 | | FT_Face |
793 | | Factory::NewFTFaceFromData(FT_Library aFTLibrary, const uint8_t* aData, size_t aDataSize, int aFaceIndex) |
794 | 0 | { |
795 | 0 | MOZ_ASSERT(mFTLock); |
796 | 0 | MutexAutoLock lock(*mFTLock); |
797 | 0 | if (!aFTLibrary) { |
798 | 0 | aFTLibrary = mFTLibrary; |
799 | 0 | } |
800 | 0 | FT_Face face; |
801 | 0 | if (FT_New_Memory_Face(aFTLibrary, aData, aDataSize, aFaceIndex, &face) != FT_Err_Ok) { |
802 | 0 | return nullptr; |
803 | 0 | } |
804 | 0 | return face; |
805 | 0 | } |
806 | | |
807 | | void |
808 | | Factory::ReleaseFTFace(FT_Face aFace) |
809 | 0 | { |
810 | 0 | // May be called during shutdown when the lock is already destroyed. |
811 | 0 | // However, there are no other threads using the face by this point, |
812 | 0 | // so it is safe to skip locking if the lock is not around. |
813 | 0 | if (mFTLock) { |
814 | 0 | mFTLock->Lock(); |
815 | 0 | } |
816 | 0 | FT_Done_Face(aFace); |
817 | 0 | if (mFTLock) { |
818 | 0 | mFTLock->Unlock(); |
819 | 0 | } |
820 | 0 | } |
821 | | |
822 | | FT_Error |
823 | | Factory::LoadFTGlyph(FT_Face aFace, uint32_t aGlyphIndex, int32_t aFlags) |
824 | 0 | { |
825 | 0 | MOZ_ASSERT(mFTLock); |
826 | 0 | MutexAutoLock lock(*mFTLock); |
827 | 0 | return FT_Load_Glyph(aFace, aGlyphIndex, aFlags); |
828 | 0 | } |
829 | | #endif |
830 | | |
831 | | #ifdef WIN32 |
832 | | already_AddRefed<DrawTarget> |
833 | | Factory::CreateDrawTargetForD3D11Texture(ID3D11Texture2D *aTexture, SurfaceFormat aFormat) |
834 | | { |
835 | | MOZ_ASSERT(aTexture); |
836 | | |
837 | | RefPtr<DrawTargetD2D1> newTarget; |
838 | | |
839 | | newTarget = new DrawTargetD2D1(); |
840 | | if (newTarget->Init(aTexture, aFormat)) { |
841 | | RefPtr<DrawTarget> retVal = newTarget; |
842 | | |
843 | | if (mRecorder) { |
844 | | retVal = new DrawTargetWrapAndRecord(mRecorder, retVal, true); |
845 | | } |
846 | | |
847 | | return retVal.forget(); |
848 | | } |
849 | | |
850 | | gfxWarning() << "Failed to create draw target for D3D11 texture."; |
851 | | |
852 | | // Failed |
853 | | return nullptr; |
854 | | } |
855 | | |
856 | | bool |
857 | | Factory::SetDirect3D11Device(ID3D11Device *aDevice) |
858 | | { |
859 | | MOZ_RELEASE_ASSERT(NS_IsMainThread()); |
860 | | |
861 | | // D2DFactory already takes the device lock, so we get the factory before |
862 | | // entering the lock scope. |
863 | | RefPtr<ID2D1Factory1> factory = D2DFactory(); |
864 | | |
865 | | StaticMutexAutoLock lock(mDeviceLock); |
866 | | |
867 | | mD3D11Device = aDevice; |
868 | | |
869 | | if (mD2D1Device) { |
870 | | mD2D1Device = nullptr; |
871 | | } |
872 | | |
873 | | if (!aDevice) { |
874 | | return true; |
875 | | } |
876 | | |
877 | | RefPtr<IDXGIDevice> device; |
878 | | aDevice->QueryInterface((IDXGIDevice**)getter_AddRefs(device)); |
879 | | |
880 | | RefPtr<ID2D1Device> d2dDevice; |
881 | | HRESULT hr = factory->CreateDevice(device, getter_AddRefs(d2dDevice)); |
882 | | if (FAILED(hr)) { |
883 | | gfxCriticalError() << "[D2D1] Failed to create gfx factory's D2D1 device, code: " << hexa(hr); |
884 | | |
885 | | mD3D11Device = nullptr; |
886 | | return false; |
887 | | } |
888 | | |
889 | | mDeviceSeq++; |
890 | | mD2D1Device = d2dDevice; |
891 | | return true; |
892 | | } |
893 | | |
894 | | RefPtr<ID3D11Device> |
895 | | Factory::GetDirect3D11Device() |
896 | | { |
897 | | StaticMutexAutoLock lock(mDeviceLock); |
898 | | return mD3D11Device; |
899 | | } |
900 | | |
901 | | RefPtr<ID2D1Device> |
902 | | Factory::GetD2D1Device(uint32_t* aOutSeqNo) |
903 | | { |
904 | | StaticMutexAutoLock lock(mDeviceLock); |
905 | | if (aOutSeqNo) { |
906 | | *aOutSeqNo = mDeviceSeq; |
907 | | } |
908 | | return mD2D1Device.get(); |
909 | | } |
910 | | |
911 | | bool |
912 | | Factory::HasD2D1Device() |
913 | | { |
914 | | return !!GetD2D1Device(); |
915 | | } |
916 | | |
917 | | RefPtr<IDWriteFactory> |
918 | | Factory::GetDWriteFactory() |
919 | | { |
920 | | StaticMutexAutoLock lock(mDeviceLock); |
921 | | return mDWriteFactory; |
922 | | } |
923 | | |
924 | | RefPtr<IDWriteFactory> |
925 | | Factory::EnsureDWriteFactory() |
926 | | { |
927 | | StaticMutexAutoLock lock(mDeviceLock); |
928 | | |
929 | | if (mDWriteFactoryInitialized) { |
930 | | return mDWriteFactory; |
931 | | } |
932 | | |
933 | | mDWriteFactoryInitialized = true; |
934 | | |
935 | | HMODULE dwriteModule = LoadLibraryW(L"dwrite.dll"); |
936 | | decltype(DWriteCreateFactory)* createDWriteFactory = (decltype(DWriteCreateFactory)*) |
937 | | GetProcAddress(dwriteModule, "DWriteCreateFactory"); |
938 | | |
939 | | if (!createDWriteFactory) { |
940 | | gfxWarning() << "Failed to locate DWriteCreateFactory function."; |
941 | | return nullptr; |
942 | | } |
943 | | |
944 | | HRESULT hr = createDWriteFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory), |
945 | | reinterpret_cast<IUnknown**>(&mDWriteFactory)); |
946 | | |
947 | | if (FAILED(hr)) { |
948 | | gfxWarning() << "Failed to create DWrite Factory."; |
949 | | } |
950 | | |
951 | | return mDWriteFactory; |
952 | | } |
953 | | |
954 | | bool |
955 | | Factory::SupportsD2D1() |
956 | | { |
957 | | return !!D2DFactory(); |
958 | | } |
959 | | |
960 | | BYTE sSystemTextQuality = CLEARTYPE_QUALITY; |
961 | | void |
962 | | Factory::SetSystemTextQuality(uint8_t aQuality) |
963 | | { |
964 | | sSystemTextQuality = aQuality; |
965 | | } |
966 | | |
967 | | uint64_t |
968 | | Factory::GetD2DVRAMUsageDrawTarget() |
969 | | { |
970 | | return DrawTargetD2D1::mVRAMUsageDT; |
971 | | } |
972 | | |
973 | | uint64_t |
974 | | Factory::GetD2DVRAMUsageSourceSurface() |
975 | | { |
976 | | return DrawTargetD2D1::mVRAMUsageSS; |
977 | | } |
978 | | |
979 | | void |
980 | | Factory::D2DCleanup() |
981 | | { |
982 | | StaticMutexAutoLock lock(mDeviceLock); |
983 | | if (mD2D1Device) { |
984 | | mD2D1Device = nullptr; |
985 | | } |
986 | | DrawTargetD2D1::CleanupD2D(); |
987 | | } |
988 | | |
989 | | already_AddRefed<ScaledFont> |
990 | | Factory::CreateScaledFontForDWriteFont(IDWriteFontFace* aFontFace, |
991 | | const gfxFontStyle* aStyle, |
992 | | const RefPtr<UnscaledFont>& aUnscaledFont, |
993 | | float aSize, |
994 | | bool aUseEmbeddedBitmap, |
995 | | bool aForceGDIMode, |
996 | | IDWriteRenderingParams* aParams, |
997 | | Float aGamma, |
998 | | Float aContrast) |
999 | | { |
1000 | | return MakeAndAddRef<ScaledFontDWrite>(aFontFace, aUnscaledFont, aSize, |
1001 | | aUseEmbeddedBitmap, aForceGDIMode, |
1002 | | aParams, aGamma, aContrast, |
1003 | | aStyle); |
1004 | | } |
1005 | | |
1006 | | #endif // XP_WIN |
1007 | | |
1008 | | #ifdef USE_SKIA_GPU |
1009 | | already_AddRefed<DrawTarget> |
1010 | | Factory::CreateDrawTargetSkiaWithGrContext(GrContext* aGrContext, |
1011 | | const IntSize &aSize, |
1012 | | SurfaceFormat aFormat) |
1013 | 0 | { |
1014 | 0 | RefPtr<DrawTarget> newTarget = new DrawTargetSkia(); |
1015 | 0 | if (!newTarget->InitWithGrContext(aGrContext, aSize, aFormat)) { |
1016 | 0 | return nullptr; |
1017 | 0 | } |
1018 | 0 | return newTarget.forget(); |
1019 | 0 | } |
1020 | | |
1021 | | #endif // USE_SKIA_GPU |
1022 | | |
1023 | | #ifdef USE_SKIA |
1024 | | already_AddRefed<DrawTarget> |
1025 | | Factory::CreateDrawTargetWithSkCanvas(SkCanvas* aCanvas) |
1026 | 0 | { |
1027 | 0 | RefPtr<DrawTargetSkia> newTarget = new DrawTargetSkia(); |
1028 | 0 | if (!newTarget->Init(aCanvas)) { |
1029 | 0 | return nullptr; |
1030 | 0 | } |
1031 | 0 | return newTarget.forget(); |
1032 | 0 | } |
1033 | | #endif |
1034 | | |
1035 | | void |
1036 | | Factory::PurgeAllCaches() |
1037 | 0 | { |
1038 | 0 | } |
1039 | | |
1040 | | already_AddRefed<DrawTarget> |
1041 | | Factory::CreateDrawTargetForCairoSurface(cairo_surface_t* aSurface, const IntSize& aSize, SurfaceFormat* aFormat) |
1042 | 0 | { |
1043 | 0 | if (!AllowedSurfaceSize(aSize)) { |
1044 | 0 | gfxWarning() << "Allowing surface with invalid size (Cairo) " << aSize; |
1045 | 0 | } |
1046 | 0 |
|
1047 | 0 | RefPtr<DrawTarget> retVal; |
1048 | 0 |
|
1049 | 0 | #ifdef USE_CAIRO |
1050 | 0 | RefPtr<DrawTargetCairo> newTarget = new DrawTargetCairo(); |
1051 | 0 |
|
1052 | 0 | if (newTarget->Init(aSurface, aSize, aFormat)) { |
1053 | 0 | retVal = newTarget; |
1054 | 0 | } |
1055 | 0 |
|
1056 | 0 | if (mRecorder && retVal) { |
1057 | 0 | return MakeAndAddRef<DrawTargetWrapAndRecord>(mRecorder, retVal, true); |
1058 | 0 | } |
1059 | 0 | #endif |
1060 | 0 | return retVal.forget(); |
1061 | 0 | } |
1062 | | |
1063 | | already_AddRefed<SourceSurface> |
1064 | | Factory::CreateSourceSurfaceForCairoSurface(cairo_surface_t* aSurface, const IntSize& aSize, SurfaceFormat aFormat) |
1065 | 0 | { |
1066 | 0 | if (aSize.width <= 0 || aSize.height <= 0) { |
1067 | 0 | gfxWarning() << "Can't create a SourceSurface without a valid size"; |
1068 | 0 | return nullptr; |
1069 | 0 | } |
1070 | 0 |
|
1071 | 0 | #ifdef USE_CAIRO |
1072 | 0 | return MakeAndAddRef<SourceSurfaceCairo>(aSurface, aSize, aFormat); |
1073 | | #else |
1074 | | return nullptr; |
1075 | | #endif |
1076 | | } |
1077 | | |
1078 | | already_AddRefed<DataSourceSurface> |
1079 | | Factory::CreateWrappingDataSourceSurface(uint8_t *aData, |
1080 | | int32_t aStride, |
1081 | | const IntSize &aSize, |
1082 | | SurfaceFormat aFormat, |
1083 | | SourceSurfaceDeallocator aDeallocator /* = nullptr */, |
1084 | | void* aClosure /* = nullptr */) |
1085 | 0 | { |
1086 | 0 | // Just check for negative/zero size instead of the full AllowedSurfaceSize() - since |
1087 | 0 | // the data is already allocated we do not need to check for a possible overflow - it |
1088 | 0 | // already worked. |
1089 | 0 | if (aSize.width <= 0 || aSize.height <= 0) { |
1090 | 0 | return nullptr; |
1091 | 0 | } |
1092 | 0 | if (!aDeallocator && aClosure) { |
1093 | 0 | return nullptr; |
1094 | 0 | } |
1095 | 0 | |
1096 | 0 | MOZ_ASSERT(aData); |
1097 | 0 |
|
1098 | 0 | RefPtr<SourceSurfaceRawData> newSurf = new SourceSurfaceRawData(); |
1099 | 0 | newSurf->InitWrappingData(aData, aSize, aStride, aFormat, aDeallocator, aClosure); |
1100 | 0 |
|
1101 | 0 | return newSurf.forget(); |
1102 | 0 | } |
1103 | | |
1104 | | already_AddRefed<DataSourceSurface> |
1105 | | Factory::CreateDataSourceSurface(const IntSize &aSize, |
1106 | | SurfaceFormat aFormat, |
1107 | | bool aZero) |
1108 | 0 | { |
1109 | 0 | if (!AllowedSurfaceSize(aSize)) { |
1110 | 0 | gfxCriticalError(LoggerOptionsBasedOnSize(aSize)) << "Failed to allocate a surface due to invalid size (DSS) " << aSize; |
1111 | 0 | return nullptr; |
1112 | 0 | } |
1113 | 0 |
|
1114 | 0 | // Skia doesn't support RGBX, so memset RGBX to 0xFF |
1115 | 0 | bool clearSurface = aZero || aFormat == SurfaceFormat::B8G8R8X8; |
1116 | 0 | uint8_t clearValue = aFormat == SurfaceFormat::B8G8R8X8 ? 0xFF : 0; |
1117 | 0 |
|
1118 | 0 | RefPtr<SourceSurfaceAlignedRawData> newSurf = new SourceSurfaceAlignedRawData(); |
1119 | 0 | if (newSurf->Init(aSize, aFormat, clearSurface, clearValue)) { |
1120 | 0 | return newSurf.forget(); |
1121 | 0 | } |
1122 | 0 | |
1123 | 0 | gfxWarning() << "CreateDataSourceSurface failed in init"; |
1124 | 0 | return nullptr; |
1125 | 0 | } |
1126 | | |
1127 | | already_AddRefed<DataSourceSurface> |
1128 | | Factory::CreateDataSourceSurfaceWithStride(const IntSize &aSize, |
1129 | | SurfaceFormat aFormat, |
1130 | | int32_t aStride, |
1131 | | bool aZero) |
1132 | 0 | { |
1133 | 0 | if (!AllowedSurfaceSize(aSize) || |
1134 | 0 | aStride < aSize.width * BytesPerPixel(aFormat)) { |
1135 | 0 | gfxCriticalError(LoggerOptionsBasedOnSize(aSize)) << "CreateDataSourceSurfaceWithStride failed with bad stride " << aStride << ", " << aSize << ", " << aFormat; |
1136 | 0 | return nullptr; |
1137 | 0 | } |
1138 | 0 |
|
1139 | 0 | // Skia doesn't support RGBX, so memset RGBX to 0xFF |
1140 | 0 | bool clearSurface = aZero || aFormat == SurfaceFormat::B8G8R8X8; |
1141 | 0 | uint8_t clearValue = aFormat == SurfaceFormat::B8G8R8X8 ? 0xFF : 0; |
1142 | 0 |
|
1143 | 0 | RefPtr<SourceSurfaceAlignedRawData> newSurf = new SourceSurfaceAlignedRawData(); |
1144 | 0 | if (newSurf->Init(aSize, aFormat, clearSurface, clearValue, aStride)) { |
1145 | 0 | return newSurf.forget(); |
1146 | 0 | } |
1147 | 0 | |
1148 | 0 | gfxCriticalError(LoggerOptionsBasedOnSize(aSize)) << "CreateDataSourceSurfaceWithStride failed to initialize " << aSize << ", " << aFormat << ", " << aStride << ", " << aZero; |
1149 | 0 | return nullptr; |
1150 | 0 | } |
1151 | | |
1152 | | void |
1153 | | Factory::CopyDataSourceSurface(DataSourceSurface* aSource, |
1154 | | DataSourceSurface* aDest) |
1155 | 0 | { |
1156 | 0 | // Don't worry too much about speed. |
1157 | 0 | MOZ_ASSERT(aSource->GetSize() == aDest->GetSize()); |
1158 | 0 | MOZ_ASSERT(aSource->GetFormat() == SurfaceFormat::R8G8B8A8 || |
1159 | 0 | aSource->GetFormat() == SurfaceFormat::R8G8B8X8 || |
1160 | 0 | aSource->GetFormat() == SurfaceFormat::B8G8R8A8 || |
1161 | 0 | aSource->GetFormat() == SurfaceFormat::B8G8R8X8); |
1162 | 0 | MOZ_ASSERT(aDest->GetFormat() == SurfaceFormat::R8G8B8A8 || |
1163 | 0 | aDest->GetFormat() == SurfaceFormat::R8G8B8X8 || |
1164 | 0 | aDest->GetFormat() == SurfaceFormat::B8G8R8A8 || |
1165 | 0 | aDest->GetFormat() == SurfaceFormat::B8G8R8X8 || |
1166 | 0 | aDest->GetFormat() == SurfaceFormat::R5G6B5_UINT16); |
1167 | 0 |
|
1168 | 0 | DataSourceSurface::MappedSurface srcMap; |
1169 | 0 | DataSourceSurface::MappedSurface destMap; |
1170 | 0 | if (!aSource->Map(DataSourceSurface::MapType::READ, &srcMap) || |
1171 | 0 | !aDest->Map(DataSourceSurface::MapType::WRITE, &destMap)) { |
1172 | 0 | MOZ_ASSERT(false, "CopyDataSourceSurface: Failed to map surface."); |
1173 | 0 | return; |
1174 | 0 | } |
1175 | 0 |
|
1176 | 0 | SwizzleData(srcMap.mData, srcMap.mStride, aSource->GetFormat(), |
1177 | 0 | destMap.mData, destMap.mStride, aDest->GetFormat(), |
1178 | 0 | aSource->GetSize()); |
1179 | 0 |
|
1180 | 0 | aSource->Unmap(); |
1181 | 0 | aDest->Unmap(); |
1182 | 0 | } |
1183 | | |
1184 | | already_AddRefed<DrawEventRecorder> |
1185 | | Factory::CreateEventRecorderForFile(const char_type* aFilename) |
1186 | 0 | { |
1187 | 0 | return MakeAndAddRef<DrawEventRecorderFile>(aFilename); |
1188 | 0 | } |
1189 | | |
1190 | | void |
1191 | | Factory::SetGlobalEventRecorder(DrawEventRecorder *aRecorder) |
1192 | 0 | { |
1193 | 0 | mRecorder = aRecorder; |
1194 | 0 | } |
1195 | | |
1196 | | // static |
1197 | | void |
1198 | | CriticalLogger::OutputMessage(const std::string &aString, |
1199 | | int aLevel, bool aNoNewline) |
1200 | 0 | { |
1201 | 0 | if (Factory::GetLogForwarder()) { |
1202 | 0 | Factory::GetLogForwarder()->Log(aString); |
1203 | 0 | } |
1204 | 0 |
|
1205 | 0 | BasicLogger::OutputMessage(aString, aLevel, aNoNewline); |
1206 | 0 | } |
1207 | | |
1208 | | void |
1209 | | CriticalLogger::CrashAction(LogReason aReason) |
1210 | 0 | { |
1211 | 0 | if (Factory::GetLogForwarder()) { |
1212 | 0 | Factory::GetLogForwarder()->CrashAction(aReason); |
1213 | 0 | } |
1214 | 0 | } |
1215 | | |
1216 | | } // namespace gfx |
1217 | | } // namespace mozilla |