// Copyright 2013 The Flutter 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 "flutter/shell/gpu/gpu_surface_gl_delegate.h"

#include <cstring>

#include "third_party/skia/include/gpu/gl/GrGLAssembleInterface.h"

namespace flutter {

GPUSurfaceGLDelegate::~GPUSurfaceGLDelegate() = default;

bool GPUSurfaceGLDelegate::GLContextFBOResetAfterPresent() const {
  return false;
}

bool GPUSurfaceGLDelegate::SurfaceSupportsReadback() const {
  return true;
}

SkMatrix GPUSurfaceGLDelegate::GLContextSurfaceTransformation() const {
  SkMatrix matrix;
  matrix.setIdentity();
  return matrix;
}

GPUSurfaceGLDelegate::GLProcResolver GPUSurfaceGLDelegate::GetGLProcResolver()
    const {
  return nullptr;
}

static bool IsProcResolverOpenGLES(
    GPUSurfaceGLDelegate::GLProcResolver proc_resolver) {
  // Version string prefix that identifies an OpenGL ES implementation.
#define GPU_GL_VERSION 0x1F02
  constexpr char kGLESVersionPrefix[] = "OpenGL ES";

  using GLGetStringProc = const char* (*)(uint32_t);

  GLGetStringProc gl_get_string =
      reinterpret_cast<GLGetStringProc>(proc_resolver("glGetString"));

  FML_CHECK(gl_get_string)
      << "The GL proc resolver could not resolve glGetString";

  const char* gl_version_string = gl_get_string(GPU_GL_VERSION);

  FML_CHECK(gl_version_string)
      << "The GL proc resolver's glGetString(GL_VERSION) failed";

  return strncmp(gl_version_string, kGLESVersionPrefix,
                 strlen(kGLESVersionPrefix)) == 0;
}

static sk_sp<const GrGLInterface> CreateGLInterface(
    GPUSurfaceGLDelegate::GLProcResolver proc_resolver) {
  if (proc_resolver == nullptr) {
    // If there is no custom proc resolver, ask Skia to guess the native
    // interface. This often leads to interesting results on most platforms.
    return GrGLMakeNativeInterface();
  }

  struct ProcResolverContext {
    GPUSurfaceGLDelegate::GLProcResolver resolver;
  };

  ProcResolverContext context = {proc_resolver};

  GrGLGetProc gl_get_proc = [](void* context,
                               const char gl_proc_name[]) -> GrGLFuncPtr {
    auto proc_resolver_context =
        reinterpret_cast<ProcResolverContext*>(context);
    return reinterpret_cast<GrGLFuncPtr>(
        proc_resolver_context->resolver(gl_proc_name));
  };

  // glGetString indicates an OpenGL ES interface.
  if (IsProcResolverOpenGLES(proc_resolver)) {
    return GrGLMakeAssembledGLESInterface(&context, gl_get_proc);
  }

  // Fallback to OpenGL.
  if (auto interface = GrGLMakeAssembledGLInterface(&context, gl_get_proc)) {
    return interface;
  }

  FML_LOG(ERROR) << "Could not create a valid GL interface.";
  return nullptr;
}

sk_sp<const GrGLInterface> GPUSurfaceGLDelegate::GetGLInterface() const {
  return CreateGLInterface(GetGLProcResolver());
}

sk_sp<const GrGLInterface>
GPUSurfaceGLDelegate::GetDefaultPlatformGLInterface() {
  return CreateGLInterface(nullptr);
}

bool GPUSurfaceGLDelegate::AllowsDrawingWhenGpuDisabled() const {
  return true;
}

}  // namespace flutter
