Index: cc/ThrottledTextureUploader.cpp |
diff --git a/cc/ThrottledTextureUploader.cpp b/cc/ThrottledTextureUploader.cpp |
index 594342e54ec96873a141c2aad5535ea7a3e62894..6fce3fa37fcee7ccebc907236af027a7b317c002 100644 |
--- a/cc/ThrottledTextureUploader.cpp |
+++ b/cc/ThrottledTextureUploader.cpp |
@@ -3,17 +3,26 @@ |
// found in the LICENSE file. |
#include "config.h" |
- |
#include "ThrottledTextureUploader.h" |
#include "Extensions3DChromium.h" |
+#include <algorithm> |
#include <public/WebGraphicsContext3D.h> |
+#include <vector> |
namespace { |
// Number of pending texture update queries to allow. |
static const size_t maxPendingQueries = 2; |
+// How many previous uploads to use when predicting future throughput. |
+static const size_t uploadHistorySize = 10; |
+ |
+// Global estimated number of pixels per second to maintain estimates across |
+// subsequent instances of ThrottledTextureUploader. |
+// More than one thread will not access this variable, so we do not need to synchronize access. |
+static double estimatedPixelsPerSecondGlobal = 256.0 * 256.0 * 48.0 * 60.0; |
+ |
} // anonymous namespace |
namespace WebCore { |
@@ -21,6 +30,9 @@ namespace WebCore { |
ThrottledTextureUploader::Query::Query(WebKit::WebGraphicsContext3D* context) |
: m_context(context) |
, m_queryId(0) |
+ , m_value(0) |
+ , m_hasValue(false) |
+ , m_pixelsUploaded(0) |
{ |
m_queryId = m_context->createQueryEXT(); |
} |
@@ -35,9 +47,10 @@ void ThrottledTextureUploader::Query::begin() |
m_context->beginQueryEXT(Extensions3DChromium::COMMANDS_ISSUED_CHROMIUM, m_queryId); |
} |
-void ThrottledTextureUploader::Query::end() |
+void ThrottledTextureUploader::Query::end(double pixelsUploaded) |
{ |
m_context->endQueryEXT(Extensions3DChromium::COMMANDS_ISSUED_CHROMIUM); |
+ m_pixelsUploaded = pixelsUploaded; |
} |
bool ThrottledTextureUploader::Query::isPending() |
@@ -49,19 +62,35 @@ bool ThrottledTextureUploader::Query::isPending() |
void ThrottledTextureUploader::Query::wait() |
{ |
- unsigned result; |
- m_context->getQueryObjectuivEXT(m_queryId, Extensions3DChromium::QUERY_RESULT_EXT, &result); |
+ value(); |
+ return; |
+} |
+ |
+unsigned ThrottledTextureUploader::Query::value() |
+{ |
+ if (!m_hasValue) |
+ m_context->getQueryObjectuivEXT(m_queryId, Extensions3DChromium::QUERY_RESULT_EXT, &m_value); |
+ return m_value; |
+} |
+ |
+double ThrottledTextureUploader::Query::pixelsUploaded() |
+{ |
+ return m_pixelsUploaded; |
} |
ThrottledTextureUploader::ThrottledTextureUploader(WebKit::WebGraphicsContext3D* context) |
: m_context(context) |
, m_maxPendingQueries(maxPendingQueries) |
+ , m_pixelsPerSecondHistory(uploadHistorySize, estimatedPixelsPerSecondGlobal) |
+ , m_pixelsUploaded(0) |
{ |
} |
ThrottledTextureUploader::ThrottledTextureUploader(WebKit::WebGraphicsContext3D* context, size_t pendingUploadLimit) |
: m_context(context) |
, m_maxPendingQueries(pendingUploadLimit) |
+ , m_pixelsPerSecondHistory(uploadHistorySize, estimatedPixelsPerSecondGlobal) |
+ , m_pixelsUploaded(0) |
{ |
ASSERT(m_context); |
} |
@@ -69,7 +98,6 @@ ThrottledTextureUploader::ThrottledTextureUploader(WebKit::WebGraphicsContext3D* |
ThrottledTextureUploader::~ThrottledTextureUploader() |
{ |
} |
- |
bool ThrottledTextureUploader::isBusy() |
{ |
processQueries(); |
@@ -84,8 +112,26 @@ bool ThrottledTextureUploader::isBusy() |
return false; |
} |
+double ThrottledTextureUploader::estimatedPixelsPerSecond() |
+{ |
+ processQueries(); |
+ |
+ // The history should never be empty because we initialize all elements with an estimate. |
+ ASSERT(m_pixelsPerSecondHistory.size() == uploadHistorySize); |
+ |
+ // Sort the history and use the median as our estimate. |
+ std::vector<double> sortedHistory(m_pixelsPerSecondHistory.begin(), |
+ m_pixelsPerSecondHistory.end()); |
+ std::sort(sortedHistory.begin(), sortedHistory.end()); |
+ |
+ estimatedPixelsPerSecondGlobal = sortedHistory[sortedHistory.size() / 2]; |
+ return estimatedPixelsPerSecondGlobal; |
+} |
+ |
void ThrottledTextureUploader::beginUploads() |
{ |
+ m_pixelsUploaded = 0; |
+ |
// Wait for query to become available. |
while (isBusy()) |
m_pendingQueries.first()->wait(); |
@@ -96,12 +142,13 @@ void ThrottledTextureUploader::beginUploads() |
void ThrottledTextureUploader::endUploads() |
{ |
- m_availableQueries.first()->end(); |
+ m_availableQueries.first()->end(m_pixelsUploaded); |
m_pendingQueries.append(m_availableQueries.takeFirst()); |
} |
void ThrottledTextureUploader::uploadTexture(CCResourceProvider* resourceProvider, Parameters upload) |
{ |
+ m_pixelsUploaded += upload.sourceRect.width() * upload.sourceRect.width(); |
upload.texture->updateRect(resourceProvider, upload.sourceRect, upload.destOffset); |
} |
@@ -111,6 +158,13 @@ void ThrottledTextureUploader::processQueries() |
if (m_pendingQueries.first()->isPending()) |
break; |
+ unsigned usElapsed = m_pendingQueries.first()->value(); |
+ double pixelsPerSecond = m_pendingQueries.first()->pixelsUploaded() / (usElapsed * 1e-6); |
+ |
+ // Remove the oldest values from our history and insert the new one |
+ m_pixelsPerSecondHistory.pop_back(); |
+ m_pixelsPerSecondHistory.push_front(pixelsPerSecond); |
+ |
m_availableQueries.append(m_pendingQueries.takeFirst()); |
} |
} |