Coverage Report

Created: 2018-09-25 14:53

/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