text: // Copyright 2019 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 "gpu/command_buffer/service/shared_image_representation_skia_gl.h"
  
  #include "base/memory/ptr_util.h"
  #include "components/viz/common/resources/resource_format_utils.h"
  #include "gpu/command_buffer/service/shared_context_state.h"
  #include "gpu/command_buffer/service/skia_utils.h"
  #include "gpu/command_buffer/service/texture_manager.h"
  #include "third_party/skia/include/core/SkPromiseImageTexture.h"
  #include "third_party/skia/include/gpu/GrBackendSurface.h"
  #include "ui/gl/gl_bindings.h"
  
  namespace gpu {
  
  std::ostream& operator<<(std::ostream& os, RepresentationAccessMode mode) {
    switch (mode) {
      case RepresentationAccessMode::kNone:
        os << "kNone";
        break;
      case RepresentationAccessMode::kRead:
        os << "kRead";
        break;
      case RepresentationAccessMode::kWrite:
        os << "kWrite";
        break;
    }
    return os;
  }
  
  // static method.
  std::unique_ptr<SharedImageRepresentationSkiaGL>
  SharedImageRepresentationSkiaGL::Create(
      std::unique_ptr<SharedImageRepresentationGLTextureBase> gl_representation,
      scoped_refptr<SharedContextState> context_state,
      SharedImageManager* manager,
      SharedImageBacking* backing,
      MemoryTypeTracker* tracker) {
    GrBackendTexture backend_texture;
    if (!GetGrBackendTexture(context_state->feature_info(),
                             gl_representation->GetTextureBase()->target(),
                             backing->size(),
                             gl_representation->GetTextureBase()->service_id(),
                             backing->format(), &backend_texture)) {
      return nullptr;
    }
    auto promise_texture = SkPromiseImageTexture::Make(backend_texture);
    if (!promise_texture)
      return nullptr;
    return base::WrapUnique(new SharedImageRepresentationSkiaGL(
        std::move(gl_representation), std::move(promise_texture),
        std::move(context_state), manager, backing, tracker));
  }
  
  SharedImageRepresentationSkiaGL::SharedImageRepresentationSkiaGL(
      std::unique_ptr<SharedImageRepresentationGLTextureBase> gl_representation,
      sk_sp<SkPromiseImageTexture> promise_texture,
      scoped_refptr<SharedContextState> context_state,
      SharedImageManager* manager,
      SharedImageBacking* backing,
      MemoryTypeTracker* tracker)
      : SharedImageRepresentationSkia(manager, backing, tracker),
        gl_representation_(std::move(gl_representation)),
        promise_texture_(std::move(promise_texture)),
        context_state_(std::move(context_state)) {
    DCHECK(gl_representation_);
  #if DCHECK_IS_ON()
    context_ = gl::GLContext::GetCurrent();
  #endif
  }
  
  SharedImageRepresentationSkiaGL::~SharedImageRepresentationSkiaGL() {
    DCHECK_EQ(RepresentationAccessMode::kNone, mode_);
    surface_.reset();
  }
  
  sk_sp<SkSurface> SharedImageRepresentationSkiaGL::BeginWriteAccess(
      int final_msaa_count,
      const SkSurfaceProps& surface_props,
      std::vector<GrBackendSemaphore>* begin_semaphores,
      std::vector<GrBackendSemaphore>* end_semaphores) {
    DCHECK_EQ(mode_, RepresentationAccessMode::kNone);
    CheckContext();
  
    if (!gl_representation_->BeginAccess(
            GL_SHARED_IMAGE_ACCESS_MODE_READWRITE_CHROMIUM)) {
      return nullptr;
    }
  
    mode_ = RepresentationAccessMode::kWrite;
  
    if (surface_)
      return surface_;
  
    SkColorType sk_color_type = viz::ResourceFormatToClosestSkColorType(
        /*gpu_compositing=*/true, format());
    // TODO(https://crbug.com/1054033): Switch back to
    // MakeFromBackendTextureAsRenderTarget once we no longer use GLRendererCopier
    // with surfaceless surfaces.
    auto surface = SkSurface::MakeFromBackendTexture(
        context_state_->gr_context(), promise_texture_->backendTexture(),
        kTopLeft_GrSurfaceOrigin, final_msaa_count, sk_color_type,
        backing()->color_space().ToSkColorSpace(), &surface_props);
    surface_ = surface;
    return surface;
  }
  
  void SharedImageRepresentationSkiaGL::EndWriteAccess(sk_sp<SkSurface> surface) {
    DCHECK_EQ(mode_, RepresentationAccessMode::kWrite);
    DCHECK(surface_);
    DCHECK_EQ(surface.get(), surface_.get());
  
    surface.reset();
    DCHECK(surface_->unique());
  
    gl_representation_->EndAccess();
    mode_ = RepresentationAccessMode::kNone;
  }
  
  sk_sp<SkPromiseImageTexture> SharedImageRepresentationSkiaGL::BeginReadAccess(
      std::vector<GrBackendSemaphore>* begin_semaphores,
      std::vector<GrBackendSemaphore>* end_semaphores) {
    DCHECK_EQ(mode_, RepresentationAccessMode::kNone);
    CheckContext();
  
    if (!gl_representation_->BeginAccess(
            GL_SHARED_IMAGE_ACCESS_MODE_READ_CHROMIUM)) {
      return nullptr;
    }
    mode_ = RepresentationAccessMode::kRead;
    return promise_texture_;
  }
  
  void SharedImageRepresentationSkiaGL::EndReadAccess() {
    DCHECK_EQ(mode_, RepresentationAccessMode::kRead);
    CheckContext();
  
    gl_representation_->EndAccess();
    mode_ = RepresentationAccessMode::kNone;
  }
  
  void SharedImageRepresentationSkiaGL::CheckContext() {
  #if DCHECK_IS_ON()
    DCHECK(gl::GLContext::GetCurrent() == context_);
  #endif
  }
  
  bool SharedImageRepresentationSkiaGL::SupportsMultipleConcurrentReadAccess() {
    return gl_representation_->SupportsMultipleConcurrentReadAccess();
  }
  
  }  // namespace gpu
  