Implement the logic to kick off image decoding jobs for TileManager
BUG=163980 Review URL: https://chromiumcodereview.appspot.com/11453014 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@172813 0039d316-1c4b-4281-b951-d872f2087c98
This commit is contained in:
@ -7,8 +7,15 @@
|
||||
#include "cc/picture.h"
|
||||
#include "cc/rendering_stats.h"
|
||||
#include "third_party/skia/include/core/SkCanvas.h"
|
||||
#include "third_party/skia/include/core/SkData.h"
|
||||
#include "third_party/skia/include/utils/SkPictureUtils.h"
|
||||
#include "ui/gfx/rect_conversions.h"
|
||||
|
||||
namespace {
|
||||
// URI label for a lazily decoded SkPixelRef.
|
||||
const char labelLazyDecoded[] = "lazy";
|
||||
}
|
||||
|
||||
namespace cc {
|
||||
|
||||
scoped_refptr<Picture> Picture::Create(gfx::Rect layer_rect) {
|
||||
@ -89,4 +96,32 @@ void Picture::Raster(SkCanvas* canvas) {
|
||||
canvas->restore();
|
||||
}
|
||||
|
||||
void Picture::GatherPixelRefs(const gfx::Rect& rect,
|
||||
std::list<skia::LazyPixelRef*>& result) {
|
||||
DCHECK(picture_);
|
||||
SkData* pixel_refs = SkPictureUtils::GatherPixelRefs(
|
||||
picture_.get(), SkRect::MakeXYWH(rect.x(),
|
||||
rect.y(),
|
||||
rect.width(),
|
||||
rect.height()));
|
||||
if (!pixel_refs)
|
||||
return;
|
||||
|
||||
void* data = const_cast<void*>(pixel_refs->data());
|
||||
if (!data) {
|
||||
pixel_refs->unref();
|
||||
return;
|
||||
}
|
||||
|
||||
SkPixelRef** refs = reinterpret_cast<SkPixelRef**>(data);
|
||||
for (unsigned int i = 0; i < pixel_refs->size() / sizeof(SkPixelRef*); ++i) {
|
||||
if (*refs && (*refs)->getURI() && !strncmp(
|
||||
(*refs)->getURI(), labelLazyDecoded, 4)) {
|
||||
result.push_back(static_cast<skia::LazyPixelRef*>(*refs));
|
||||
}
|
||||
refs++;
|
||||
}
|
||||
pixel_refs->unref();
|
||||
}
|
||||
|
||||
} // namespace cc
|
||||
|
@ -5,11 +5,15 @@
|
||||
#ifndef CC_PICTURE_H_
|
||||
#define CC_PICTURE_H_
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "base/memory/ref_counted.h"
|
||||
#include "cc/cc_export.h"
|
||||
#include "skia/ext/lazy_pixel_ref.h"
|
||||
#include "skia/ext/refptr.h"
|
||||
#include "third_party/skia/include/core/SkPicture.h"
|
||||
#include "third_party/skia/include/core/SkPixelRef.h"
|
||||
#include "ui/gfx/rect.h"
|
||||
|
||||
namespace cc {
|
||||
@ -39,6 +43,9 @@ public:
|
||||
// Assumes contentsScale have already been applied.
|
||||
void Raster(SkCanvas* canvas);
|
||||
|
||||
void GatherPixelRefs(const gfx::Rect& rect,
|
||||
std::list<skia::LazyPixelRef*>&);
|
||||
|
||||
private:
|
||||
Picture(gfx::Rect layer_rect);
|
||||
// This constructor assumes SkPicture is already ref'd and transfers
|
||||
|
@ -79,4 +79,14 @@ void PicturePileImpl::Raster(
|
||||
rasterizeBeginTime).InSecondsF();
|
||||
}
|
||||
|
||||
void PicturePileImpl::GatherPixelRefs(
|
||||
const gfx::Rect& rect, std::list<skia::LazyPixelRef*>& pixel_refs) {
|
||||
std::list<skia::LazyPixelRef*> result;
|
||||
for (PicturePile::Pile::const_iterator i = pile_.begin();
|
||||
i != pile_.end(); ++i) {
|
||||
(*i)->GatherPixelRefs(rect, result);
|
||||
pixel_refs.splice(pixel_refs.end(), result);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace cc
|
||||
|
@ -5,6 +5,7 @@
|
||||
#ifndef CC_PICTURE_PILE_IMPL_H_
|
||||
#define CC_PICTURE_PILE_IMPL_H_
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
#include "base/basictypes.h"
|
||||
@ -38,6 +39,8 @@ public:
|
||||
float contents_scale,
|
||||
RenderingStats* stats);
|
||||
|
||||
void GatherPixelRefs(const gfx::Rect&, std::list<skia::LazyPixelRef*>&);
|
||||
|
||||
private:
|
||||
friend class PicturePile;
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "cc/tile_manager.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "base/command_line.h"
|
||||
@ -66,6 +67,16 @@ class RasterThread : public base::Thread {
|
||||
base::Bind(&RasterThread::RunReply, base::Unretained(this), reply));
|
||||
}
|
||||
|
||||
void PostImageDecodingTaskAndReply(const tracked_objects::Location& from_here,
|
||||
skia::LazyPixelRef* pixel_ref,
|
||||
const base::Closure& reply) {
|
||||
++num_pending_tasks_;
|
||||
message_loop_proxy()->PostTaskAndReply(
|
||||
from_here,
|
||||
base::Bind(&RunImageDecodeTask, base::Unretained(pixel_ref)),
|
||||
base::Bind(&RasterThread::RunReply, base::Unretained(this), reply));
|
||||
}
|
||||
|
||||
private:
|
||||
static void RunRasterTask(PicturePileImpl* picture_pile,
|
||||
uint8_t* mapped_buffer,
|
||||
@ -87,6 +98,11 @@ class RasterThread : public base::Thread {
|
||||
stats);
|
||||
}
|
||||
|
||||
static void RunImageDecodeTask(skia::LazyPixelRef* pixel_ref) {
|
||||
TRACE_EVENT0("cc", "RasterThread::RunImageDecodeTask");
|
||||
pixel_ref->Decode();
|
||||
}
|
||||
|
||||
void RunReply(const base::Closure& reply) {
|
||||
--num_pending_tasks_;
|
||||
reply.Run();
|
||||
@ -101,7 +117,8 @@ ManagedTileState::ManagedTileState()
|
||||
: can_use_gpu_memory(false),
|
||||
can_be_freed(true),
|
||||
resource_is_being_initialized(false),
|
||||
contents_swizzled(false) {
|
||||
contents_swizzled(false),
|
||||
need_to_gather_pixel_refs(true) {
|
||||
}
|
||||
|
||||
ManagedTileState::~ManagedTileState() {
|
||||
@ -284,7 +301,7 @@ void TileManager::ManageTiles() {
|
||||
AssignGpuMemoryToTiles();
|
||||
|
||||
// Finally, kick the rasterizer.
|
||||
DispatchMoreRasterTasks();
|
||||
DispatchMoreTasks();
|
||||
}
|
||||
|
||||
void TileManager::CheckForCompletedSetPixels() {
|
||||
@ -332,6 +349,15 @@ void TileManager::AssignGpuMemoryToTiles() {
|
||||
tiles_that_need_to_be_rasterized_.begin(),
|
||||
tiles_that_need_to_be_rasterized_.end());
|
||||
|
||||
// Record all the tiles in the image decoding list. A tile will not be
|
||||
// inserted to the rasterizer queue if it is waiting for image decoding.
|
||||
std::set<Tile*> image_decoding_tile_set;
|
||||
for (std::list<Tile*>::iterator it = tiles_with_image_decoding_tasks_.begin();
|
||||
it != tiles_with_image_decoding_tasks_.end(); ++it) {
|
||||
image_decoding_tile_set.insert(*it);
|
||||
}
|
||||
tiles_with_image_decoding_tasks_.clear();
|
||||
|
||||
size_t bytes_left = global_state_.memory_limit_in_bytes - unreleasable_bytes;
|
||||
for (TileVector::iterator it = tiles_.begin(); it != tiles_.end(); ++it) {
|
||||
Tile* tile = *it;
|
||||
@ -352,8 +378,12 @@ void TileManager::AssignGpuMemoryToTiles() {
|
||||
bytes_left -= tile_bytes;
|
||||
managed_tile_state.can_use_gpu_memory = true;
|
||||
if (!managed_tile_state.resource &&
|
||||
!managed_tile_state.resource_is_being_initialized)
|
||||
tiles_that_need_to_be_rasterized_.push_back(tile);
|
||||
!managed_tile_state.resource_is_being_initialized) {
|
||||
if (image_decoding_tile_set.end() != image_decoding_tile_set.find(tile))
|
||||
tiles_with_image_decoding_tasks_.push_back(tile);
|
||||
else
|
||||
tiles_that_need_to_be_rasterized_.push_back(tile);
|
||||
}
|
||||
}
|
||||
|
||||
// Reverse two tiles_that_need_* vectors such that pop_back gets
|
||||
@ -370,28 +400,125 @@ void TileManager::FreeResourcesForTile(Tile* tile) {
|
||||
resource_pool_->ReleaseResource(managed_tile_state.resource.Pass());
|
||||
}
|
||||
|
||||
void TileManager::DispatchMoreRasterTasks() {
|
||||
while (!tiles_that_need_to_be_rasterized_.empty()) {
|
||||
RasterThread* thread = 0;
|
||||
RasterThread* TileManager::GetFreeRasterThread() {
|
||||
RasterThread* thread = 0;
|
||||
for (RasterThreadVector::iterator it = raster_threads_.begin();
|
||||
it != raster_threads_.end(); ++it) {
|
||||
if ((*it)->num_pending_tasks() == kNumPendingRasterTasksPerThread)
|
||||
continue;
|
||||
// Check if this is the best thread we've found so far.
|
||||
if (!thread || (*it)->num_pending_tasks() < thread->num_pending_tasks())
|
||||
thread = *it;
|
||||
}
|
||||
return thread;
|
||||
}
|
||||
|
||||
for (RasterThreadVector::iterator it = raster_threads_.begin();
|
||||
it != raster_threads_.end(); ++it) {
|
||||
if ((*it)->num_pending_tasks() == kNumPendingRasterTasksPerThread)
|
||||
continue;
|
||||
// Check if this is the best thread we've found so far.
|
||||
if (!thread || (*it)->num_pending_tasks() < thread->num_pending_tasks())
|
||||
thread = *it;
|
||||
}
|
||||
|
||||
// Stop dispatching tasks when all threads are busy.
|
||||
if (!thread)
|
||||
void TileManager::DispatchMoreTasks() {
|
||||
// Because tiles in the image decoding list have higher priorities, we
|
||||
// need to process those tiles first before we start to handle the tiles
|
||||
// in the need_to_be_rasterized queue.
|
||||
std::list<Tile*>::iterator it = tiles_with_image_decoding_tasks_.begin();
|
||||
while (it != tiles_with_image_decoding_tasks_.end()) {
|
||||
DispatchImageDecodingTasksForTile(*it);
|
||||
ManagedTileState& managed_state = (*it)->managed_state();
|
||||
if (managed_state.pending_pixel_refs.empty()) {
|
||||
RasterThread* thread = GetFreeRasterThread();
|
||||
if (!thread)
|
||||
return;
|
||||
DispatchOneRasterTask(thread, *it);
|
||||
tiles_with_image_decoding_tasks_.erase(it++);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
DispatchOneRasterTask(thread, tiles_that_need_to_be_rasterized_.back());
|
||||
// Process all tiles in the need_to_be_rasterized queue. If a tile has
|
||||
// image decoding tasks, put it to the back of the image decoding list.
|
||||
while (!tiles_that_need_to_be_rasterized_.empty()) {
|
||||
Tile* tile = tiles_that_need_to_be_rasterized_.back();
|
||||
DispatchImageDecodingTasksForTile(tile);
|
||||
ManagedTileState& managed_state = tile->managed_state();
|
||||
if (!managed_state.pending_pixel_refs.empty()) {
|
||||
tiles_with_image_decoding_tasks_.push_back(tile);
|
||||
} else {
|
||||
RasterThread* thread = GetFreeRasterThread();
|
||||
if (!thread)
|
||||
return;
|
||||
DispatchOneRasterTask(thread, tile);
|
||||
}
|
||||
tiles_that_need_to_be_rasterized_.pop_back();
|
||||
}
|
||||
}
|
||||
|
||||
void TileManager::DispatchImageDecodingTasksForTile(Tile* tile) {
|
||||
ManagedTileState& managed_state = tile->managed_state();
|
||||
if (managed_state.need_to_gather_pixel_refs) {
|
||||
TRACE_EVENT0("cc",
|
||||
"TileManager::DispatchImageDecodingTaskForTile: Gather PixelRefs");
|
||||
const_cast<PicturePileImpl *>(tile->picture_pile())->GatherPixelRefs(
|
||||
tile->content_rect_, managed_state.pending_pixel_refs);
|
||||
managed_state.need_to_gather_pixel_refs = false;
|
||||
}
|
||||
|
||||
std::list<skia::LazyPixelRef*>& pending_pixel_refs =
|
||||
tile->managed_state().pending_pixel_refs;
|
||||
std::list<skia::LazyPixelRef*>::iterator it = pending_pixel_refs.begin();
|
||||
while (it != pending_pixel_refs.end()) {
|
||||
if (pending_decode_tasks_.end() != pending_decode_tasks_.find(
|
||||
(*it)->getGenerationID())) {
|
||||
++it;
|
||||
continue;
|
||||
}
|
||||
// TODO(qinmin): passing correct image size to PrepareToDecode().
|
||||
if ((*it)->PrepareToDecode(skia::LazyPixelRef::PrepareParams())) {
|
||||
pending_pixel_refs.erase(it++);
|
||||
} else {
|
||||
RasterThread* thread = GetFreeRasterThread();
|
||||
if (thread)
|
||||
DispatchOneImageDecodingTask(thread, tile, *it);
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TileManager::DispatchOneImageDecodingTask(RasterThread* thread,
|
||||
scoped_refptr<Tile> tile,
|
||||
skia::LazyPixelRef* pixel_ref) {
|
||||
TRACE_EVENT0("cc", "TileManager::DispatchOneImageDecodingTask");
|
||||
uint32_t pixel_ref_id = pixel_ref->getGenerationID();
|
||||
DCHECK(pending_decode_tasks_.end() ==
|
||||
pending_decode_tasks_.find(pixel_ref_id));
|
||||
pending_decode_tasks_[pixel_ref_id] = pixel_ref;
|
||||
|
||||
thread->PostImageDecodingTaskAndReply(
|
||||
FROM_HERE,
|
||||
pixel_ref,
|
||||
base::Bind(&TileManager::OnImageDecodingTaskCompleted,
|
||||
base::Unretained(this),
|
||||
tile,
|
||||
pixel_ref_id));
|
||||
}
|
||||
|
||||
void TileManager::OnImageDecodingTaskCompleted(scoped_refptr<Tile> tile,
|
||||
uint32_t pixel_ref_id) {
|
||||
TRACE_EVENT0("cc", "TileManager::OnImageDecoded");
|
||||
pending_decode_tasks_.erase(pixel_ref_id);
|
||||
|
||||
for (TileList::iterator it = tiles_with_image_decoding_tasks_.begin();
|
||||
it != tiles_with_image_decoding_tasks_.end(); ++it) {
|
||||
std::list<skia::LazyPixelRef*>& pixel_refs =
|
||||
(*it)->managed_state().pending_pixel_refs;
|
||||
for (std::list<skia::LazyPixelRef*>::iterator pixel_it =
|
||||
pixel_refs.begin(); pixel_it != pixel_refs.end(); ++pixel_it) {
|
||||
if (pixel_ref_id == (*pixel_it)->getGenerationID()) {
|
||||
pixel_refs.erase(pixel_it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
DispatchMoreTasks();
|
||||
}
|
||||
|
||||
void TileManager::DispatchOneRasterTask(
|
||||
RasterThread* thread, scoped_refptr<Tile> tile) {
|
||||
TRACE_EVENT0("cc", "TileManager::DispatchOneRasterTask");
|
||||
@ -446,7 +573,7 @@ void TileManager::OnRasterTaskCompleted(
|
||||
// tiles. The result of this could be that this tile is no longer
|
||||
// allowed to use gpu memory and in that case we need to abort
|
||||
// initialization and free all associated resources before calling
|
||||
// DispatchMoreRasterTasks().
|
||||
// DispatchMoreTasks().
|
||||
AssignGpuMemoryToTiles();
|
||||
|
||||
// Finish resource initialization if |can_use_gpu_memory| is true.
|
||||
@ -470,8 +597,7 @@ void TileManager::OnRasterTaskCompleted(
|
||||
resource_pool_->ReleaseResource(resource.Pass());
|
||||
managed_tile_state.resource_is_being_initialized = false;
|
||||
}
|
||||
|
||||
DispatchMoreRasterTasks();
|
||||
DispatchMoreTasks();
|
||||
}
|
||||
|
||||
void TileManager::DidFinishTileInitialization(Tile* tile) {
|
||||
|
@ -5,9 +5,11 @@
|
||||
#ifndef CC_TILE_MANAGER_H_
|
||||
#define CC_TILE_MANAGER_H_
|
||||
|
||||
#include <list>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
|
||||
#include "base/hash_tables.h"
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "base/values.h"
|
||||
#include "cc/resource_pool.h"
|
||||
@ -53,6 +55,8 @@ class CC_EXPORT ManagedTileState {
|
||||
scoped_ptr<ResourcePool::Resource> resource;
|
||||
bool resource_is_being_initialized;
|
||||
bool contents_swizzled;
|
||||
bool need_to_gather_pixel_refs;
|
||||
std::list<skia::LazyPixelRef*> pending_pixel_refs;
|
||||
|
||||
// Ephemeral state, valid only during Manage.
|
||||
TileManagerBin bin;
|
||||
@ -91,7 +95,7 @@ class CC_EXPORT TileManager {
|
||||
void FreeResourcesForTile(Tile*);
|
||||
void ScheduleManageTiles();
|
||||
void ScheduleCheckForCompletedSetPixels();
|
||||
void DispatchMoreRasterTasks();
|
||||
void DispatchMoreTasks();
|
||||
void DispatchOneRasterTask(RasterThread*, scoped_refptr<Tile>);
|
||||
void OnRasterTaskCompleted(
|
||||
scoped_refptr<Tile>,
|
||||
@ -99,6 +103,11 @@ class CC_EXPORT TileManager {
|
||||
scoped_refptr<PicturePileImpl>,
|
||||
RenderingStats*);
|
||||
void DidFinishTileInitialization(Tile*);
|
||||
void DispatchImageDecodingTasksForTile(Tile*);
|
||||
void OnImageDecodingTaskCompleted(scoped_refptr<Tile>, uint32_t);
|
||||
void DispatchOneImageDecodingTask(
|
||||
RasterThread*, scoped_refptr<Tile>, skia::LazyPixelRef*);
|
||||
RasterThread* GetFreeRasterThread();
|
||||
|
||||
TileManagerClient* client_;
|
||||
scoped_ptr<ResourcePool> resource_pool_;
|
||||
@ -111,6 +120,14 @@ class CC_EXPORT TileManager {
|
||||
TileVector tiles_;
|
||||
TileVector tiles_that_need_to_be_rasterized_;
|
||||
|
||||
typedef std::list<Tile*> TileList;
|
||||
// Tiles with image decoding tasks. These tiles need to be rasterized
|
||||
// when all the image decoding tasks finish.
|
||||
TileList tiles_with_image_decoding_tasks_;
|
||||
|
||||
typedef base::hash_map<uint32_t, skia::LazyPixelRef*> PixelRefMap;
|
||||
PixelRefMap pending_decode_tasks_;
|
||||
|
||||
typedef std::queue<scoped_refptr<Tile> > TileQueue;
|
||||
TileQueue tiles_with_pending_set_pixels_;
|
||||
|
||||
|
@ -136,7 +136,7 @@
|
||||
'../third_party/skia/src/utils/SkNullCanvas.cpp',
|
||||
'../third_party/skia/include/utils/SkNWayCanvas.h',
|
||||
'../third_party/skia/src/utils/SkNWayCanvas.cpp',
|
||||
|
||||
'../third_party/skia/src/utils/SkPictureUtils.cpp',
|
||||
'../third_party/skia/include/pdf/SkPDFDevice.h',
|
||||
'../third_party/skia/include/pdf/SkPDFDocument.h',
|
||||
|
||||
@ -151,7 +151,7 @@
|
||||
'../third_party/skia/include/images/SkPageFlipper.h',
|
||||
|
||||
'../third_party/skia/include/utils/SkNullCanvas.h',
|
||||
|
||||
'../third_party/skia/include/utils/SkPictureUtils.h',
|
||||
'ext/bitmap_platform_device.h',
|
||||
'ext/bitmap_platform_device_android.cc',
|
||||
'ext/bitmap_platform_device_android.h',
|
||||
|
Reference in New Issue
Block a user