Bug 1366097 - Part 4. Mark VectorImage as surface as shared when used outside an image layer. r=tnikkel

This is important because it ensures we release the shared memory handle
(although not the data itself) for the underlying surface buffer when it
turns out we will probably never need to share it. If we do need to
share the surface data with the GPU process, it will reallocate a handle
if necessary, and close it when it is finished. On some platforms we
only have a finite number of handles, so if we don't need them, we
should close them.
This commit is contained in:
Andrew Osmond 2017-11-17 14:08:52 -05:00
Родитель c94d4d3f78
Коммит c6bd7fcdf9
2 изменённых файлов: 41 добавлений и 14 удалений

Просмотреть файл

@ -742,7 +742,12 @@ VectorImage::GetFrameAtSize(const IntSize& aSize,
uint32_t aFlags) uint32_t aFlags)
{ {
auto result = GetFrameInternal(aSize, aWhichFrame, aFlags); auto result = GetFrameInternal(aSize, aWhichFrame, aFlags);
return Get<2>(result).forget(); RefPtr<SourceSurface> surf = Get<2>(result).forget();
// If we are here, it suggests the image is embedded in a canvas or some
// other path besides layers, and we won't need the file handle.
MarkSurfaceShared(surf);
return surf.forget();
} }
Tuple<DrawResult, IntSize, RefPtr<SourceSurface>> Tuple<DrawResult, IntSize, RefPtr<SourceSurface>>
@ -798,9 +803,17 @@ VectorImage::GetFrameInternal(const IntSize& aSize,
mSVGDocumentWrapper->GetCurrentTime(), mSVGDocumentWrapper->GetCurrentTime(),
aFlags, 1.0); aFlags, 1.0);
DrawInternal(params, false); // DrawInternal may return a surface which is stored in the cache. It is
RefPtr<SourceSurface> sourceSurface = dt->Snapshot(); // important to prefer this result over the snapshot because it may be a
return MakeTuple(DrawResult::SUCCESS, aSize, Move(sourceSurface)); // different surface type (e.g. SourceSurfaceSharedData for WebRender). If
// we did not put anything in the cache, we will need to fallback to the
// snapshot surface.
RefPtr<SourceSurface> surface = DrawInternal(params, false);
if (!surface) {
surface = dt->Snapshot();
}
return MakeTuple(DrawResult::SUCCESS, aSize, Move(surface));
} }
//****************************************************************************** //******************************************************************************
@ -954,11 +967,16 @@ VectorImage::Draw(gfxContext* aContext,
return DrawResult::TEMPORARY_ERROR; return DrawResult::TEMPORARY_ERROR;
} }
DrawInternal(params, haveContextPaint && !blockContextPaint); RefPtr<SourceSurface> surface =
DrawInternal(params, haveContextPaint && !blockContextPaint);
// Image got put into a painted layer, it will not be shared with another
// process.
MarkSurfaceShared(surface);
return DrawResult::SUCCESS; return DrawResult::SUCCESS;
} }
void already_AddRefed<SourceSurface>
VectorImage::DrawInternal(const SVGDrawingParameters& aParams, VectorImage::DrawInternal(const SVGDrawingParameters& aParams,
bool aContextPaint) bool aContextPaint)
{ {
@ -985,7 +1003,7 @@ VectorImage::DrawInternal(const SVGDrawingParameters& aParams,
// We didn't get a hit in the surface cache, so we'll need to rerasterize. // We didn't get a hit in the surface cache, so we'll need to rerasterize.
BackendType backend = aParams.context->GetDrawTarget()->GetBackendType(); BackendType backend = aParams.context->GetDrawTarget()->GetBackendType();
CreateSurfaceAndShow(aParams, backend); return CreateSurfaceAndShow(aParams, backend);
} }
already_AddRefed<SourceSurface> already_AddRefed<SourceSurface>
@ -1024,7 +1042,7 @@ VectorImage::LookupCachedSurface(const IntSize& aSize,
return sourceSurface.forget(); return sourceSurface.forget();
} }
void already_AddRefed<SourceSurface>
VectorImage::CreateSurfaceAndShow(const SVGDrawingParameters& aParams, BackendType aBackend) VectorImage::CreateSurfaceAndShow(const SVGDrawingParameters& aParams, BackendType aBackend)
{ {
mSVGDocumentWrapper->UpdateViewportBounds(aParams.viewportSize); mSVGDocumentWrapper->UpdateViewportBounds(aParams.viewportSize);
@ -1046,7 +1064,8 @@ VectorImage::CreateSurfaceAndShow(const SVGDrawingParameters& aParams, BackendTy
// The image is too big to fit in the cache: // The image is too big to fit in the cache:
!SurfaceCache::CanHold(aParams.size); !SurfaceCache::CanHold(aParams.size);
if (bypassCache) { if (bypassCache) {
return Show(svgDrawable, aParams); Show(svgDrawable, aParams);
return nullptr;
} }
// We're about to rerasterize, which may mean that some of the previous // We're about to rerasterize, which may mean that some of the previous
@ -1070,14 +1089,16 @@ VectorImage::CreateSurfaceAndShow(const SVGDrawingParameters& aParams, BackendTy
// up way too big. Generally it also wouldn't fit in the cache, but the prefs // up way too big. Generally it also wouldn't fit in the cache, but the prefs
// could be set such that the cache isn't the limiting factor. // could be set such that the cache isn't the limiting factor.
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
return Show(svgDrawable, aParams); Show(svgDrawable, aParams);
return nullptr;
} }
// Take a strong reference to the frame's surface and make sure it hasn't // Take a strong reference to the frame's surface and make sure it hasn't
// already been purged by the operating system. // already been purged by the operating system.
RefPtr<SourceSurface> surface = frame->GetSourceSurface(); RefPtr<SourceSurface> surface = frame->GetSourceSurface();
if (!surface) { if (!surface) {
return Show(svgDrawable, aParams); Show(svgDrawable, aParams);
return nullptr;
} }
// Attempt to cache the frame. // Attempt to cache the frame.
@ -1108,6 +1129,8 @@ VectorImage::CreateSurfaceAndShow(const SVGDrawingParameters& aParams, BackendTy
} }
})); }));
} }
return surface.forget();
} }

Просмотреть файл

@ -96,9 +96,13 @@ private:
const Maybe<SVGImageContext>& aSVGContext, const Maybe<SVGImageContext>& aSVGContext,
uint32_t aFlags); uint32_t aFlags);
void DrawInternal(const SVGDrawingParameters& aParams, bool aContextPaint); already_AddRefed<SourceSurface>
void CreateSurfaceAndShow(const SVGDrawingParameters& aParams, DrawInternal(const SVGDrawingParameters& aParams, bool aContextPaint);
gfx::BackendType aBackend);
already_AddRefed<SourceSurface>
CreateSurfaceAndShow(const SVGDrawingParameters& aParams,
gfx::BackendType aBackend);
void Show(gfxDrawable* aDrawable, const SVGDrawingParameters& aParams); void Show(gfxDrawable* aDrawable, const SVGDrawingParameters& aParams);
nsresult Init(const char* aMimeType, uint32_t aFlags); nsresult Init(const char* aMimeType, uint32_t aFlags);