Index: cc/resources/texture_uploader.cc |
diff --git a/cc/resources/texture_uploader.cc b/cc/resources/texture_uploader.cc |
deleted file mode 100644 |
index 601fa8fbff89de41c26075cf1be5d97dff61fdd3..0000000000000000000000000000000000000000 |
--- a/cc/resources/texture_uploader.cc |
+++ /dev/null |
@@ -1,315 +0,0 @@ |
-// Copyright 2014 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "cc/resources/texture_uploader.h" |
- |
-#include <algorithm> |
-#include <vector> |
- |
-#include "base/metrics/histogram.h" |
-#include "base/trace_event/trace_event.h" |
-#include "cc/base/util.h" |
-#include "cc/resources/resource.h" |
-#include "gpu/GLES2/gl2extchromium.h" |
-#include "gpu/command_buffer/client/gles2_interface.h" |
-#include "third_party/khronos/GLES2/gl2.h" |
-#include "third_party/khronos/GLES2/gl2ext.h" |
-#include "ui/gfx/geometry/rect.h" |
-#include "ui/gfx/geometry/vector2d.h" |
- |
-using gpu::gles2::GLES2Interface; |
- |
-namespace { |
- |
-// How many previous uploads to use when predicting future throughput. |
-static const size_t kUploadHistorySizeMax = 1000; |
-static const size_t kUploadHistorySizeInitial = 100; |
- |
-// Global estimated number of textures per second to maintain estimates across |
-// subsequent instances of TextureUploader. |
-// More than one thread will not access this variable, so we do not need to |
-// synchronize access. |
-static const double kDefaultEstimatedTexturesPerSecond = 48.0 * 60.0; |
- |
-// Flush interval when performing texture uploads. |
-static const size_t kTextureUploadFlushPeriod = 4; |
- |
-} // anonymous namespace |
- |
-namespace cc { |
- |
-TextureUploader::Query::Query(GLES2Interface* gl) |
- : gl_(gl), |
- query_id_(0), |
- value_(0), |
- has_value_(false), |
- is_non_blocking_(false) { |
- gl_->GenQueriesEXT(1, &query_id_); |
-} |
- |
-TextureUploader::Query::~Query() { gl_->DeleteQueriesEXT(1, &query_id_); } |
- |
-void TextureUploader::Query::Begin() { |
- has_value_ = false; |
- is_non_blocking_ = false; |
- gl_->BeginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM, query_id_); |
-} |
- |
-void TextureUploader::Query::End() { |
- gl_->EndQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM); |
-} |
- |
-bool TextureUploader::Query::IsPending() { |
- unsigned available = 1; |
- gl_->GetQueryObjectuivEXT( |
- query_id_, GL_QUERY_RESULT_AVAILABLE_EXT, &available); |
- return !available; |
-} |
- |
-unsigned TextureUploader::Query::Value() { |
- if (!has_value_) { |
- gl_->GetQueryObjectuivEXT(query_id_, GL_QUERY_RESULT_EXT, &value_); |
- has_value_ = true; |
- } |
- return value_; |
-} |
- |
-TextureUploader::TextureUploader(GLES2Interface* gl) |
- : gl_(gl), |
- num_blocking_texture_uploads_(0), |
- sub_image_size_(0), |
- num_texture_uploads_since_last_flush_(0) { |
- for (size_t i = kUploadHistorySizeInitial; i > 0; i--) |
- textures_per_second_history_.insert(kDefaultEstimatedTexturesPerSecond); |
-} |
- |
-TextureUploader::~TextureUploader() {} |
- |
-size_t TextureUploader::NumBlockingUploads() { |
- ProcessQueries(); |
- return num_blocking_texture_uploads_; |
-} |
- |
-void TextureUploader::MarkPendingUploadsAsNonBlocking() { |
- for (ScopedPtrDeque<Query>::iterator it = pending_queries_.begin(); |
- it != pending_queries_.end(); |
- ++it) { |
- if ((*it)->is_non_blocking()) |
- continue; |
- |
- num_blocking_texture_uploads_--; |
- (*it)->mark_as_non_blocking(); |
- } |
- |
- DCHECK(!num_blocking_texture_uploads_); |
-} |
- |
-double TextureUploader::EstimatedTexturesPerSecond() { |
- ProcessQueries(); |
- |
- // Use the median as our estimate. |
- std::multiset<double>::iterator median = textures_per_second_history_.begin(); |
- std::advance(median, textures_per_second_history_.size() / 2); |
- return *median; |
-} |
- |
-void TextureUploader::BeginQuery() { |
- // Check to see if any of the pending queries are free before allocating a |
- // new one. If this is not done, queries may be allocated without bound. |
- // http://crbug.com/398072 |
- if (available_queries_.empty()) |
- ProcessQueries(); |
- |
- if (available_queries_.empty()) |
- available_queries_.push_back(Query::Create(gl_)); |
- |
- available_queries_.front()->Begin(); |
-} |
- |
-void TextureUploader::EndQuery() { |
- available_queries_.front()->End(); |
- pending_queries_.push_back(available_queries_.take_front()); |
- num_blocking_texture_uploads_++; |
-} |
- |
-void TextureUploader::Upload(const uint8* image, |
- const gfx::Rect& image_rect, |
- const gfx::Rect& source_rect, |
- gfx::Vector2d dest_offset, |
- ResourceFormat format, |
- const gfx::Size& size) { |
- CHECK(image_rect.Contains(source_rect)); |
- |
- bool is_full_upload = dest_offset.IsZero() && source_rect.size() == size; |
- |
- if (is_full_upload) |
- BeginQuery(); |
- |
- UploadWithMapTexSubImage(image, image_rect, source_rect, dest_offset, format); |
- |
- if (is_full_upload) |
- EndQuery(); |
- |
- num_texture_uploads_since_last_flush_++; |
- if (num_texture_uploads_since_last_flush_ >= kTextureUploadFlushPeriod) |
- Flush(); |
-} |
- |
-void TextureUploader::Flush() { |
- if (!num_texture_uploads_since_last_flush_) |
- return; |
- |
- gl_->ShallowFlushCHROMIUM(); |
- |
- num_texture_uploads_since_last_flush_ = 0; |
-} |
- |
-void TextureUploader::ReleaseCachedQueries() { |
- ProcessQueries(); |
- available_queries_.clear(); |
-} |
- |
-void TextureUploader::UploadWithTexSubImage(const uint8* image, |
- const gfx::Rect& image_rect, |
- const gfx::Rect& source_rect, |
- gfx::Vector2d dest_offset, |
- ResourceFormat format) { |
- TRACE_EVENT0("cc", "TextureUploader::UploadWithTexSubImage"); |
- |
- // Early-out if this is a no-op, and assert that |image| be valid if this is |
- // not a no-op. |
- if (source_rect.IsEmpty()) |
- return; |
- DCHECK(image); |
- |
- // Offset from image-rect to source-rect. |
- gfx::Vector2d offset(source_rect.origin() - image_rect.origin()); |
- |
- const uint8* pixel_source; |
- unsigned bytes_per_pixel = BitsPerPixel(format) / 8; |
- // Use 4-byte row alignment (OpenGL default) for upload performance. |
- // Assuming that GL_UNPACK_ALIGNMENT has not changed from default. |
- unsigned upload_image_stride = |
- RoundUp(bytes_per_pixel * source_rect.width(), 4u); |
- |
- if (upload_image_stride == image_rect.width() * bytes_per_pixel && |
- !offset.x()) { |
- pixel_source = &image[image_rect.width() * bytes_per_pixel * offset.y()]; |
- } else { |
- size_t needed_size = upload_image_stride * source_rect.height(); |
- if (sub_image_size_ < needed_size) { |
- sub_image_.reset(new uint8[needed_size]); |
- sub_image_size_ = needed_size; |
- } |
- // Strides not equal, so do a row-by-row memcpy from the |
- // paint results into a temp buffer for uploading. |
- for (int row = 0; row < source_rect.height(); ++row) |
- memcpy(&sub_image_[upload_image_stride * row], |
- &image[bytes_per_pixel * |
- (offset.x() + (offset.y() + row) * image_rect.width())], |
- source_rect.width() * bytes_per_pixel); |
- |
- pixel_source = &sub_image_[0]; |
- } |
- |
- gl_->TexSubImage2D(GL_TEXTURE_2D, |
- 0, |
- dest_offset.x(), |
- dest_offset.y(), |
- source_rect.width(), |
- source_rect.height(), |
- GLDataFormat(format), |
- GLDataType(format), |
- pixel_source); |
-} |
- |
-void TextureUploader::UploadWithMapTexSubImage(const uint8* image, |
- const gfx::Rect& image_rect, |
- const gfx::Rect& source_rect, |
- gfx::Vector2d dest_offset, |
- ResourceFormat format) { |
- TRACE_EVENT0("cc", "TextureUploader::UploadWithMapTexSubImage"); |
- |
- // Early-out if this is a no-op, and assert that |image| be valid if this is |
- // not a no-op. |
- if (source_rect.IsEmpty()) |
- return; |
- DCHECK(image); |
- // Compressed textures have no implementation of mapTexSubImage. |
- DCHECK_NE(ETC1, format); |
- |
- // Offset from image-rect to source-rect. |
- gfx::Vector2d offset(source_rect.origin() - image_rect.origin()); |
- |
- unsigned bytes_per_pixel = BitsPerPixel(format) / 8; |
- // Use 4-byte row alignment (OpenGL default) for upload performance. |
- // Assuming that GL_UNPACK_ALIGNMENT has not changed from default. |
- unsigned upload_image_stride = |
- RoundUp(bytes_per_pixel * source_rect.width(), 4u); |
- |
- // Upload tile data via a mapped transfer buffer |
- uint8* pixel_dest = |
- static_cast<uint8*>(gl_->MapTexSubImage2DCHROMIUM(GL_TEXTURE_2D, |
- 0, |
- dest_offset.x(), |
- dest_offset.y(), |
- source_rect.width(), |
- source_rect.height(), |
- GLDataFormat(format), |
- GLDataType(format), |
- GL_WRITE_ONLY)); |
- |
- if (!pixel_dest) { |
- UploadWithTexSubImage(image, image_rect, source_rect, dest_offset, format); |
- return; |
- } |
- |
- if (upload_image_stride == image_rect.width() * bytes_per_pixel && |
- !offset.x()) { |
- memcpy(pixel_dest, |
- &image[image_rect.width() * bytes_per_pixel * offset.y()], |
- source_rect.height() * image_rect.width() * bytes_per_pixel); |
- } else { |
- // Strides not equal, so do a row-by-row memcpy from the |
- // paint results into the pixel_dest. |
- for (int row = 0; row < source_rect.height(); ++row) { |
- memcpy(&pixel_dest[upload_image_stride * row], |
- &image[bytes_per_pixel * |
- (offset.x() + (offset.y() + row) * image_rect.width())], |
- source_rect.width() * bytes_per_pixel); |
- } |
- } |
- |
- gl_->UnmapTexSubImage2DCHROMIUM(pixel_dest); |
-} |
- |
-void TextureUploader::ProcessQueries() { |
- while (!pending_queries_.empty()) { |
- if (pending_queries_.front()->IsPending()) |
- break; |
- |
- unsigned us_elapsed = pending_queries_.front()->Value(); |
- UMA_HISTOGRAM_CUSTOM_COUNTS( |
- "Renderer4.TextureGpuUploadTimeUS", us_elapsed, 0, 100000, 50); |
- |
- // Clamp the queries to saner values in case the queries fail. |
- us_elapsed = std::max(1u, us_elapsed); |
- us_elapsed = std::min(15000u, us_elapsed); |
- |
- if (!pending_queries_.front()->is_non_blocking()) |
- num_blocking_texture_uploads_--; |
- |
- // Remove the min and max value from our history and insert the new one. |
- double textures_per_second = 1.0 / (us_elapsed * 1e-6); |
- if (textures_per_second_history_.size() >= kUploadHistorySizeMax) { |
- textures_per_second_history_.erase(textures_per_second_history_.begin()); |
- textures_per_second_history_.erase(--textures_per_second_history_.end()); |
- } |
- textures_per_second_history_.insert(textures_per_second); |
- |
- available_queries_.push_back(pending_queries_.take_front()); |
- } |
-} |
- |
-} // namespace cc |