Commit 74522773 authored by Eric Karl's avatar Eric Karl Committed by Commit Bot

Revert "Remove use of DeferredTextureImageData APIs and Support Decode to Scale"

This reverts commit 86c790e6.

Reason for revert: This is causing performance / memory regressions that are trickier to address than expected. Reverting this for now.

Original change's description:
> Remove use of DeferredTextureImageData APIs and Support Decode to Scale
> 
> We aren't benefitting from the complexity added by the
> DeferredTextureImageData APIs, and this API blocks us from using
> PaintImage::Decode's decode-to-scale functionality.
> 
> This change removes our usage of DeferredTextureImageData APIs,
> instead using SkImage::makeTextureImage to handle upload. Additionally,
> we now use the PaintImage::Decode API, adding decode-to-scale support.
> 
> Bug: 773799
> Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel
> Change-Id: Ia5f480213c3a5c8225ccd289aa2c081056840f94
> Reviewed-on: https://chromium-review.googlesource.com/713593
> Reviewed-by: vmpstr <vmpstr@chromium.org>
> Commit-Queue: Eric Karl <ericrk@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#517206}

TBR=vmpstr@chromium.org,ericrk@chromium.org

# Not skipping CQ checks because original CL landed > 1 day ago.

Bug: 773799
Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel;master.tryserver.chromium.android:android_optional_gpu_tests_rel
Change-Id: Ie4493559e334100f03dfed1dfb7a408fc26a33e0
Reviewed-on: https://chromium-review.googlesource.com/830587
Commit-Queue: Eric Karl <ericrk@chromium.org>
Reviewed-by: default avatarEric Karl <ericrk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#524613}
parent 9161f6b9
...@@ -161,6 +161,9 @@ class CC_PAINT_EXPORT PaintImage { ...@@ -161,6 +161,9 @@ class CC_PAINT_EXPORT PaintImage {
// Returns the total number of frames known to exist in this image. // Returns the total number of frames known to exist in this image.
size_t FrameCount() const; size_t FrameCount() const;
// Returns an SkImage for the frame at |index|.
sk_sp<SkImage> GetSkImageForFrame(size_t index) const;
std::string ToString() const; std::string ToString() const;
private: private:
...@@ -179,9 +182,6 @@ class CC_PAINT_EXPORT PaintImage { ...@@ -179,9 +182,6 @@ class CC_PAINT_EXPORT PaintImage {
void CreateSkImage(); void CreateSkImage();
PaintImage MakeSubset(const gfx::Rect& subset) const; PaintImage MakeSubset(const gfx::Rect& subset) const;
// Returns an SkImage for the frame at |index|.
sk_sp<SkImage> GetSkImageForFrame(size_t index) const;
sk_sp<SkImage> sk_image_; sk_sp<SkImage> sk_image_;
sk_sp<PaintRecord> paint_record_; sk_sp<PaintRecord> paint_record_;
......
...@@ -126,61 +126,36 @@ gfx::Size CalculateSizeForMipLevel(const DrawImage& draw_image, int mip_level) { ...@@ -126,61 +126,36 @@ gfx::Size CalculateSizeForMipLevel(const DrawImage& draw_image, int mip_level) {
} }
// Draws and scales the provided |draw_image| into the |target_pixmap|. If the // Draws and scales the provided |draw_image| into the |target_pixmap|. If the
// draw/scale can be done directly, calls directly into PaintImage::Decode. // draw/scale can be done directly, calls directly into SkImage::scalePixels,
// if not, decodes to a compatible temporary pixmap and then converts that into // if not, decodes to a compatible temporary pixmap and then converts that into
// the |target_pixmap|. // the |target_pixmap|.
bool DrawAndScaleImage(const DrawImage& draw_image, SkPixmap* target_pixmap) { bool DrawAndScaleImage(const DrawImage& draw_image, SkPixmap* target_pixmap) {
// We don't want to perform any color conversion here, so create a new pixmap sk_sp<SkImage> image =
// with a null colorspace that shares |target_pixmap|'s memory. draw_image.paint_image().GetSkImageForFrame(draw_image.frame_index());
SkPixmap pixmap(target_pixmap->info().makeColorSpace(nullptr), if (image->dimensions() == target_pixmap->bounds().size() ||
target_pixmap->writable_addr(), target_pixmap->rowBytes()); target_pixmap->info().colorType() == kN32_SkColorType) {
// If no scaling is occurring, or if the target colortype is already N32,
const PaintImage& paint_image = draw_image.paint_image(); // just scale directly.
SkISize supported_size = return image->scalePixels(*target_pixmap,
paint_image.GetSupportedDecodeSize(pixmap.bounds().size()); CalculateDesiredFilterQuality(draw_image),
SkImage::kDisallow_CachingHint);
if (supported_size == pixmap.bounds().size()) { }
SkImageInfo info = pixmap.info();
return paint_image.Decode(pixmap.writable_addr(), &info, nullptr, // If the target colortype is not N32, it may be impossible to scale
draw_image.frame_index()); // directly. Instead scale into an N32 pixmap, and convert that into the
} // |target_pixmap|.
SkImageInfo decode_info =
// If we can't decode/scale directly, we will handle this in up to 3 steps. target_pixmap->info().makeColorType(kN32_SkColorType);
// Step 1: Decode at the nearest (larger) directly supported size.
SkImageInfo decode_info = SkImageInfo::MakeN32Premul(supported_size.width(),
supported_size.height());
SkBitmap decode_bitmap; SkBitmap decode_bitmap;
if (!decode_bitmap.tryAllocPixels(decode_info)) if (!decode_bitmap.tryAllocPixels(decode_info))
return false; return false;
SkPixmap decode_pixmap(decode_bitmap.info(), decode_bitmap.getPixels(), SkPixmap decode_pixmap(decode_bitmap.info(), decode_bitmap.getPixels(),
decode_bitmap.rowBytes()); decode_bitmap.rowBytes());
if (!paint_image.Decode(decode_pixmap.writable_addr(), &decode_info, nullptr, if (!image->scalePixels(decode_pixmap,
draw_image.frame_index())) { CalculateDesiredFilterQuality(draw_image),
return false; SkImage::kDisallow_CachingHint))
}
// Step 2a: Scale to |pixmap| directly if kN32_SkColorType.
if (pixmap.info().colorType() == kN32_SkColorType) {
return decode_pixmap.scalePixels(pixmap,
CalculateDesiredFilterQuality(draw_image));
}
// Step 2b: Scale to temporary pixmap of kN32_SkColorType.
SkImageInfo scaled_info = pixmap.info().makeColorType(kN32_SkColorType);
SkBitmap scaled_bitmap;
if (!scaled_bitmap.tryAllocPixels(scaled_info))
return false;
SkPixmap scaled_pixmap(scaled_bitmap.info(), scaled_bitmap.getPixels(),
scaled_bitmap.rowBytes());
if (!decode_pixmap.scalePixels(scaled_pixmap,
CalculateDesiredFilterQuality(draw_image))) {
return false; return false;
} return decode_pixmap.readPixels(*target_pixmap);
// Step 3: Copy the temporary scaled pixmap to |pixmap|, performing
// color type conversion. We can't do the color conversion in step 1, as
// the scale in step 2 must happen in kN32_SkColorType.
return scaled_pixmap.readPixels(pixmap);
} }
// Returns the GL texture ID backing the given SkImage. // Returns the GL texture ID backing the given SkImage.
...@@ -408,23 +383,16 @@ void GpuImageDecodeCache::DecodedImageData::Unlock() { ...@@ -408,23 +383,16 @@ void GpuImageDecodeCache::DecodedImageData::Unlock() {
void GpuImageDecodeCache::DecodedImageData::SetLockedData( void GpuImageDecodeCache::DecodedImageData::SetLockedData(
std::unique_ptr<base::DiscardableMemory> data, std::unique_ptr<base::DiscardableMemory> data,
sk_sp<SkImage> image,
bool out_of_raster) { bool out_of_raster) {
DCHECK(data); DCHECK(data);
DCHECK(!data_); DCHECK(!data_);
DCHECK(image);
DCHECK(!image_);
data_ = std::move(data); data_ = std::move(data);
image_ = std::move(image);
OnSetLockedData(out_of_raster); OnSetLockedData(out_of_raster);
} }
void GpuImageDecodeCache::DecodedImageData::ResetData() { void GpuImageDecodeCache::DecodedImageData::ResetData() {
if (data_) { if (data_)
DCHECK(image_);
ReportUsageStats(); ReportUsageStats();
}
image_ = nullptr;
data_ = nullptr; data_ = nullptr;
OnResetData(); OnResetData();
} }
...@@ -476,13 +444,11 @@ GpuImageDecodeCache::ImageData::ImageData( ...@@ -476,13 +444,11 @@ GpuImageDecodeCache::ImageData::ImageData(
DecodedDataMode mode, DecodedDataMode mode,
size_t size, size_t size,
const gfx::ColorSpace& target_color_space, const gfx::ColorSpace& target_color_space,
SkFilterQuality quality, const SkImage::DeferredTextureImageUsageParams& upload_params)
int mip_level)
: mode(mode), : mode(mode),
size(size), size(size),
target_color_space(target_color_space), target_color_space(target_color_space),
quality(quality), upload_params(upload_params) {}
mip_level(mip_level) {}
GpuImageDecodeCache::ImageData::~ImageData() { GpuImageDecodeCache::ImageData::~ImageData() {
// We should never delete ImageData while it is in use or before it has been // We should never delete ImageData while it is in use or before it has been
...@@ -502,11 +468,12 @@ GpuImageDecodeCache::GpuImageDecodeCache(viz::ContextProvider* context, ...@@ -502,11 +468,12 @@ GpuImageDecodeCache::GpuImageDecodeCache(viz::ContextProvider* context,
context_(context), context_(context),
persistent_cache_(PersistentCache::NO_AUTO_EVICT), persistent_cache_(PersistentCache::NO_AUTO_EVICT),
max_working_set_bytes_(max_working_set_bytes) { max_working_set_bytes_(max_working_set_bytes) {
// Acquire the context_lock so that we can safely retrieve // Acquire the context_lock so that we can safely retrieve the
// |max_texture_size_|. // GrContextThreadSafeProxy. This proxy can then be used with no lock held.
{ {
viz::ContextProvider::ScopedContextLock context_lock(context_); viz::ContextProvider::ScopedContextLock context_lock(context_);
max_texture_size_ = context_->GrContext()->caps()->maxTextureSize(); context_threadsafe_proxy_ = sk_sp<GrContextThreadSafeProxy>(
context_->GrContext()->threadSafeProxy());
} }
// In certain cases, ThreadTaskRunnerHandle isn't set (Android Webview). // In certain cases, ThreadTaskRunnerHandle isn't set (Android Webview).
...@@ -686,8 +653,8 @@ DecodedDrawImage GpuImageDecodeCache::GetDecodedImageForDraw( ...@@ -686,8 +653,8 @@ DecodedDrawImage GpuImageDecodeCache::GetDecodedImageForDraw(
image_data->upload.mark_used(); image_data->upload.mark_used();
DCHECK(image || image_data->decode.decode_failure); DCHECK(image || image_data->decode.decode_failure);
SkSize scale_factor = SkSize scale_factor = CalculateScaleFactorForMipLevel(
CalculateScaleFactorForMipLevel(draw_image, image_data->mip_level); draw_image, image_data->upload_params.fPreScaleMipLevel);
DecodedDrawImage decoded_draw_image( DecodedDrawImage decoded_draw_image(
std::move(image), SkSize(), scale_factor, std::move(image), SkSize(), scale_factor,
CalculateDesiredFilterQuality(draw_image)); CalculateDesiredFilterQuality(draw_image));
...@@ -1230,43 +1197,65 @@ void GpuImageDecodeCache::DecodeImageIfNecessary(const DrawImage& draw_image, ...@@ -1230,43 +1197,65 @@ void GpuImageDecodeCache::DecodeImageIfNecessary(const DrawImage& draw_image,
} }
TRACE_EVENT0("cc", "GpuImageDecodeCache::DecodeImage"); TRACE_EVENT0("cc", "GpuImageDecodeCache::DecodeImage");
RecordImageMipLevelUMA(image_data->mip_level); RecordImageMipLevelUMA(image_data->upload_params.fPreScaleMipLevel);
image_data->decode.ResetData(); image_data->decode.ResetData();
std::unique_ptr<base::DiscardableMemory> backing_memory; std::unique_ptr<base::DiscardableMemory> backing_memory;
sk_sp<SkImage> image;
{ {
base::AutoUnlock unlock(lock_); base::AutoUnlock unlock(lock_);
backing_memory = base::DiscardableMemoryAllocator::GetInstance() backing_memory = base::DiscardableMemoryAllocator::GetInstance()
->AllocateLockedDiscardableMemory(image_data->size); ->AllocateLockedDiscardableMemory(image_data->size);
SkImageInfo image_info =
CreateImageInfoForDrawImage(draw_image, image_data->mip_level); switch (image_data->mode) {
SkPixmap pixmap(image_info, backing_memory->data(), case DecodedDataMode::CPU: {
image_info.minRowBytes()); SkImageInfo image_info = CreateImageInfoForDrawImage(
if (!DrawAndScaleImage(draw_image, &pixmap)) { draw_image, image_data->upload_params.fPreScaleMipLevel);
DLOG(ERROR) << "DrawAndScaleImage failed."; // In order to match GPU scaling quality (which uses mip-maps at high
// quality), we want to use at most medium filter quality for the
// scale.
SkPixmap image_pixmap(image_info.makeColorSpace(nullptr),
backing_memory->data(), image_info.minRowBytes());
// Note that scalePixels falls back to readPixels if the scale is 1x, so
// no need to special case that as an optimization.
if (!DrawAndScaleImage(draw_image, &image_pixmap)) {
DLOG(ERROR) << "scalePixels failed.";
backing_memory->Unlock(); backing_memory->Unlock();
backing_memory.reset(); backing_memory.reset();
} else { }
image = break;
SkImage::MakeFromRaster(pixmap, [](const void*, void*) {}, nullptr); }
case DecodedDataMode::GPU: {
// TODO(crbug.com/649167): Params should not have changed since initial
// sizing. Somehow this still happens. We should investigate and re-add
// DCHECKs here to enforce this.
sk_sp<SkImage> image = draw_image.paint_image().GetSkImageForFrame(
draw_image.frame_index());
if (!image->getDeferredTextureImageData(
*context_threadsafe_proxy_.get(), &image_data->upload_params, 1,
backing_memory->data(), nullptr, color_type_)) {
DLOG(ERROR) << "getDeferredTextureImageData failed despite params "
<< "having validated.";
backing_memory->Unlock();
backing_memory.reset();
}
break;
}
} }
} }
if (image_data->decode.data()) { if (image_data->decode.data()) {
DCHECK(image_data->decode.image());
// An at-raster task decoded this before us. Ingore our decode. // An at-raster task decoded this before us. Ingore our decode.
return; return;
} }
if (!backing_memory) { if (!backing_memory) {
DCHECK(!image);
// If |backing_memory| was not populated, we had a non-decodable image. // If |backing_memory| was not populated, we had a non-decodable image.
image_data->decode.decode_failure = true; image_data->decode.decode_failure = true;
return; return;
} }
image_data->decode.SetLockedData(std::move(backing_memory), std::move(image), image_data->decode.SetLockedData(std::move(backing_memory),
task_type == TaskType::kOutOfRaster); task_type == TaskType::kOutOfRaster);
} }
...@@ -1296,11 +1285,26 @@ void GpuImageDecodeCache::UploadImageIfNecessary(const DrawImage& draw_image, ...@@ -1296,11 +1285,26 @@ void GpuImageDecodeCache::UploadImageIfNecessary(const DrawImage& draw_image,
DCHECK_GT(image_data->decode.ref_count, 0u); DCHECK_GT(image_data->decode.ref_count, 0u);
DCHECK_GT(image_data->upload.ref_count, 0u); DCHECK_GT(image_data->upload.ref_count, 0u);
sk_sp<SkImage> uploaded_image = image_data->decode.image(); sk_sp<SkImage> uploaded_image;
if (image_data->mode == DecodedDataMode::GPU) { {
base::AutoUnlock unlock(lock_); base::AutoUnlock unlock(lock_);
switch (image_data->mode) {
case DecodedDataMode::CPU: {
SkImageInfo image_info = CreateImageInfoForDrawImage(
draw_image, image_data->upload_params.fPreScaleMipLevel);
SkPixmap pixmap(image_info, image_data->decode.data()->data(),
image_info.minRowBytes());
uploaded_image = uploaded_image =
uploaded_image->makeTextureImage(context_->GrContext(), nullptr); SkImage::MakeFromRaster(pixmap, [](const void*, void*) {}, nullptr);
break;
}
case DecodedDataMode::GPU: {
uploaded_image = SkImage::MakeFromDeferredTextureImageData(
context_->GrContext(), image_data->decode.data()->data(),
SkBudgeted::kNo);
break;
}
}
} }
image_data->decode.mark_used(); image_data->decode.mark_used();
...@@ -1345,22 +1349,30 @@ GpuImageDecodeCache::CreateImageData(const DrawImage& draw_image) { ...@@ -1345,22 +1349,30 @@ GpuImageDecodeCache::CreateImageData(const DrawImage& draw_image) {
"GpuImageDecodeCache::CreateImageData"); "GpuImageDecodeCache::CreateImageData");
lock_.AssertAcquired(); lock_.AssertAcquired();
int mip_level = CalculateUploadScaleMipLevel(draw_image);
SkImageInfo image_info = CreateImageInfoForDrawImage(draw_image, mip_level);
DecodedDataMode mode; DecodedDataMode mode;
if (image_info.width() > max_texture_size_ || int upload_scale_mip_level = CalculateUploadScaleMipLevel(draw_image);
image_info.height() > max_texture_size_) { // TODO(ericrk): Remove the matrix parameter in this call.
// Image too large to upload. Try to use SW fallback. auto params = SkImage::DeferredTextureImageUsageParams(
SkMatrix::I(), CalculateDesiredFilterQuality(draw_image),
upload_scale_mip_level);
sk_sp<SkImage> image =
draw_image.paint_image().GetSkImageForFrame(draw_image.frame_index());
size_t data_size = image->getDeferredTextureImageData(
*context_threadsafe_proxy_.get(), &params, 1, nullptr, nullptr,
color_type_);
if (data_size == 0) {
// Can't upload image, too large or other failure. Try to use SW fallback.
SkImageInfo image_info =
CreateImageInfoForDrawImage(draw_image, upload_scale_mip_level);
data_size = image_info.computeMinByteSize();
mode = DecodedDataMode::CPU; mode = DecodedDataMode::CPU;
} else { } else {
mode = DecodedDataMode::GPU; mode = DecodedDataMode::GPU;
} }
size_t data_size = image_info.computeMinByteSize(); return base::MakeRefCounted<ImageData>(
return base::WrapRefCounted( mode, data_size, draw_image.target_color_space(), params);
new ImageData(mode, data_size, draw_image.target_color_space(),
CalculateDesiredFilterQuality(draw_image), mip_level));
} }
void GpuImageDecodeCache::DeleteImage(ImageData* image_data) { void GpuImageDecodeCache::DeleteImage(ImageData* image_data) {
...@@ -1417,7 +1429,7 @@ SkImageInfo GpuImageDecodeCache::CreateImageInfoForDrawImage( ...@@ -1417,7 +1429,7 @@ SkImageInfo GpuImageDecodeCache::CreateImageInfoForDrawImage(
CalculateSizeForMipLevel(draw_image, upload_scale_mip_level); CalculateSizeForMipLevel(draw_image, upload_scale_mip_level);
return SkImageInfo::Make(mip_size.width(), mip_size.height(), color_type_, return SkImageInfo::Make(mip_size.width(), mip_size.height(), color_type_,
kPremul_SkAlphaType, kPremul_SkAlphaType,
sk_ref_sp(draw_image.paint_image().color_space())); draw_image.target_color_space().ToSkColorSpace());
} }
bool GpuImageDecodeCache::TryLockImage(HaveContextLock have_context_lock, bool GpuImageDecodeCache::TryLockImage(HaveContextLock have_context_lock,
...@@ -1490,11 +1502,11 @@ GpuImageDecodeCache::ImageData* GpuImageDecodeCache::GetImageDataForDrawImage( ...@@ -1490,11 +1502,11 @@ GpuImageDecodeCache::ImageData* GpuImageDecodeCache::GetImageDataForDrawImage(
// the provided |draw_image|. // the provided |draw_image|.
bool GpuImageDecodeCache::IsCompatible(const ImageData* image_data, bool GpuImageDecodeCache::IsCompatible(const ImageData* image_data,
const DrawImage& draw_image) const { const DrawImage& draw_image) const {
bool is_scaled = image_data->mip_level != 0; bool is_scaled = image_data->upload_params.fPreScaleMipLevel != 0;
bool scale_is_compatible = bool scale_is_compatible = CalculateUploadScaleMipLevel(draw_image) >=
CalculateUploadScaleMipLevel(draw_image) >= image_data->mip_level; image_data->upload_params.fPreScaleMipLevel;
bool quality_is_compatible = bool quality_is_compatible = CalculateDesiredFilterQuality(draw_image) <=
CalculateDesiredFilterQuality(draw_image) <= image_data->quality; image_data->upload_params.fQuality;
bool color_is_compatible = bool color_is_compatible =
image_data->target_color_space == draw_image.target_color_space(); image_data->target_color_space == draw_image.target_color_space();
if (!color_is_compatible) if (!color_is_compatible)
......
...@@ -203,14 +203,9 @@ class CC_EXPORT GpuImageDecodeCache ...@@ -203,14 +203,9 @@ class CC_EXPORT GpuImageDecodeCache
void Unlock(); void Unlock();
void SetLockedData(std::unique_ptr<base::DiscardableMemory> data, void SetLockedData(std::unique_ptr<base::DiscardableMemory> data,
sk_sp<SkImage> image,
bool out_of_raster); bool out_of_raster);
void ResetData(); void ResetData();
base::DiscardableMemory* data() const { return data_.get(); } base::DiscardableMemory* data() const { return data_.get(); }
sk_sp<SkImage> image() const {
DCHECK(is_locked());
return image_;
}
bool decode_failure = false; bool decode_failure = false;
// Similar to |task|, but only is generated if there is no associated upload // Similar to |task|, but only is generated if there is no associated upload
...@@ -221,7 +216,6 @@ class CC_EXPORT GpuImageDecodeCache ...@@ -221,7 +216,6 @@ class CC_EXPORT GpuImageDecodeCache
void ReportUsageStats() const; void ReportUsageStats() const;
std::unique_ptr<base::DiscardableMemory> data_; std::unique_ptr<base::DiscardableMemory> data_;
sk_sp<SkImage> image_;
}; };
// Stores the GPU-side image and supporting fields. // Stores the GPU-side image and supporting fields.
...@@ -249,15 +243,13 @@ class CC_EXPORT GpuImageDecodeCache ...@@ -249,15 +243,13 @@ class CC_EXPORT GpuImageDecodeCache
ImageData(DecodedDataMode mode, ImageData(DecodedDataMode mode,
size_t size, size_t size,
const gfx::ColorSpace& target_color_space, const gfx::ColorSpace& target_color_space,
SkFilterQuality quality, const SkImage::DeferredTextureImageUsageParams& upload_params);
int mip_level);
const DecodedDataMode mode; const DecodedDataMode mode;
const size_t size; const size_t size;
gfx::ColorSpace target_color_space; gfx::ColorSpace target_color_space;
SkFilterQuality quality;
int mip_level;
bool is_at_raster = false; bool is_at_raster = false;
SkImage::DeferredTextureImageUsageParams upload_params;
// If true, this image is no longer in our |persistent_cache_| and will be // If true, this image is no longer in our |persistent_cache_| and will be
// deleted as soon as its ref count reaches zero. // deleted as soon as its ref count reaches zero.
...@@ -381,7 +373,7 @@ class CC_EXPORT GpuImageDecodeCache ...@@ -381,7 +373,7 @@ class CC_EXPORT GpuImageDecodeCache
const SkColorType color_type_; const SkColorType color_type_;
viz::ContextProvider* context_; viz::ContextProvider* context_;
int max_texture_size_ = 0; sk_sp<GrContextThreadSafeProxy> context_threadsafe_proxy_;
// All members below this point must only be accessed while holding |lock_|. // All members below this point must only be accessed while holding |lock_|.
// The exception are const members like |normal_max_cache_bytes_| that can // The exception are const members like |normal_max_cache_bytes_| that can
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment