blob: 5295724ef10111ed1cf152602444c96a383665b9 [file] [log] [blame]
[email protected]94f206c12012-08-25 00:09:141// Copyright 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "config.h"
6
[email protected]b4da2032012-10-25 21:22:557#include "cc/resource_update_controller.h"
[email protected]94f206c12012-08-25 00:09:148
[email protected]6331a1172012-10-18 11:35:139#include "base/debug/trace_event.h"
[email protected]1e5b6bf52012-10-18 01:44:5210#include "cc/prioritized_texture.h"
[email protected]5bc29a22012-11-01 21:21:5911#include "cc/proxy.h"
[email protected]c4040a522012-10-21 15:01:4012#include "cc/resource_provider.h"
[email protected]a8461d82012-10-16 21:11:1413#include "cc/texture_copier.h"
[email protected]4a0488912012-10-30 23:29:5014#include "cc/thread.h"
[email protected]4456eee22012-10-19 18:16:3815#include "third_party/khronos/GLES2/gl2.h"
16#include "third_party/skia/include/gpu/SkGpuDevice.h"
[email protected]41b8f682012-09-19 01:51:1717#include <limits>
[email protected]1e5b6bf52012-10-18 01:44:5218#include <public/WebGraphicsContext3D.h>
19#include <public/WebSharedGraphicsContext3D.h>
[email protected]94f206c12012-08-25 00:09:1420
[email protected]1e5b6bf52012-10-18 01:44:5221using WebKit::WebGraphicsContext3D;
22using WebKit::WebSharedGraphicsContext3D;
23
[email protected]94f206c12012-08-25 00:09:1424namespace {
25
[email protected]41b8f682012-09-19 01:51:1726// Number of partial updates we allow.
[email protected]2d86b922012-10-13 16:57:4727const size_t partialTextureUpdatesMax = 12;
[email protected]94f206c12012-08-25 00:09:1428
29// Measured in seconds.
[email protected]2d86b922012-10-13 16:57:4730const double textureUpdateTickRate = 0.004;
[email protected]94f206c12012-08-25 00:09:1431
[email protected]12695152012-09-17 22:28:1432// Measured in seconds.
[email protected]2d86b922012-10-13 16:57:4733const double uploaderBusyTickRate = 0.001;
[email protected]12695152012-09-17 22:28:1434
[email protected]94f206c12012-08-25 00:09:1435// Flush interval when performing texture uploads.
[email protected]2d86b922012-10-13 16:57:4736const int textureUploadFlushPeriod = 4;
[email protected]94f206c12012-08-25 00:09:1437
[email protected]b914e102012-10-02 08:11:5238// Number of blocking update intervals to allow.
[email protected]2d86b922012-10-13 16:57:4739const size_t maxBlockingUpdateIntervals = 4;
[email protected]549526e92012-09-29 15:43:0840
[email protected]1e5b6bf52012-10-18 01:44:5241scoped_ptr<SkCanvas> createAcceleratedCanvas(
[email protected]f809d3bb2012-10-31 20:52:2542 GrContext* grContext, gfx::Size canvasSize, unsigned textureId)
[email protected]1e5b6bf52012-10-18 01:44:5243{
44 GrPlatformTextureDesc textureDesc;
45 textureDesc.fFlags = kRenderTarget_GrPlatformTextureFlag;
46 textureDesc.fWidth = canvasSize.width();
47 textureDesc.fHeight = canvasSize.height();
48 textureDesc.fConfig = kSkia8888_GrPixelConfig;
49 textureDesc.fTextureHandle = textureId;
50 SkAutoTUnref<GrTexture> target(
51 grContext->createPlatformTexture(textureDesc));
52 SkAutoTUnref<SkDevice> device(new SkGpuDevice(grContext, target.get()));
53 return make_scoped_ptr(new SkCanvas(device.get()));
54}
55
[email protected]2d86b922012-10-13 16:57:4756} // namespace
[email protected]94f206c12012-08-25 00:09:1457
[email protected]9c88e562012-09-14 22:21:3058namespace cc {
[email protected]94f206c12012-08-25 00:09:1459
[email protected]b4da2032012-10-25 21:22:5560size_t ResourceUpdateController::maxPartialTextureUpdates()
[email protected]94f206c12012-08-25 00:09:1461{
[email protected]a7c078b2012-09-20 17:52:1262 return partialTextureUpdatesMax;
[email protected]41b8f682012-09-19 01:51:1763}
64
[email protected]b4da2032012-10-25 21:22:5565size_t ResourceUpdateController::maxFullUpdatesPerTick(
[email protected]96baf3e2012-10-22 23:09:5566 ResourceProvider* resourceProvider)
[email protected]41b8f682012-09-19 01:51:1767{
[email protected]e2249592012-10-19 06:59:0968 double texturesPerSecond = resourceProvider->estimatedUploadsPerSecond();
[email protected]41b8f682012-09-19 01:51:1769 size_t texturesPerTick = floor(textureUpdateTickRate * texturesPerSecond);
70 return texturesPerTick ? texturesPerTick : 1;
[email protected]94f206c12012-08-25 00:09:1471}
72
[email protected]5bc29a22012-11-01 21:21:5973ResourceUpdateController::ResourceUpdateController(ResourceUpdateControllerClient* client, Thread* thread, scoped_ptr<ResourceUpdateQueue> queue, ResourceProvider* resourceProvider)
[email protected]3c496dc2012-09-13 23:14:2074 : m_client(client)
[email protected]b1b800c2012-10-16 05:03:5975 , m_queue(queue.Pass())
[email protected]94f206c12012-08-25 00:09:1476 , m_resourceProvider(resourceProvider)
[email protected]e2249592012-10-19 06:59:0977 , m_textureUpdatesPerTick(maxFullUpdatesPerTick(resourceProvider))
[email protected]94f206c12012-08-25 00:09:1478 , m_firstUpdateAttempt(true)
[email protected]4a0488912012-10-30 23:29:5079 , m_thread(thread)
80 , m_weakFactory(ALLOW_THIS_IN_INITIALIZER_LIST(this))
81 , m_taskPosted(false)
[email protected]94f206c12012-08-25 00:09:1482{
83}
84
[email protected]b4da2032012-10-25 21:22:5585ResourceUpdateController::~ResourceUpdateController()
[email protected]94f206c12012-08-25 00:09:1486{
87}
88
[email protected]b4da2032012-10-25 21:22:5589void ResourceUpdateController::performMoreUpdates(
[email protected]d918afe2012-09-27 19:27:2190 base::TimeTicks timeLimit)
[email protected]94f206c12012-08-25 00:09:1491{
[email protected]d918afe2012-09-27 19:27:2192 m_timeLimit = timeLimit;
[email protected]94f206c12012-08-25 00:09:1493
[email protected]3c496dc2012-09-13 23:14:2094 // Update already in progress.
[email protected]4a0488912012-10-30 23:29:5095 if (m_taskPosted)
[email protected]94f206c12012-08-25 00:09:1496 return;
97
98 // Call updateMoreTexturesNow() directly unless it's the first update
99 // attempt. This ensures that we empty the update queue in a finite
100 // amount of time.
101 if (m_firstUpdateAttempt) {
[email protected]3c496dc2012-09-13 23:14:20102 // Post a 0-delay task when no updates were left. When it runs,
[email protected]12695152012-09-17 22:28:14103 // readyToFinalizeTextureUpdates() will be called.
[email protected]4a0488912012-10-30 23:29:50104 if (!updateMoreTexturesIfEnoughTimeRemaining()) {
105 m_taskPosted = true;
106 m_thread->postTask(base::Bind(&ResourceUpdateController::onTimerFired,
107 m_weakFactory.GetWeakPtr()));
108 }
[email protected]3c496dc2012-09-13 23:14:20109
[email protected]94f206c12012-08-25 00:09:14110 m_firstUpdateAttempt = false;
111 } else
112 updateMoreTexturesNow();
113}
114
[email protected]b4da2032012-10-25 21:22:55115void ResourceUpdateController::discardUploadsToEvictedResources()
[email protected]77a60b9b2012-09-19 23:59:01116{
117 m_queue->clearUploadsToEvictedResources();
118}
119
[email protected]b4da2032012-10-25 21:22:55120void ResourceUpdateController::updateTexture(ResourceUpdate update)
[email protected]1e5b6bf52012-10-18 01:44:52121{
122 if (update.picture) {
[email protected]96baf3e2012-10-22 23:09:55123 PrioritizedTexture* texture = update.texture;
[email protected]f809d3bb2012-10-31 20:52:25124 gfx::Rect pictureRect = update.content_rect;
125 gfx::Rect sourceRect = update.source_rect;
126 gfx::Vector2d destOffset = update.dest_offset;
[email protected]1e5b6bf52012-10-18 01:44:52127
128 texture->acquireBackingTexture(m_resourceProvider);
[email protected]1d993172012-10-18 18:15:04129 DCHECK(texture->haveBackingTexture());
[email protected]1e5b6bf52012-10-18 01:44:52130
[email protected]1d993172012-10-18 18:15:04131 DCHECK(m_resourceProvider->resourceType(texture->resourceId()) ==
[email protected]96baf3e2012-10-22 23:09:55132 ResourceProvider::GLTexture);
[email protected]1e5b6bf52012-10-18 01:44:52133
[email protected]5bc29a22012-11-01 21:21:59134 WebGraphicsContext3D* paintContext = Proxy::hasImplThread() ?
[email protected]1e5b6bf52012-10-18 01:44:52135 WebSharedGraphicsContext3D::compositorThreadContext() :
136 WebSharedGraphicsContext3D::mainThreadContext();
[email protected]5bc29a22012-11-01 21:21:59137 GrContext* paintGrContext = Proxy::hasImplThread() ?
[email protected]1e5b6bf52012-10-18 01:44:52138 WebSharedGraphicsContext3D::compositorThreadGrContext() :
139 WebSharedGraphicsContext3D::mainThreadGrContext();
140
141 // Flush the context in which the backing texture is created so that it
142 // is available in other shared contexts. It is important to do here
143 // because the backing texture is created in one context while it is
144 // being written to in another.
145 m_resourceProvider->flush();
[email protected]96baf3e2012-10-22 23:09:55146 ResourceProvider::ScopedWriteLockGL lock(
[email protected]1e5b6bf52012-10-18 01:44:52147 m_resourceProvider, texture->resourceId());
148
149 // Make sure ganesh uses the correct GL context.
150 paintContext->makeContextCurrent();
151
152 // Create an accelerated canvas to draw on.
153 scoped_ptr<SkCanvas> canvas = createAcceleratedCanvas(
154 paintGrContext, texture->size(), lock.textureId());
155
156 // The compositor expects the textures to be upside-down so it can flip
157 // the final composited image. Ganesh renders the image upright so we
158 // need to do a y-flip.
159 canvas->translate(0.0, texture->size().height());
160 canvas->scale(1.0, -1.0);
161 // Clip to the destination on the texture that must be updated.
[email protected]f809d3bb2012-10-31 20:52:25162 canvas->clipRect(SkRect::MakeXYWH(destOffset.x(),
163 destOffset.y(),
[email protected]1e5b6bf52012-10-18 01:44:52164 sourceRect.width(),
165 sourceRect.height()));
166 // Translate the origin of pictureRect to destOffset.
167 // Note that destOffset is defined relative to sourceRect.
168 canvas->translate(
[email protected]f809d3bb2012-10-31 20:52:25169 pictureRect.x() - sourceRect.x() + destOffset.x(),
170 pictureRect.y() - sourceRect.y() + destOffset.y());
[email protected]1e5b6bf52012-10-18 01:44:52171 canvas->drawPicture(*update.picture);
172
173 // Flush ganesh context so that all the rendered stuff appears on the
174 // texture.
175 paintGrContext->flush();
176
177 // Flush the GL context so rendering results from this context are
178 // visible in the compositor's context.
179 paintContext->flush();
180 }
181
182 if (update.bitmap) {
[email protected]e2249592012-10-19 06:59:09183 update.bitmap->lockPixels();
[email protected]a3d24452012-11-02 06:26:24184 update.texture->setPixels(
[email protected]e2249592012-10-19 06:59:09185 m_resourceProvider,
186 static_cast<const uint8_t*>(update.bitmap->getPixels()),
187 update.content_rect,
188 update.source_rect,
189 update.dest_offset);
190 update.bitmap->unlockPixels();
[email protected]1e5b6bf52012-10-18 01:44:52191 }
192}
193
[email protected]b4da2032012-10-25 21:22:55194void ResourceUpdateController::finalize()
[email protected]12695152012-09-17 22:28:14195{
[email protected]f961b792012-09-20 07:27:33196 size_t uploadCount = 0;
197 while (m_queue->fullUploadSize()) {
198 if (!(uploadCount % textureUploadFlushPeriod) && uploadCount)
199 m_resourceProvider->shallowFlushIfSupported();
200
[email protected]1e5b6bf52012-10-18 01:44:52201 updateTexture(m_queue->takeFirstFullUpload());
[email protected]f961b792012-09-20 07:27:33202 uploadCount++;
203 }
204
205 while (m_queue->partialUploadSize()) {
206 if (!(uploadCount % textureUploadFlushPeriod) && uploadCount)
207 m_resourceProvider->shallowFlushIfSupported();
208
[email protected]1e5b6bf52012-10-18 01:44:52209 updateTexture(m_queue->takeFirstPartialUpload());
[email protected]f961b792012-09-20 07:27:33210 uploadCount++;
211 }
212
213 if (uploadCount)
214 m_resourceProvider->shallowFlushIfSupported();
215
216 if (m_queue->copySize()) {
217 TextureCopier* copier = m_resourceProvider->textureCopier();
218 while (m_queue->copySize())
219 copier->copyTexture(m_queue->takeFirstCopy());
220
221 // If we've performed any texture copies, we need to insert a flush
222 // here into the compositor context before letting the main thread
223 // proceed as it may make draw calls to the source texture of one of
224 // our copy operations.
225 copier->flush();
226 }
[email protected]12695152012-09-17 22:28:14227}
228
[email protected]b4da2032012-10-25 21:22:55229void ResourceUpdateController::onTimerFired()
[email protected]94f206c12012-08-25 00:09:14230{
[email protected]4a0488912012-10-30 23:29:50231 m_taskPosted = false;
[email protected]17953082012-10-24 20:13:32232 ResourceProvider::debugNotifyEnterZone(0xB000000);
[email protected]3c496dc2012-09-13 23:14:20233 if (!updateMoreTexturesIfEnoughTimeRemaining())
[email protected]12695152012-09-17 22:28:14234 m_client->readyToFinalizeTextureUpdates();
[email protected]17953082012-10-24 20:13:32235 ResourceProvider::debugNotifyLeaveZone();
[email protected]94f206c12012-08-25 00:09:14236}
237
[email protected]b4da2032012-10-25 21:22:55238base::TimeTicks ResourceUpdateController::now() const
[email protected]94f206c12012-08-25 00:09:14239{
[email protected]d918afe2012-09-27 19:27:21240 return base::TimeTicks::Now();
[email protected]94f206c12012-08-25 00:09:14241}
242
[email protected]b4da2032012-10-25 21:22:55243base::TimeDelta ResourceUpdateController::updateMoreTexturesTime() const
[email protected]94f206c12012-08-25 00:09:14244{
[email protected]d918afe2012-09-27 19:27:21245 return base::TimeDelta::FromMilliseconds(textureUpdateTickRate * 1000);
[email protected]94f206c12012-08-25 00:09:14246}
247
[email protected]b4da2032012-10-25 21:22:55248size_t ResourceUpdateController::updateMoreTexturesSize() const
[email protected]94f206c12012-08-25 00:09:14249{
[email protected]41b8f682012-09-19 01:51:17250 return m_textureUpdatesPerTick;
[email protected]94f206c12012-08-25 00:09:14251}
252
[email protected]b4da2032012-10-25 21:22:55253size_t ResourceUpdateController::maxBlockingUpdates() const
[email protected]549526e92012-09-29 15:43:08254{
[email protected]b914e102012-10-02 08:11:52255 return updateMoreTexturesSize() * maxBlockingUpdateIntervals;
[email protected]549526e92012-09-29 15:43:08256}
257
[email protected]b4da2032012-10-25 21:22:55258bool ResourceUpdateController::updateMoreTexturesIfEnoughTimeRemaining()
[email protected]94f206c12012-08-25 00:09:14259{
[email protected]b914e102012-10-02 08:11:52260 // Blocking uploads will increase when we're too aggressive in our upload
[email protected]549526e92012-09-29 15:43:08261 // time estimate. We use a different timeout here to prevent unnecessary
[email protected]b914e102012-10-02 08:11:52262 // amounts of idle time when blocking uploads have reached the max.
[email protected]e2249592012-10-19 06:59:09263 if (m_resourceProvider->numBlockingUploads() >= maxBlockingUpdates()) {
[email protected]4a0488912012-10-30 23:29:50264 m_taskPosted = true;
265 m_thread->postDelayedTask(base::Bind(&ResourceUpdateController::onTimerFired,
266 m_weakFactory.GetWeakPtr()),
267 uploaderBusyTickRate * 1000);
[email protected]12695152012-09-17 22:28:14268 return true;
269 }
270
271 if (!m_queue->fullUploadSize())
[email protected]3c496dc2012-09-13 23:14:20272 return false;
273
[email protected]e8e410d2012-09-28 01:47:01274 bool hasTimeRemaining = m_timeLimit.is_null() ||
275 this->now() < m_timeLimit - updateMoreTexturesTime();
[email protected]94f206c12012-08-25 00:09:14276 if (hasTimeRemaining)
277 updateMoreTexturesNow();
[email protected]3c496dc2012-09-13 23:14:20278
279 return true;
[email protected]94f206c12012-08-25 00:09:14280}
281
[email protected]b4da2032012-10-25 21:22:55282void ResourceUpdateController::updateMoreTexturesNow()
[email protected]94f206c12012-08-25 00:09:14283{
[email protected]12695152012-09-17 22:28:14284 size_t uploads = std::min(
285 m_queue->fullUploadSize(), updateMoreTexturesSize());
[email protected]4a0488912012-10-30 23:29:50286 m_taskPosted = true;
287 m_thread->postDelayedTask(base::Bind(&ResourceUpdateController::onTimerFired,
288 m_weakFactory.GetWeakPtr()),
289 updateMoreTexturesTime().InSecondsF() / updateMoreTexturesSize() * uploads * 1000);
[email protected]12695152012-09-17 22:28:14290
291 if (!uploads)
292 return;
293
[email protected]12695152012-09-17 22:28:14294 size_t uploadCount = 0;
[email protected]41b8f682012-09-19 01:51:17295 while (m_queue->fullUploadSize() && uploadCount < uploads) {
296 if (!(uploadCount % textureUploadFlushPeriod) && uploadCount)
[email protected]12695152012-09-17 22:28:14297 m_resourceProvider->shallowFlushIfSupported();
[email protected]1e5b6bf52012-10-18 01:44:52298 updateTexture(m_queue->takeFirstFullUpload());
[email protected]41b8f682012-09-19 01:51:17299 uploadCount++;
[email protected]12695152012-09-17 22:28:14300 }
[email protected]41b8f682012-09-19 01:51:17301 m_resourceProvider->shallowFlushIfSupported();
[email protected]94f206c12012-08-25 00:09:14302}
303
[email protected]2d86b922012-10-13 16:57:47304} // namespace cc