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

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

Issue 1755163003: CL for perf tryjob on mac Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: 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 for (const auto& it : m_imageInfoCache) {
143 deleteCHROMIUMImage(it);
144 }
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 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 return true; 193 return true;
190 if (m_surface) // && !m_layer is implied 194 if (m_surface) // && !m_layer is implied
191 return false; 195 return false;
192 196
193 // Whether or not to accelerate is not yet resolved, determine whether immed iate presentation 197 // Whether or not to accelerate is not yet resolved, determine whether immed iate presentation
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
203 GLenum Canvas2DLayerBridge::getGLFilter()
204 {
205 return m_filterQuality == kNone_SkFilterQuality ? GL_NEAREST : GL_LINEAR;
206 }
207
208 bool Canvas2DLayerBridge::prepareIOSurfaceMailboxFromImage(RefPtr<SkImage> image , WebExternalTextureMailbox* outMailbox)
209 {
210 ImageInfo imageInfo = createIOSurfaceBackedTexture();
211 if (imageInfo.empty())
212 return false;
213
214 GLuint imageTexture = skia::GrBackendObjectToGrGLTextureInfo(image->getTextu reHandle(true))->fID;
215 context()->copyTextureCHROMIUM(imageTexture, imageInfo.m_textureId, GL_BGRA_ EXT, GL_UNSIGNED_BYTE, GL_FALSE, GL_FALSE, GL_FALSE);
216
217 MailboxInfo& info = createMailboxInfo();
218 info.m_mailbox.textureTarget = GC3D_TEXTURE_RECTANGLE_ARB;
219 context()->genMailboxCHROMIUM(info.m_mailbox.name);
220 context()->produceTextureDirectCHROMIUM(imageInfo.m_textureId, info.m_mailbo x.textureTarget, info.m_mailbox.name);
221 info.m_mailbox.allowOverlay = true;
222 info.m_mailbox.nearestNeighbor = getGLFilter();
223
224 const WGC3Duint64 fenceSync = context()->insertFenceSyncCHROMIUM();
225 context()->flush();
226 info.m_mailbox.validSyncToken = context()->genSyncTokenCHROMIUM(fenceSync, i nfo.m_mailbox.syncToken);
227
228 info.m_imageInfo = imageInfo;
229 *outMailbox = info.m_mailbox;
230
231 // Because we are changing the texture binding without going through skia,
232 // we must dirty the context.
233 GrContext* grContext = m_contextProvider->grContext();
234 grContext->resetContext(kTextureBinding_GrGLBackendState);
235
236 return true;
237 }
238
239 Canvas2DLayerBridge::ImageInfo Canvas2DLayerBridge::createIOSurfaceBackedTexture ()
240 {
241 if (!m_imageInfoCache.isEmpty()) {
242 Canvas2DLayerBridge::ImageInfo info = m_imageInfoCache.last();
243 m_imageInfoCache.removeLast();
244 return info;
245 }
246
247 WebGraphicsContext3D* webContext = context();
248 GLuint imageId = webContext->createGpuMemoryBufferImageCHROMIUM(m_size.width (), m_size.height(), GL_BGRA_EXT, GC3D_SCANOUT_CHROMIUM);
249 if (!imageId)
250 return Canvas2DLayerBridge::ImageInfo();
251
252 GLuint textureId= webContext->createTexture();
253 if (!textureId) {
254 webContext->destroyImageCHROMIUM(imageId);
255 return Canvas2DLayerBridge::ImageInfo();
256 }
257
258 GLenum target = GC3D_TEXTURE_RECTANGLE_ARB;
259 webContext->bindTexture(target, textureId);
260 webContext->texParameteri(target, GL_TEXTURE_MAG_FILTER, getGLFilter());
261 webContext->texParameteri(target, GL_TEXTURE_MIN_FILTER, getGLFilter());
262 webContext->texParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
263 webContext->texParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
264 webContext->bindTexImage2DCHROMIUM(target, imageId);
265
266 return Canvas2DLayerBridge::ImageInfo(imageId, textureId);
267 }
268
269 Canvas2DLayerBridge::MailboxInfo& Canvas2DLayerBridge::createMailboxInfo()
270 {
271 MailboxInfo tmp;
272 tmp.m_parentLayerBridge = this;
273 m_mailboxes.prepend(tmp);
274 MailboxInfo& mailboxInfo = m_mailboxes.first();
275 return mailboxInfo;
276 }
277
278 bool Canvas2DLayerBridge::prepareMailboxFromImage(RefPtr<SkImage> image, WebExte rnalTextureMailbox* outMailbox)
279 {
280 GrContext* grContext = m_contextProvider->grContext();
281 if (RuntimeEnabledFeatures::canvas2dImageChromiumEnabled()) {
282 if (grContext && prepareIOSurfaceMailboxFromImage(image, outMailbox))
283 return true;
284 }
285
286 MailboxInfo& mailboxInfo = createMailboxInfo();
287 mailboxInfo.m_mailbox.nearestNeighbor = getGLFilter() == GL_NEAREST;
288 mailboxInfo.m_image = image;
289
290 if (!grContext)
291 return true; // for testing: skip gl stuff when using a mock graphics co ntext.
292
293 if (RuntimeEnabledFeatures::forceDisable2dCanvasCopyOnWriteEnabled())
294 m_surface->notifyContentWillChange(SkSurface::kRetain_ContentChangeMode) ;
295
296 // Need to flush skia's internal queue because texture is about to be access ed directly
297 grContext->flush();
298
299 // Because of texture sharing with the compositor, we must invalidate
300 // the state cached in skia so that the deferred copy on write
301 // in SkSurface_Gpu does not make any false assumptions.
302 mailboxInfo.m_image->getTexture()->textureParamsModified();
303 mailboxInfo.m_mailbox.textureTarget = GL_TEXTURE_2D;
304
305 WebGraphicsContext3D* webContext = context();
306 GLuint textureID = skia::GrBackendObjectToGrGLTextureInfo(mailboxInfo.m_imag e->getTextureHandle(true))->fID;
307 webContext->bindTexture(GL_TEXTURE_2D, textureID);
308 webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, getGLFilter( ));
309 webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, getGLFilter( ));
310 webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
311 webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
312
313 // Re-use the texture's existing mailbox, if there is one.
314 if (image->getTexture()->getCustomData()) {
315 ASSERT(image->getTexture()->getCustomData()->size() == sizeof(mailboxInf o.m_mailbox.name));
316 memcpy(&mailboxInfo.m_mailbox.name[0], image->getTexture()->getCustomDat a()->data(), sizeof(mailboxInfo.m_mailbox.name));
317 } else {
318 context()->genMailboxCHROMIUM(mailboxInfo.m_mailbox.name);
319 RefPtr<SkData> mailboxNameData = adoptRef(SkData::NewWithCopy(&mailboxIn fo.m_mailbox.name[0], sizeof(mailboxInfo.m_mailbox.name)));
320 image->getTexture()->setCustomData(mailboxNameData.get());
321 webContext->produceTextureCHROMIUM(GL_TEXTURE_2D, mailboxInfo.m_mailbox. name);
322 }
323
324 if (isHidden()) {
325 // With hidden canvases, we release the SkImage immediately because
326 // there is no need for animations to be double buffered.
327 mailboxInfo.m_image.clear();
328 } else {
329 // FIXME: We'd rather insert a syncpoint than perform a flush here,
330 // but currently the canvas will flicker if we don't flush here.
331 const WGC3Duint64 fenceSync = webContext->insertFenceSyncCHROMIUM();
332 webContext->flush();
333 mailboxInfo.m_mailbox.validSyncToken = webContext->genSyncTokenCHROMIUM( fenceSync, mailboxInfo.m_mailbox.syncToken);
334 }
335 webContext->bindTexture(GL_TEXTURE_2D, 0);
336 // Because we are changing the texture binding without going through skia,
337 // we must dirty the context.
338 grContext->resetContext(kTextureBinding_GrGLBackendState);
339
340 *outMailbox = mailboxInfo.m_mailbox;
341 return true;
342 }
343
344 void Canvas2DLayerBridge::resetSkiaTextureBinding()
345 {
346 GrContext* grContext = m_contextProvider->grContext();
347 if (grContext)
348 grContext->resetContext(kTextureBinding_GrGLBackendState);
349 }
350
351 void Canvas2DLayerBridge::deleteCHROMIUMImage(ImageInfo info)
352 {
353 WebGraphicsContext3D* webContext = context();
354 if (webContext->isContextLost())
355 return;
356
357 GLenum target = GC3D_TEXTURE_RECTANGLE_ARB;
358 webContext->bindTexture(target, info.m_textureId);
359 webContext->releaseTexImage2DCHROMIUM(target, info.m_imageId);
360 webContext->destroyImageCHROMIUM(info.m_imageId);
361 webContext->deleteTexture(info.m_textureId);
362 webContext->bindTexture(target, 0);
363
364 resetSkiaTextureBinding();
365 }
366
199 static void hibernateWrapper(WeakPtr<Canvas2DLayerBridge> bridge, double /*idleD eadline*/) 367 static void hibernateWrapper(WeakPtr<Canvas2DLayerBridge> bridge, double /*idleD eadline*/)
200 { 368 {
201 if (bridge) { 369 if (bridge) {
202 bridge->hibernate(); 370 bridge->hibernate();
203 } else { 371 } else {
204 Canvas2DLayerBridge::Logger localLogger; 372 Canvas2DLayerBridge::Logger localLogger;
205 localLogger.reportHibernationEvent(Canvas2DLayerBridge::HibernationAbort edDueToDestructionWhileHibernatePending); 373 localLogger.reportHibernationEvent(Canvas2DLayerBridge::HibernationAbort edDueToDestructionWhileHibernatePending);
206 } 374 }
207 } 375 }
208 376
(...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after
609 // not care about producing any results for this canvas. 777 // not care about producing any results for this canvas.
610 skipQueuedDrawCommands(); 778 skipQueuedDrawCommands();
611 m_lastImageId = 0; 779 m_lastImageId = 0;
612 return false; 780 return false;
613 } 781 }
614 782
615 RefPtr<SkImage> image = newImageSnapshot(PreferAcceleration, SnapshotReasonU nknown); 783 RefPtr<SkImage> image = newImageSnapshot(PreferAcceleration, SnapshotReasonU nknown);
616 if (!image || !image->getTexture()) 784 if (!image || !image->getTexture())
617 return false; 785 return false;
618 786
619 WebGraphicsContext3D* webContext = context(); 787 // Early exit if canvas was not drawn to since last prepareMailbox.
620 788 GLenum filter = getGLFilter();
621 // Early exit if canvas was not drawn to since last prepareMailbox
622 GLenum filter = m_filterQuality == kNone_SkFilterQuality ? GL_NEAREST : GL_L INEAR;
623 if (image->uniqueID() == m_lastImageId && filter == m_lastFilter) 789 if (image->uniqueID() == m_lastImageId && filter == m_lastFilter)
624 return false; 790 return false;
625 m_lastImageId = image->uniqueID(); 791 m_lastImageId = image->uniqueID();
626 m_lastFilter = filter; 792 m_lastFilter = filter;
627 793
628 { 794 return prepareMailboxFromImage(image, outMailbox);
629 MailboxInfo tmp;
630 tmp.m_image = image;
631 tmp.m_parentLayerBridge = this;
632 m_mailboxes.prepend(tmp);
633 }
634 MailboxInfo& mailboxInfo = m_mailboxes.first();
635
636 mailboxInfo.m_mailbox.nearestNeighbor = filter == GL_NEAREST;
637
638 GrContext* grContext = m_contextProvider->grContext();
639 if (!grContext)
640 return true; // for testing: skip gl stuff when using a mock graphics co ntext.
641
642 if (RuntimeEnabledFeatures::forceDisable2dCanvasCopyOnWriteEnabled())
643 m_surface->notifyContentWillChange(SkSurface::kRetain_ContentChangeMode) ;
644
645 // Because of texture sharing with the compositor, we must invalidate
646 // the state cached in skia so that the deferred copy on write
647 // in SkSurface_Gpu does not make any false assumptions.
648 mailboxInfo.m_image->getTexture()->textureParamsModified();
649 mailboxInfo.m_mailbox.textureTarget = GL_TEXTURE_2D;
650
651 // Passing true because we need to flush skia's internal queue since texture is about to be accessed directly
652 GLuint textureID = skia::GrBackendObjectToGrGLTextureInfo(mailboxInfo.m_imag e->getTextureHandle(true))->fID;
653 webContext->bindTexture(GL_TEXTURE_2D, textureID);
654 webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
655 webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
656 webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
657 webContext->texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
658
659 // Re-use the texture's existing mailbox, if there is one.
660 if (image->getTexture()->getCustomData()) {
661 ASSERT(image->getTexture()->getCustomData()->size() == sizeof(mailboxInf o.m_mailbox.name));
662 memcpy(&mailboxInfo.m_mailbox.name[0], image->getTexture()->getCustomDat a()->data(), sizeof(mailboxInfo.m_mailbox.name));
663 } else {
664 context()->genMailboxCHROMIUM(mailboxInfo.m_mailbox.name);
665 RefPtr<SkData> mailboxNameData = adoptRef(SkData::NewWithCopy(&mailboxIn fo.m_mailbox.name[0], sizeof(mailboxInfo.m_mailbox.name)));
666 image->getTexture()->setCustomData(mailboxNameData.get());
667 webContext->produceTextureCHROMIUM(GL_TEXTURE_2D, mailboxInfo.m_mailbox. name);
668 }
669
670 if (isHidden()) {
671 // With hidden canvases, we release the SkImage immediately because
672 // there is no need for animations to be double buffered.
673 mailboxInfo.m_image.clear();
674 } else {
675 // FIXME: We'd rather insert a syncpoint than perform a flush here,
676 // but currently the canvas will flicker if we don't flush here.
677 const WGC3Duint64 fenceSync = webContext->insertFenceSyncCHROMIUM();
678 webContext->flush();
679 mailboxInfo.m_mailbox.validSyncToken = webContext->genSyncTokenCHROMIUM( fenceSync, mailboxInfo.m_mailbox.syncToken);
680 }
681 webContext->bindTexture(GL_TEXTURE_2D, 0);
682 // Because we are changing the texture binding without going through skia,
683 // we must dirty the context.
684 grContext->resetContext(kTextureBinding_GrGLBackendState);
685
686 *outMailbox = mailboxInfo.m_mailbox;
687 return true;
688 } 795 }
689 796
690 void Canvas2DLayerBridge::mailboxReleased(const WebExternalTextureMailbox& mailb ox, bool lostResource) 797 void Canvas2DLayerBridge::mailboxReleased(const WebExternalTextureMailbox& mailb ox, bool lostResource)
691 { 798 {
692 ASSERT(isAccelerated() || isHibernating()); 799 ASSERT(isAccelerated() || isHibernating());
693 bool contextLost = !isHibernating() && (!m_surface || m_contextProvider->con text3d()->isContextLost()); 800 bool contextLost = !isHibernating() && (!m_surface || m_contextProvider->con text3d()->isContextLost());
694 ASSERT(m_mailboxes.last().m_parentLayerBridge.get() == this); 801 ASSERT(m_mailboxes.last().m_parentLayerBridge.get() == this);
695 802
696 // Mailboxes are typically released in FIFO order, so we iterate 803 // Mailboxes are typically released in FIFO order, so we iterate
697 // from the end of m_mailboxes. 804 // from the end of m_mailboxes.
(...skipping 16 matching lines...) Expand all
714 } 821 }
715 GrTexture* texture = releasedMailboxInfo->m_image->getTexture(); 822 GrTexture* texture = releasedMailboxInfo->m_image->getTexture();
716 if (texture) { 823 if (texture) {
717 if (lostResource) { 824 if (lostResource) {
718 texture->abandon(); 825 texture->abandon();
719 } else { 826 } else {
720 texture->textureParamsModified(); 827 texture->textureParamsModified();
721 } 828 }
722 } 829 }
723 } 830 }
831
832 if (!releasedMailboxInfo->m_imageInfo.empty() && !lostResource) {
833 m_imageInfoCache.append(releasedMailboxInfo->m_imageInfo);
834 }
724 } 835 }
725 836
726 RefPtr<Canvas2DLayerBridge> selfRef; 837 RefPtr<Canvas2DLayerBridge> selfRef;
727 if (m_destructionInProgress) { 838 if (m_destructionInProgress) {
728 // To avoid memory use after free, take a scoped self-reference 839 // To avoid memory use after free, take a scoped self-reference
729 // to postpone destruction until the end of this function. 840 // to postpone destruction until the end of this function.
730 selfRef = this; 841 selfRef = this;
731 } 842 }
732 843
733 // The destruction of 'releasedMailboxInfo' will: 844 // The destruction of 'releasedMailboxInfo' will:
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
821 // parameters. 932 // parameters.
822 getOrCreateSurface()->notifyContentWillChange(SkSurface::kRetain_ContentChan geMode); 933 getOrCreateSurface()->notifyContentWillChange(SkSurface::kRetain_ContentChan geMode);
823 return adoptRef(m_surface->newImageSnapshot()); 934 return adoptRef(m_surface->newImageSnapshot());
824 } 935 }
825 936
826 void Canvas2DLayerBridge::willOverwriteCanvas() 937 void Canvas2DLayerBridge::willOverwriteCanvas()
827 { 938 {
828 skipQueuedDrawCommands(); 939 skipQueuedDrawCommands();
829 } 940 }
830 941
942 Canvas2DLayerBridge::ImageInfo::ImageInfo(GLuint imageId, GLuint textureId) : m_ imageId(imageId), m_textureId(textureId)
943 {
944 ASSERT(imageId);
945 ASSERT(textureId);
946 }
947
948 bool Canvas2DLayerBridge::ImageInfo::empty()
949 {
950 return m_imageId == 0;
951 }
952
831 Canvas2DLayerBridge::MailboxInfo::MailboxInfo(const MailboxInfo& other) 953 Canvas2DLayerBridge::MailboxInfo::MailboxInfo(const MailboxInfo& other)
832 { 954 {
833 memcpy(&m_mailbox, &other.m_mailbox, sizeof(m_mailbox)); 955 memcpy(&m_mailbox, &other.m_mailbox, sizeof(m_mailbox));
834 m_image = other.m_image; 956 m_image = other.m_image;
835 m_parentLayerBridge = other.m_parentLayerBridge; 957 m_parentLayerBridge = other.m_parentLayerBridge;
958 m_imageInfo = other.m_imageInfo;
836 } 959 }
837 960
838 void Canvas2DLayerBridge::Logger::reportHibernationEvent(HibernationEvent event) 961 void Canvas2DLayerBridge::Logger::reportHibernationEvent(HibernationEvent event)
839 { 962 {
840 DEFINE_STATIC_LOCAL(EnumerationHistogram, hibernationHistogram, ("Canvas.Hib ernationEvents", HibernationEventCount)); 963 DEFINE_STATIC_LOCAL(EnumerationHistogram, hibernationHistogram, ("Canvas.Hib ernationEvents", HibernationEventCount));
841 hibernationHistogram.count(event); 964 hibernationHistogram.count(event);
842 } 965 }
843 966
844 } // namespace blink 967 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698