Index: cc/ThrottledTextureUploader.cpp |
diff --git a/cc/ThrottledTextureUploader.cpp b/cc/ThrottledTextureUploader.cpp |
index 274205da3970520c5168a57e6012e7b99442e657..f9de78cc32fe9e1f497ae9ff2764e42196d5d589 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 textures 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 estimatedTexturesPerSecondGlobal = 48.0 * 60.0; |
+ |
} // anonymous namespace |
namespace cc { |
@@ -21,6 +30,9 @@ namespace cc { |
ThrottledTextureUploader::Query::Query(WebKit::WebGraphicsContext3D* context) |
: m_context(context) |
, m_queryId(0) |
+ , m_value(0) |
+ , m_hasValue(false) |
+ , m_texturesUploaded(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 texturesUploaded) |
{ |
m_context->endQueryEXT(Extensions3DChromium::COMMANDS_ISSUED_CHROMIUM); |
+ m_texturesUploaded = texturesUploaded; |
} |
bool ThrottledTextureUploader::Query::isPending() |
@@ -49,19 +62,37 @@ 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); |
+ m_hasValue = true; |
+ } |
+ return m_value; |
+} |
+ |
+double ThrottledTextureUploader::Query::texturesUploaded() |
+{ |
+ return m_texturesUploaded; |
} |
ThrottledTextureUploader::ThrottledTextureUploader(WebKit::WebGraphicsContext3D* context) |
: m_context(context) |
, m_maxPendingQueries(maxPendingQueries) |
+ , m_texturesPerSecondHistory(uploadHistorySize, estimatedTexturesPerSecondGlobal) |
+ , m_texturesUploaded(0) |
{ |
} |
ThrottledTextureUploader::ThrottledTextureUploader(WebKit::WebGraphicsContext3D* context, size_t pendingUploadLimit) |
: m_context(context) |
, m_maxPendingQueries(pendingUploadLimit) |
+ , m_texturesPerSecondHistory(uploadHistorySize, estimatedTexturesPerSecondGlobal) |
+ , m_texturesUploaded(0) |
{ |
ASSERT(m_context); |
} |
@@ -84,8 +115,26 @@ bool ThrottledTextureUploader::isBusy() |
return false; |
} |
+double ThrottledTextureUploader::estimatedTexturesPerSecond() |
+{ |
+ processQueries(); |
+ |
+ // The history should never be empty because we initialize all elements with an estimate. |
+ ASSERT(m_texturesPerSecondHistory.size() == uploadHistorySize); |
+ |
+ // Sort the history and use the median as our estimate. |
+ std::vector<double> sortedHistory(m_texturesPerSecondHistory.begin(), |
+ m_texturesPerSecondHistory.end()); |
+ std::sort(sortedHistory.begin(), sortedHistory.end()); |
+ |
+ estimatedTexturesPerSecondGlobal = sortedHistory[sortedHistory.size() / 2]; |
+ return estimatedTexturesPerSecondGlobal; |
+} |
+ |
void ThrottledTextureUploader::beginUploads() |
{ |
+ m_texturesUploaded = 0; |
+ |
// Wait for query to become available. |
while (isBusy()) |
m_pendingQueries.first()->wait(); |
@@ -96,12 +145,13 @@ void ThrottledTextureUploader::beginUploads() |
void ThrottledTextureUploader::endUploads() |
{ |
- m_availableQueries.first()->end(); |
+ m_availableQueries.first()->end(m_texturesUploaded); |
m_pendingQueries.append(m_availableQueries.takeFirst()); |
} |
void ThrottledTextureUploader::uploadTexture(CCResourceProvider* resourceProvider, Parameters upload) |
{ |
+ m_texturesUploaded++; |
upload.texture->updateRect(resourceProvider, upload.sourceRect, upload.destOffset); |
} |
@@ -111,6 +161,13 @@ void ThrottledTextureUploader::processQueries() |
if (m_pendingQueries.first()->isPending()) |
break; |
+ unsigned usElapsed = m_pendingQueries.first()->value(); |
+ double texturesPerSecond = m_pendingQueries.first()->texturesUploaded() / (usElapsed * 1e-6); |
+ |
+ // Remove the oldest values from our history and insert the new one |
+ m_texturesPerSecondHistory.pop_back(); |
+ m_texturesPerSecondHistory.push_front(texturesPerSecond); |
+ |
m_availableQueries.append(m_pendingQueries.takeFirst()); |
} |
} |