void TextureHostYCbCrD3D11::UpdateImpl(const SurfaceDescriptor& aImage, nsIntRegion *aRegion) { MOZ_ASSERT(aImage.type() == SurfaceDescriptor::TYCbCrImage); ShmemYCbCrImage shmemImage(aImage.get_YCbCrImage().data(), aImage.get_YCbCrImage().offset()); gfxIntSize gfxCbCrSize = shmemImage.GetCbCrSize(); gfxIntSize size = shmemImage.GetYSize(); D3D11_SUBRESOURCE_DATA initData; initData.pSysMem = shmemImage.GetYData(); initData.SysMemPitch = shmemImage.GetYStride(); CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_R8_UNORM, size.width, size.height, 1, 1, D3D11_BIND_SHADER_RESOURCE, D3D11_USAGE_IMMUTABLE); mDevice->CreateTexture2D(&desc, &initData, byRef(mTextures[0])); initData.pSysMem = shmemImage.GetCbData(); initData.SysMemPitch = shmemImage.GetCbCrStride(); desc.Width = shmemImage.GetCbCrSize().width; desc.Height = shmemImage.GetCbCrSize().height; mDevice->CreateTexture2D(&desc, &initData, byRef(mTextures[1])); initData.pSysMem = shmemImage.GetCrData(); mDevice->CreateTexture2D(&desc, &initData, byRef(mTextures[2])); mSize = IntSize(size.width, size.height); }
bool AutoLockYCbCrClient::Update(PlanarYCbCrImage* aImage) { MOZ_ASSERT(aImage); MOZ_ASSERT(mDescriptor); const PlanarYCbCrImage::Data *data = aImage->GetData(); NS_ASSERTION(data, "Must be able to retrieve yuv data from image!"); if (!data) { return false; } if (!EnsureTextureClient(aImage)) { return false; } ipc::Shmem& shmem = mDescriptor->get_YCbCrImage().data(); ShmemYCbCrImage shmemImage(shmem); if (!shmemImage.CopyData(data->mYChannel, data->mCbChannel, data->mCrChannel, data->mYSize, data->mYStride, data->mCbCrSize, data->mCbCrStride, data->mYSkip, data->mCbSkip)) { NS_WARNING("Failed to copy image data!"); return false; } return true; }
bool ImageContainerChild::CopyDataIntoSharedImage(Image* src, SharedImage* dest) { if ((src->GetFormat() == PLANAR_YCBCR) && (dest->type() == SharedImage::TYCbCrImage)) { PlanarYCbCrImage *planarYCbCrImage = static_cast<PlanarYCbCrImage*>(src); const PlanarYCbCrImage::Data *data =planarYCbCrImage->GetData(); NS_ASSERTION(data, "Must be able to retrieve yuv data from image!"); YCbCrImage& yuv = dest->get_YCbCrImage(); ShmemYCbCrImage shmemImage(yuv.data(), yuv.offset()); 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); } return true; } return false; // TODO: support more image formats }
bool AutoLockYCbCrClient::EnsureTextureClient(PlanarYCbCrImage* aImage) { MOZ_ASSERT(aImage); if (!aImage) { return false; } const PlanarYCbCrImage::Data *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(); ShmemYCbCrImage shmemImage(shmem); if (shmemImage.GetYSize() != data->mYSize || shmemImage.GetCbCrSize() != data->mCbCrSize) { needsAllocation = true; } } if (!needsAllocation) { return true; } mTextureClient->ReleaseResources(); ipc::SharedMemory::SharedMemoryType shmType = OptimalShmemType(); size_t size = ShmemYCbCrImage::ComputeMinBufferSize(data->mYSize, data->mCbCrSize); ipc::Shmem shmem; if (!mTextureClient->GetForwarder()->AllocUnsafeShmem(size, shmType, &shmem)) { return false; } ShmemYCbCrImage::InitializeBufferInfo(shmem.get<uint8_t>(), data->mYSize, data->mCbCrSize); *mDescriptor = YCbCrImage(shmem, 0, 0); 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 ImageContainerChild::CopyDataIntoSharedImage(Image* src, SharedImage* dest) { if ((src->GetFormat() == PLANAR_YCBCR) && (dest->type() == SharedImage::TYCbCrImage)) { PlanarYCbCrImage *planarYCbCrImage = static_cast<PlanarYCbCrImage*>(src); const PlanarYCbCrImage::Data *data = planarYCbCrImage->GetData(); NS_ASSERTION(data, "Must be able to retrieve yuv data from image!"); YCbCrImage& yuv = dest->get_YCbCrImage(); ShmemYCbCrImage shmemImage(yuv.data(), yuv.offset()); if (!shmemImage.CopyData(data->mYChannel, data->mCbChannel, data->mCrChannel, data->mYSize, data->mYStride, data->mCbCrSize, data->mCbCrStride)) { NS_WARNING("Failed to copy image data!"); return false; } return true; } return false; // TODO: support more image formats }
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; }