void CopyableCanvasLayer::UpdateSurface(gfxASurface* aDestSurface, Layer* aMaskLayer) { if (!IsDirty()) return; Painted(); if (mDrawTarget) { mDrawTarget->Flush(); mSurface = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget); } if (!mGLContext && aDestSurface) { nsRefPtr<gfxContext> tmpCtx = new gfxContext(aDestSurface); tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE); CopyableCanvasLayer::PaintWithOpacity(tmpCtx, 1.0f, aMaskLayer); return; } if (mGLContext) { if (aDestSurface && aDestSurface->GetType() != gfxASurface::SurfaceTypeImage) { MOZ_ASSERT(false, "Destination surface must be ImageSurface type."); return; } nsRefPtr<gfxImageSurface> readSurf; nsRefPtr<gfxImageSurface> resultSurf; SharedSurface* sharedSurf = mGLContext->RequestFrame(); if (!sharedSurf) { NS_WARNING("Null frame received."); return; } gfxIntSize readSize(sharedSurf->Size()); gfxImageFormat format = (GetContentFlags() & CONTENT_OPAQUE) ? gfxASurface::ImageFormatRGB24 : gfxASurface::ImageFormatARGB32; if (aDestSurface) { resultSurf = static_cast<gfxImageSurface*>(aDestSurface); } else { resultSurf = GetTempSurface(readSize, format); } MOZ_ASSERT(resultSurf); if (resultSurf->CairoStatus() != 0) { MOZ_ASSERT(false, "Bad resultSurf->CairoStatus()."); return; } MOZ_ASSERT(sharedSurf->APIType() == APITypeT::OpenGL); SharedSurface_GL* surfGL = SharedSurface_GL::Cast(sharedSurf); if (surfGL->Type() == SharedSurfaceType::Basic) { SharedSurface_Basic* sharedSurf_Basic = SharedSurface_Basic::Cast(surfGL); readSurf = sharedSurf_Basic->GetData(); } else { if (resultSurf->Format() == format && resultSurf->GetSize() == readSize) { readSurf = resultSurf; } else { readSurf = GetTempSurface(readSize, format); } // Readback handles Flush/MarkDirty. mGLContext->Screen()->Readback(surfGL, readSurf); } MOZ_ASSERT(readSurf); bool needsPremult = surfGL->HasAlpha() && !mIsGLAlphaPremult; if (needsPremult) { gfxImageSurface* sizedReadSurf = nullptr; if (readSurf->Format() == resultSurf->Format() && readSurf->GetSize() == resultSurf->GetSize()) { sizedReadSurf = readSurf; } else { readSurf->Flush(); nsRefPtr<gfxContext> ctx = new gfxContext(resultSurf); ctx->SetOperator(gfxContext::OPERATOR_SOURCE); ctx->SetSource(readSurf); ctx->Paint(); sizedReadSurf = resultSurf; } MOZ_ASSERT(sizedReadSurf); readSurf->Flush(); resultSurf->Flush(); gfxUtils::PremultiplyImageSurface(readSurf, resultSurf); resultSurf->MarkDirty(); } else if (resultSurf != readSurf) { // Didn't need premult, but we do need to blit to resultSurf readSurf->Flush(); nsRefPtr<gfxContext> ctx = new gfxContext(resultSurf); ctx->SetOperator(gfxContext::OPERATOR_SOURCE); ctx->SetSource(readSurf); ctx->Paint(); } // stick our surface into mSurface, so that the Paint() path is the same if (!aDestSurface) { mSurface = resultSurf; } } }
void CopyableCanvasLayer::UpdateSurface(gfxASurface* aDestSurface, Layer* aMaskLayer) { if (!IsDirty()) return; Painted(); if (mDrawTarget) { mDrawTarget->Flush(); if (mDrawTarget->GetType() == BACKEND_COREGRAPHICS_ACCELERATED) { // We have an accelerated CG context which has changed, unlike a bitmap surface // where we can alias the bits on initializing the mDrawTarget, we need to readback // and copy the accelerated surface each frame. We want to support this for quick // thumbnail but if we're going to be doing this every frame it likely is better // to use a non accelerated (bitmap) canvas. mSurface = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget); } } if (!mGLContext && aDestSurface) { nsRefPtr<gfxContext> tmpCtx = new gfxContext(aDestSurface); tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE); CopyableCanvasLayer::PaintWithOpacity(tmpCtx, 1.0f, aMaskLayer); return; } if (mGLContext) { if (aDestSurface && aDestSurface->GetType() != gfxASurface::SurfaceTypeImage) { MOZ_ASSERT(false, "Destination surface must be ImageSurface type."); return; } nsRefPtr<gfxImageSurface> readSurf; nsRefPtr<gfxImageSurface> resultSurf; SharedSurface* sharedSurf = mGLContext->RequestFrame(); if (!sharedSurf) { NS_WARNING("Null frame received."); return; } gfxIntSize readSize(sharedSurf->Size()); gfxImageFormat format = (GetContentFlags() & CONTENT_OPAQUE) ? gfxASurface::ImageFormatRGB24 : gfxASurface::ImageFormatARGB32; if (aDestSurface) { resultSurf = static_cast<gfxImageSurface*>(aDestSurface); } else { resultSurf = GetTempSurface(readSize, format); } MOZ_ASSERT(resultSurf); if (resultSurf->CairoStatus() != 0) { MOZ_ASSERT(false, "Bad resultSurf->CairoStatus()."); return; } MOZ_ASSERT(sharedSurf->APIType() == APITypeT::OpenGL); SharedSurface_GL* surfGL = SharedSurface_GL::Cast(sharedSurf); if (surfGL->Type() == SharedSurfaceType::Basic) { SharedSurface_Basic* sharedSurf_Basic = SharedSurface_Basic::Cast(surfGL); readSurf = sharedSurf_Basic->GetData(); } else { if (resultSurf->Format() == format && resultSurf->GetSize() == readSize) { readSurf = resultSurf; } else { readSurf = GetTempSurface(readSize, format); } // Readback handles Flush/MarkDirty. mGLContext->Screen()->Readback(surfGL, readSurf); } MOZ_ASSERT(readSurf); bool needsPremult = surfGL->HasAlpha() && !mIsGLAlphaPremult; if (needsPremult) { gfxImageSurface* sizedReadSurf = nullptr; if (readSurf->Format() == resultSurf->Format() && readSurf->GetSize() == resultSurf->GetSize()) { sizedReadSurf = readSurf; } else { readSurf->Flush(); nsRefPtr<gfxContext> ctx = new gfxContext(resultSurf); ctx->SetOperator(gfxContext::OPERATOR_SOURCE); ctx->SetSource(readSurf); ctx->Paint(); sizedReadSurf = resultSurf; } MOZ_ASSERT(sizedReadSurf); readSurf->Flush(); resultSurf->Flush(); gfxUtils::PremultiplyImageSurface(readSurf, resultSurf); resultSurf->MarkDirty(); } else if (resultSurf != readSurf) { // Didn't need premult, but we do need to blit to resultSurf readSurf->Flush(); nsRefPtr<gfxContext> ctx = new gfxContext(resultSurf); ctx->SetOperator(gfxContext::OPERATOR_SOURCE); ctx->SetSource(readSurf); ctx->Paint(); } // stick our surface into mSurface, so that the Paint() path is the same if (!aDestSurface) { mSurface = resultSurf; } } }
void CopyableCanvasLayer::UpdateSurface(gfxASurface* aDestSurface, Layer* aMaskLayer) { if (!IsDirty()) return; Painted(); if (mDrawTarget) { mDrawTarget->Flush(); mSurface = gfxPlatform::GetPlatform()->CreateThebesSurfaceAliasForDrawTarget_hack(mDrawTarget); } if (!mGLContext && aDestSurface) { nsRefPtr<gfxContext> tmpCtx = new gfxContext(aDestSurface); tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE); CopyableCanvasLayer::PaintWithOpacity(tmpCtx, 1.0f, aMaskLayer); return; } if (mGLContext) { nsRefPtr<gfxImageSurface> readSurf; nsRefPtr<gfxASurface> resultSurf; SharedSurface* sharedSurf = mGLContext->RequestFrame(); if (!sharedSurf) { NS_WARNING("Null frame received."); return; } IntSize readSize(ToIntSize(sharedSurf->Size())); gfxImageFormat format = (GetContentFlags() & CONTENT_OPAQUE) ? gfxImageFormatRGB24 : gfxImageFormatARGB32; if (aDestSurface) { resultSurf = aDestSurface; } else { resultSurf = GetTempSurface(readSize, format); } MOZ_ASSERT(resultSurf); if (resultSurf->CairoStatus() != 0) { MOZ_ASSERT(false, "Bad resultSurf->CairoStatus()."); return; } MOZ_ASSERT(sharedSurf->APIType() == APITypeT::OpenGL); SharedSurface_GL* surfGL = SharedSurface_GL::Cast(sharedSurf); if (surfGL->Type() == SharedSurfaceType::Basic) { SharedSurface_Basic* sharedSurf_Basic = SharedSurface_Basic::Cast(surfGL); readSurf = sharedSurf_Basic->GetData(); } else { if (ToIntSize(resultSurf->GetSize()) != readSize || !(readSurf = resultSurf->GetAsImageSurface()) || readSurf->Format() != format) { readSurf = GetTempSurface(readSize, format); } // Readback handles Flush/MarkDirty. mGLContext->Screen()->Readback(surfGL, readSurf); } MOZ_ASSERT(readSurf); bool needsPremult = surfGL->HasAlpha() && !mIsGLAlphaPremult; if (needsPremult) { readSurf->Flush(); gfxUtils::PremultiplyImageSurface(readSurf); readSurf->MarkDirty(); } if (readSurf != resultSurf) { readSurf->Flush(); nsRefPtr<gfxContext> ctx = new gfxContext(resultSurf); ctx->SetOperator(gfxContext::OPERATOR_SOURCE); ctx->SetSource(readSurf); ctx->Paint(); } // If !aDestSurface then we will end up painting using mSurface, so // stick our surface into mSurface, so that the Paint() path is the same. if (!aDestSurface) { mSurface = resultSurf; } } }