// 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;
}

SurfaceFrame::FramebufferInfo GPUSurfaceGLDelegate::GLContextFramebufferInfo()
    const {
  SurfaceFrame::FramebufferInfo res;
  res.supports_readback = true;
  return res;
}

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";

#ifdef WIN32
  using GLGetStringProc = const char*(__stdcall*)(uint32_t);
#else
  using GLGetStringProc = const char* (*)(uint32_t);
#endif

  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
