Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1996)

Unified Diff: cc/tiles/software_image_decode_controller.cc

Issue 1839833003: Add medium image quality to software predecode. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Using SkSize instead of SkMatrix, some renaming + comments. Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « cc/tiles/software_image_decode_controller.h ('k') | cc/tiles/software_image_decode_controller_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: cc/tiles/software_image_decode_controller.cc
diff --git a/cc/tiles/software_image_decode_controller.cc b/cc/tiles/software_image_decode_controller.cc
index c074af98857be59b59f895bd53b380b75ca746ea..9b05964c23072fe6d42dd004f209011de56cd60b 100644
--- a/cc/tiles/software_image_decode_controller.cc
+++ b/cc/tiles/software_image_decode_controller.cc
@@ -6,6 +6,7 @@
#include <stdint.h>
+#include <algorithm>
#include <functional>
#include "base/format_macros.h"
@@ -96,17 +97,65 @@ class ImageDecodeTaskImpl : public TileTask {
DISALLOW_COPY_AND_ASSIGN(ImageDecodeTaskImpl);
};
+// Most images are scaled from the source image's size to the target size.
+// But in the case of mipmaps, we are scaling from the mip level which is
+// larger than we need.
+// This function gets the scale of the mip level which will be used.
+SkSize GetMipMapScaleAdjustment(
+ const SoftwareImageDecodeController::ImageKey& key) {
+ gfx::Rect src_rect = key.src_rect();
+ int src_height = src_rect.height();
+ int src_width = src_rect.width();
+
+ int next_mip_height = src_height;
+ int next_mip_width = src_width;
+ for (int current_mip_level = 0;; current_mip_level++) {
+ int mip_height = next_mip_height;
+ int mip_width = next_mip_width;
+
+ next_mip_height = std::max(1, src_height / (1 << (current_mip_level + 1)));
+ next_mip_width = std::max(1, src_width / (1 << (current_mip_level + 1)));
+
+ // Check if an axis on the next mip level would be smaller than the target.
+ // If so, use the current mip level.
+ // This effectively always uses the larger image and always scales down.
+ if (next_mip_height < key.target_size().height() ||
+ next_mip_width < key.target_size().width()) {
ericrk 2016/04/23 00:25:48 I think this hits an edge case if you actually wan
cblume 2016/04/27 08:10:36 Done.
+ SkScalar y_scale = 1.f;
+ SkScalar x_scale = 1.f;
+ if (current_mip_level != 0) {
+ y_scale = static_cast<float>(mip_height) / src_height;
+ x_scale = static_cast<float>(mip_width) / src_width;
+ }
+
+ return SkSize::Make(x_scale, y_scale);
+ }
+
+ if (mip_height == 1 && mip_width == 1) {
+ // We have reached the final mip level
+ break;
+ }
+ }
+
+ return SkSize::Make(-1.f, -1.f);
+}
+
SkSize GetScaleAdjustment(const ImageDecodeControllerKey& key) {
// If the requested filter quality did not require scale, then the adjustment
// is identity.
- if (key.can_use_original_decode())
+ if (key.can_use_original_decode()) {
return SkSize::Make(1.f, 1.f);
-
- float x_scale =
- key.target_size().width() / static_cast<float>(key.src_rect().width());
- float y_scale =
- key.target_size().height() / static_cast<float>(key.src_rect().height());
- return SkSize::Make(x_scale, y_scale);
+ } else {
+ if (key.filter_quality() == kMedium_SkFilterQuality) {
+ return GetMipMapScaleAdjustment(key);
+ } else {
+ float x_scale = key.target_size().width() /
+ static_cast<float>(key.src_rect().width());
+ float y_scale = key.target_size().height() /
+ static_cast<float>(key.src_rect().height());
+ return SkSize::Make(x_scale, y_scale);
+ }
+ }
}
SkFilterQuality GetDecodedFilterQuality(const ImageDecodeControllerKey& key) {
@@ -173,25 +222,6 @@ bool SoftwareImageDecodeController::GetTaskForImageAndRef(
return false;
}
- // If we're not going to do a scale, we will just create a task to preroll the
- // image the first time we see it. This doesn't need to account for memory.
- // TODO(vmpstr): We can also lock the original sized image, in which case it
- // does require memory bookkeeping.
- if (!CanHandleImage(key)) {
- base::AutoLock lock(lock_);
- if (prerolled_images_.count(key.image_id()) == 0) {
- scoped_refptr<TileTask>& existing_task = pending_image_tasks_[key];
- if (!existing_task) {
- existing_task = make_scoped_refptr(
- new ImageDecodeTaskImpl(this, key, image, prepare_tiles_id));
- }
- *task = existing_task;
- } else {
- *task = nullptr;
- }
- return false;
- }
-
base::AutoLock lock(lock_);
// If we already have the image in cache, then we can return it.
@@ -263,7 +293,6 @@ void SoftwareImageDecodeController::UnrefImage(const DrawImage& image) {
// it yet (or failed to decode it).
// 2b. Unlock the image but keep it in list.
const ImageKey& key = ImageKey::FromDrawImage(image);
- DCHECK(CanHandleImage(key)) << key.ToString();
TRACE_EVENT1("disabled-by-default-cc.debug",
"SoftwareImageDecodeController::UnrefImage", "key",
key.ToString());
@@ -294,20 +323,6 @@ void SoftwareImageDecodeController::DecodeImage(const ImageKey& key,
const DrawImage& image) {
TRACE_EVENT1("cc", "SoftwareImageDecodeController::DecodeImage", "key",
key.ToString());
- if (!CanHandleImage(key)) {
- image.image()->preroll();
-
- base::AutoLock lock(lock_);
- prerolled_images_.insert(key.image_id());
- // Erase the pending task from the queue, since the task won't be doing
- // anything useful after this function terminates. Since we don't preroll
- // images twice, this is actually not necessary but it behaves similar to
- // the other code path: when this function finishes, the task isn't in the
- // pending_image_tasks_ list.
- pending_image_tasks_.erase(key);
- return;
- }
-
base::AutoLock lock(lock_);
AutoRemoveKeyFromTaskMap remove_key_from_task_map(&pending_image_tasks_, key);
@@ -364,6 +379,24 @@ void SoftwareImageDecodeController::DecodeImage(const ImageKey& key,
}
std::unique_ptr<SoftwareImageDecodeController::DecodedImage>
+SoftwareImageDecodeController::GetMediumQualityImageDecode(
+ const ImageKey& key,
+ const SkImage& image) {
+ SkSize mipmap_scale = GetMipMapScaleAdjustment(key);
+ // -1 represents an invalid scale.
+ // So add 1 and compare to epsilon.
vmpstr 2016/04/22 18:17:10 Comment is incorrect
cblume 2016/04/27 08:10:36 Done.
+ if (mipmap_scale.width() == -1.f || mipmap_scale.height() == -1.f) {
vmpstr 2016/04/22 18:17:10 I understand your reasoning, but I think changing
vmpstr 2016/04/25 18:27:21 Also... The situation in which this can happen is
cblume 2016/04/27 08:10:36 Done.
+ return nullptr;
+ }
+
+ DrawImage mip_image(
+ &image, gfx::RectToSkIRect(key.src_rect()), kMedium_SkFilterQuality,
+ SkMatrix::MakeScale(mipmap_scale.width(), mipmap_scale.height()));
+ auto mip_key = ImageKey::FromDrawImage(mip_image);
+ return GetScaledImageDecode(mip_key, image);
+}
+
+std::unique_ptr<SoftwareImageDecodeController::DecodedImage>
SoftwareImageDecodeController::DecodeImageInternal(
const ImageKey& key,
const DrawImage& draw_image) {
@@ -379,8 +412,7 @@ SoftwareImageDecodeController::DecodeImageInternal(
case kLow_SkFilterQuality:
return GetOriginalImageDecode(key, *image);
case kMedium_SkFilterQuality:
- NOTIMPLEMENTED();
- return nullptr;
+ return GetMediumQualityImageDecode(key, *image);
case kHigh_SkFilterQuality:
return GetScaledImageDecode(key, *image);
default:
@@ -399,9 +431,6 @@ DecodedDrawImage SoftwareImageDecodeController::GetDecodedImageForDraw(
if (key.target_size().IsEmpty())
return DecodedDrawImage(nullptr, kNone_SkFilterQuality);
- if (!CanHandleImage(key))
- return DecodedDrawImage(draw_image.image(), draw_image.filter_quality());
-
return GetDecodedImageForDrawInternal(key, draw_image);
}
@@ -577,8 +606,8 @@ SoftwareImageDecodeController::GetScaledImageDecode(const ImageKey& key,
}
SkPixmap scaled_pixmap(scaled_info, scaled_pixels->data(),
scaled_info.minRowBytes());
- // TODO(vmpstr): Start handling more than just high filter quality.
- DCHECK_EQ(kHigh_SkFilterQuality, key.filter_quality());
+ DCHECK(key.filter_quality() == kHigh_SkFilterQuality ||
+ key.filter_quality() == kMedium_SkFilterQuality);
{
TRACE_EVENT0("disabled-by-default-cc.debug",
"SoftwareImageDecodeController::ScaleImage - scale pixels");
@@ -605,7 +634,7 @@ void SoftwareImageDecodeController::DrawWithImageFinished(
"SoftwareImageDecodeController::DrawWithImageFinished", "key",
ImageKey::FromDrawImage(image).ToString());
ImageKey key = ImageKey::FromDrawImage(image);
- if (!decoded_image.image() || !CanHandleImage(key))
+ if (!decoded_image.image())
return;
if (decoded_image.is_at_raster_decode())
@@ -672,11 +701,6 @@ void SoftwareImageDecodeController::UnrefAtRasterImage(const ImageKey& key) {
}
}
-bool SoftwareImageDecodeController::CanHandleImage(const ImageKey& key) {
- // TODO(vmpstr): Start handling medium filter quality as well.
- return key.filter_quality() != kMedium_SkFilterQuality;
-}
-
void SoftwareImageDecodeController::ReduceCacheUsage() {
TRACE_EVENT0("cc", "SoftwareImageDecodeController::ReduceCacheUsage");
base::AutoLock lock(lock_);
« no previous file with comments | « cc/tiles/software_image_decode_controller.h ('k') | cc/tiles/software_image_decode_controller_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698