/src/mozilla-central/gfx/layers/BufferTexture.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 "BufferTexture.h" |
8 | | #include "mozilla/layers/ImageDataSerializer.h" |
9 | | #include "mozilla/layers/ISurfaceAllocator.h" |
10 | | #include "mozilla/layers/CompositableForwarder.h" |
11 | | #include "mozilla/gfx/Logging.h" |
12 | | #include "mozilla/gfx/2D.h" |
13 | | #include "mozilla/fallible.h" |
14 | | #include "libyuv.h" |
15 | | |
16 | | #ifdef MOZ_WIDGET_GTK |
17 | | #include "gfxPlatformGtk.h" |
18 | | #endif |
19 | | |
20 | | namespace mozilla { |
21 | | namespace layers { |
22 | | |
23 | | class MemoryTextureData : public BufferTextureData |
24 | | { |
25 | | public: |
26 | | static MemoryTextureData* Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, |
27 | | gfx::BackendType aMoz2DBackend, |
28 | | LayersBackend aLayersBackend, |
29 | | TextureFlags aFlags, |
30 | | TextureAllocationFlags aAllocFlags, |
31 | | LayersIPCChannel* aAllocator); |
32 | | |
33 | | virtual TextureData* |
34 | | CreateSimilar(LayersIPCChannel* aAllocator, |
35 | | LayersBackend aLayersBackend, |
36 | | TextureFlags aFlags = TextureFlags::DEFAULT, |
37 | | TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const override; |
38 | | |
39 | | virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override; |
40 | | |
41 | | virtual void Deallocate(LayersIPCChannel*) override; |
42 | | |
43 | | MemoryTextureData(const BufferDescriptor& aDesc, |
44 | | gfx::BackendType aMoz2DBackend, |
45 | | uint8_t* aBuffer, size_t aBufferSize) |
46 | | : BufferTextureData(aDesc, aMoz2DBackend) |
47 | | , mBuffer(aBuffer) |
48 | | , mBufferSize(aBufferSize) |
49 | 0 | { |
50 | 0 | MOZ_ASSERT(aBuffer); |
51 | 0 | MOZ_ASSERT(aBufferSize); |
52 | 0 | } |
53 | | |
54 | 0 | virtual uint8_t* GetBuffer() override { return mBuffer; } |
55 | | |
56 | 0 | virtual size_t GetBufferSize() override { return mBufferSize; } |
57 | | |
58 | | protected: |
59 | | uint8_t* mBuffer; |
60 | | size_t mBufferSize; |
61 | | }; |
62 | | |
63 | | class ShmemTextureData : public BufferTextureData |
64 | | { |
65 | | public: |
66 | | static ShmemTextureData* Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, |
67 | | gfx::BackendType aMoz2DBackend, |
68 | | LayersBackend aLayersBackend, |
69 | | TextureFlags aFlags, |
70 | | TextureAllocationFlags aAllocFlags, |
71 | | LayersIPCChannel* aAllocator); |
72 | | |
73 | | virtual TextureData* |
74 | | CreateSimilar(LayersIPCChannel* aAllocator, |
75 | | LayersBackend aLayersBackend, |
76 | | TextureFlags aFlags = TextureFlags::DEFAULT, |
77 | | TextureAllocationFlags aAllocFlags = ALLOC_DEFAULT) const override; |
78 | | |
79 | | virtual bool Serialize(SurfaceDescriptor& aOutDescriptor) override; |
80 | | |
81 | | virtual void Deallocate(LayersIPCChannel* aAllocator) override; |
82 | | |
83 | | ShmemTextureData(const BufferDescriptor& aDesc, |
84 | | gfx::BackendType aMoz2DBackend, mozilla::ipc::Shmem aShmem) |
85 | | : BufferTextureData(aDesc, aMoz2DBackend) |
86 | | , mShmem(aShmem) |
87 | 0 | { |
88 | 0 | MOZ_ASSERT(mShmem.Size<uint8_t>()); |
89 | 0 | } |
90 | | |
91 | 0 | virtual uint8_t* GetBuffer() override { return mShmem.get<uint8_t>(); } |
92 | | |
93 | 0 | virtual size_t GetBufferSize() override { return mShmem.Size<uint8_t>(); } |
94 | | |
95 | | protected: |
96 | | mozilla::ipc::Shmem mShmem; |
97 | | }; |
98 | | |
99 | | static bool UsingX11Compositor() |
100 | 0 | { |
101 | 0 | #ifdef MOZ_WIDGET_GTK |
102 | 0 | return gfx::gfxVars::UseXRender(); |
103 | 0 | #endif |
104 | 0 | return false; |
105 | 0 | } |
106 | | |
107 | | bool ComputeHasIntermediateBuffer(gfx::SurfaceFormat aFormat, |
108 | | LayersBackend aLayersBackend, |
109 | | bool aSupportsTextureDirectMapping) |
110 | 0 | { |
111 | 0 | if (aSupportsTextureDirectMapping) { |
112 | 0 | return false; |
113 | 0 | } |
114 | 0 | |
115 | 0 | return aLayersBackend != LayersBackend::LAYERS_BASIC |
116 | 0 | || UsingX11Compositor() |
117 | 0 | || aFormat == gfx::SurfaceFormat::UNKNOWN; |
118 | 0 | } |
119 | | |
120 | | BufferTextureData* |
121 | | BufferTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, |
122 | | gfx::BackendType aMoz2DBackend, |
123 | | LayersBackend aLayersBackend, TextureFlags aFlags, |
124 | | TextureAllocationFlags aAllocFlags, |
125 | | LayersIPCChannel* aAllocator) |
126 | 0 | { |
127 | 0 | if (!aAllocator || aAllocator->IsSameProcess()) { |
128 | 0 | return MemoryTextureData::Create(aSize, aFormat, aMoz2DBackend, |
129 | 0 | aLayersBackend, aFlags, |
130 | 0 | aAllocFlags, aAllocator); |
131 | 0 | } else { |
132 | 0 | return ShmemTextureData::Create(aSize, aFormat, aMoz2DBackend, |
133 | 0 | aLayersBackend, aFlags, |
134 | 0 | aAllocFlags, aAllocator); |
135 | 0 | } |
136 | 0 | } |
137 | | |
138 | | BufferTextureData* |
139 | | BufferTextureData::CreateInternal(LayersIPCChannel* aAllocator, |
140 | | const BufferDescriptor& aDesc, |
141 | | gfx::BackendType aMoz2DBackend, |
142 | | int32_t aBufferSize, |
143 | | TextureFlags aTextureFlags) |
144 | 0 | { |
145 | 0 | if (!aAllocator || aAllocator->IsSameProcess()) { |
146 | 0 | uint8_t* buffer = new (fallible) uint8_t[aBufferSize]; |
147 | 0 | if (!buffer) { |
148 | 0 | return nullptr; |
149 | 0 | } |
150 | 0 | |
151 | 0 | GfxMemoryImageReporter::DidAlloc(buffer); |
152 | 0 |
|
153 | 0 | return new MemoryTextureData(aDesc, aMoz2DBackend, buffer, aBufferSize); |
154 | 0 | } else { |
155 | 0 | ipc::Shmem shm; |
156 | 0 | if (!aAllocator->AllocUnsafeShmem(aBufferSize, OptimalShmemType(), &shm)) { |
157 | 0 | return nullptr; |
158 | 0 | } |
159 | 0 | |
160 | 0 | return new ShmemTextureData(aDesc, aMoz2DBackend, shm); |
161 | 0 | } |
162 | 0 | } |
163 | | |
164 | | BufferTextureData* |
165 | | BufferTextureData::CreateForYCbCr(KnowsCompositor* aAllocator, |
166 | | gfx::IntSize aYSize, |
167 | | uint32_t aYStride, |
168 | | gfx::IntSize aCbCrSize, |
169 | | uint32_t aCbCrStride, |
170 | | StereoMode aStereoMode, |
171 | | YUVColorSpace aYUVColorSpace, |
172 | | uint32_t aBitDepth, |
173 | | TextureFlags aTextureFlags) |
174 | 0 | { |
175 | 0 | uint32_t bufSize = ImageDataSerializer::ComputeYCbCrBufferSize( |
176 | 0 | aYSize, aYStride, aCbCrSize, aCbCrStride); |
177 | 0 | if (bufSize == 0) { |
178 | 0 | return nullptr; |
179 | 0 | } |
180 | 0 | |
181 | 0 | uint32_t yOffset; |
182 | 0 | uint32_t cbOffset; |
183 | 0 | uint32_t crOffset; |
184 | 0 | ImageDataSerializer::ComputeYCbCrOffsets(aYStride, aYSize.height, |
185 | 0 | aCbCrStride, aCbCrSize.height, |
186 | 0 | yOffset, cbOffset, crOffset); |
187 | 0 |
|
188 | 0 | bool supportsTextureDirectMapping = |
189 | 0 | aAllocator->SupportsTextureDirectMapping() && aAllocator->GetMaxTextureSize() > |
190 | 0 | std::max(aYSize.width, std::max(aYSize.height, std::max(aCbCrSize.width, aCbCrSize.height))); |
191 | 0 |
|
192 | 0 | bool hasIntermediateBuffer = |
193 | 0 | aAllocator |
194 | 0 | ? ComputeHasIntermediateBuffer(gfx::SurfaceFormat::YUV, |
195 | 0 | aAllocator->GetCompositorBackendType(), |
196 | 0 | supportsTextureDirectMapping) |
197 | 0 | : true; |
198 | 0 |
|
199 | 0 | YCbCrDescriptor descriptor = YCbCrDescriptor(aYSize, aYStride, |
200 | 0 | aCbCrSize, aCbCrStride, |
201 | 0 | yOffset, cbOffset, crOffset, |
202 | 0 | aStereoMode, |
203 | 0 | aYUVColorSpace, |
204 | 0 | aBitDepth, |
205 | 0 | hasIntermediateBuffer); |
206 | 0 |
|
207 | 0 | return CreateInternal(aAllocator ? aAllocator->GetTextureForwarder() |
208 | 0 | : nullptr, |
209 | 0 | descriptor, |
210 | 0 | gfx::BackendType::NONE, |
211 | 0 | bufSize, |
212 | 0 | aTextureFlags); |
213 | 0 | } |
214 | | |
215 | | void |
216 | | BufferTextureData::FillInfo(TextureData::Info& aInfo) const |
217 | 0 | { |
218 | 0 | aInfo.size = GetSize(); |
219 | 0 | aInfo.format = GetFormat(); |
220 | 0 | aInfo.hasSynchronization = false; |
221 | 0 | aInfo.canExposeMappedData = true; |
222 | 0 |
|
223 | 0 | if (mDescriptor.type() == BufferDescriptor::TYCbCrDescriptor) { |
224 | 0 | aInfo.hasIntermediateBuffer = mDescriptor.get_YCbCrDescriptor().hasIntermediateBuffer(); |
225 | 0 | } else { |
226 | 0 | aInfo.hasIntermediateBuffer = mDescriptor.get_RGBDescriptor().hasIntermediateBuffer(); |
227 | 0 | } |
228 | 0 |
|
229 | 0 | switch (aInfo.format) { |
230 | 0 | case gfx::SurfaceFormat::YUV: |
231 | 0 | case gfx::SurfaceFormat::UNKNOWN: |
232 | 0 | aInfo.supportsMoz2D = false; |
233 | 0 | break; |
234 | 0 | default: |
235 | 0 | aInfo.supportsMoz2D = true; |
236 | 0 | } |
237 | 0 | } |
238 | | |
239 | | gfx::IntSize |
240 | | BufferTextureData::GetSize() const |
241 | 0 | { |
242 | 0 | return ImageDataSerializer::SizeFromBufferDescriptor(mDescriptor); |
243 | 0 | } |
244 | | |
245 | | Maybe<gfx::IntSize> |
246 | | BufferTextureData::GetCbCrSize() const |
247 | 0 | { |
248 | 0 | return ImageDataSerializer::CbCrSizeFromBufferDescriptor(mDescriptor); |
249 | 0 | } |
250 | | |
251 | | Maybe<YUVColorSpace> |
252 | | BufferTextureData::GetYUVColorSpace() const |
253 | 0 | { |
254 | 0 | return ImageDataSerializer::YUVColorSpaceFromBufferDescriptor(mDescriptor); |
255 | 0 | } |
256 | | |
257 | | Maybe<uint32_t> |
258 | | BufferTextureData::GetBitDepth() const |
259 | 0 | { |
260 | 0 | return ImageDataSerializer::BitDepthFromBufferDescriptor(mDescriptor); |
261 | 0 | } |
262 | | |
263 | | Maybe<StereoMode> |
264 | | BufferTextureData::GetStereoMode() const |
265 | 0 | { |
266 | 0 | return ImageDataSerializer::StereoModeFromBufferDescriptor(mDescriptor); |
267 | 0 | } |
268 | | |
269 | | gfx::SurfaceFormat |
270 | | BufferTextureData::GetFormat() const |
271 | 0 | { |
272 | 0 | return ImageDataSerializer::FormatFromBufferDescriptor(mDescriptor); |
273 | 0 | } |
274 | | |
275 | | already_AddRefed<gfx::DrawTarget> |
276 | | BufferTextureData::BorrowDrawTarget() |
277 | 0 | { |
278 | 0 | if (mDrawTarget) { |
279 | 0 | mDrawTarget->SetTransform(gfx::Matrix()); |
280 | 0 | RefPtr<gfx::DrawTarget> dt = mDrawTarget; |
281 | 0 | return dt.forget(); |
282 | 0 | } |
283 | 0 | |
284 | 0 | if (mDescriptor.type() != BufferDescriptor::TRGBDescriptor) { |
285 | 0 | return nullptr; |
286 | 0 | } |
287 | 0 | |
288 | 0 | const RGBDescriptor& rgb = mDescriptor.get_RGBDescriptor(); |
289 | 0 |
|
290 | 0 | uint32_t stride = ImageDataSerializer::GetRGBStride(rgb); |
291 | 0 | if (gfx::Factory::DoesBackendSupportDataDrawtarget(mMoz2DBackend)) { |
292 | 0 | mDrawTarget = gfx::Factory::CreateDrawTargetForData(mMoz2DBackend, |
293 | 0 | GetBuffer(), rgb.size(), |
294 | 0 | stride, rgb.format(), true); |
295 | 0 | } else { |
296 | 0 | // Fall back to supported platform backend. Note that mMoz2DBackend |
297 | 0 | // does not match the draw target type. |
298 | 0 | mDrawTarget = gfxPlatform::CreateDrawTargetForData(GetBuffer(), rgb.size(), |
299 | 0 | stride, rgb.format(), |
300 | 0 | true); |
301 | 0 | } |
302 | 0 |
|
303 | 0 | if (mDrawTarget) { |
304 | 0 | RefPtr<gfx::DrawTarget> dt = mDrawTarget; |
305 | 0 | return dt.forget(); |
306 | 0 | } |
307 | 0 | |
308 | 0 | // TODO - should we warn? should we really fallback to cairo? perhaps |
309 | 0 | // at least update mMoz2DBackend... |
310 | 0 | if (mMoz2DBackend != gfx::BackendType::CAIRO) { |
311 | 0 | gfxCriticalNote << "Falling to CAIRO from " << (int)mMoz2DBackend; |
312 | 0 | mDrawTarget = gfx::Factory::CreateDrawTargetForData(gfx::BackendType::CAIRO, |
313 | 0 | GetBuffer(), rgb.size(), |
314 | 0 | stride, rgb.format(), true); |
315 | 0 | } |
316 | 0 |
|
317 | 0 | if (!mDrawTarget) { |
318 | 0 | gfxCriticalNote << "BorrowDrawTarget failure, original backend " << (int)mMoz2DBackend; |
319 | 0 | } |
320 | 0 |
|
321 | 0 | RefPtr<gfx::DrawTarget> dt = mDrawTarget; |
322 | 0 | return dt.forget(); |
323 | 0 | } |
324 | | |
325 | | bool |
326 | | BufferTextureData::BorrowMappedData(MappedTextureData& aData) |
327 | 0 | { |
328 | 0 | if (GetFormat() == gfx::SurfaceFormat::YUV) { |
329 | 0 | return false; |
330 | 0 | } |
331 | 0 | |
332 | 0 | gfx::IntSize size = GetSize(); |
333 | 0 |
|
334 | 0 | aData.data = GetBuffer(); |
335 | 0 | aData.size = size; |
336 | 0 | aData.format = GetFormat(); |
337 | 0 | aData.stride = ImageDataSerializer::ComputeRGBStride(aData.format, size.width); |
338 | 0 |
|
339 | 0 | return true; |
340 | 0 | } |
341 | | |
342 | | bool |
343 | | BufferTextureData::BorrowMappedYCbCrData(MappedYCbCrTextureData& aMap) |
344 | 0 | { |
345 | 0 | if (mDescriptor.type() != BufferDescriptor::TYCbCrDescriptor) { |
346 | 0 | return false; |
347 | 0 | } |
348 | 0 | |
349 | 0 | const YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor(); |
350 | 0 |
|
351 | 0 | uint8_t* data = GetBuffer(); |
352 | 0 | auto ySize = desc.ySize(); |
353 | 0 | auto cbCrSize = desc.cbCrSize(); |
354 | 0 |
|
355 | 0 | aMap.stereoMode = desc.stereoMode(); |
356 | 0 | aMap.metadata = nullptr; |
357 | 0 | uint32_t bytesPerPixel = desc.bitDepth() > 8 ? 2 : 1; |
358 | 0 |
|
359 | 0 | aMap.y.data = data + desc.yOffset(); |
360 | 0 | aMap.y.size = ySize; |
361 | 0 | aMap.y.stride = desc.yStride(); |
362 | 0 | aMap.y.skip = 0; |
363 | 0 | aMap.y.bytesPerPixel = bytesPerPixel; |
364 | 0 |
|
365 | 0 | aMap.cb.data = data + desc.cbOffset(); |
366 | 0 | aMap.cb.size = cbCrSize; |
367 | 0 | aMap.cb.stride = desc.cbCrStride(); |
368 | 0 | aMap.cb.skip = 0; |
369 | 0 | aMap.cb.bytesPerPixel = bytesPerPixel; |
370 | 0 |
|
371 | 0 | aMap.cr.data = data + desc.crOffset(); |
372 | 0 | aMap.cr.size = cbCrSize; |
373 | 0 | aMap.cr.stride = desc.cbCrStride(); |
374 | 0 | aMap.cr.skip = 0; |
375 | 0 | aMap.cr.bytesPerPixel = bytesPerPixel; |
376 | 0 |
|
377 | 0 | return true; |
378 | 0 | } |
379 | | |
380 | | bool |
381 | | BufferTextureData::UpdateFromSurface(gfx::SourceSurface* aSurface) |
382 | 0 | { |
383 | 0 | if (mDescriptor.type() != BufferDescriptor::TRGBDescriptor) { |
384 | 0 | return false; |
385 | 0 | } |
386 | 0 | const RGBDescriptor& rgb = mDescriptor.get_RGBDescriptor(); |
387 | 0 |
|
388 | 0 | uint32_t stride = ImageDataSerializer::GetRGBStride(rgb); |
389 | 0 | RefPtr<gfx::DataSourceSurface> surface = |
390 | 0 | gfx::Factory::CreateWrappingDataSourceSurface(GetBuffer(), stride, |
391 | 0 | rgb.size(), rgb.format()); |
392 | 0 |
|
393 | 0 | if (!surface) { |
394 | 0 | gfxCriticalError() << "Failed to get serializer as surface!"; |
395 | 0 | return false; |
396 | 0 | } |
397 | 0 |
|
398 | 0 | RefPtr<gfx::DataSourceSurface> srcSurf = aSurface->GetDataSurface(); |
399 | 0 |
|
400 | 0 | if (!srcSurf) { |
401 | 0 | gfxCriticalError() << "Failed to GetDataSurface in UpdateFromSurface (BT)."; |
402 | 0 | return false; |
403 | 0 | } |
404 | 0 |
|
405 | 0 | if (surface->GetSize() != srcSurf->GetSize() || surface->GetFormat() != srcSurf->GetFormat()) { |
406 | 0 | gfxCriticalError() << "Attempt to update texture client from a surface with a different size or format (BT)! This: " << surface->GetSize() << " " << surface->GetFormat() << " Other: " << aSurface->GetSize() << " " << aSurface->GetFormat(); |
407 | 0 | return false; |
408 | 0 | } |
409 | 0 |
|
410 | 0 | gfx::DataSourceSurface::MappedSurface sourceMap; |
411 | 0 | gfx::DataSourceSurface::MappedSurface destMap; |
412 | 0 | if (!srcSurf->Map(gfx::DataSourceSurface::READ, &sourceMap)) { |
413 | 0 | gfxCriticalError() << "Failed to map source surface for UpdateFromSurface (BT)."; |
414 | 0 | return false; |
415 | 0 | } |
416 | 0 |
|
417 | 0 | if (!surface->Map(gfx::DataSourceSurface::WRITE, &destMap)) { |
418 | 0 | srcSurf->Unmap(); |
419 | 0 | gfxCriticalError() << "Failed to map destination surface for UpdateFromSurface."; |
420 | 0 | return false; |
421 | 0 | } |
422 | 0 |
|
423 | 0 |
|
424 | 0 | for (int y = 0; y < srcSurf->GetSize().height; y++) { |
425 | 0 | memcpy(destMap.mData + destMap.mStride * y, |
426 | 0 | sourceMap.mData + sourceMap.mStride * y, |
427 | 0 | srcSurf->GetSize().width * BytesPerPixel(srcSurf->GetFormat())); |
428 | 0 | } |
429 | 0 |
|
430 | 0 | srcSurf->Unmap(); |
431 | 0 | surface->Unmap(); |
432 | 0 |
|
433 | 0 | return true; |
434 | 0 | } |
435 | | |
436 | | void |
437 | | BufferTextureData::SetDesciptor(const BufferDescriptor& aDescriptor) |
438 | 0 | { |
439 | 0 | MOZ_ASSERT(mDescriptor.type() == BufferDescriptor::TYCbCrDescriptor); |
440 | 0 | MOZ_ASSERT(mDescriptor.get_YCbCrDescriptor().ySize() == gfx::IntSize()); |
441 | 0 | mDescriptor = aDescriptor; |
442 | 0 | } |
443 | | |
444 | | bool |
445 | | MemoryTextureData::Serialize(SurfaceDescriptor& aOutDescriptor) |
446 | 0 | { |
447 | 0 | MOZ_ASSERT(GetFormat() != gfx::SurfaceFormat::UNKNOWN); |
448 | 0 | if (GetFormat() == gfx::SurfaceFormat::UNKNOWN) { |
449 | 0 | return false; |
450 | 0 | } |
451 | 0 | |
452 | 0 | uintptr_t ptr = reinterpret_cast<uintptr_t>(mBuffer); |
453 | 0 | aOutDescriptor = SurfaceDescriptorBuffer(mDescriptor, MemoryOrShmem(ptr)); |
454 | 0 |
|
455 | 0 | return true; |
456 | 0 | } |
457 | | |
458 | | static bool |
459 | | InitBuffer(uint8_t* buf, size_t bufSize, |
460 | | gfx::SurfaceFormat aFormat, TextureAllocationFlags aAllocFlags, |
461 | | bool aAlreadyZero) |
462 | 0 | { |
463 | 0 | if (!buf) { |
464 | 0 | gfxDebug() << "BufferTextureData: Failed to allocate " << bufSize << " bytes"; |
465 | 0 | return false; |
466 | 0 | } |
467 | 0 |
|
468 | 0 | if ((aAllocFlags & ALLOC_CLEAR_BUFFER) || |
469 | 0 | (aAllocFlags & ALLOC_CLEAR_BUFFER_BLACK)) { |
470 | 0 | if (aFormat == gfx::SurfaceFormat::B8G8R8X8) { |
471 | 0 | // Even though BGRX was requested, XRGB_UINT32 is what is meant, |
472 | 0 | // so use 0xFF000000 to put alpha in the right place. |
473 | 0 | libyuv::ARGBRect(buf, bufSize, 0, 0, bufSize / sizeof(uint32_t), 1, 0xFF000000); |
474 | 0 | } else if (!aAlreadyZero) { |
475 | 0 | memset(buf, 0, bufSize); |
476 | 0 | } |
477 | 0 | } |
478 | 0 |
|
479 | 0 | if (aAllocFlags & ALLOC_CLEAR_BUFFER_WHITE) { |
480 | 0 | memset(buf, 0xFF, bufSize); |
481 | 0 | } |
482 | 0 |
|
483 | 0 | return true; |
484 | 0 | } |
485 | | |
486 | | MemoryTextureData* |
487 | | MemoryTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, |
488 | | gfx::BackendType aMoz2DBackend, |
489 | | LayersBackend aLayersBackend, TextureFlags aFlags, |
490 | | TextureAllocationFlags aAllocFlags, |
491 | | LayersIPCChannel* aAllocator) |
492 | 0 | { |
493 | 0 | // Should have used CreateForYCbCr. |
494 | 0 | MOZ_ASSERT(aFormat != gfx::SurfaceFormat::YUV); |
495 | 0 |
|
496 | 0 | if (aSize.width <= 0 || aSize.height <= 0) { |
497 | 0 | gfxDebug() << "Asking for buffer of invalid size " << aSize.width << "x" << aSize.height; |
498 | 0 | return nullptr; |
499 | 0 | } |
500 | 0 |
|
501 | 0 | uint32_t bufSize = ImageDataSerializer::ComputeRGBBufferSize(aSize, aFormat); |
502 | 0 | if (!bufSize) { |
503 | 0 | return nullptr; |
504 | 0 | } |
505 | 0 | |
506 | 0 | uint8_t* buf = new (fallible) uint8_t[bufSize]; |
507 | 0 | if (!InitBuffer(buf, bufSize, aFormat, aAllocFlags, false)) { |
508 | 0 | return nullptr; |
509 | 0 | } |
510 | 0 | |
511 | 0 | bool hasIntermediateBuffer = ComputeHasIntermediateBuffer(aFormat, |
512 | 0 | aLayersBackend, |
513 | 0 | aAllocFlags & ALLOC_ALLOW_DIRECT_MAPPING); |
514 | 0 |
|
515 | 0 | GfxMemoryImageReporter::DidAlloc(buf); |
516 | 0 |
|
517 | 0 | BufferDescriptor descriptor = RGBDescriptor(aSize, aFormat, hasIntermediateBuffer); |
518 | 0 |
|
519 | 0 | return new MemoryTextureData(descriptor, aMoz2DBackend, buf, bufSize); |
520 | 0 | } |
521 | | |
522 | | void |
523 | | MemoryTextureData::Deallocate(LayersIPCChannel*) |
524 | 0 | { |
525 | 0 | MOZ_ASSERT(mBuffer); |
526 | 0 | GfxMemoryImageReporter::WillFree(mBuffer); |
527 | 0 | delete [] mBuffer; |
528 | 0 | mBuffer = nullptr; |
529 | 0 | } |
530 | | |
531 | | TextureData* |
532 | | MemoryTextureData::CreateSimilar(LayersIPCChannel* aAllocator, |
533 | | LayersBackend aLayersBackend, |
534 | | TextureFlags aFlags, |
535 | | TextureAllocationFlags aAllocFlags) const |
536 | 0 | { |
537 | 0 | return MemoryTextureData::Create(GetSize(), GetFormat(), mMoz2DBackend, |
538 | 0 | aLayersBackend, aFlags, aAllocFlags, aAllocator); |
539 | 0 | } |
540 | | |
541 | | bool |
542 | | ShmemTextureData::Serialize(SurfaceDescriptor& aOutDescriptor) |
543 | 0 | { |
544 | 0 | MOZ_ASSERT(GetFormat() != gfx::SurfaceFormat::UNKNOWN); |
545 | 0 | if (GetFormat() == gfx::SurfaceFormat::UNKNOWN) { |
546 | 0 | return false; |
547 | 0 | } |
548 | 0 | |
549 | 0 | aOutDescriptor = SurfaceDescriptorBuffer(mDescriptor, MemoryOrShmem(mShmem)); |
550 | 0 |
|
551 | 0 | return true; |
552 | 0 | } |
553 | | |
554 | | ShmemTextureData* |
555 | | ShmemTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, |
556 | | gfx::BackendType aMoz2DBackend, |
557 | | LayersBackend aLayersBackend, TextureFlags aFlags, |
558 | | TextureAllocationFlags aAllocFlags, |
559 | | LayersIPCChannel* aAllocator) |
560 | 0 | { |
561 | 0 | MOZ_ASSERT(aAllocator); |
562 | 0 | // Should have used CreateForYCbCr. |
563 | 0 | MOZ_ASSERT(aFormat != gfx::SurfaceFormat::YUV); |
564 | 0 |
|
565 | 0 | if (!aAllocator) { |
566 | 0 | return nullptr; |
567 | 0 | } |
568 | 0 | |
569 | 0 | if (aSize.width <= 0 || aSize.height <= 0) { |
570 | 0 | gfxDebug() << "Asking for buffer of invalid size " << aSize.width << "x" << aSize.height; |
571 | 0 | return nullptr; |
572 | 0 | } |
573 | 0 |
|
574 | 0 | uint32_t bufSize = ImageDataSerializer::ComputeRGBBufferSize(aSize, aFormat); |
575 | 0 | if (!bufSize) { |
576 | 0 | return nullptr; |
577 | 0 | } |
578 | 0 | |
579 | 0 | mozilla::ipc::Shmem shm; |
580 | 0 | if (!aAllocator->AllocUnsafeShmem(bufSize, OptimalShmemType(), &shm)) { |
581 | 0 | return nullptr; |
582 | 0 | } |
583 | 0 | |
584 | 0 | uint8_t* buf = shm.get<uint8_t>(); |
585 | 0 | if (!InitBuffer(buf, bufSize, aFormat, aAllocFlags, true)) { |
586 | 0 | return nullptr; |
587 | 0 | } |
588 | 0 | |
589 | 0 | bool hasIntermediateBuffer = ComputeHasIntermediateBuffer(aFormat, |
590 | 0 | aLayersBackend, |
591 | 0 | aAllocFlags & ALLOC_ALLOW_DIRECT_MAPPING); |
592 | 0 |
|
593 | 0 | BufferDescriptor descriptor = RGBDescriptor(aSize, aFormat, hasIntermediateBuffer); |
594 | 0 |
|
595 | 0 | return new ShmemTextureData(descriptor, aMoz2DBackend, shm); |
596 | 0 |
|
597 | 0 | return nullptr; |
598 | 0 | } |
599 | | |
600 | | TextureData* |
601 | | ShmemTextureData::CreateSimilar(LayersIPCChannel* aAllocator, |
602 | | LayersBackend aLayersBackend, |
603 | | TextureFlags aFlags, |
604 | | TextureAllocationFlags aAllocFlags) const |
605 | 0 | { |
606 | 0 | return ShmemTextureData::Create(GetSize(), GetFormat(), mMoz2DBackend, |
607 | 0 | aLayersBackend, aFlags, aAllocFlags, aAllocator); |
608 | 0 | } |
609 | | |
610 | | void |
611 | | ShmemTextureData::Deallocate(LayersIPCChannel* aAllocator) |
612 | 0 | { |
613 | 0 | aAllocator->DeallocShmem(mShmem); |
614 | 0 | } |
615 | | |
616 | | } // namespace |
617 | | } // namespace |