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 CanvasClientSurfaceStream::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer) { GLScreenBuffer* screen = aLayer->mGLContext->Screen(); SurfaceStream* stream = screen->Stream(); bool isCrossProcess = !(XRE_GetProcessType() == GeckoProcessType_Default); bool bufferCreated = false; if (isCrossProcess) { #ifdef MOZ_WIDGET_GONK SharedSurface* surf = stream->SwapConsumer(); if (!surf) { printf_stderr("surf is null post-SwapConsumer!\n"); return; } if (surf->Type() != SharedSurfaceType::Gralloc) { printf_stderr("Unexpected non-Gralloc SharedSurface in IPC path!"); MOZ_ASSERT(false); return; } SharedSurface_Gralloc* grallocSurf = SharedSurface_Gralloc::Cast(surf); GrallocTextureClientOGL* grallocTextureClient = static_cast<GrallocTextureClientOGL*>(grallocSurf->GetTextureClient()); // If IPDLActor is null means this TextureClient didn't AddTextureClient yet if (!grallocTextureClient->GetIPDLActor()) { grallocTextureClient->SetTextureFlags(mTextureInfo.mTextureFlags); AddTextureClient(grallocTextureClient); } if (grallocTextureClient->GetIPDLActor()) { GetForwarder()->UseTexture(this, grallocTextureClient); } #else printf_stderr("isCrossProcess, but not MOZ_WIDGET_GONK! Someone needs to write some code!"); MOZ_ASSERT(false); #endif } else { if (!mBuffer) { StreamTextureClientOGL* textureClient = new StreamTextureClientOGL(mTextureInfo.mTextureFlags); textureClient->InitWith(stream); mBuffer = textureClient; bufferCreated = true; } if (bufferCreated && !AddTextureClient(mBuffer)) { mBuffer = nullptr; } if (mBuffer) { GetForwarder()->UseTexture(this, mBuffer); } } aLayer->Painted(); }
void CanvasClientSharedSurface::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer) { if (mFront) { mPrevFront = mFront; mFront = nullptr; } auto gl = aLayer->mGLContext; gl->MakeCurrent(); if (aLayer->mGLFrontbuffer) { mFront = CloneSurface(aLayer->mGLFrontbuffer.get(), aLayer->mFactory.get()); if (mFront) mFront->Surf()->Fence(); } else { mFront = gl->Screen()->Front(); if (!mFront) return; } MOZ_ASSERT(mFront); // Alright, now sort out the IPC goop. SharedSurface* surf = mFront->Surf(); auto forwarder = GetForwarder(); auto flags = GetTextureFlags() | TextureFlags::IMMUTABLE; // Get a TexClient from our surf. RefPtr<TextureClient> newTex = TexClientFromShSurf(surf, flags); if (!newTex) { auto manager = aLayer->ClientManager(); auto shadowForwarder = manager->AsShadowForwarder(); auto layersBackend = shadowForwarder->GetCompositorBackendType(); newTex = TexClientFromReadback(surf, forwarder, flags, layersBackend); } MOZ_ASSERT(newTex); // Add the new TexClient. MOZ_ALWAYS_TRUE( AddTextureClient(newTex) ); // Remove the old TexClient. if (mFrontTex) { // remove old buffer from CompositableHost RefPtr<AsyncTransactionTracker> tracker = new RemoveTextureFromCompositableTracker(); // Hold TextureClient until transaction complete. tracker->SetTextureClient(mFrontTex); mFrontTex->SetRemoveFromCompositableTracker(tracker); // RemoveTextureFromCompositableAsync() expects CompositorChild's presence. GetForwarder()->RemoveTextureFromCompositableAsync(tracker, this, mFrontTex); mFrontTex = nullptr; } // Use the new TexClient. mFrontTex = newTex; forwarder->UpdatedTexture(this, mFrontTex, nullptr); forwarder->UseTexture(this, mFrontTex); }
void CanvasClient2D::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer) { AutoRemoveTexture autoRemove(this); if (mBuffer && (mBuffer->IsImmutable() || mBuffer->GetSize() != aSize)) { autoRemove.mTexture = 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; } gfx::SurfaceFormat surfaceFormat = gfx::ImageFormatToSurfaceFormat(format); mBuffer = CreateTextureClientForCanvas(surfaceFormat, aSize, flags, aLayer); 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->BorrowDrawTarget(); 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); } }
void ContentClientDoubleBuffered::CreateFrontBuffer(const nsIntRect& aBufferRect) { if (!CreateAndAllocateTextureClient(mFrontClient, TEXTURE_ON_BLACK) || !AddTextureClient(mFrontClient)) { AbortTextureClientCreation(); return; } if (mTextureInfo.mTextureFlags & TEXTURE_COMPONENT_ALPHA) { if (!CreateAndAllocateTextureClient(mFrontClientOnWhite, TEXTURE_ON_WHITE) || !AddTextureClient(mFrontClientOnWhite)) { AbortTextureClientCreation(); return; } } mFrontBufferRect = aBufferRect; mFrontBufferRotation = nsIntPoint(); }
void ContentClientRemoteBuffer::BuildTextureClients(SurfaceFormat aFormat, const nsIntRect& aRect, uint32_t aFlags) { // If we hit this assertion, then it might be due to an empty transaction // followed by a real transaction. Our buffers should be created (but not // painted in the empty transaction) and then painted (but not created) in the // real transaction. That is kind of fragile, and this assert will catch // circumstances where we screw that up, e.g., by unnecessarily recreating our // buffers. NS_ABORT_IF_FALSE(!mIsNewBuffer, "Bad! Did we create a buffer twice without painting?"); mIsNewBuffer = true; DestroyBuffers(); mSurfaceFormat = aFormat; mSize = gfx::IntSize(aRect.width, aRect.height); mTextureInfo.mTextureFlags = TextureFlagsForRotatedContentBufferFlags(aFlags); if (!CreateAndAllocateTextureClient(mTextureClient, TEXTURE_ON_BLACK) || !AddTextureClient(mTextureClient)) { AbortTextureClientCreation(); return; } if (aFlags & BUFFER_COMPONENT_ALPHA) { if (!CreateAndAllocateTextureClient(mTextureClientOnWhite, TEXTURE_ON_WHITE) || !AddTextureClient(mTextureClientOnWhite)) { AbortTextureClientCreation(); return; } mTextureInfo.mTextureFlags |= TEXTURE_COMPONENT_ALPHA; } CreateFrontBuffer(aRect); }
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); mBuffer = CreateBufferTextureClient(gfx::ImageFormatToSurfaceFormat(format)); MOZ_ASSERT(mBuffer->AsTextureClientSurface()); mBuffer->AsTextureClientSurface()->AllocateForSurface(aSize); bufferCreated = true; } if (!mBuffer->Lock(OPEN_WRITE_ONLY)) { return; } bool updated = false; { // Restrict drawTarget to a scope so that terminates before Unlock. RefPtr<DrawTarget> drawTarget = mBuffer->AsTextureClientDrawTarget()->GetAsDrawTarget(); if (drawTarget) { aLayer->UpdateTarget(drawTarget); updated = true; } } mBuffer->Unlock(); if (bufferCreated && !AddTextureClient(mBuffer)) { mBuffer = nullptr; return; } if (updated) { GetForwarder()->UpdatedTexture(this, mBuffer, nullptr); GetForwarder()->UseTexture(this, mBuffer); } }
void CanvasClientSharedSurface::Updated() { if (!mNewFront) { return; } auto forwarder = GetForwarder(); #ifndef MOZ_WIDGET_GONK if (mFront) { if (mFront->GetFlags() & TextureFlags::RECYCLE) { mFront->WaitForCompositorRecycle(); } } #else // AutoRemoveTexture does the followings. // - Ensure to deliver FenceHandle from TextureHost to TextureClient, before // next TextureClient usage. // - Control TextureClient's recycling timing. // - Call RemoveTexture() after newFront's UseTextures() call. // It could improve performance of Host side's EGL handling on gonk AutoRemoveTexture autoRemove(this); if (mFront && mFront != mNewFront) { autoRemove.mTexture = mFront; } #endif mFront = mNewFront; mNewFront = nullptr; // Add the new TexClient. MOZ_ALWAYS_TRUE( AddTextureClient(mFront) ); AutoTArray<CompositableForwarder::TimedTextureClient,1> textures; CompositableForwarder::TimedTextureClient* t = textures.AppendElement(); t->mTextureClient = mFront; t->mPictureRect = nsIntRect(nsIntPoint(0, 0), mFront->GetSize()); t->mFrameID = mFrameID; // XXX TODO - This reference to VRManagerChild will be moved with the // implementation of the WebVR 1.0 API, which will enable // the inputFrameID to be passed through Javascript with // the new VRDisplay API. t->mInputFrameID = VRManagerChild::Get()->GetInputFrameID(); forwarder->UseTextures(this, textures); }
void CanvasClient2D::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer) { if (mBuffer && (mBuffer->IsImmutable() || mBuffer->GetSize() != aSize)) { mBuffer->ForceRemove(); mBuffer = nullptr; } bool bufferCreated = false; if (!mBuffer) { bool isOpaque = (aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE); gfxContentType contentType = isOpaque ? GFX_CONTENT_COLOR : GFX_CONTENT_COLOR_ALPHA; gfxImageFormat format = gfxPlatform::GetPlatform()->OptimalFormatForContent(contentType); mBuffer = CreateBufferTextureClient(gfx::ImageFormatToSurfaceFormat(format)); MOZ_ASSERT(mBuffer->AsTextureClientSurface()); mBuffer->AsTextureClientSurface()->AllocateForSurface(aSize); bufferCreated = true; } if (!mBuffer->Lock(OPEN_WRITE_ONLY)) { return; } nsRefPtr<gfxASurface> surface = mBuffer->AsTextureClientSurface()->GetAsSurface(); if (surface) { aLayer->UpdateSurface(surface); } mBuffer->Unlock(); if (bufferCreated && !AddTextureClient(mBuffer)) { mBuffer = nullptr; return; } if (surface) { GetForwarder()->UpdatedTexture(this, mBuffer, nullptr); GetForwarder()->UseTexture(this, mBuffer); } }
void CanvasClientSharedSurface::Updated() { if (!mNewFront) { return; } auto forwarder = GetForwarder(); #ifndef MOZ_WIDGET_GONK if (mFront) { if (mFront->GetFlags() & TextureFlags::RECYCLE) { mFront->WaitForCompositorRecycle(); } } #else // AutoRemoveTexture does the followings. // - Ensure to deliver FenceHandle from TextureHost to TextureClient, before // next TextureClient usage. // - Control TextureClient's recycling timing. // - Call RemoveTexture() after newFront's UseTextures() call. // It could improve performance of Host side's EGL handling on gonk AutoRemoveTexture autoRemove(this); if (mFront && mFront != mNewFront) { autoRemove.mTexture = mFront; } #endif mFront = mNewFront; mNewFront = nullptr; // Add the new TexClient. MOZ_ALWAYS_TRUE( AddTextureClient(mFront) ); nsAutoTArray<CompositableForwarder::TimedTextureClient,1> textures; CompositableForwarder::TimedTextureClient* t = textures.AppendElement(); t->mTextureClient = mFront; t->mPictureRect = nsIntRect(nsIntPoint(0, 0), mFront->GetSize()); t->mFrameID = mFrameID; forwarder->UseTextures(this, textures); }
void CanvasClient2D::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer) { AutoRemoveTexture autoRemove(this); if (mBuffer && (mBuffer->IsImmutable() || mBuffer->GetSize() != aSize)) { autoRemove.mTexture = mBuffer; mBuffer = nullptr; } bool bufferCreated = false; if (!mBuffer) { bool isOpaque = (aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE); gfxContentType contentType = isOpaque ? gfxContentType::COLOR : gfxContentType::COLOR_ALPHA; gfx::SurfaceFormat surfaceFormat = gfxPlatform::GetPlatform()->Optimal2DFormatForContent(contentType); TextureFlags flags = TextureFlags::DEFAULT; if (mTextureFlags & TextureFlags::ORIGIN_BOTTOM_LEFT) { flags |= TextureFlags::ORIGIN_BOTTOM_LEFT; } mBuffer = CreateTextureClientForCanvas(surfaceFormat, aSize, flags, aLayer); if (!mBuffer) { NS_WARNING("Failed to allocate the TextureClient"); return; } MOZ_ASSERT(mBuffer->CanExposeDrawTarget()); bufferCreated = true; } bool updated = false; { TextureClientAutoLock autoLock(mBuffer, OpenMode::OPEN_WRITE_ONLY); if (!autoLock.Succeeded()) { mBuffer = nullptr; return; } RefPtr<DrawTarget> target = mBuffer->BorrowDrawTarget(); if (target) { aLayer->UpdateTarget(target); updated = true; } } if (bufferCreated && !AddTextureClient(mBuffer)) { mBuffer = nullptr; return; } if (updated) { nsAutoTArray<CompositableForwarder::TimedTextureClient,1> textures; CompositableForwarder::TimedTextureClient* t = textures.AppendElement(); t->mTextureClient = mBuffer; t->mPictureRect = nsIntRect(nsIntPoint(0, 0), mBuffer->GetSize()); t->mFrameID = mFrameID; GetForwarder()->UseTextures(this, textures); mBuffer->SyncWithObject(GetForwarder()->GetSyncObject()); } }
void CanvasClientSurfaceStream::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer) { aLayer->mGLContext->MakeCurrent(); GLScreenBuffer* screen = aLayer->mGLContext->Screen(); SurfaceStream* stream = nullptr; if (aLayer->mStream) { stream = aLayer->mStream; // Copy our current surface to the current producer surface in our stream, then // call SwapProducer to make a new buffer ready. stream->CopySurfaceToProducer(aLayer->mTextureSurface, aLayer->mFactory); stream->SwapProducer(aLayer->mFactory, gfx::IntSize(aSize.width, aSize.height)); } else { stream = screen->Stream(); } bool isCrossProcess = !(XRE_GetProcessType() == GeckoProcessType_Default); bool bufferCreated = false; if (isCrossProcess) { #ifdef MOZ_WIDGET_GONK SharedSurface* surf = stream->SwapConsumer(); if (!surf) { printf_stderr("surf is null post-SwapConsumer!\n"); return; } if (surf->Type() != SharedSurfaceType::Gralloc) { printf_stderr("Unexpected non-Gralloc SharedSurface in IPC path!"); MOZ_ASSERT(false); return; } SharedSurface_Gralloc* grallocSurf = SharedSurface_Gralloc::Cast(surf); RefPtr<GrallocTextureClientOGL> grallocTextureClient = static_cast<GrallocTextureClientOGL*>(grallocSurf->GetTextureClient()); // If IPDLActor is null means this TextureClient didn't AddTextureClient yet if (!grallocTextureClient->GetIPDLActor()) { grallocTextureClient->SetTextureFlags(mTextureInfo.mTextureFlags); AddTextureClient(grallocTextureClient); } if (grallocTextureClient->GetIPDLActor()) { UseTexture(grallocTextureClient); } if (mBuffer && CompositorChild::ChildProcessHasCompositor()) { // remove old buffer from CompositableHost RefPtr<AsyncTransactionTracker> tracker = new RemoveTextureFromCompositableTracker(); // Hold TextureClient until transaction complete. tracker->SetTextureClient(mBuffer); mBuffer->SetRemoveFromCompositableTracker(tracker); // RemoveTextureFromCompositableAsync() expects CompositorChild's presence. GetForwarder()->RemoveTextureFromCompositableAsync(tracker, this, mBuffer); } mBuffer = grallocTextureClient; #else printf_stderr("isCrossProcess, but not MOZ_WIDGET_GONK! Someone needs to write some code!"); MOZ_ASSERT(false); #endif } else { if (!mBuffer) { StreamTextureClientOGL* textureClient = new StreamTextureClientOGL(mTextureInfo.mTextureFlags); textureClient->InitWith(stream); mBuffer = textureClient; bufferCreated = true; } if (bufferCreated && !AddTextureClient(mBuffer)) { mBuffer = nullptr; } if (mBuffer) { GetForwarder()->UseTexture(this, mBuffer); } } aLayer->Painted(); }
void CanvasClientSharedSurface::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer) { auto gl = aLayer->mGLContext; gl->MakeCurrent(); RefPtr<TextureClient> newFront; if (aLayer->mGLFrontbuffer) { mShSurfClient = CloneSurface(aLayer->mGLFrontbuffer.get(), aLayer->mFactory.get()); if (!mShSurfClient) { gfxCriticalError() << "Invalid canvas front buffer"; return; } } else { mShSurfClient = gl->Screen()->Front(); if (!mShSurfClient) { return; } } MOZ_ASSERT(mShSurfClient); newFront = mShSurfClient; SharedSurface* surf = mShSurfClient->Surf(); // Readback if needed. mReadbackClient = nullptr; auto forwarder = GetForwarder(); bool needsReadback = (surf->mType == SharedSurfaceType::Basic); if (needsReadback) { TextureFlags flags = aLayer->Flags() | TextureFlags::IMMUTABLE; auto manager = aLayer->ClientManager(); auto shadowForwarder = manager->AsShadowForwarder(); auto layersBackend = shadowForwarder->GetCompositorBackendType(); mReadbackClient = TexClientFromReadback(surf, forwarder, flags, layersBackend); newFront = mReadbackClient; } else { mReadbackClient = nullptr; } MOZ_ASSERT(newFront); if (!newFront) { // May happen in a release build in case of memory pressure. gfxCriticalError() << "Failed to allocate a TextureClient for SharedSurface Canvas. Size: " << aSize; return; } if (mFront) { if (mFront->GetFlags() & TextureFlags::RECYCLE) { mFront->WaitForCompositorRecycle(); } } mFront = newFront; // Add the new TexClient. MOZ_ALWAYS_TRUE( AddTextureClient(mFront) ); forwarder->UseTexture(this, mFront); }
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; }
bool ImageClientSingle::UpdateImage(ImageContainer* aContainer, uint32_t aContentFlags) { AutoLockImage autoLock(aContainer); Image *image = autoLock.GetImage(); if (!image) { return false; } if (mLastPaintedImageSerial == image->GetSerial()) { return true; } if (image->AsSharedImage() && image->AsSharedImage()->GetTextureClient()) { // fast path: no need to allocate and/or copy image data RefPtr<TextureClient> texture = image->AsSharedImage()->GetTextureClient(); if (texture->IsSharedWithCompositor()) { // XXX - temporary fix for bug 911941 // This will be changed with bug 912907 return false; } if (mFrontBuffer) { RemoveTextureClient(mFrontBuffer); } mFrontBuffer = texture; AddTextureClient(texture); GetForwarder()->UpdatedTexture(this, texture, nullptr); GetForwarder()->UseTexture(this, texture); } else if (image->GetFormat() == PLANAR_YCBCR) { PlanarYCbCrImage* ycbcr = static_cast<PlanarYCbCrImage*>(image); const PlanarYCbCrData* data = ycbcr->GetData(); if (!data) { return false; } if (mFrontBuffer && mFrontBuffer->IsImmutable()) { RemoveTextureClient(mFrontBuffer); mFrontBuffer = nullptr; } bool bufferCreated = false; if (!mFrontBuffer) { mFrontBuffer = CreateBufferTextureClient(gfx::FORMAT_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_READ_WRITE)) { return false; } bool status = mFrontBuffer->AsTextureClientYCbCr()->UpdateYCbCr(*data); mFrontBuffer->Unlock(); if (bufferCreated) { AddTextureClient(mFrontBuffer); } if (status) { GetForwarder()->UpdatedTexture(this, mFrontBuffer, nullptr); GetForwarder()->UseTexture(this, mFrontBuffer); } else { MOZ_ASSERT(false); return false; } } else if (image->GetFormat() == 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) { RemoveTextureClient(mFrontBuffer); mFrontBuffer = nullptr; } RefPtr<SharedTextureClientOGL> buffer = new SharedTextureClientOGL(mTextureFlags); buffer->InitWith(data->mHandle, size, data->mShareType, data->mInverted); mFrontBuffer = buffer; AddTextureClient(mFrontBuffer); GetForwarder()->UseTexture(this, mFrontBuffer); } else { nsRefPtr<gfxASurface> surface = image->GetAsSurface(); MOZ_ASSERT(surface); gfx::IntSize size = gfx::IntSize(image->GetSize().width, image->GetSize().height); if (mFrontBuffer && (mFrontBuffer->IsImmutable() || mFrontBuffer->GetSize() != size)) { RemoveTextureClient(mFrontBuffer); mFrontBuffer = nullptr; } bool bufferCreated = false; if (!mFrontBuffer) { gfxImageFormat format = gfxPlatform::GetPlatform()->OptimalFormatForContent(surface->GetContentType()); mFrontBuffer = CreateBufferTextureClient(gfx::ImageFormatToSurfaceFormat(format), TEXTURE_FLAGS_DEFAULT); MOZ_ASSERT(mFrontBuffer->AsTextureClientSurface()); mFrontBuffer->AsTextureClientSurface()->AllocateForSurface(size); bufferCreated = true; } if (!mFrontBuffer->Lock(OPEN_READ_WRITE)) { return false; } bool status = mFrontBuffer->AsTextureClientSurface()->UpdateSurface(surface); mFrontBuffer->Unlock(); if (bufferCreated) { AddTextureClient(mFrontBuffer); } if (status) { GetForwarder()->UpdatedTexture(this, mFrontBuffer, nullptr); GetForwarder()->UseTexture(this, mFrontBuffer); } else { return false; } } UpdatePictureRect(image->GetPictureRect()); mLastPaintedImageSerial = image->GetSerial(); aContainer->NotifyPaintedImage(image); return true; }