blob: ab57e09d3d5d36e348726f95f94d7ed10a506a11 [file] [log] [blame]
// 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 "platform/graphics/SkiaTextureHolder.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "platform/CrossThreadFunctional.h"
#include "platform/graphics/MailboxTextureHolder.h"
#include "platform/graphics/gpu/SharedGpuContext.h"
#include "public/platform/Platform.h"
#include "skia/ext/texture_handle.h"
#include "third_party/skia/include/gpu/GrContext.h"
namespace blink {
namespace {
void ReleaseImage(sk_sp<SkImage>&& image,
std::unique_ptr<gpu::SyncToken>&& sync_token) {
if (SharedGpuContext::IsValid() && sync_token->HasData())
SharedGpuContext::Gl()->WaitSyncTokenCHROMIUM(sync_token->GetData());
image.reset();
}
} // namespace
SkiaTextureHolder::SkiaTextureHolder(sk_sp<SkImage> image)
: image_(std::move(image)),
shared_context_id_(SharedGpuContext::ContextId()) {}
SkiaTextureHolder::SkiaTextureHolder(
std::unique_ptr<TextureHolder> texture_holder) {
DCHECK(texture_holder->IsMailboxTextureHolder());
const gpu::Mailbox mailbox = texture_holder->GetMailbox();
const gpu::SyncToken sync_token = texture_holder->GetSyncToken();
const IntSize mailbox_size = texture_holder->Size();
gpu::gles2::GLES2Interface* shared_gl = SharedGpuContext::Gl();
GrContext* shared_gr_context = SharedGpuContext::Gr();
DCHECK(shared_gl &&
shared_gr_context); // context isValid already checked in callers
shared_gl->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
GLuint shared_context_texture_id =
shared_gl->CreateAndConsumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
GrGLTextureInfo texture_info;
texture_info.fTarget = GL_TEXTURE_2D;
texture_info.fID = shared_context_texture_id;
GrBackendTextureDesc backend_texture;
backend_texture.fOrigin = kBottomLeft_GrSurfaceOrigin;
backend_texture.fWidth = mailbox_size.Width();
backend_texture.fHeight = mailbox_size.Height();
backend_texture.fConfig = kSkia8888_GrPixelConfig;
backend_texture.fTextureHandle =
skia::GrGLTextureInfoToGrBackendObject(texture_info);
sk_sp<SkImage> new_image =
SkImage::MakeFromAdoptedTexture(shared_gr_context, backend_texture);
ReleaseImageThreadSafe();
image_ = new_image;
shared_context_id_ = SharedGpuContext::ContextId();
}
SkiaTextureHolder::~SkiaTextureHolder() {
ReleaseImageThreadSafe();
}
unsigned SkiaTextureHolder::SharedContextId() {
return shared_context_id_;
}
void SkiaTextureHolder::ReleaseImageThreadSafe() {
// If m_image belongs to a GrContext that is on another thread, it
// must be released on that thread.
if (TextureThreadTaskRunner() && image_ && WasTransferred() &&
SharedGpuContext::IsValid()) {
gpu::gles2::GLES2Interface* shared_gl = SharedGpuContext::Gl();
std::unique_ptr<gpu::SyncToken> release_sync_token(new gpu::SyncToken);
const GLuint64 fence_sync = shared_gl->InsertFenceSyncCHROMIUM();
shared_gl->Flush();
shared_gl->GenSyncTokenCHROMIUM(fence_sync, release_sync_token->GetData());
TextureThreadTaskRunner()->PostTask(
BLINK_FROM_HERE,
CrossThreadBind(&ReleaseImage, WTF::Passed(std::move(image_)),
WTF::Passed(std::move(release_sync_token))));
}
image_ = nullptr;
SetWasTransferred(false);
SetTextureThreadTaskRunner(nullptr);
}
} // namespace blink