bool ContentClientRemoteBuffer::CreateAndAllocateTextureClient(RefPtr<TextureClient>& aClient, TextureFlags aFlags) { // gfx::BackendType::NONE means fallback to the content backend aClient = CreateTextureClientForDrawing(mSurfaceFormat, mTextureInfo.mTextureFlags | aFlags, gfx::BackendType::NONE, mSize); if (!aClient) { return false; } if (!aClient->AllocateForSurface(mSize, ALLOC_CLEAR_BUFFER)) { aClient = CreateTextureClientForDrawing(mSurfaceFormat, mTextureInfo.mTextureFlags | TEXTURE_ALLOC_FALLBACK | aFlags, gfx::BackendType::NONE, mSize); if (!aClient) { return false; } if (!aClient->AllocateForSurface(mSize, ALLOC_CLEAR_BUFFER)) { NS_WARNING("Could not allocate texture client"); aClient = nullptr; return false; } } NS_WARN_IF_FALSE(aClient->IsValid(), "Created an invalid texture client"); return true; }
already_AddRefed<TextureClient> CanvasClient2D::CreateTextureClientForCanvas(gfx::SurfaceFormat aFormat, gfx::IntSize aSize, TextureFlags aFlags, ClientCanvasLayer* aLayer) { if (aLayer->IsGLLayer()) { // We want a cairo backend here as we don't want to be copying into // an accelerated backend and we like LockBits to work. This is currently // the most effective way to make this work. return TextureClient::CreateForRawBufferAccess(GetForwarder(), aFormat, aSize, BackendType::CAIRO, mTextureFlags | aFlags); } #ifdef XP_WIN return CreateTextureClientForDrawing(aFormat, aSize, BackendSelector::Canvas, aFlags); #else // XXX - We should use CreateTextureClientForDrawing, but we first need // to use double buffering. gfx::BackendType backend = gfxPlatform::GetPlatform()->GetPreferredCanvasBackend(); return TextureClient::CreateForRawBufferAccess(GetForwarder(), aFormat, aSize, backend, mTextureFlags | aFlags); #endif }
void ContentClientRemoteBuffer::CreateBackBuffer(const IntRect& aBufferRect) { // gfx::BackendType::NONE means fallback to the content backend mTextureClient = CreateTextureClientForDrawing( mSurfaceFormat, mSize, gfx::BackendType::NONE, mTextureFlags | ExtraTextureFlags(), TextureAllocationFlags::ALLOC_CLEAR_BUFFER ); if (!mTextureClient || !AddTextureClient(mTextureClient)) { AbortTextureClientCreation(); return; } if (mTextureFlags & TextureFlags::COMPONENT_ALPHA) { mTextureClientOnWhite = mTextureClient->CreateSimilar( mTextureFlags | ExtraTextureFlags(), TextureAllocationFlags::ALLOC_CLEAR_BUFFER_WHITE ); if (!mTextureClientOnWhite || !AddTextureClient(mTextureClientOnWhite)) { AbortTextureClientCreation(); return; } } }
void CanvasClient2D::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer) { if (mBuffer && (mBuffer->IsImmutable() || mBuffer->GetSize() != aSize)) { GetForwarder()->RemoveTextureFromCompositable(this, mBuffer); mBuffer = nullptr; } bool bufferCreated = false; if (!mBuffer) { bool isOpaque = (aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE); gfxContentType contentType = isOpaque ? gfxContentType::COLOR : gfxContentType::COLOR_ALPHA; gfxImageFormat format = gfxPlatform::GetPlatform()->OptimalFormatForContent(contentType); TextureFlags flags = TextureFlags::DEFAULT; if (mTextureFlags & TextureFlags::NEEDS_Y_FLIP) { flags |= TextureFlags::NEEDS_Y_FLIP; } mBuffer = CreateTextureClientForDrawing(gfx::ImageFormatToSurfaceFormat(format), flags, gfxPlatform::GetPlatform()->GetPreferredCanvasBackend(), aSize); MOZ_ASSERT(mBuffer->CanExposeDrawTarget()); mBuffer->AllocateForSurface(aSize); bufferCreated = true; } if (!mBuffer->Lock(OpenMode::OPEN_WRITE_ONLY)) { mBuffer = nullptr; return; } bool updated = false; { // Restrict drawTarget to a scope so that terminates before Unlock. RefPtr<DrawTarget> target = mBuffer->GetAsDrawTarget(); if (target) { aLayer->UpdateTarget(target); updated = true; } } mBuffer->Unlock(); if (bufferCreated && !AddTextureClient(mBuffer)) { mBuffer = nullptr; return; } if (updated) { GetForwarder()->UpdatedTexture(this, mBuffer, nullptr); GetForwarder()->UseTexture(this, mBuffer); } }
bool ImageClientSingle::UpdateImageInternal(ImageContainer* aContainer, uint32_t aContentFlags, bool* aIsSwapped) { AutoLockImage autoLock(aContainer); *aIsSwapped = false; Image *image = autoLock.GetImage(); if (!image) { return false; } if (mLastPaintedImageSerial == image->GetSerial()) { return true; } if (image->AsSharedImage() && image->AsSharedImage()->GetTextureClient(this)) { // fast path: no need to allocate and/or copy image data RefPtr<TextureClient> texture = image->AsSharedImage()->GetTextureClient(this); if (mFrontBuffer) { GetForwarder()->RemoveTextureFromCompositable(this, mFrontBuffer); } mFrontBuffer = texture; if (!AddTextureClient(texture)) { mFrontBuffer = nullptr; return false; } GetForwarder()->UpdatedTexture(this, texture, nullptr); GetForwarder()->UseTexture(this, texture); } else if (image->GetFormat() == ImageFormat::PLANAR_YCBCR) { PlanarYCbCrImage* ycbcr = static_cast<PlanarYCbCrImage*>(image); const PlanarYCbCrData* data = ycbcr->GetData(); if (!data) { return false; } if (mFrontBuffer && mFrontBuffer->IsImmutable()) { GetForwarder()->RemoveTextureFromCompositable(this, mFrontBuffer); mFrontBuffer = nullptr; } bool bufferCreated = false; if (!mFrontBuffer) { mFrontBuffer = CreateBufferTextureClient(gfx::SurfaceFormat::YUV, TEXTURE_FLAGS_DEFAULT); gfx::IntSize ySize(data->mYSize.width, data->mYSize.height); gfx::IntSize cbCrSize(data->mCbCrSize.width, data->mCbCrSize.height); if (!mFrontBuffer->AsTextureClientYCbCr()->AllocateForYCbCr(ySize, cbCrSize, data->mStereoMode)) { mFrontBuffer = nullptr; return false; } bufferCreated = true; } if (!mFrontBuffer->Lock(OPEN_WRITE_ONLY)) { return false; } bool status = mFrontBuffer->AsTextureClientYCbCr()->UpdateYCbCr(*data); mFrontBuffer->Unlock(); if (bufferCreated) { if (!AddTextureClient(mFrontBuffer)) { mFrontBuffer = nullptr; return false; } } if (status) { GetForwarder()->UpdatedTexture(this, mFrontBuffer, nullptr); GetForwarder()->UseTexture(this, mFrontBuffer); } else { MOZ_ASSERT(false); return false; } } else if (image->GetFormat() == ImageFormat::SHARED_TEXTURE) { SharedTextureImage* sharedImage = static_cast<SharedTextureImage*>(image); const SharedTextureImage::Data *data = sharedImage->GetData(); gfx::IntSize size = gfx::IntSize(image->GetSize().width, image->GetSize().height); if (mFrontBuffer) { GetForwarder()->RemoveTextureFromCompositable(this, mFrontBuffer); mFrontBuffer = nullptr; } RefPtr<SharedTextureClientOGL> buffer = new SharedTextureClientOGL(mTextureFlags); buffer->InitWith(data->mHandle, size, data->mShareType, data->mInverted); mFrontBuffer = buffer; if (!AddTextureClient(mFrontBuffer)) { mFrontBuffer = nullptr; return false; } GetForwarder()->UseTexture(this, mFrontBuffer); } else { RefPtr<gfx::SourceSurface> surface = image->GetAsSourceSurface(); MOZ_ASSERT(surface); gfx::IntSize size = image->GetSize(); if (mFrontBuffer && (mFrontBuffer->IsImmutable() || mFrontBuffer->GetSize() != size)) { GetForwarder()->RemoveTextureFromCompositable(this, mFrontBuffer); mFrontBuffer = nullptr; } bool bufferCreated = false; if (!mFrontBuffer) { gfxImageFormat format = gfxPlatform::GetPlatform()->OptimalFormatForContent(gfx::ContentForFormat(surface->GetFormat())); mFrontBuffer = CreateTextureClientForDrawing(gfx::ImageFormatToSurfaceFormat(format), mTextureFlags, gfx::BackendType::NONE, size); MOZ_ASSERT(mFrontBuffer->AsTextureClientDrawTarget()); if (!mFrontBuffer->AsTextureClientDrawTarget()->AllocateForSurface(size)) { mFrontBuffer = nullptr; return false; } bufferCreated = true; } if (!mFrontBuffer->Lock(OPEN_WRITE_ONLY)) { return false; } { // We must not keep a reference to the DrawTarget after it has been unlocked. RefPtr<DrawTarget> dt = mFrontBuffer->AsTextureClientDrawTarget()->GetAsDrawTarget(); MOZ_ASSERT(surface.get()); dt->CopySurface(surface, IntRect(IntPoint(), surface->GetSize()), IntPoint()); } mFrontBuffer->Unlock(); if (bufferCreated) { if (!AddTextureClient(mFrontBuffer)) { mFrontBuffer = nullptr; return false; } } GetForwarder()->UpdatedTexture(this, mFrontBuffer, nullptr); GetForwarder()->UseTexture(this, mFrontBuffer); } UpdatePictureRect(image->GetPictureRect()); mLastPaintedImageSerial = image->GetSerial(); aContainer->NotifyPaintedImage(image); *aIsSwapped = true; return true; }