Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(427)

Side by Side Diff: third_party/WebKit/Source/platform/graphics/Canvas2DLayerBridge.cpp

Issue 1752083003: mac: Use IOSurfaces in Canvas2DLayerBridge. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@temp36_canvas2d_refactor
Patch Set: Rebase. Group macros. Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2012 Google Inc. All rights reserved. 2 * Copyright (C) 2012 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation", TRACE_EVENT_ SCOPE_GLOBAL); 132 TRACE_EVENT_INSTANT0("test_gpu", "Canvas2DLayerBridgeCreation", TRACE_EVENT_ SCOPE_GLOBAL);
133 startRecording(); 133 startRecording();
134 #ifndef NDEBUG 134 #ifndef NDEBUG
135 canvas2DLayerBridgeInstanceCounter().increment(); 135 canvas2DLayerBridgeInstanceCounter().increment();
136 #endif 136 #endif
137 } 137 }
138 138
139 Canvas2DLayerBridge::~Canvas2DLayerBridge() 139 Canvas2DLayerBridge::~Canvas2DLayerBridge()
140 { 140 {
141 ASSERT(m_destructionInProgress); 141 ASSERT(m_destructionInProgress);
142 #if USE_IOSURFACE_FOR_2D_CANVAS
143 clearCHROMIUMImageCache();
144 #endif // USE_IOSURFACE_FOR_2D_CANVAS
145
142 m_layer.clear(); 146 m_layer.clear();
143 ASSERT(m_mailboxes.size() == 0); 147 ASSERT(m_mailboxes.size() == 0);
144 #ifndef NDEBUG 148 #ifndef NDEBUG
145 canvas2DLayerBridgeInstanceCounter().decrement(); 149 canvas2DLayerBridgeInstanceCounter().decrement();
146 #endif 150 #endif
147 } 151 }
148 152
149 void Canvas2DLayerBridge::startRecording() 153 void Canvas2DLayerBridge::startRecording()
150 { 154 {
151 ASSERT(m_isDeferralEnabled); 155 ASSERT(m_isDeferralEnabled);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
194 // of the canvas would result in the canvas being accelerated. Presentation is assumed to be 198 // of the canvas would result in the canvas being accelerated. Presentation is assumed to be
195 // a 'PreferAcceleration' operation. 199 // a 'PreferAcceleration' operation.
196 return shouldAccelerate(PreferAcceleration); 200 return shouldAccelerate(PreferAcceleration);
197 } 201 }
198 202
199 GLenum Canvas2DLayerBridge::getGLFilter() 203 GLenum Canvas2DLayerBridge::getGLFilter()
200 { 204 {
201 return m_filterQuality == kNone_SkFilterQuality ? GL_NEAREST : GL_LINEAR; 205 return m_filterQuality == kNone_SkFilterQuality ? GL_NEAREST : GL_LINEAR;
202 } 206 }
203 207
204 Canvas2DLayerBridge::MailboxInfo& Canvas2DLayerBridge::createMailboxInfo() 208 #if USE_IOSURFACE_FOR_2D_CANVAS
209 bool Canvas2DLayerBridge::prepareIOSurfaceMailboxFromImage(SkImage* image, WebEx ternalTextureMailbox* outMailbox)
210 {
211 // Need to flush skia's internal queue because texture is about to be access ed directly
212 GrContext* grContext = m_contextProvider->grContext();
213 grContext->flush();
214
215 ImageInfo imageInfo = createIOSurfaceBackedTexture();
216 if (imageInfo.empty())
217 return false;
218
219 GLuint imageTexture = skia::GrBackendObjectToGrGLTextureInfo(image->getTextu reHandle(true))->fID;
220 context()->copySubTextureCHROMIUM(imageTexture, imageInfo.m_textureId, 0, 0, 0, 0, m_size.width(), m_size.height(), GL_FALSE, GL_FALSE, GL_FALSE);
221
222 MailboxInfo& info = m_mailboxes.first();
223 info.m_mailbox.textureTarget = GC3D_TEXTURE_RECTANGLE_ARB;
224 context()->genMailboxCHROMIUM(info.m_mailbox.name);
225 context()->produceTextureDirectCHROMIUM(imageInfo.m_textureId, info.m_mailbo x.textureTarget, info.m_mailbox.name);
226 info.m_mailbox.allowOverlay = true;
227
228 const WGC3Duint64 fenceSync = context()->insertFenceSyncCHROMIUM();
229 context()->flush();
230 info.m_mailbox.validSyncToken = context()->genSyncTokenCHROMIUM(fenceSync, i nfo.m_mailbox.syncToken);
231
232 info.m_imageInfo = imageInfo;
233 *outMailbox = info.m_mailbox;
234
235 context()->bindTexture(GC3D_TEXTURE_RECTANGLE_ARB, 0);
236
237 // Because we are changing the texture binding without going through skia,
238 // we must dirty the context.
239 grContext->resetContext(kTextureBinding_GrGLBackendState);
240
241 return true;
242 }
243
244 Canvas2DLayerBridge::ImageInfo Canvas2DLayerBridge::createIOSurfaceBackedTexture ()
245 {
246 if (!m_imageInfoCache.isEmpty()) {
247 Canvas2DLayerBridge::ImageInfo info = m_imageInfoCache.last();
248 m_imageInfoCache.removeLast();
249 return info;
250 }
251
252 WebGraphicsContext3D* webContext = context();
253 GLuint imageId = webContext->createGpuMemoryBufferImageCHROMIUM(m_size.width (), m_size.height(), GL_BGRA_EXT, GC3D_SCANOUT_CHROMIUM);
254 if (!imageId)
255 return Canvas2DLayerBridge::ImageInfo();
256
257 GLuint textureId= webContext->createTexture();
258 if (!textureId) {
259 webContext->destroyImageCHROMIUM(imageId);
260 return Canvas2DLayerBridge::ImageInfo();
261 }
262
263 GLenum target = GC3D_TEXTURE_RECTANGLE_ARB;
264 webContext->bindTexture(target, textureId);
265 webContext->texParameteri(target, GL_TEXTURE_MAG_FILTER, getGLFilter());
266 webContext->texParameteri(target, GL_TEXTURE_MIN_FILTER, getGLFilter());
267 webContext->texParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
268 webContext->texParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
269 webContext->bindTexImage2DCHROMIUM(target, imageId);
270
271 return Canvas2DLayerBridge::ImageInfo(imageId, textureId);
272 }
273
274 void Canvas2DLayerBridge::deleteCHROMIUMImage(ImageInfo info)
275 {
276 WebGraphicsContext3D* webContext = context();
277 if (webContext->isContextLost())
278 return;
279
280 GLenum target = GC3D_TEXTURE_RECTANGLE_ARB;
281 webContext->bindTexture(target, info.m_textureId);
282 webContext->releaseTexImage2DCHROMIUM(target, info.m_imageId);
283 webContext->destroyImageCHROMIUM(info.m_imageId);
284 webContext->deleteTexture(info.m_textureId);
285 webContext->bindTexture(target, 0);
286
287 resetSkiaTextureBinding();
288 }
289
290 void Canvas2DLayerBridge::clearCHROMIUMImageCache()
Ken Russell (switch to Gerrit) 2016/03/10 01:58:04 This must be called when the canvas is resized, co
erikchen 2016/03/10 02:03:37 I am under the impression that resizing happens in
Ken Russell (switch to Gerrit) 2016/03/10 02:59:41 OK, yes, it looks like HTMLCanvasElement::m_imageB
291 {
292 for (const auto& it : m_imageInfoCache) {
293 deleteCHROMIUMImage(it);
294 }
295 m_imageInfoCache.clear();
296 }
297 #endif // USE_IOSURFACE_FOR_2D_CANVAS
298
299 void Canvas2DLayerBridge::createMailboxInfo()
205 { 300 {
206 MailboxInfo tmp; 301 MailboxInfo tmp;
207 tmp.m_parentLayerBridge = this; 302 tmp.m_parentLayerBridge = this;
208 m_mailboxes.prepend(tmp); 303 m_mailboxes.prepend(tmp);
209 MailboxInfo& mailboxInfo = m_mailboxes.first();
210 return mailboxInfo;
211 } 304 }
212 305
213 bool Canvas2DLayerBridge::prepareMailboxFromImage(PassRefPtr<SkImage> image, Web ExternalTextureMailbox* outMailbox) 306 bool Canvas2DLayerBridge::prepareMailboxFromImage(PassRefPtr<SkImage> image, Web ExternalTextureMailbox* outMailbox)
214 { 307 {
215 MailboxInfo& mailboxInfo = createMailboxInfo(); 308 createMailboxInfo();
309 MailboxInfo& mailboxInfo = m_mailboxes.first();
216 mailboxInfo.m_mailbox.nearestNeighbor = getGLFilter() == GL_NEAREST; 310 mailboxInfo.m_mailbox.nearestNeighbor = getGLFilter() == GL_NEAREST;
217 mailboxInfo.m_image = image;
218 311
219 GrContext* grContext = m_contextProvider->grContext(); 312 GrContext* grContext = m_contextProvider->grContext();
220 if (!grContext) 313 if (!grContext) {
314 mailboxInfo.m_image = image;
221 return true; // for testing: skip gl stuff when using a mock graphics co ntext. 315 return true; // for testing: skip gl stuff when using a mock graphics co ntext.
316 }
317
318 #if USE_IOSURFACE_FOR_2D_CANVAS
319 if (RuntimeEnabledFeatures::canvas2dImageChromiumEnabled()) {
320 if (prepareIOSurfaceMailboxFromImage(image.get(), outMailbox))
321 return true;
322 // Note: if IOSurface backed texture creation failed we fall back to the
323 // non-IOSurface path.
324 }
325 #endif // USE_IOSURFACE_FOR_2D_CANVAS
326
327 mailboxInfo.m_image = image;
222 328
223 if (RuntimeEnabledFeatures::forceDisable2dCanvasCopyOnWriteEnabled()) 329 if (RuntimeEnabledFeatures::forceDisable2dCanvasCopyOnWriteEnabled())
224 m_surface->notifyContentWillChange(SkSurface::kRetain_ContentChangeMode) ; 330 m_surface->notifyContentWillChange(SkSurface::kRetain_ContentChangeMode) ;
225 331
226 // Need to flush skia's internal queue because texture is about to be access ed directly 332 // Need to flush skia's internal queue because texture is about to be access ed directly
227 grContext->flush(); 333 grContext->flush();
228 334
229 // Because of texture sharing with the compositor, we must invalidate 335 // Because of texture sharing with the compositor, we must invalidate
230 // the state cached in skia so that the deferred copy on write 336 // the state cached in skia so that the deferred copy on write
231 // in SkSurface_Gpu does not make any false assumptions. 337 // in SkSurface_Gpu does not make any false assumptions.
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
264 } 370 }
265 webContext->bindTexture(GL_TEXTURE_2D, 0); 371 webContext->bindTexture(GL_TEXTURE_2D, 0);
266 // Because we are changing the texture binding without going through skia, 372 // Because we are changing the texture binding without going through skia,
267 // we must dirty the context. 373 // we must dirty the context.
268 grContext->resetContext(kTextureBinding_GrGLBackendState); 374 grContext->resetContext(kTextureBinding_GrGLBackendState);
269 375
270 *outMailbox = mailboxInfo.m_mailbox; 376 *outMailbox = mailboxInfo.m_mailbox;
271 return true; 377 return true;
272 } 378 }
273 379
380 void Canvas2DLayerBridge::resetSkiaTextureBinding()
381 {
382 GrContext* grContext = m_contextProvider->grContext();
383 if (grContext)
384 grContext->resetContext(kTextureBinding_GrGLBackendState);
385 }
386
274 static void hibernateWrapper(WeakPtr<Canvas2DLayerBridge> bridge, double /*idleD eadline*/) 387 static void hibernateWrapper(WeakPtr<Canvas2DLayerBridge> bridge, double /*idleD eadline*/)
275 { 388 {
276 if (bridge) { 389 if (bridge) {
277 bridge->hibernate(); 390 bridge->hibernate();
278 } else { 391 } else {
279 Canvas2DLayerBridge::Logger localLogger; 392 Canvas2DLayerBridge::Logger localLogger;
280 localLogger.reportHibernationEvent(Canvas2DLayerBridge::HibernationAbort edDueToDestructionWhileHibernatePending); 393 localLogger.reportHibernationEvent(Canvas2DLayerBridge::HibernationAbort edDueToDestructionWhileHibernatePending);
281 } 394 }
282 } 395 }
283 396
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
327 // case because flushRecordingOnly should only fail it it fails to allocate 440 // case because flushRecordingOnly should only fail it it fails to allocate
328 // a surface, and we have an early exit at the top of this function for when 441 // a surface, and we have an early exit at the top of this function for when
329 // 'this' does not already have a surface. 442 // 'this' does not already have a surface.
330 ASSERT(!m_haveRecordedDrawCommands); 443 ASSERT(!m_haveRecordedDrawCommands);
331 SkPaint copyPaint; 444 SkPaint copyPaint;
332 copyPaint.setXfermodeMode(SkXfermode::kSrc_Mode); 445 copyPaint.setXfermodeMode(SkXfermode::kSrc_Mode);
333 m_surface->draw(tempHibernationSurface->getCanvas(), 0, 0, &copyPaint); // G PU readback 446 m_surface->draw(tempHibernationSurface->getCanvas(), 0, 0, &copyPaint); // G PU readback
334 m_hibernationImage = adoptRef(tempHibernationSurface->newImageSnapshot()); 447 m_hibernationImage = adoptRef(tempHibernationSurface->newImageSnapshot());
335 m_surface.clear(); // destroy the GPU-backed buffer 448 m_surface.clear(); // destroy the GPU-backed buffer
336 m_layer->clearTexture(); 449 m_layer->clearTexture();
450 #if USE_IOSURFACE_FOR_2D_CANVAS
451 clearCHROMIUMImageCache();
452 #endif // USE_IOSURFACE_FOR_2D_CANVAS
337 m_logger->didStartHibernating(); 453 m_logger->didStartHibernating();
338
339 } 454 }
340 455
341 void Canvas2DLayerBridge::reportSurfaceCreationFailure() 456 void Canvas2DLayerBridge::reportSurfaceCreationFailure()
342 { 457 {
343 if (!m_surfaceCreationFailedAtLeastOnce) { 458 if (!m_surfaceCreationFailedAtLeastOnce) {
344 // Only count the failure once per instance so that the histogram may 459 // Only count the failure once per instance so that the histogram may
345 // reflect the proportion of Canvas2DLayerBridge instances with surface 460 // reflect the proportion of Canvas2DLayerBridge instances with surface
346 // allocation failures. 461 // allocation failures.
347 CanvasMetrics::countCanvasContextUsage(CanvasMetrics::GPUAccelerated2DCa nvasSurfaceCreationFailed); 462 CanvasMetrics::countCanvasContextUsage(CanvasMetrics::GPUAccelerated2DCa nvasSurfaceCreationFailed);
348 m_surfaceCreationFailedAtLeastOnce = true; 463 m_surfaceCreationFailedAtLeastOnce = true;
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after
716 --releasedMailboxInfo; 831 --releasedMailboxInfo;
717 if (nameEquals(releasedMailboxInfo->m_mailbox, mailbox)) { 832 if (nameEquals(releasedMailboxInfo->m_mailbox, mailbox)) {
718 break; 833 break;
719 } 834 }
720 ASSERT(releasedMailboxInfo != firstMailbox); 835 ASSERT(releasedMailboxInfo != firstMailbox);
721 } 836 }
722 837
723 if (!contextLost) { 838 if (!contextLost) {
724 // Invalidate texture state in case the compositor altered it since the copy-on-write. 839 // Invalidate texture state in case the compositor altered it since the copy-on-write.
725 if (releasedMailboxInfo->m_image) { 840 if (releasedMailboxInfo->m_image) {
841 #if USE_IOSURFACE_FOR_2D_CANVAS
842 ASSERT(releasedMailboxInfo->m_imageInfo.empty());
843 #endif // USE_IOSURFACE_FOR_2D_CANVAS
726 if (mailbox.validSyncToken) { 844 if (mailbox.validSyncToken) {
727 context()->waitSyncTokenCHROMIUM(mailbox.syncToken); 845 context()->waitSyncTokenCHROMIUM(mailbox.syncToken);
728 } 846 }
729 GrTexture* texture = releasedMailboxInfo->m_image->getTexture(); 847 GrTexture* texture = releasedMailboxInfo->m_image->getTexture();
730 if (texture) { 848 if (texture) {
731 if (lostResource) { 849 if (lostResource) {
732 texture->abandon(); 850 texture->abandon();
733 } else { 851 } else {
734 texture->textureParamsModified(); 852 texture->textureParamsModified();
735 } 853 }
736 } 854 }
737 } 855 }
856
857 #if USE_IOSURFACE_FOR_2D_CANVAS
858 if (!releasedMailboxInfo->m_imageInfo.empty() && !lostResource) {
859 m_imageInfoCache.append(releasedMailboxInfo->m_imageInfo);
860 }
861 #endif // USE_IOSURFACE_FOR_2D_CANVAS
738 } 862 }
739 863
740 RefPtr<Canvas2DLayerBridge> selfRef; 864 RefPtr<Canvas2DLayerBridge> selfRef;
741 if (m_destructionInProgress) { 865 if (m_destructionInProgress) {
742 // To avoid memory use after free, take a scoped self-reference 866 // To avoid memory use after free, take a scoped self-reference
743 // to postpone destruction until the end of this function. 867 // to postpone destruction until the end of this function.
744 selfRef = this; 868 selfRef = this;
745 } 869 }
746 870
747 // The destruction of 'releasedMailboxInfo' will: 871 // The destruction of 'releasedMailboxInfo' will:
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
835 // parameters. 959 // parameters.
836 getOrCreateSurface()->notifyContentWillChange(SkSurface::kRetain_ContentChan geMode); 960 getOrCreateSurface()->notifyContentWillChange(SkSurface::kRetain_ContentChan geMode);
837 return adoptRef(m_surface->newImageSnapshot()); 961 return adoptRef(m_surface->newImageSnapshot());
838 } 962 }
839 963
840 void Canvas2DLayerBridge::willOverwriteCanvas() 964 void Canvas2DLayerBridge::willOverwriteCanvas()
841 { 965 {
842 skipQueuedDrawCommands(); 966 skipQueuedDrawCommands();
843 } 967 }
844 968
969 #if USE_IOSURFACE_FOR_2D_CANVAS
970 Canvas2DLayerBridge::ImageInfo::ImageInfo(GLuint imageId, GLuint textureId) : m_ imageId(imageId), m_textureId(textureId)
971 {
972 ASSERT(imageId);
973 ASSERT(textureId);
974 }
975
976 bool Canvas2DLayerBridge::ImageInfo::empty()
977 {
978 return m_imageId == 0;
979 }
980 #endif // USE_IOSURFACE_FOR_2D_CANVAS
981
845 Canvas2DLayerBridge::MailboxInfo::MailboxInfo(const MailboxInfo& other) 982 Canvas2DLayerBridge::MailboxInfo::MailboxInfo(const MailboxInfo& other)
846 { 983 {
847 memcpy(&m_mailbox, &other.m_mailbox, sizeof(m_mailbox)); 984 memcpy(&m_mailbox, &other.m_mailbox, sizeof(m_mailbox));
848 m_image = other.m_image; 985 m_image = other.m_image;
849 m_parentLayerBridge = other.m_parentLayerBridge; 986 m_parentLayerBridge = other.m_parentLayerBridge;
987 #if USE_IOSURFACE_FOR_2D_CANVAS
988 m_imageInfo = other.m_imageInfo;
989 #endif // USE_IOSURFACE_FOR_2D_CANVAS
850 } 990 }
851 991
852 void Canvas2DLayerBridge::Logger::reportHibernationEvent(HibernationEvent event) 992 void Canvas2DLayerBridge::Logger::reportHibernationEvent(HibernationEvent event)
853 { 993 {
854 DEFINE_STATIC_LOCAL(EnumerationHistogram, hibernationHistogram, ("Canvas.Hib ernationEvents", HibernationEventCount)); 994 DEFINE_STATIC_LOCAL(EnumerationHistogram, hibernationHistogram, ("Canvas.Hib ernationEvents", HibernationEventCount));
855 hibernationHistogram.count(event); 995 hibernationHistogram.count(event);
856 } 996 }
857 997
858 } // namespace blink 998 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698