blob: d1ba4cf722ddc63977024cb82083ea7d5053549f [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
[email protected]b4da2032012-10-25 21:22:555#include "cc/resource_update_controller.h"
[email protected]94f206c12012-08-25 00:09:146
[email protected]920caa52012-12-18 22:39:507#include <limits>
8
[email protected]6331a1172012-10-18 11:35:139#include "base/debug/trace_event.h"
[email protected]3b10a302012-11-07 21:16:4010#include "cc/prioritized_resource.h"
[email protected]c4040a522012-10-21 15:01:4011#include "cc/resource_provider.h"
[email protected]a8461d82012-10-16 21:11:1412#include "cc/texture_copier.h"
[email protected]4a0488912012-10-30 23:29:5013#include "cc/thread.h"
[email protected]1940c4e2012-12-04 05:08:1514#include "skia/ext/refptr.h"
[email protected]920caa52012-12-18 22:39:5015#include "third_party/WebKit/Source/Platform/chromium/public/WebGraphicsContext3D.h"
16#include "third_party/WebKit/Source/Platform/chromium/public/WebSharedGraphicsContext3D.h"
[email protected]4456eee22012-10-19 18:16:3817#include "third_party/khronos/GLES2/gl2.h"
18#include "third_party/skia/include/gpu/SkGpuDevice.h"
[email protected]94f206c12012-08-25 00:09:1419
[email protected]1e5b6bf52012-10-18 01:44:5220using WebKit::WebGraphicsContext3D;
21using WebKit::WebSharedGraphicsContext3D;
22
[email protected]94f206c12012-08-25 00:09:1423namespace {
24
[email protected]41b8f682012-09-19 01:51:1725// Number of partial updates we allow.
[email protected]8284dcb2012-11-07 04:40:1226#if defined(OS_ANDROID)
27const size_t partialTextureUpdatesMax = 0;
28#else
[email protected]2d86b922012-10-13 16:57:4729const size_t partialTextureUpdatesMax = 12;
[email protected]8284dcb2012-11-07 04:40:1230#endif
[email protected]94f206c12012-08-25 00:09:1431
32// Measured in seconds.
[email protected]2d86b922012-10-13 16:57:4733const double textureUpdateTickRate = 0.004;
[email protected]94f206c12012-08-25 00:09:1434
[email protected]12695152012-09-17 22:28:1435// Measured in seconds.
[email protected]2d86b922012-10-13 16:57:4736const double uploaderBusyTickRate = 0.001;
[email protected]12695152012-09-17 22:28: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]1940c4e2012-12-04 05:08:1541skia::RefPtr<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;
[email protected]1940c4e2012-12-04 05:08:1550 skia::RefPtr<GrTexture> target =
51 skia::AdoptRef(grContext->createPlatformTexture(textureDesc));
52 skia::RefPtr<SkDevice> device =
53 skia::AdoptRef(new SkGpuDevice(grContext, target.get()));
54 return skia::AdoptRef(new SkCanvas(device.get()));
[email protected]1e5b6bf52012-10-18 01:44:5255}
56
[email protected]2d86b922012-10-13 16:57:4757} // namespace
[email protected]94f206c12012-08-25 00:09:1458
[email protected]9c88e562012-09-14 22:21:3059namespace cc {
[email protected]94f206c12012-08-25 00:09:1460
[email protected]b4da2032012-10-25 21:22:5561size_t ResourceUpdateController::maxPartialTextureUpdates()
[email protected]94f206c12012-08-25 00:09:1462{
[email protected]a7c078b2012-09-20 17:52:1263 return partialTextureUpdatesMax;
[email protected]41b8f682012-09-19 01:51:1764}
65
[email protected]b4da2032012-10-25 21:22:5566size_t ResourceUpdateController::maxFullUpdatesPerTick(
[email protected]96baf3e2012-10-22 23:09:5567 ResourceProvider* resourceProvider)
[email protected]41b8f682012-09-19 01:51:1768{
[email protected]e2249592012-10-19 06:59:0969 double texturesPerSecond = resourceProvider->estimatedUploadsPerSecond();
[email protected]41b8f682012-09-19 01:51:1770 size_t texturesPerTick = floor(textureUpdateTickRate * texturesPerSecond);
71 return texturesPerTick ? texturesPerTick : 1;
[email protected]94f206c12012-08-25 00:09:1472}
73
[email protected]61de5812012-11-08 07:03:4474ResourceUpdateController::ResourceUpdateController(ResourceUpdateControllerClient* client, Thread* thread, scoped_ptr<ResourceUpdateQueue> queue, ResourceProvider* resourceProvider, bool hasImplThread)
[email protected]3c496dc2012-09-13 23:14:2075 : m_client(client)
[email protected]61de5812012-11-08 07:03:4476 , m_hasImplThread(hasImplThread)
[email protected]b1b800c2012-10-16 05:03:5977 , m_queue(queue.Pass())
[email protected]94f206c12012-08-25 00:09:1478 , m_resourceProvider(resourceProvider)
[email protected]e2249592012-10-19 06:59:0979 , m_textureUpdatesPerTick(maxFullUpdatesPerTick(resourceProvider))
[email protected]94f206c12012-08-25 00:09:1480 , m_firstUpdateAttempt(true)
[email protected]4a0488912012-10-30 23:29:5081 , m_thread(thread)
82 , m_weakFactory(ALLOW_THIS_IN_INITIALIZER_LIST(this))
83 , m_taskPosted(false)
[email protected]94f206c12012-08-25 00:09:1484{
85}
86
[email protected]b4da2032012-10-25 21:22:5587ResourceUpdateController::~ResourceUpdateController()
[email protected]94f206c12012-08-25 00:09:1488{
89}
90
[email protected]b4da2032012-10-25 21:22:5591void ResourceUpdateController::performMoreUpdates(
[email protected]d918afe2012-09-27 19:27:2192 base::TimeTicks timeLimit)
[email protected]94f206c12012-08-25 00:09:1493{
[email protected]d918afe2012-09-27 19:27:2194 m_timeLimit = timeLimit;
[email protected]94f206c12012-08-25 00:09:1495
[email protected]3c496dc2012-09-13 23:14:2096 // Update already in progress.
[email protected]4a0488912012-10-30 23:29:5097 if (m_taskPosted)
[email protected]94f206c12012-08-25 00:09:1498 return;
99
100 // Call updateMoreTexturesNow() directly unless it's the first update
101 // attempt. This ensures that we empty the update queue in a finite
102 // amount of time.
[email protected]bb87580f2012-11-06 23:26:51103 if (!m_firstUpdateAttempt)
[email protected]94f206c12012-08-25 00:09:14104 updateMoreTexturesNow();
[email protected]bb87580f2012-11-06 23:26:51105
106 // Post a 0-delay task when no updates were left. When it runs,
107 // readyToFinalizeTextureUpdates() will be called.
108 if (!updateMoreTexturesIfEnoughTimeRemaining()) {
109 m_taskPosted = true;
110 m_thread->postTask(
111 base::Bind(&ResourceUpdateController::onTimerFired,
112 m_weakFactory.GetWeakPtr()));
113 }
114
115 m_firstUpdateAttempt = false;
[email protected]94f206c12012-08-25 00:09:14116}
117
[email protected]b4da2032012-10-25 21:22:55118void ResourceUpdateController::discardUploadsToEvictedResources()
[email protected]77a60b9b2012-09-19 23:59:01119{
120 m_queue->clearUploadsToEvictedResources();
121}
122
[email protected]b4da2032012-10-25 21:22:55123void ResourceUpdateController::updateTexture(ResourceUpdate update)
[email protected]1e5b6bf52012-10-18 01:44:52124{
125 if (update.picture) {
[email protected]3b10a302012-11-07 21:16:40126 PrioritizedResource* texture = update.texture;
[email protected]f809d3bb2012-10-31 20:52:25127 gfx::Rect pictureRect = update.content_rect;
128 gfx::Rect sourceRect = update.source_rect;
129 gfx::Vector2d destOffset = update.dest_offset;
[email protected]1e5b6bf52012-10-18 01:44:52130
131 texture->acquireBackingTexture(m_resourceProvider);
[email protected]1d993172012-10-18 18:15:04132 DCHECK(texture->haveBackingTexture());
[email protected]1e5b6bf52012-10-18 01:44:52133
[email protected]1d993172012-10-18 18:15:04134 DCHECK(m_resourceProvider->resourceType(texture->resourceId()) ==
[email protected]96baf3e2012-10-22 23:09:55135 ResourceProvider::GLTexture);
[email protected]1e5b6bf52012-10-18 01:44:52136
[email protected]61de5812012-11-08 07:03:44137 WebGraphicsContext3D* paintContext = m_hasImplThread ?
[email protected]1e5b6bf52012-10-18 01:44:52138 WebSharedGraphicsContext3D::compositorThreadContext() :
139 WebSharedGraphicsContext3D::mainThreadContext();
[email protected]61de5812012-11-08 07:03:44140 GrContext* paintGrContext = m_hasImplThread ?
[email protected]1e5b6bf52012-10-18 01:44:52141 WebSharedGraphicsContext3D::compositorThreadGrContext() :
142 WebSharedGraphicsContext3D::mainThreadGrContext();
143
144 // Flush the context in which the backing texture is created so that it
145 // is available in other shared contexts. It is important to do here
146 // because the backing texture is created in one context while it is
147 // being written to in another.
148 m_resourceProvider->flush();
[email protected]96baf3e2012-10-22 23:09:55149 ResourceProvider::ScopedWriteLockGL lock(
[email protected]1e5b6bf52012-10-18 01:44:52150 m_resourceProvider, texture->resourceId());
151
152 // Make sure ganesh uses the correct GL context.
153 paintContext->makeContextCurrent();
154
155 // Create an accelerated canvas to draw on.
[email protected]1940c4e2012-12-04 05:08:15156 skia::RefPtr<SkCanvas> canvas = createAcceleratedCanvas(
[email protected]1e5b6bf52012-10-18 01:44:52157 paintGrContext, texture->size(), lock.textureId());
158
159 // The compositor expects the textures to be upside-down so it can flip
160 // the final composited image. Ganesh renders the image upright so we
161 // need to do a y-flip.
162 canvas->translate(0.0, texture->size().height());
163 canvas->scale(1.0, -1.0);
164 // Clip to the destination on the texture that must be updated.
[email protected]f809d3bb2012-10-31 20:52:25165 canvas->clipRect(SkRect::MakeXYWH(destOffset.x(),
166 destOffset.y(),
[email protected]1e5b6bf52012-10-18 01:44:52167 sourceRect.width(),
168 sourceRect.height()));
169 // Translate the origin of pictureRect to destOffset.
170 // Note that destOffset is defined relative to sourceRect.
171 canvas->translate(
[email protected]f809d3bb2012-10-31 20:52:25172 pictureRect.x() - sourceRect.x() + destOffset.x(),
173 pictureRect.y() - sourceRect.y() + destOffset.y());
[email protected]1e5b6bf52012-10-18 01:44:52174 canvas->drawPicture(*update.picture);
175
176 // Flush ganesh context so that all the rendered stuff appears on the
177 // texture.
178 paintGrContext->flush();
179
180 // Flush the GL context so rendering results from this context are
181 // visible in the compositor's context.
182 paintContext->flush();
183 }
184
185 if (update.bitmap) {
[email protected]e2249592012-10-19 06:59:09186 update.bitmap->lockPixels();
[email protected]a3d24452012-11-02 06:26:24187 update.texture->setPixels(
[email protected]e2249592012-10-19 06:59:09188 m_resourceProvider,
189 static_cast<const uint8_t*>(update.bitmap->getPixels()),
190 update.content_rect,
191 update.source_rect,
192 update.dest_offset);
193 update.bitmap->unlockPixels();
[email protected]1e5b6bf52012-10-18 01:44:52194 }
195}
196
[email protected]b4da2032012-10-25 21:22:55197void ResourceUpdateController::finalize()
[email protected]12695152012-09-17 22:28:14198{
[email protected]2b37dfd2012-11-03 20:52:32199 while (m_queue->fullUploadSize())
[email protected]1e5b6bf52012-10-18 01:44:52200 updateTexture(m_queue->takeFirstFullUpload());
[email protected]f961b792012-09-20 07:27:33201
[email protected]2b37dfd2012-11-03 20:52:32202 while (m_queue->partialUploadSize())
[email protected]1e5b6bf52012-10-18 01:44:52203 updateTexture(m_queue->takeFirstPartialUpload());
[email protected]f961b792012-09-20 07:27:33204
[email protected]2b37dfd2012-11-03 20:52:32205 m_resourceProvider->flushUploads();
[email protected]f961b792012-09-20 07:27:33206
207 if (m_queue->copySize()) {
208 TextureCopier* copier = m_resourceProvider->textureCopier();
209 while (m_queue->copySize())
210 copier->copyTexture(m_queue->takeFirstCopy());
211
212 // If we've performed any texture copies, we need to insert a flush
213 // here into the compositor context before letting the main thread
214 // proceed as it may make draw calls to the source texture of one of
215 // our copy operations.
216 copier->flush();
217 }
[email protected]12695152012-09-17 22:28:14218}
219
[email protected]b4da2032012-10-25 21:22:55220void ResourceUpdateController::onTimerFired()
[email protected]94f206c12012-08-25 00:09:14221{
[email protected]4a0488912012-10-30 23:29:50222 m_taskPosted = false;
[email protected]3c496dc2012-09-13 23:14:20223 if (!updateMoreTexturesIfEnoughTimeRemaining())
[email protected]12695152012-09-17 22:28:14224 m_client->readyToFinalizeTextureUpdates();
[email protected]94f206c12012-08-25 00:09:14225}
226
[email protected]b4da2032012-10-25 21:22:55227base::TimeTicks ResourceUpdateController::now() const
[email protected]94f206c12012-08-25 00:09:14228{
[email protected]d918afe2012-09-27 19:27:21229 return base::TimeTicks::Now();
[email protected]94f206c12012-08-25 00:09:14230}
231
[email protected]b4da2032012-10-25 21:22:55232base::TimeDelta ResourceUpdateController::updateMoreTexturesTime() const
[email protected]94f206c12012-08-25 00:09:14233{
[email protected]d918afe2012-09-27 19:27:21234 return base::TimeDelta::FromMilliseconds(textureUpdateTickRate * 1000);
[email protected]94f206c12012-08-25 00:09:14235}
236
[email protected]b4da2032012-10-25 21:22:55237size_t ResourceUpdateController::updateMoreTexturesSize() const
[email protected]94f206c12012-08-25 00:09:14238{
[email protected]41b8f682012-09-19 01:51:17239 return m_textureUpdatesPerTick;
[email protected]94f206c12012-08-25 00:09:14240}
241
[email protected]b4da2032012-10-25 21:22:55242size_t ResourceUpdateController::maxBlockingUpdates() const
[email protected]549526e92012-09-29 15:43:08243{
[email protected]b914e102012-10-02 08:11:52244 return updateMoreTexturesSize() * maxBlockingUpdateIntervals;
[email protected]549526e92012-09-29 15:43:08245}
246
[email protected]bb87580f2012-11-06 23:26:51247base::TimeDelta ResourceUpdateController::pendingUpdateTime() const
248{
249 base::TimeDelta updateOneResourceTime =
250 updateMoreTexturesTime() / updateMoreTexturesSize();
251 return updateOneResourceTime * m_resourceProvider->numBlockingUploads();
252}
253
[email protected]b4da2032012-10-25 21:22:55254bool ResourceUpdateController::updateMoreTexturesIfEnoughTimeRemaining()
[email protected]94f206c12012-08-25 00:09:14255{
[email protected]bb87580f2012-11-06 23:26:51256 while (m_resourceProvider->numBlockingUploads() < maxBlockingUpdates()) {
257 if (!m_queue->fullUploadSize())
258 return false;
259
260 if (!m_timeLimit.is_null()) {
261 // Estimated completion time of all pending updates.
262 base::TimeTicks completionTime = this->now() + pendingUpdateTime();
263
264 // Time remaining based on current completion estimate.
265 base::TimeDelta timeRemaining = m_timeLimit - completionTime;
266
267 if (timeRemaining < updateMoreTexturesTime())
268 return true;
269 }
270
271 updateMoreTexturesNow();
[email protected]12695152012-09-17 22:28:14272 }
273
[email protected]bb87580f2012-11-06 23:26:51274 m_taskPosted = true;
275 m_thread->postDelayedTask(
276 base::Bind(&ResourceUpdateController::onTimerFired,
277 m_weakFactory.GetWeakPtr()),
278 uploaderBusyTickRate * 1000);
[email protected]3c496dc2012-09-13 23:14:20279 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]12695152012-09-17 22:28:14286
287 if (!uploads)
288 return;
289
[email protected]2b37dfd2012-11-03 20:52:32290 while (m_queue->fullUploadSize() && uploads--)
[email protected]1e5b6bf52012-10-18 01:44:52291 updateTexture(m_queue->takeFirstFullUpload());
[email protected]2b37dfd2012-11-03 20:52:32292
293 m_resourceProvider->flushUploads();
[email protected]94f206c12012-08-25 00:09:14294}
295
[email protected]2d86b922012-10-13 16:57:47296} // namespace cc