| OLD | NEW |
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "config.h" | 5 #include "config.h" |
| 6 #include "ThrottledTextureUploader.h" | 6 #include "ThrottledTextureUploader.h" |
| 7 | 7 |
| 8 #include "CCPrioritizedTexture.h" |
| 9 #include "CCProxy.h" |
| 8 #include "Extensions3DChromium.h" | 10 #include "Extensions3DChromium.h" |
| 11 #include "SkGpuDevice.h" |
| 9 #include "TraceEvent.h" | 12 #include "TraceEvent.h" |
| 10 #include <algorithm> | 13 #include <algorithm> |
| 11 #include <public/Platform.h> | 14 #include <public/Platform.h> |
| 12 #include <public/WebGraphicsContext3D.h> | 15 #include <public/WebGraphicsContext3D.h> |
| 16 #include <public/WebSharedGraphicsContext3D.h> |
| 13 #include <vector> | 17 #include <vector> |
| 14 | 18 |
| 19 using WebKit::WebGraphicsContext3D; |
| 20 using WebKit::WebSharedGraphicsContext3D; |
| 21 |
| 15 namespace { | 22 namespace { |
| 16 | 23 |
| 17 // How many previous uploads to use when predicting future throughput. | 24 // How many previous uploads to use when predicting future throughput. |
| 18 static const size_t uploadHistorySize = 100; | 25 static const size_t uploadHistorySize = 100; |
| 19 | 26 |
| 20 // Global estimated number of textures per second to maintain estimates across | 27 // Global estimated number of textures per second to maintain estimates across |
| 21 // subsequent instances of ThrottledTextureUploader. | 28 // subsequent instances of ThrottledTextureUploader. |
| 22 // More than one thread will not access this variable, so we do not need to sync
hronize access. | 29 // More than one thread will not access this variable, so we do not need to sync
hronize access. |
| 23 static double estimatedTexturesPerSecondGlobal = 48.0 * 60.0; | 30 static double estimatedTexturesPerSecondGlobal = 48.0 * 60.0; |
| 24 | 31 |
| 32 PassOwnPtr<SkCanvas> createAcceleratedCanvas(GrContext* grContext, |
| 33 cc::IntSize canvasSize, |
| 34 unsigned textureId) |
| 35 { |
| 36 GrPlatformTextureDesc textureDesc; |
| 37 textureDesc.fFlags = kRenderTarget_GrPlatformTextureFlag; |
| 38 textureDesc.fWidth = canvasSize.width(); |
| 39 textureDesc.fHeight = canvasSize.height(); |
| 40 textureDesc.fConfig = kSkia8888_GrPixelConfig; |
| 41 textureDesc.fTextureHandle = textureId; |
| 42 SkAutoTUnref<GrTexture> target( |
| 43 grContext->createPlatformTexture(textureDesc)); |
| 44 SkAutoTUnref<SkDevice> device(new SkGpuDevice(grContext, target.get())); |
| 45 return adoptPtr(new SkCanvas(device.get())); |
| 46 } |
| 47 |
| 25 } // anonymous namespace | 48 } // anonymous namespace |
| 26 | 49 |
| 27 namespace cc { | 50 namespace cc { |
| 28 | 51 |
| 29 ThrottledTextureUploader::Query::Query(WebKit::WebGraphicsContext3D* context) | 52 ThrottledTextureUploader::Query::Query(WebKit::WebGraphicsContext3D* context) |
| 30 : m_context(context) | 53 : m_context(context) |
| 31 , m_queryId(0) | 54 , m_queryId(0) |
| 32 , m_value(0) | 55 , m_value(0) |
| 33 , m_hasValue(false) | 56 , m_hasValue(false) |
| 34 , m_isNonBlocking(false) | 57 , m_isNonBlocking(false) |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 143 | 166 |
| 144 void ThrottledTextureUploader::endQuery() | 167 void ThrottledTextureUploader::endQuery() |
| 145 { | 168 { |
| 146 m_availableQueries.first()->end(); | 169 m_availableQueries.first()->end(); |
| 147 m_pendingQueries.append(m_availableQueries.takeFirst()); | 170 m_pendingQueries.append(m_availableQueries.takeFirst()); |
| 148 m_numBlockingTextureUploads++; | 171 m_numBlockingTextureUploads++; |
| 149 } | 172 } |
| 150 | 173 |
| 151 void ThrottledTextureUploader::uploadTexture(CCResourceProvider* resourceProvide
r, Parameters upload) | 174 void ThrottledTextureUploader::uploadTexture(CCResourceProvider* resourceProvide
r, Parameters upload) |
| 152 { | 175 { |
| 153 bool isFullUpload = upload.destOffset.isZero() && | 176 bool isFullUpload = upload.geometry.destOffset.isZero() && |
| 154 upload.sourceRect.size() == upload.texture->texture()->s
ize(); | 177 upload.geometry.sourceRect.size() == upload.texture->siz
e(); |
| 155 | 178 |
| 156 if (isFullUpload) | 179 if (isFullUpload) |
| 157 beginQuery(); | 180 beginQuery(); |
| 158 | 181 |
| 159 upload.texture->updateRect(resourceProvider, upload.sourceRect, upload.destO
ffset); | 182 if (upload.bitmap) { |
| 183 upload.bitmap->lockPixels(); |
| 184 upload.texture->upload( |
| 185 resourceProvider, |
| 186 static_cast<const uint8_t*>(upload.bitmap->getPixels()), |
| 187 upload.geometry.contentRect, |
| 188 upload.geometry.sourceRect, |
| 189 upload.geometry.destOffset); |
| 190 upload.bitmap->unlockPixels(); |
| 191 } |
| 192 |
| 193 // TODO(reveman): Move this logic to CCTextureUpdateController after |
| 194 // removing Parameters struct. |
| 195 if (upload.picture) { |
| 196 CCPrioritizedTexture* texture = upload.texture; |
| 197 IntRect pictureRect = upload.geometry.contentRect; |
| 198 IntRect sourceRect = upload.geometry.sourceRect; |
| 199 IntSize destOffset = upload.geometry.destOffset; |
| 200 |
| 201 texture->acquireBackingTexture(resourceProvider); |
| 202 ASSERT(texture->haveBackingTexture()); |
| 203 |
| 204 ASSERT(resourceProvider->resourceType(texture->resourceId()) == |
| 205 CCResourceProvider::GLTexture); |
| 206 |
| 207 WebGraphicsContext3D* paintContext = CCProxy::hasImplThread() ? |
| 208 WebSharedGraphicsContext3D::compositorThreadContext() : |
| 209 WebSharedGraphicsContext3D::mainThreadContext(); |
| 210 GrContext* paintGrContext = CCProxy::hasImplThread() ? |
| 211 WebSharedGraphicsContext3D::compositorThreadGrContext() : |
| 212 WebSharedGraphicsContext3D::mainThreadGrContext(); |
| 213 |
| 214 // Flush the context in which the backing texture is created so that it |
| 215 // is available in other shared contexts. It is important to do here |
| 216 // because the backing texture is created in one context while it is |
| 217 // being written to in another. |
| 218 resourceProvider->flush(); |
| 219 CCResourceProvider::ScopedWriteLockGL lock( |
| 220 resourceProvider, texture->resourceId()); |
| 221 |
| 222 // Make sure ganesh uses the correct GL context. |
| 223 paintContext->makeContextCurrent(); |
| 224 |
| 225 // Create an accelerated canvas to draw on. |
| 226 OwnPtr<SkCanvas> canvas = createAcceleratedCanvas( |
| 227 paintGrContext, texture->size(), lock.textureId()); |
| 228 |
| 229 // The compositor expects the textures to be upside-down so it can flip |
| 230 // the final composited image. Ganesh renders the image upright so we |
| 231 // need to do a y-flip. |
| 232 canvas->translate(0.0, texture->size().height()); |
| 233 canvas->scale(1.0, -1.0); |
| 234 // Clip to the destination on the texture that must be updated. |
| 235 canvas->clipRect(SkRect::MakeXYWH(destOffset.width(), |
| 236 destOffset.height(), |
| 237 sourceRect.width(), |
| 238 sourceRect.height())); |
| 239 // Translate the origin of pictureRect to destOffset. |
| 240 // Note that destOffset is defined relative to sourceRect. |
| 241 canvas->translate( |
| 242 pictureRect.x() - sourceRect.x() + destOffset.width(), |
| 243 pictureRect.y() - sourceRect.y() + destOffset.height()); |
| 244 canvas->drawPicture(*upload.picture); |
| 245 |
| 246 // Flush ganesh context so that all the rendered stuff appears on the |
| 247 // texture. |
| 248 paintGrContext->flush(); |
| 249 |
| 250 // Flush the GL context so rendering results from this context are |
| 251 // visible in the compositor's context. |
| 252 paintContext->flush(); |
| 253 } |
| 160 | 254 |
| 161 if (isFullUpload) | 255 if (isFullUpload) |
| 162 endQuery(); | 256 endQuery(); |
| 163 } | 257 } |
| 164 | 258 |
| 165 void ThrottledTextureUploader::processQueries() | 259 void ThrottledTextureUploader::processQueries() |
| 166 { | 260 { |
| 167 while (!m_pendingQueries.isEmpty()) { | 261 while (!m_pendingQueries.isEmpty()) { |
| 168 if (m_pendingQueries.first()->isPending()) | 262 if (m_pendingQueries.first()->isPending()) |
| 169 break; | 263 break; |
| 170 | 264 |
| 171 unsigned usElapsed = m_pendingQueries.first()->value(); | 265 unsigned usElapsed = m_pendingQueries.first()->value(); |
| 172 WebKit::Platform::current()->histogramCustomCounts("Renderer4.TextureGpu
UploadTimeUS", usElapsed, 0, 100000, 50); | 266 WebKit::Platform::current()->histogramCustomCounts("Renderer4.TextureGpu
UploadTimeUS", usElapsed, 0, 100000, 50); |
| 173 | 267 |
| 174 if (!m_pendingQueries.first()->isNonBlocking()) | 268 if (!m_pendingQueries.first()->isNonBlocking()) |
| 175 m_numBlockingTextureUploads--; | 269 m_numBlockingTextureUploads--; |
| 176 | 270 |
| 177 // Remove the oldest values from our history and insert the new one | 271 // Remove the oldest values from our history and insert the new one |
| 178 double texturesPerSecond = 1.0 / (usElapsed * 1e-6); | 272 double texturesPerSecond = 1.0 / (usElapsed * 1e-6); |
| 179 m_texturesPerSecondHistory.pop_back(); | 273 m_texturesPerSecondHistory.pop_back(); |
| 180 m_texturesPerSecondHistory.push_front(texturesPerSecond); | 274 m_texturesPerSecondHistory.push_front(texturesPerSecond); |
| 181 | 275 |
| 182 m_availableQueries.append(m_pendingQueries.takeFirst()); | 276 m_availableQueries.append(m_pendingQueries.takeFirst()); |
| 183 } | 277 } |
| 184 } | 278 } |
| 185 | 279 |
| 186 } | 280 } |
| OLD | NEW |