BufferTextureData* BufferTextureData::CreateInternal(ClientIPCAllocator* aAllocator, const BufferDescriptor& aDesc, gfx::BackendType aMoz2DBackend, int32_t aBufferSize, TextureFlags aTextureFlags) { if (!aAllocator || aAllocator->IsSameProcess()) { uint8_t* buffer = new (fallible) uint8_t[aBufferSize]; if (!buffer) { return nullptr; } GfxMemoryImageReporter::DidAlloc(buffer); return new MemoryTextureData(aDesc, aMoz2DBackend, buffer, aBufferSize); } else if (aAllocator->AsShmemAllocator()) { ipc::Shmem shm; if (!aAllocator->AsShmemAllocator()->AllocUnsafeShmem(aBufferSize, OptimalShmemType(), &shm)) { return nullptr; } return new ShmemTextureData(aDesc, aMoz2DBackend, shm); } return nullptr; }
bool ShmemTextureClient::Allocate(uint32_t aSize) { MOZ_ASSERT(IsValid()); ipc::SharedMemory::SharedMemoryType memType = OptimalShmemType(); mAllocated = GetAllocator()->AllocUnsafeShmem(aSize, memType, &mShmem); return mAllocated; }
bool AutoLockYCbCrClient::EnsureDeprecatedTextureClient(PlanarYCbCrImage* aImage) { MOZ_ASSERT(aImage); if (!aImage) { return false; } const PlanarYCbCrData *data = aImage->GetData(); NS_ASSERTION(data, "Must be able to retrieve yuv data from image!"); if (!data) { return false; } bool needsAllocation = false; if (mDescriptor->type() != SurfaceDescriptor::TYCbCrImage) { needsAllocation = true; } else { ipc::Shmem& shmem = mDescriptor->get_YCbCrImage().data(); YCbCrImageDataSerializer serializer(shmem.get<uint8_t>()); if (serializer.GetYSize() != data->mYSize || serializer.GetCbCrSize() != data->mCbCrSize) { needsAllocation = true; } } if (!needsAllocation) { return true; } mDeprecatedTextureClient->ReleaseResources(); ipc::SharedMemory::SharedMemoryType shmType = OptimalShmemType(); size_t size = YCbCrImageDataSerializer::ComputeMinBufferSize(data->mYSize, data->mCbCrSize); ipc::Shmem shmem; if (!mDeprecatedTextureClient->GetForwarder()->AllocUnsafeShmem(size, shmType, &shmem)) { return false; } YCbCrImageDataSerializer serializer(shmem.get<uint8_t>()); serializer.InitializeBufferInfo(data->mYSize, data->mCbCrSize, data->mStereoMode); *mDescriptor = YCbCrImage(shmem, 0); return true; }
ShmemTextureData* ShmemTextureData::Create(gfx::IntSize aSize, gfx::SurfaceFormat aFormat, gfx::BackendType aMoz2DBackend, LayersBackend aLayersBackend, TextureFlags aFlags, TextureAllocationFlags aAllocFlags, ClientIPCAllocator* aAllocator) { MOZ_ASSERT(aAllocator); // Should have used CreateForYCbCr. MOZ_ASSERT(aFormat != gfx::SurfaceFormat::YUV); if (!aAllocator || !aAllocator->AsShmemAllocator()) { return nullptr; } if (aSize.width <= 0 || aSize.height <= 0) { gfxDebug() << "Asking for buffer of invalid size " << aSize.width << "x" << aSize.height; return nullptr; } uint32_t bufSize = ImageDataSerializer::ComputeRGBBufferSize(aSize, aFormat); if (!bufSize) { return nullptr; } mozilla::ipc::Shmem shm; if (!aAllocator->AsShmemAllocator()->AllocUnsafeShmem(bufSize, OptimalShmemType(), &shm)) { return nullptr; } uint8_t* buf = shm.get<uint8_t>(); if (!InitBuffer(buf, bufSize, aFormat, aAllocFlags, true)) { return nullptr; } // LAYERS_NONE must imply that we have no compositable forwarder MOZ_ASSERT_IF(aLayersBackend == LayersBackend::LAYERS_NONE, !aAllocator || !aAllocator->AsCompositableForwarder()); bool hasIntermediateBuffer = ComputeHasIntermediateBuffer(aFormat, aLayersBackend); BufferDescriptor descriptor = RGBDescriptor(aSize, aFormat, hasIntermediateBuffer); return new ShmemTextureData(descriptor, aMoz2DBackend, shm); return nullptr; }
bool ISurfaceAllocator::AllocSharedImageSurface(const gfxIntSize& aSize, gfxASurface::gfxContentType aContent, gfxSharedImageSurface** aBuffer) { SharedMemory::SharedMemoryType shmemType = OptimalShmemType(); gfxASurface::gfxImageFormat format = gfxPlatform::GetPlatform()->OptimalFormatForContent(aContent); nsRefPtr<gfxSharedImageSurface> back = gfxSharedImageSurface::CreateUnsafe(this, aSize, format, shmemType); if (!back) return false; *aBuffer = nullptr; back.swap(*aBuffer); return true; }
bool DeprecatedSharedRGBImage::AllocateBuffer(nsIntSize aSize, gfxImageFormat aImageFormat) { if (mAllocated) { NS_WARNING("Already allocated shmem"); return false; } size_t size = GetBufferSize(); if (size == 0 || size > MAX_FRAME_SIZE) { NS_WARNING("Invalid frame size"); } if (mSurfaceAllocator->AllocUnsafeShmem(size, OptimalShmemType(), mShmem)) { mAllocated = true; } return mAllocated; }
bool ShadowLayerForwarder::AllocBuffer(const gfxIntSize& aSize, gfxASurface::gfxContentType aContent, gfxSharedImageSurface** aBuffer) { NS_ABORT_IF_FALSE(HasShadowManager(), "no manager to forward to"); gfxASurface::gfxImageFormat format = OptimalFormatFor(aContent); SharedMemory::SharedMemoryType shmemType = OptimalShmemType(); nsRefPtr<gfxSharedImageSurface> back = gfxSharedImageSurface::CreateUnsafe(mShadowManager, aSize, format, shmemType); if (!back) return false; *aBuffer = nsnull; back.swap(*aBuffer); return true; }
SharedImage* ImageContainerChild::AllocateSharedImageFor(Image* image) { NS_ABORT_IF_FALSE(InImageBridgeChildThread(), "Should be in ImageBridgeChild thread."); if (!image) { return nullptr; } if (image->GetFormat() == PLANAR_YCBCR ) { PlanarYCbCrImage *planarYCbCrImage = static_cast<PlanarYCbCrImage*>(image); const PlanarYCbCrImage::Data *data = planarYCbCrImage->GetData(); NS_ASSERTION(data, "Must be able to retrieve yuv data from image!"); if (!data) { return nullptr; } SharedMemory::SharedMemoryType shmType = OptimalShmemType(); size_t size = ShmemYCbCrImage::ComputeMinBufferSize(data->mYSize, data->mCbCrSize); Shmem shmem; if (!AllocUnsafeShmem(size, shmType, &shmem)) { return nullptr; } ShmemYCbCrImage::InitializeBufferInfo(shmem.get<uint8_t>(), data->mYSize, data->mCbCrSize); ShmemYCbCrImage shmemImage(shmem); if (!shmemImage.IsValid()) { NS_WARNING("Failed to properly allocate image data!"); DeallocShmem(shmem); return nullptr; } ++mActiveImageCount; return new SharedImage(YCbCrImage(shmem, 0, data->GetPictureRect())); } else { NS_RUNTIMEABORT("TODO: Only YCbCrImage is supported here right now."); } return nullptr; }
bool FixedSizeSmallShmemSectionAllocator::AllocShmemSection(uint32_t aSize, ShmemSection* aShmemSection) { // For now we only support sizes of 4. If we want to support different sizes // some more complicated bookkeeping should be added. MOZ_ASSERT(aSize == sSupportedBlockSize); MOZ_ASSERT(aShmemSection); if (!IPCOpen()) { gfxCriticalError() << "Attempt to allocate a ShmemSection after shutdown."; return false; } uint32_t allocationSize = (aSize + sizeof(ShmemSectionHeapAllocation)); for (size_t i = 0; i < mUsedShmems.size(); i++) { ShmemSectionHeapHeader* header = mUsedShmems[i].get<ShmemSectionHeapHeader>(); if ((header->mAllocatedBlocks + 1) * allocationSize + sizeof(ShmemSectionHeapHeader) < sShmemPageSize) { aShmemSection->shmem() = mUsedShmems[i]; MOZ_ASSERT(mUsedShmems[i].IsWritable()); break; } } if (!aShmemSection->shmem().IsWritable()) { ipc::Shmem tmp; if (!GetShmAllocator()->AllocUnsafeShmem(sShmemPageSize, OptimalShmemType(), &tmp)) { return false; } ShmemSectionHeapHeader* header = tmp.get<ShmemSectionHeapHeader>(); header->mTotalBlocks = 0; header->mAllocatedBlocks = 0; mUsedShmems.push_back(tmp); aShmemSection->shmem() = tmp; } MOZ_ASSERT(aShmemSection->shmem().IsWritable()); ShmemSectionHeapHeader* header = aShmemSection->shmem().get<ShmemSectionHeapHeader>(); uint8_t* heap = aShmemSection->shmem().get<uint8_t>() + sizeof(ShmemSectionHeapHeader); ShmemSectionHeapAllocation* allocHeader = nullptr; if (header->mTotalBlocks > header->mAllocatedBlocks) { // Search for the first available block. for (size_t i = 0; i < header->mTotalBlocks; i++) { allocHeader = reinterpret_cast<ShmemSectionHeapAllocation*>(heap); if (allocHeader->mStatus == STATUS_FREED) { break; } heap += allocationSize; } MOZ_ASSERT(allocHeader && allocHeader->mStatus == STATUS_FREED); MOZ_ASSERT(allocHeader->mSize == sSupportedBlockSize); } else { heap += header->mTotalBlocks * allocationSize; header->mTotalBlocks++; allocHeader = reinterpret_cast<ShmemSectionHeapAllocation*>(heap); allocHeader->mSize = aSize; } MOZ_ASSERT(allocHeader); header->mAllocatedBlocks++; allocHeader->mStatus = STATUS_ALLOCATED; aShmemSection->size() = aSize; aShmemSection->offset() = (heap + sizeof(ShmemSectionHeapAllocation)) - aShmemSection->shmem().get<uint8_t>(); ShrinkShmemSectionHeap(); return true; }
SharedImage* ImageContainerChild::CreateSharedImageFromData(Image* image) { NS_ABORT_IF_FALSE(InImageBridgeChildThread(), "Should be in ImageBridgeChild thread."); if (!image) { return nullptr; } if (image->GetFormat() == PLANAR_YCBCR ) { PlanarYCbCrImage *planarYCbCrImage = static_cast<PlanarYCbCrImage*>(image); const PlanarYCbCrImage::Data *data = planarYCbCrImage->GetData(); NS_ASSERTION(data, "Must be able to retrieve yuv data from image!"); if (!data) { return nullptr; } SharedMemory::SharedMemoryType shmType = OptimalShmemType(); size_t size = ShmemYCbCrImage::ComputeMinBufferSize(data->mYSize, data->mCbCrSize); Shmem shmem; if (!AllocUnsafeShmem(size, shmType, &shmem)) { return nullptr; } ShmemYCbCrImage::InitializeBufferInfo(shmem.get<uint8_t>(), data->mYSize, data->mCbCrSize); ShmemYCbCrImage shmemImage(shmem); if (!shmemImage.IsValid() || shmem.Size<uint8_t>() < size) { DeallocShmem(shmem); return nullptr; } for (int i = 0; i < data->mYSize.height; i++) { memcpy(shmemImage.GetYData() + i * shmemImage.GetYStride(), data->mYChannel + i * data->mYStride, data->mYSize.width); } for (int i = 0; i < data->mCbCrSize.height; i++) { memcpy(shmemImage.GetCbData() + i * shmemImage.GetCbCrStride(), data->mCbChannel + i * data->mCbCrStride, data->mCbCrSize.width); memcpy(shmemImage.GetCrData() + i * shmemImage.GetCbCrStride(), data->mCrChannel + i * data->mCbCrStride, data->mCbCrSize.width); } ++mActiveImageCount; SharedImage* result = new SharedImage(YCbCrImage(shmem, 0, data->GetPictureRect())); return result; #ifdef MOZ_WIDGET_GONK } else if (image->GetFormat() == GONK_IO_SURFACE) { GonkIOSurfaceImage* gonkImage = static_cast<GonkIOSurfaceImage*>(image); SharedImage* result = new SharedImage(gonkImage->GetSurfaceDescriptor()); return result; } else if (image->GetFormat() == GRALLOC_PLANAR_YCBCR) { GrallocPlanarYCbCrImage* GrallocImage = static_cast<GrallocPlanarYCbCrImage*>(image); SharedImage* result = new SharedImage(GrallocImage->GetSurfaceDescriptor()); return result; #endif } else { NS_RUNTIMEABORT("TODO: Only YCbCrImage is supported here right now."); } return nullptr; }