summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc')
-rw-r--r--chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc300
1 files changed, 300 insertions, 0 deletions
diff --git a/chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc b/chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc
new file mode 100644
index 00000000000..3598106da0b
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.cc
@@ -0,0 +1,300 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h"
+
+#include "gpu/command_buffer/client/gles2_interface.h"
+#include "gpu/command_buffer/common/sync_token.h"
+#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/public/platform/web_graphics_context_3d_provider.h"
+#include "third_party/blink/renderer/platform/cross_thread_functional.h"
+#include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h"
+#include "third_party/blink/renderer/platform/graphics/mailbox_texture_holder.h"
+#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
+#include "third_party/blink/renderer/platform/graphics/skia_texture_holder.h"
+#include "third_party/blink/renderer/platform/web_task_runner.h"
+#include "third_party/skia/include/core/SkImage.h"
+#include "third_party/skia/include/gpu/GrTexture.h"
+
+#include <memory>
+#include <utility>
+
+namespace blink {
+
+scoped_refptr<AcceleratedStaticBitmapImage>
+AcceleratedStaticBitmapImage::CreateFromSkImage(
+ sk_sp<SkImage> image,
+ base::WeakPtr<WebGraphicsContext3DProviderWrapper>
+ context_provider_wrapper) {
+ CHECK(image && image->isTextureBacked());
+ return base::AdoptRef(new AcceleratedStaticBitmapImage(
+ std::move(image), std::move(context_provider_wrapper)));
+}
+
+scoped_refptr<AcceleratedStaticBitmapImage>
+AcceleratedStaticBitmapImage::CreateFromWebGLContextImage(
+ const gpu::Mailbox& mailbox,
+ const gpu::SyncToken& sync_token,
+ unsigned texture_id,
+ base::WeakPtr<WebGraphicsContext3DProviderWrapper>&&
+ context_provider_wrapper,
+ IntSize mailbox_size) {
+ return base::AdoptRef(new AcceleratedStaticBitmapImage(
+ mailbox, sync_token, texture_id, std::move(context_provider_wrapper),
+ mailbox_size));
+}
+
+AcceleratedStaticBitmapImage::AcceleratedStaticBitmapImage(
+ sk_sp<SkImage> image,
+ base::WeakPtr<WebGraphicsContext3DProviderWrapper>&&
+ context_provider_wrapper)
+ : paint_image_content_id_(cc::PaintImage::GetNextContentId()) {
+ CHECK(image && image->isTextureBacked());
+ texture_holder_ = std::make_unique<SkiaTextureHolder>(
+ std::move(image), std::move(context_provider_wrapper));
+ thread_checker_.DetachFromThread();
+}
+
+AcceleratedStaticBitmapImage::AcceleratedStaticBitmapImage(
+ const gpu::Mailbox& mailbox,
+ const gpu::SyncToken& sync_token,
+ unsigned texture_id,
+ base::WeakPtr<WebGraphicsContext3DProviderWrapper>&&
+ context_provider_wrapper,
+ IntSize mailbox_size)
+ : paint_image_content_id_(cc::PaintImage::GetNextContentId()) {
+ texture_holder_ = std::make_unique<MailboxTextureHolder>(
+ mailbox, sync_token, texture_id, std::move(context_provider_wrapper),
+ mailbox_size);
+ thread_checker_.DetachFromThread();
+}
+
+namespace {
+
+void DestroySkImageOnOriginalThread(
+ sk_sp<SkImage> image,
+ base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper,
+ std::unique_ptr<gpu::SyncToken> sync_token) {
+ if (context_provider_wrapper &&
+ image->isValid(
+ context_provider_wrapper->ContextProvider()->GetGrContext())) {
+ if (sync_token->HasData()) {
+ // To make sure skia does not recycle the texture while it is still in use
+ // by another context.
+ context_provider_wrapper->ContextProvider()
+ ->ContextGL()
+ ->WaitSyncTokenCHROMIUM(sync_token->GetData());
+ }
+ // In case texture was used by compositor, which may have changed params.
+ image->getTexture()->textureParamsModified();
+ }
+ // destroy by letting |image| go out of scope
+}
+
+} // unnamed namespace
+
+AcceleratedStaticBitmapImage::~AcceleratedStaticBitmapImage() {
+ // If the original SkImage was retained, it must be destroyed on the thread
+ // where it came from. In the same thread case, there is nothing to do because
+ // the regular destruction flow is fine.
+ if (original_skia_image_) {
+ std::unique_ptr<gpu::SyncToken> sync_token =
+ base::WrapUnique(new gpu::SyncToken(texture_holder_->GetSyncToken()));
+ if (original_skia_image_thread_id_ !=
+ Platform::Current()->CurrentThread()->ThreadId()) {
+ PostCrossThreadTask(
+ *original_skia_image_task_runner_, FROM_HERE,
+ CrossThreadBind(
+ &DestroySkImageOnOriginalThread, std::move(original_skia_image_),
+ std::move(original_skia_image_context_provider_wrapper_),
+ WTF::Passed(std::move(sync_token))));
+ } else {
+ DestroySkImageOnOriginalThread(
+ std::move(original_skia_image_),
+ std::move(original_skia_image_context_provider_wrapper_),
+ std::move(sync_token));
+ }
+ }
+}
+
+void AcceleratedStaticBitmapImage::RetainOriginalSkImage() {
+ DCHECK(texture_holder_->IsSkiaTextureHolder());
+ original_skia_image_ = texture_holder_->GetSkImage();
+ original_skia_image_context_provider_wrapper_ = ContextProviderWrapper();
+ DCHECK(original_skia_image_);
+ WebThread* thread = Platform::Current()->CurrentThread();
+ original_skia_image_thread_id_ = thread->ThreadId();
+ original_skia_image_task_runner_ = thread->GetTaskRunner();
+}
+
+IntSize AcceleratedStaticBitmapImage::Size() const {
+ return texture_holder_->Size();
+}
+
+scoped_refptr<StaticBitmapImage>
+AcceleratedStaticBitmapImage::MakeUnaccelerated() {
+ CreateImageFromMailboxIfNeeded();
+ return StaticBitmapImage::Create(
+ texture_holder_->GetSkImage()->makeNonTextureImage());
+}
+
+void AcceleratedStaticBitmapImage::UpdateSyncToken(gpu::SyncToken sync_token) {
+ texture_holder_->UpdateSyncToken(sync_token);
+}
+
+bool AcceleratedStaticBitmapImage::CopyToTexture(
+ gpu::gles2::GLES2Interface* dest_gl,
+ GLenum dest_target,
+ GLuint dest_texture_id,
+ bool unpack_premultiply_alpha,
+ bool unpack_flip_y,
+ const IntPoint& dest_point,
+ const IntRect& source_sub_rectangle) {
+ CheckThread();
+ if (!IsValid())
+ return false;
+ // This method should only be used for cross-context copying, otherwise it's
+ // wasting overhead.
+ DCHECK(texture_holder_->IsCrossThread() ||
+ dest_gl != ContextProviderWrapper()->ContextProvider()->ContextGL());
+
+ // TODO(junov) : could reduce overhead by using kOrderingBarrier when we know
+ // that the source and destination context or on the same stream.
+ EnsureMailbox(kUnverifiedSyncToken, GL_NEAREST);
+
+ // Get a texture id that |destProvider| knows about and copy from it.
+ dest_gl->WaitSyncTokenCHROMIUM(
+ texture_holder_->GetSyncToken().GetConstData());
+ GLuint source_texture_id = dest_gl->CreateAndConsumeTextureCHROMIUM(
+ texture_holder_->GetMailbox().name);
+ dest_gl->CopySubTextureCHROMIUM(
+ source_texture_id, 0, dest_target, dest_texture_id, 0, dest_point.X(),
+ dest_point.Y(), source_sub_rectangle.X(), source_sub_rectangle.Y(),
+ source_sub_rectangle.Width(), source_sub_rectangle.Height(),
+ unpack_flip_y ? GL_FALSE : GL_TRUE, GL_FALSE,
+ unpack_premultiply_alpha ? GL_FALSE : GL_TRUE);
+ // This drops the |destGL| context's reference on our |m_mailbox|, but it's
+ // still held alive by our SkImage.
+ dest_gl->DeleteTextures(1, &source_texture_id);
+
+ // We need to update the texture holder's sync token to ensure that when this
+ // image is deleted, the texture resource will not be recycled by skia before
+ // the above texture copy has completed.
+ gpu::SyncToken sync_token;
+ dest_gl->GenUnverifiedSyncTokenCHROMIUM(sync_token.GetData());
+ texture_holder_->UpdateSyncToken(sync_token);
+
+ return true;
+}
+
+PaintImage AcceleratedStaticBitmapImage::PaintImageForCurrentFrame() {
+ // TODO(ccameron): This function should not ignore |colorBehavior|.
+ // https://crbug.com/672306
+ CheckThread();
+ if (!IsValid())
+ return PaintImage();
+
+ sk_sp<SkImage> image;
+ if (original_skia_image_ &&
+ original_skia_image_thread_id_ ==
+ Platform::Current()->CurrentThread()->ThreadId()) {
+ // We need to avoid consuming the mailbox in the context where it
+ // originated. This avoids swapping back and forth between TextureHolder
+ // types.
+ image = original_skia_image_;
+ } else {
+ CreateImageFromMailboxIfNeeded();
+ image = texture_holder_->GetSkImage();
+ }
+
+ return CreatePaintImageBuilder()
+ .set_image(image, paint_image_content_id_)
+ .set_completion_state(PaintImage::CompletionState::DONE)
+ .TakePaintImage();
+}
+
+void AcceleratedStaticBitmapImage::Draw(PaintCanvas* canvas,
+ const PaintFlags& flags,
+ const FloatRect& dst_rect,
+ const FloatRect& src_rect,
+ RespectImageOrientationEnum,
+ ImageClampingMode image_clamping_mode,
+ ImageDecodingMode decode_mode) {
+ auto paint_image = PaintImageForCurrentFrame();
+ if (!paint_image)
+ return;
+ auto paint_image_decoding_mode = ToPaintImageDecodingMode(decode_mode);
+ if (paint_image.decoding_mode() != paint_image_decoding_mode) {
+ paint_image = PaintImageBuilder::WithCopy(std::move(paint_image))
+ .set_decoding_mode(paint_image_decoding_mode)
+ .TakePaintImage();
+ }
+ StaticBitmapImage::DrawHelper(canvas, flags, dst_rect, src_rect,
+ image_clamping_mode, paint_image);
+}
+
+bool AcceleratedStaticBitmapImage::IsValid() const {
+ return texture_holder_ && texture_holder_->IsValid();
+}
+
+WebGraphicsContext3DProvider* AcceleratedStaticBitmapImage::ContextProvider()
+ const {
+ if (!IsValid())
+ return nullptr;
+ return texture_holder_->ContextProvider();
+}
+
+base::WeakPtr<WebGraphicsContext3DProviderWrapper>
+AcceleratedStaticBitmapImage::ContextProviderWrapper() const {
+ if (!IsValid())
+ return nullptr;
+ return texture_holder_->ContextProviderWrapper();
+}
+
+void AcceleratedStaticBitmapImage::CreateImageFromMailboxIfNeeded() {
+ if (texture_holder_->IsSkiaTextureHolder())
+ return;
+ texture_holder_ =
+ std::make_unique<SkiaTextureHolder>(std::move(texture_holder_));
+}
+
+void AcceleratedStaticBitmapImage::EnsureMailbox(MailboxSyncMode mode,
+ GLenum filter) {
+ if (!texture_holder_->IsMailboxTextureHolder()) {
+ if (!original_skia_image_) {
+ // To ensure that the texture resource stays alive we only really need
+ // to retain the source SkImage until the mailbox is consumed, but this
+ // works too.
+ RetainOriginalSkImage();
+ }
+
+ texture_holder_ = std::make_unique<MailboxTextureHolder>(
+ std::move(texture_holder_), filter);
+ }
+ texture_holder_->Sync(mode);
+}
+
+void AcceleratedStaticBitmapImage::Transfer() {
+ CheckThread();
+ EnsureMailbox(kUnverifiedSyncToken, GL_NEAREST);
+ detach_thread_at_next_check_ = true;
+}
+
+bool AcceleratedStaticBitmapImage::CurrentFrameKnownToBeOpaque() {
+ return texture_holder_->CurrentFrameKnownToBeOpaque();
+}
+
+void AcceleratedStaticBitmapImage::CheckThread() {
+ if (detach_thread_at_next_check_) {
+ thread_checker_.DetachFromThread();
+ detach_thread_at_next_check_ = false;
+ }
+ CHECK(thread_checker_.CalledOnValidThread());
+}
+
+void AcceleratedStaticBitmapImage::Abandon() {
+ texture_holder_->Abandon();
+}
+
+} // namespace blink