OLD | NEW |
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 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
48 #include "third_party/skia/include/core/SkPictureRecorder.h" | 48 #include "third_party/skia/include/core/SkPictureRecorder.h" |
49 #include "third_party/skia/include/core/SkSurface.h" | 49 #include "third_party/skia/include/core/SkSurface.h" |
50 #include "third_party/skia/include/gpu/GrContext.h" | 50 #include "third_party/skia/include/gpu/GrContext.h" |
51 #include "third_party/skia/include/gpu/gl/GrGLTypes.h" | 51 #include "third_party/skia/include/gpu/gl/GrGLTypes.h" |
52 #include "wtf/PtrUtil.h" | 52 #include "wtf/PtrUtil.h" |
53 #include <memory> | 53 #include <memory> |
54 | 54 |
55 namespace { | 55 namespace { |
56 enum { | 56 enum { |
57 InvalidMailboxIndex = -1, | 57 InvalidMailboxIndex = -1, |
58 MaxCanvasAnimationBacklog = | 58 MaxCanvasAnimationBacklog = 2, // Make sure the the GPU is never more than |
59 2, // Make sure the the GPU is never more than two animation frames behin
d. | 59 // two animation frames behind. |
60 }; | 60 }; |
61 } // namespace | 61 } // namespace |
62 | 62 |
63 namespace blink { | 63 namespace blink { |
64 | 64 |
65 #if USE_IOSURFACE_FOR_2D_CANVAS | 65 #if USE_IOSURFACE_FOR_2D_CANVAS |
66 struct Canvas2DLayerBridge::ImageInfo : public RefCounted<ImageInfo> { | 66 struct Canvas2DLayerBridge::ImageInfo : public RefCounted<ImageInfo> { |
67 ImageInfo(std::unique_ptr<gfx::GpuMemoryBuffer>, | 67 ImageInfo(std::unique_ptr<gfx::GpuMemoryBuffer>, |
68 GLuint imageId, | 68 GLuint imageId, |
69 GLuint textureId); | 69 GLuint textureId); |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
198 return accelerate; | 198 return accelerate; |
199 } | 199 } |
200 | 200 |
201 bool Canvas2DLayerBridge::isAccelerated() const { | 201 bool Canvas2DLayerBridge::isAccelerated() const { |
202 if (m_accelerationMode == DisableAcceleration) | 202 if (m_accelerationMode == DisableAcceleration) |
203 return false; | 203 return false; |
204 if (isHibernating()) | 204 if (isHibernating()) |
205 return false; | 205 return false; |
206 if (m_softwareRenderingWhileHidden) | 206 if (m_softwareRenderingWhileHidden) |
207 return false; | 207 return false; |
208 if (m_layer) // We don't check m_surface, so this returns true if context was
lost (m_surface is null) with restoration pending. | 208 if (m_layer) { |
| 209 // We don't check |m_surface|, so this returns true if context was lost |
| 210 // (|m_surface| is null) with restoration pending. |
209 return true; | 211 return true; |
| 212 } |
210 if (m_surface) // && !m_layer is implied | 213 if (m_surface) // && !m_layer is implied |
211 return false; | 214 return false; |
212 | 215 |
213 // Whether or not to accelerate is not yet resolved, determine whether immedia
te presentation | 216 // Whether or not to accelerate is not yet resolved. Determine whether |
214 // of the canvas would result in the canvas being accelerated. Presentation is
assumed to be | 217 // immediate presentation of the canvas would result in the canvas being |
215 // a 'PreferAcceleration' operation. | 218 // accelerated. Presentation is assumed to be a 'PreferAcceleration' |
| 219 // operation. |
216 return shouldAccelerate(PreferAcceleration); | 220 return shouldAccelerate(PreferAcceleration); |
217 } | 221 } |
218 | 222 |
219 GLenum Canvas2DLayerBridge::getGLFilter() { | 223 GLenum Canvas2DLayerBridge::getGLFilter() { |
220 return m_filterQuality == kNone_SkFilterQuality ? GL_NEAREST : GL_LINEAR; | 224 return m_filterQuality == kNone_SkFilterQuality ? GL_NEAREST : GL_LINEAR; |
221 } | 225 } |
222 | 226 |
223 #if USE_IOSURFACE_FOR_2D_CANVAS | 227 #if USE_IOSURFACE_FOR_2D_CANVAS |
224 bool Canvas2DLayerBridge::prepareIOSurfaceMailboxFromImage( | 228 bool Canvas2DLayerBridge::prepareIOSurfaceMailboxFromImage( |
225 SkImage* image, | 229 SkImage* image, |
226 cc::TextureMailbox* outMailbox) { | 230 cc::TextureMailbox* outMailbox) { |
227 // Need to flush skia's internal queue because texture is about to be accessed
directly | 231 // Need to flush skia's internal queue, because the texture is about to be |
| 232 // accessed directly. |
228 GrContext* grContext = m_contextProvider->grContext(); | 233 GrContext* grContext = m_contextProvider->grContext(); |
229 grContext->flush(); | 234 grContext->flush(); |
230 | 235 |
231 RefPtr<ImageInfo> imageInfo = createIOSurfaceBackedTexture(); | 236 RefPtr<ImageInfo> imageInfo = createIOSurfaceBackedTexture(); |
232 if (!imageInfo) | 237 if (!imageInfo) |
233 return false; | 238 return false; |
234 | 239 |
235 gpu::gles2::GLES2Interface* gl = contextGL(); | 240 gpu::gles2::GLES2Interface* gl = contextGL(); |
236 if (!gl) | 241 if (!gl) |
237 return false; | 242 return false; |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
355 | 360 |
356 bool Canvas2DLayerBridge::prepareMailboxFromImage( | 361 bool Canvas2DLayerBridge::prepareMailboxFromImage( |
357 sk_sp<SkImage> image, | 362 sk_sp<SkImage> image, |
358 cc::TextureMailbox* outMailbox) { | 363 cc::TextureMailbox* outMailbox) { |
359 createMailboxInfo(); | 364 createMailboxInfo(); |
360 MailboxInfo& mailboxInfo = m_mailboxes.first(); | 365 MailboxInfo& mailboxInfo = m_mailboxes.first(); |
361 | 366 |
362 GrContext* grContext = m_contextProvider->grContext(); | 367 GrContext* grContext = m_contextProvider->grContext(); |
363 if (!grContext) { | 368 if (!grContext) { |
364 mailboxInfo.m_image = std::move(image); | 369 mailboxInfo.m_image = std::move(image); |
365 return true; // for testing: skip gl stuff when using a mock graphics conte
xt. | 370 // For testing, skip GL stuff when using a mock graphics context. |
| 371 return true; |
366 } | 372 } |
367 | 373 |
368 #if USE_IOSURFACE_FOR_2D_CANVAS | 374 #if USE_IOSURFACE_FOR_2D_CANVAS |
369 if (RuntimeEnabledFeatures::canvas2dImageChromiumEnabled()) { | 375 if (RuntimeEnabledFeatures::canvas2dImageChromiumEnabled()) { |
370 if (prepareIOSurfaceMailboxFromImage(image.get(), outMailbox)) | 376 if (prepareIOSurfaceMailboxFromImage(image.get(), outMailbox)) |
371 return true; | 377 return true; |
372 // Note: if IOSurface backed texture creation failed we fall back to the | 378 // Note: if IOSurface backed texture creation failed we fall back to the |
373 // non-IOSurface path. | 379 // non-IOSurface path. |
374 } | 380 } |
375 #endif // USE_IOSURFACE_FOR_2D_CANVAS | 381 #endif // USE_IOSURFACE_FOR_2D_CANVAS |
376 | 382 |
377 mailboxInfo.m_image = std::move(image); | 383 mailboxInfo.m_image = std::move(image); |
378 | 384 |
379 if (RuntimeEnabledFeatures::forceDisable2dCanvasCopyOnWriteEnabled()) | 385 if (RuntimeEnabledFeatures::forceDisable2dCanvasCopyOnWriteEnabled()) |
380 m_surface->notifyContentWillChange(SkSurface::kRetain_ContentChangeMode); | 386 m_surface->notifyContentWillChange(SkSurface::kRetain_ContentChangeMode); |
381 | 387 |
382 // Need to flush skia's internal queue because texture is about to be accessed
directly | 388 // Need to flush skia's internal queue, because the texture is about to be |
| 389 // accessed directly. |
383 grContext->flush(); | 390 grContext->flush(); |
384 | 391 |
385 // Because of texture sharing with the compositor, we must invalidate | 392 // Because of texture sharing with the compositor, we must invalidate |
386 // the state cached in skia so that the deferred copy on write | 393 // the state cached in skia so that the deferred copy on write |
387 // in SkSurface_Gpu does not make any false assumptions. | 394 // in SkSurface_Gpu does not make any false assumptions. |
388 mailboxInfo.m_image->getTexture()->textureParamsModified(); | 395 mailboxInfo.m_image->getTexture()->textureParamsModified(); |
389 | 396 |
390 gpu::gles2::GLES2Interface* gl = contextGL(); | 397 gpu::gles2::GLES2Interface* gl = contextGL(); |
391 if (!gl) | 398 if (!gl) |
392 return false; | 399 return false; |
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
776 gpu::gles2::GLES2Interface* gl = contextGL(); | 783 gpu::gles2::GLES2Interface* gl = contextGL(); |
777 if (isAccelerated() && gl) | 784 if (isAccelerated() && gl) |
778 gl->Flush(); | 785 gl->Flush(); |
779 } | 786 } |
780 | 787 |
781 gpu::gles2::GLES2Interface* Canvas2DLayerBridge::contextGL() { | 788 gpu::gles2::GLES2Interface* Canvas2DLayerBridge::contextGL() { |
782 // Check on m_layer is necessary because contextGL() may be called during | 789 // Check on m_layer is necessary because contextGL() may be called during |
783 // the destruction of m_layer | 790 // the destruction of m_layer |
784 if (m_layer && m_accelerationMode != DisableAcceleration && | 791 if (m_layer && m_accelerationMode != DisableAcceleration && |
785 !m_destructionInProgress) { | 792 !m_destructionInProgress) { |
786 // Call checkSurfaceValid to ensure rate limiter is disabled if context is l
ost. | 793 // Call checkSurfaceValid to ensure the rate limiter is disabled if the |
| 794 // context is lost. |
787 if (!checkSurfaceValid()) | 795 if (!checkSurfaceValid()) |
788 return nullptr; | 796 return nullptr; |
789 } | 797 } |
790 return m_contextProvider ? m_contextProvider->contextGL() : nullptr; | 798 return m_contextProvider ? m_contextProvider->contextGL() : nullptr; |
791 } | 799 } |
792 | 800 |
793 bool Canvas2DLayerBridge::checkSurfaceValid() { | 801 bool Canvas2DLayerBridge::checkSurfaceValid() { |
794 DCHECK(!m_destructionInProgress); | 802 DCHECK(!m_destructionInProgress); |
795 if (m_destructionInProgress) | 803 if (m_destructionInProgress) |
796 return false; | 804 return false; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
832 if (sharedGL && sharedGL->GetGraphicsResetStatusKHR() == GL_NO_ERROR) { | 840 if (sharedGL && sharedGL->GetGraphicsResetStatusKHR() == GL_NO_ERROR) { |
833 GrContext* grCtx = m_contextProvider->grContext(); | 841 GrContext* grCtx = m_contextProvider->grContext(); |
834 bool surfaceIsAccelerated; | 842 bool surfaceIsAccelerated; |
835 sk_sp<SkSurface> surface(createSkSurface(grCtx, m_size, m_msaaSampleCount, | 843 sk_sp<SkSurface> surface(createSkSurface(grCtx, m_size, m_msaaSampleCount, |
836 m_opacityMode, m_colorSpace, | 844 m_opacityMode, m_colorSpace, |
837 &surfaceIsAccelerated)); | 845 &surfaceIsAccelerated)); |
838 | 846 |
839 if (!m_surface) | 847 if (!m_surface) |
840 reportSurfaceCreationFailure(); | 848 reportSurfaceCreationFailure(); |
841 | 849 |
842 // Current paradigm does support switching from accelerated to non-accelerat
ed, which would be tricky | 850 // The current paradigm does not support switching from accelerated to |
843 // due to changes to the layer tree, which can only happen at specific times
during the document lifecycle. | 851 // non-accelerated, which would be tricky due to changes to the layer tree, |
| 852 // which can only happen at specific times during the document lifecycle. |
844 // Therefore, we can only accept the restored surface if it is accelerated. | 853 // Therefore, we can only accept the restored surface if it is accelerated. |
845 if (surface && surfaceIsAccelerated) { | 854 if (surface && surfaceIsAccelerated) { |
846 m_surface = std::move(surface); | 855 m_surface = std::move(surface); |
847 // FIXME: draw sad canvas picture into new buffer crbug.com/243842 | 856 // FIXME: draw sad canvas picture into new buffer crbug.com/243842 |
848 } | 857 } |
849 } | 858 } |
850 if (m_imageBuffer) | 859 if (m_imageBuffer) |
851 m_imageBuffer->updateGPUMemoryUsage(); | 860 m_imageBuffer->updateGPUMemoryUsage(); |
852 | 861 |
853 return m_surface.get(); | 862 return m_surface.get(); |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
946 auto firstMailbox = m_mailboxes.begin(); | 955 auto firstMailbox = m_mailboxes.begin(); |
947 | 956 |
948 while (true) { | 957 while (true) { |
949 --releasedMailboxInfo; | 958 --releasedMailboxInfo; |
950 if (releasedMailboxInfo->m_mailbox == mailbox) | 959 if (releasedMailboxInfo->m_mailbox == mailbox) |
951 break; | 960 break; |
952 DCHECK(releasedMailboxInfo != firstMailbox); | 961 DCHECK(releasedMailboxInfo != firstMailbox); |
953 } | 962 } |
954 | 963 |
955 if (!contextLost) { | 964 if (!contextLost) { |
956 // Invalidate texture state in case the compositor altered it since the copy
-on-write. | 965 // Invalidate texture state in case the compositor altered it since the |
| 966 // copy-on-write. |
957 if (releasedMailboxInfo->m_image) { | 967 if (releasedMailboxInfo->m_image) { |
958 #if USE_IOSURFACE_FOR_2D_CANVAS | 968 #if USE_IOSURFACE_FOR_2D_CANVAS |
959 DCHECK(!releasedMailboxInfo->m_imageInfo); | 969 DCHECK(!releasedMailboxInfo->m_imageInfo); |
960 #endif // USE_IOSURFACE_FOR_2D_CANVAS | 970 #endif // USE_IOSURFACE_FOR_2D_CANVAS |
961 if (syncToken.HasData()) { | 971 if (syncToken.HasData()) { |
962 contextGL()->WaitSyncTokenCHROMIUM(syncToken.GetConstData()); | 972 contextGL()->WaitSyncTokenCHROMIUM(syncToken.GetConstData()); |
963 } | 973 } |
964 GrTexture* texture = releasedMailboxInfo->m_image->getTexture(); | 974 GrTexture* texture = releasedMailboxInfo->m_image->getTexture(); |
965 if (texture) { | 975 if (texture) { |
966 if (lostResource) { | 976 if (lostResource) { |
967 texture->abandon(); | 977 texture->abandon(); |
968 } else { | 978 } else { |
969 texture->textureParamsModified(); | 979 texture->textureParamsModified(); |
970 // Break the mailbox association to avoid leaking mailboxes every time
skia recycles a texture. | 980 // Break the mailbox association to avoid leaking mailboxes every time |
| 981 // skia recycles a texture. |
971 gpu::gles2::GLES2Interface* gl = contextGL(); | 982 gpu::gles2::GLES2Interface* gl = contextGL(); |
972 if (gl) | 983 if (gl) |
973 gl->ProduceTextureDirectCHROMIUM( | 984 gl->ProduceTextureDirectCHROMIUM( |
974 0, GL_TEXTURE_2D, releasedMailboxInfo->m_mailbox.name); | 985 0, GL_TEXTURE_2D, releasedMailboxInfo->m_mailbox.name); |
975 } | 986 } |
976 } | 987 } |
977 } | 988 } |
978 | 989 |
979 #if USE_IOSURFACE_FOR_2D_CANVAS | 990 #if USE_IOSURFACE_FOR_2D_CANVAS |
980 if (releasedMailboxInfo->m_imageInfo && !lostResource) { | 991 if (releasedMailboxInfo->m_imageInfo && !lostResource) { |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1111 default; | 1122 default; |
1112 | 1123 |
1113 void Canvas2DLayerBridge::Logger::reportHibernationEvent( | 1124 void Canvas2DLayerBridge::Logger::reportHibernationEvent( |
1114 HibernationEvent event) { | 1125 HibernationEvent event) { |
1115 DEFINE_STATIC_LOCAL(EnumerationHistogram, hibernationHistogram, | 1126 DEFINE_STATIC_LOCAL(EnumerationHistogram, hibernationHistogram, |
1116 ("Canvas.HibernationEvents", HibernationEventCount)); | 1127 ("Canvas.HibernationEvents", HibernationEventCount)); |
1117 hibernationHistogram.count(event); | 1128 hibernationHistogram.count(event); |
1118 } | 1129 } |
1119 | 1130 |
1120 } // namespace blink | 1131 } // namespace blink |
OLD | NEW |