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