void DeprecatedTextureHostYCbCrD3D11::UpdateImpl(const SurfaceDescriptor& aImage, nsIntRegion* aRegion, nsIntPoint* aOffset) { MOZ_ASSERT(aImage.type() == SurfaceDescriptor::TYCbCrImage); YCbCrImageDataDeserializer yuvDeserializer(aImage.get_YCbCrImage().data().get<uint8_t>()); gfxIntSize gfxCbCrSize = yuvDeserializer.GetCbCrSize(); gfxIntSize size = yuvDeserializer.GetYSize(); D3D11_SUBRESOURCE_DATA initData; initData.pSysMem = yuvDeserializer.GetYData(); initData.SysMemPitch = yuvDeserializer.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 = yuvDeserializer.GetCbData(); initData.SysMemPitch = yuvDeserializer.GetCbCrStride(); desc.Width = yuvDeserializer.GetCbCrSize().width; desc.Height = yuvDeserializer.GetCbCrSize().height; mDevice->CreateTexture2D(&desc, &initData, byRef(mTextures[1])); initData.pSysMem = yuvDeserializer.GetCrData(); mDevice->CreateTexture2D(&desc, &initData, byRef(mTextures[2])); mSize = IntSize(size.width, size.height); }
already_AddRefed<gfxImageSurface> BufferTextureHost::GetAsSurface() { nsRefPtr<gfxImageSurface> result; if (mFormat == gfx::FORMAT_UNKNOWN) { NS_WARNING("BufferTextureHost: unsupported format!"); return nullptr; } else if (mFormat == gfx::FORMAT_YUV) { YCbCrImageDataDeserializer yuvDeserializer(GetBuffer()); if (!yuvDeserializer.IsValid()) { return nullptr; } result = new gfxImageSurface(yuvDeserializer.GetYData(), yuvDeserializer.GetYSize(), yuvDeserializer.GetYStride(), gfxASurface::ImageFormatA8); } else { ImageDataDeserializer deserializer(GetBuffer()); if (!deserializer.IsValid()) { return nullptr; } RefPtr<gfxImageSurface> surf = deserializer.GetAsThebesSurface(); result = surf.get(); } return result.forget(); }
TemporaryRef<gfx::DataSourceSurface> BufferTextureHost::GetAsSurface() { RefPtr<gfx::DataSourceSurface> result; if (mFormat == gfx::SurfaceFormat::UNKNOWN) { NS_WARNING("BufferTextureHost: unsupported format!"); return nullptr; } else if (mFormat == gfx::SurfaceFormat::YUV) { YCbCrImageDataDeserializer yuvDeserializer(GetBuffer(), GetBufferSize()); if (!yuvDeserializer.IsValid()) { return nullptr; } result = yuvDeserializer.ToDataSourceSurface(); if (NS_WARN_IF(!result)) { return nullptr; } } else { ImageDataDeserializer deserializer(GetBuffer(), GetBufferSize()); if (!deserializer.IsValid()) { NS_ERROR("Failed to deserialize image!"); return nullptr; } result = deserializer.GetAsSurface(); } return result.forget(); }
// Same as above, for YCbCr surfaces void TestTextureClientYCbCr(TextureClient* client, PlanarYCbCrData& ycbcrData) { // client allocation ASSERT_TRUE(client->AsTextureClientYCbCr() != nullptr); TextureClientYCbCr* texture = client->AsTextureClientYCbCr(); texture->AllocateForYCbCr(ycbcrData.mYSize, ycbcrData.mCbCrSize, ycbcrData.mStereoMode); ASSERT_TRUE(client->IsAllocated()); ASSERT_TRUE(client->Lock(OPEN_READ_WRITE)); // client painting texture->UpdateYCbCr(ycbcrData); client->Unlock(); // client serialization SurfaceDescriptor descriptor; ASSERT_TRUE(client->ToSurfaceDescriptor(descriptor)); ASSERT_NE(descriptor.type(), SurfaceDescriptor::Tnull_t); // host deserialization RefPtr<TextureHost> textureHost = CreateBackendIndependentTextureHost(descriptor, nullptr, client->GetFlags()); RefPtr<BufferTextureHost> host = static_cast<BufferTextureHost*>(textureHost.get()); ASSERT_TRUE(host.get() != nullptr); ASSERT_EQ(host->GetFlags(), client->GetFlags()); // host read ASSERT_TRUE(host->Lock()); // This will work iff the compositor is not BasicCompositor ASSERT_EQ(host->GetFormat(), mozilla::gfx::SurfaceFormat::YUV); YCbCrImageDataDeserializer yuvDeserializer(host->GetBuffer(), host->GetBufferSize()); ASSERT_TRUE(yuvDeserializer.IsValid()); PlanarYCbCrData data; data.mYChannel = yuvDeserializer.GetYData(); data.mCbChannel = yuvDeserializer.GetCbData(); data.mCrChannel = yuvDeserializer.GetCrData(); data.mYStride = yuvDeserializer.GetYStride(); data.mCbCrStride = yuvDeserializer.GetCbCrStride(); data.mStereoMode = yuvDeserializer.GetStereoMode(); data.mYSize = yuvDeserializer.GetYSize(); data.mCbCrSize = yuvDeserializer.GetCbCrSize(); data.mYSkip = 0; data.mCbSkip = 0; data.mCrSkip = 0; data.mPicSize = data.mYSize; data.mPicX = 0; data.mPicY = 0; AssertYCbCrSurfacesEqual(&ycbcrData, &data); host->Unlock(); }
void BufferTextureHost::InitSize() { if (mFormat == gfx::SurfaceFormat::YUV) { YCbCrImageDataDeserializer yuvDeserializer(GetBuffer(), GetBufferSize()); if (yuvDeserializer.IsValid()) { mSize = yuvDeserializer.GetYSize(); } } else if (mFormat != gfx::SurfaceFormat::UNKNOWN) { ImageDataDeserializer deserializer(GetBuffer(), GetBufferSize()); if (deserializer.IsValid()) { mSize = deserializer.GetSize(); } } }
TemporaryRef<gfx::DataSourceSurface> BufferTextureHost::GetAsSurface() { RefPtr<gfx::DataSourceSurface> result; if (mFormat == gfx::FORMAT_UNKNOWN) { NS_WARNING("BufferTextureHost: unsupported format!"); return nullptr; } else if (mFormat == gfx::FORMAT_YUV) { YCbCrImageDataDeserializer yuvDeserializer(GetBuffer()); if (!yuvDeserializer.IsValid()) { return nullptr; } result = yuvDeserializer.ToDataSourceSurface(); } else { ImageDataDeserializer deserializer(GetBuffer()); if (!deserializer.IsValid()) { return nullptr; } result = deserializer.GetAsSurface(); } return result.forget(); }
bool BufferTextureHost::Upload(nsIntRegion *aRegion) { if (mFormat == gfx::FORMAT_UNKNOWN) { NS_WARNING("BufferTextureHost: unsupported format!"); return false; } else if (mFormat == gfx::FORMAT_YUV) { YCbCrImageDataDeserializer yuvDeserializer(GetBuffer()); MOZ_ASSERT(yuvDeserializer.IsValid()); if (!mCompositor->SupportsEffect(EFFECT_YCBCR)) { RefPtr<gfx::DataSourceSurface> surf = yuvDeserializer.ToDataSourceSurface(); if (!mFirstSource) { mFirstSource = mCompositor->CreateDataTextureSource(mFlags); } mFirstSource->Update(surf, mFlags, aRegion); return true; } RefPtr<DataTextureSource> srcY; RefPtr<DataTextureSource> srcU; RefPtr<DataTextureSource> srcV; if (!mFirstSource) { // We don't support BigImages for YCbCr compositing. srcY = mCompositor->CreateDataTextureSource(mFlags|TEXTURE_DISALLOW_BIGIMAGE); srcU = mCompositor->CreateDataTextureSource(mFlags|TEXTURE_DISALLOW_BIGIMAGE); srcV = mCompositor->CreateDataTextureSource(mFlags|TEXTURE_DISALLOW_BIGIMAGE); mFirstSource = srcY; srcY->SetNextSibling(srcU); srcU->SetNextSibling(srcV); } else { // mFormat never changes so if this was created as a YCbCr host and already // contains a source it should already have 3 sources. // BufferTextureHost only uses DataTextureSources so it is safe to assume // all 3 sources are DataTextureSource. MOZ_ASSERT(mFirstSource->GetNextSibling()); MOZ_ASSERT(mFirstSource->GetNextSibling()->GetNextSibling()); srcY = mFirstSource; srcU = mFirstSource->GetNextSibling()->AsDataTextureSource(); srcV = mFirstSource->GetNextSibling()->GetNextSibling()->AsDataTextureSource(); } RefPtr<gfx::DataSourceSurface> tempY = gfx::Factory::CreateWrappingDataSourceSurface(yuvDeserializer.GetYData(), yuvDeserializer.GetYStride(), gfx::ToIntSize(yuvDeserializer.GetYSize()), gfx::FORMAT_A8); RefPtr<gfx::DataSourceSurface> tempCb = gfx::Factory::CreateWrappingDataSourceSurface(yuvDeserializer.GetCbData(), yuvDeserializer.GetCbCrStride(), gfx::ToIntSize(yuvDeserializer.GetCbCrSize()), gfx::FORMAT_A8); RefPtr<gfx::DataSourceSurface> tempCr = gfx::Factory::CreateWrappingDataSourceSurface(yuvDeserializer.GetCrData(), yuvDeserializer.GetCbCrStride(), gfx::ToIntSize(yuvDeserializer.GetCbCrSize()), gfx::FORMAT_A8); // We don't support partial updates for Y U V textures NS_ASSERTION(!aRegion, "Unsupported partial updates for YCbCr textures"); if (!srcY->Update(tempY, mFlags) || !srcU->Update(tempCb, mFlags) || !srcV->Update(tempCr, mFlags)) { NS_WARNING("failed to update the DataTextureSource"); return false; } } else { // non-YCbCr case if (!mFirstSource) { mFirstSource = mCompositor->CreateDataTextureSource(); } ImageDataDeserializer deserializer(GetBuffer()); if (!deserializer.IsValid()) { NS_WARNING("failed to open shmem surface"); return false; } RefPtr<gfx::DataSourceSurface> surf = deserializer.GetAsSurface(); if (!surf) { return false; } if (!mFirstSource->Update(surf.get(), mFlags, aRegion)) { NS_WARNING("failed to update the DataTextureSource"); return false; } } return true; }
bool BufferTextureHost::Upload(nsIntRegion *aRegion) { if (!GetBuffer()) { // We don't have a buffer; a possible cause is that the IPDL actor // is already dead. This inevitably happens as IPDL actors can die // at any time, so we want to silently return in this case. return false; } if (!mCompositor) { NS_WARNING("Tried to upload without a compositor. Skipping texture upload..."); // If we are in this situation it means we should have called SetCompositor // earlier. It is conceivable that on certain rare conditions with async-video // we may end up here for the first frame, but this should not happen repeatedly. return false; } if (mFormat == gfx::FORMAT_UNKNOWN) { NS_WARNING("BufferTextureHost: unsupported format!"); return false; } else if (mFormat == gfx::FORMAT_YUV) { YCbCrImageDataDeserializer yuvDeserializer(GetBuffer()); MOZ_ASSERT(yuvDeserializer.IsValid()); if (!mCompositor->SupportsEffect(EFFECT_YCBCR)) { RefPtr<gfx::DataSourceSurface> surf = yuvDeserializer.ToDataSourceSurface(); if (!mFirstSource) { mFirstSource = mCompositor->CreateDataTextureSource(mFlags); } mFirstSource->Update(surf, mFlags, aRegion); return true; } RefPtr<DataTextureSource> srcY; RefPtr<DataTextureSource> srcU; RefPtr<DataTextureSource> srcV; if (!mFirstSource) { // We don't support BigImages for YCbCr compositing. srcY = mCompositor->CreateDataTextureSource(mFlags|TEXTURE_DISALLOW_BIGIMAGE); srcU = mCompositor->CreateDataTextureSource(mFlags|TEXTURE_DISALLOW_BIGIMAGE); srcV = mCompositor->CreateDataTextureSource(mFlags|TEXTURE_DISALLOW_BIGIMAGE); mFirstSource = srcY; srcY->SetNextSibling(srcU); srcU->SetNextSibling(srcV); } else { // mFormat never changes so if this was created as a YCbCr host and already // contains a source it should already have 3 sources. // BufferTextureHost only uses DataTextureSources so it is safe to assume // all 3 sources are DataTextureSource. MOZ_ASSERT(mFirstSource->GetNextSibling()); MOZ_ASSERT(mFirstSource->GetNextSibling()->GetNextSibling()); srcY = mFirstSource; srcU = mFirstSource->GetNextSibling()->AsDataTextureSource(); srcV = mFirstSource->GetNextSibling()->GetNextSibling()->AsDataTextureSource(); } RefPtr<gfx::DataSourceSurface> tempY = gfx::Factory::CreateWrappingDataSourceSurface(yuvDeserializer.GetYData(), yuvDeserializer.GetYStride(), gfx::ToIntSize(yuvDeserializer.GetYSize()), gfx::FORMAT_A8); RefPtr<gfx::DataSourceSurface> tempCb = gfx::Factory::CreateWrappingDataSourceSurface(yuvDeserializer.GetCbData(), yuvDeserializer.GetCbCrStride(), gfx::ToIntSize(yuvDeserializer.GetCbCrSize()), gfx::FORMAT_A8); RefPtr<gfx::DataSourceSurface> tempCr = gfx::Factory::CreateWrappingDataSourceSurface(yuvDeserializer.GetCrData(), yuvDeserializer.GetCbCrStride(), gfx::ToIntSize(yuvDeserializer.GetCbCrSize()), gfx::FORMAT_A8); // We don't support partial updates for Y U V textures NS_ASSERTION(!aRegion, "Unsupported partial updates for YCbCr textures"); if (!srcY->Update(tempY, mFlags) || !srcU->Update(tempCb, mFlags) || !srcV->Update(tempCr, mFlags)) { NS_WARNING("failed to update the DataTextureSource"); return false; } } else { // non-YCbCr case if (!mFirstSource) { mFirstSource = mCompositor->CreateDataTextureSource(); } ImageDataDeserializer deserializer(GetBuffer()); if (!deserializer.IsValid()) { NS_WARNING("failed to open shmem surface"); return false; } RefPtr<gfx::DataSourceSurface> surf = deserializer.GetAsSurface(); if (!surf) { return false; } if (!mFirstSource->Update(surf.get(), mFlags, aRegion)) { NS_WARNING("failed to update the DataTextureSource"); return false; } } return true; }
bool BufferTextureHost::Upload(nsIntRegion *aRegion) { if (!GetBuffer()) { // We don't have a buffer; a possible cause is that the IPDL actor // is already dead. This inevitably happens as IPDL actors can die // at any time, so we want to silently return in this case. return false; } if (!mCompositor) { // This can happen if we send textures to a compositable that isn't yet // attached to a layer. return false; } if (mFormat == gfx::SurfaceFormat::UNKNOWN) { NS_WARNING("BufferTextureHost: unsupported format!"); return false; } else if (mFormat == gfx::SurfaceFormat::YUV) { YCbCrImageDataDeserializer yuvDeserializer(GetBuffer(), GetBufferSize()); MOZ_ASSERT(yuvDeserializer.IsValid()); if (!mCompositor->SupportsEffect(EffectTypes::YCBCR)) { RefPtr<gfx::DataSourceSurface> surf = yuvDeserializer.ToDataSourceSurface(); if (NS_WARN_IF(!surf)) { return false; } if (!mFirstSource) { mFirstSource = mCompositor->CreateDataTextureSource(mFlags); } mFirstSource->Update(surf, aRegion); return true; } RefPtr<DataTextureSource> srcY; RefPtr<DataTextureSource> srcU; RefPtr<DataTextureSource> srcV; if (!mFirstSource) { // We don't support BigImages for YCbCr compositing. srcY = mCompositor->CreateDataTextureSource(mFlags|TextureFlags::DISALLOW_BIGIMAGE); srcU = mCompositor->CreateDataTextureSource(mFlags|TextureFlags::DISALLOW_BIGIMAGE); srcV = mCompositor->CreateDataTextureSource(mFlags|TextureFlags::DISALLOW_BIGIMAGE); mFirstSource = srcY; srcY->SetNextSibling(srcU); srcU->SetNextSibling(srcV); } else { // mFormat never changes so if this was created as a YCbCr host and already // contains a source it should already have 3 sources. // BufferTextureHost only uses DataTextureSources so it is safe to assume // all 3 sources are DataTextureSource. MOZ_ASSERT(mFirstSource->GetNextSibling()); MOZ_ASSERT(mFirstSource->GetNextSibling()->GetNextSibling()); srcY = mFirstSource; srcU = mFirstSource->GetNextSibling()->AsDataTextureSource(); srcV = mFirstSource->GetNextSibling()->GetNextSibling()->AsDataTextureSource(); } RefPtr<gfx::DataSourceSurface> tempY = gfx::Factory::CreateWrappingDataSourceSurface(yuvDeserializer.GetYData(), yuvDeserializer.GetYStride(), yuvDeserializer.GetYSize(), gfx::SurfaceFormat::A8); RefPtr<gfx::DataSourceSurface> tempCb = gfx::Factory::CreateWrappingDataSourceSurface(yuvDeserializer.GetCbData(), yuvDeserializer.GetCbCrStride(), yuvDeserializer.GetCbCrSize(), gfx::SurfaceFormat::A8); RefPtr<gfx::DataSourceSurface> tempCr = gfx::Factory::CreateWrappingDataSourceSurface(yuvDeserializer.GetCrData(), yuvDeserializer.GetCbCrStride(), yuvDeserializer.GetCbCrSize(), gfx::SurfaceFormat::A8); // We don't support partial updates for Y U V textures NS_ASSERTION(!aRegion, "Unsupported partial updates for YCbCr textures"); if (!tempY || !tempCb || !tempCr || !srcY->Update(tempY) || !srcU->Update(tempCb) || !srcV->Update(tempCr)) { NS_WARNING("failed to update the DataTextureSource"); return false; } } else { // non-YCbCr case if (!mFirstSource) { mFirstSource = mCompositor->CreateDataTextureSource(); } ImageDataDeserializer deserializer(GetBuffer(), GetBufferSize()); if (!deserializer.IsValid()) { NS_ERROR("Failed to deserialize image!"); return false; } RefPtr<gfx::DataSourceSurface> surf = deserializer.GetAsSurface(); if (!surf) { return false; } if (!mFirstSource->Update(surf.get(), aRegion)) { NS_WARNING("failed to update the DataTextureSource"); return false; } } MOZ_ASSERT(mFirstSource); return true; }