// 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 "fl_renderer.h"

#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/linux/egl_utils.h"

G_DEFINE_QUARK(fl_renderer_error_quark, fl_renderer_error)

typedef struct {
  EGLDisplay egl_display;
  EGLConfig egl_config;
  EGLSurface egl_surface;
  EGLContext egl_context;

  EGLSurface resource_surface;
  EGLContext resource_context;
} FlRendererPrivate;

G_DEFINE_TYPE_WITH_PRIVATE(FlRenderer, fl_renderer, G_TYPE_OBJECT)

static void fl_renderer_class_init(FlRendererClass* klass) {}

static void fl_renderer_init(FlRenderer* self) {}

// Initializes EGL and gets a valid EGL OpenGL ES configuration.
static gboolean setup_egl_display(FlRenderer* self, GError** error) {
  FlRendererPrivate* priv =
      static_cast<FlRendererPrivate*>(fl_renderer_get_instance_private(self));

  if (priv->egl_display != EGL_NO_DISPLAY) {
    g_set_error(error, fl_renderer_error_quark(), FL_RENDERER_ERROR_FAILED,
                "EGL display already set up");
    return FALSE;
  }

  priv->egl_display = FL_RENDERER_GET_CLASS(self)->create_display(self);

  if (priv->egl_display == EGL_NO_DISPLAY) {
    g_set_error(error, fl_renderer_error_quark(), FL_RENDERER_ERROR_FAILED,
                "Failed to create EGL display");
    return FALSE;
  }

  if (!eglInitialize(priv->egl_display, nullptr, nullptr)) {
    g_set_error(error, fl_renderer_error_quark(), FL_RENDERER_ERROR_FAILED,
                "Failed to initialze EGL");
    return FALSE;
  }

  EGLint attributes[] = {EGL_RENDERABLE_TYPE,
                         EGL_OPENGL_ES2_BIT,
                         EGL_RED_SIZE,
                         8,
                         EGL_GREEN_SIZE,
                         8,
                         EGL_BLUE_SIZE,
                         8,
                         EGL_ALPHA_SIZE,
                         8,
                         EGL_NONE};
  EGLint n_config;
  if (!eglChooseConfig(priv->egl_display, attributes, &priv->egl_config, 1,
                       &n_config)) {
    g_set_error(error, fl_renderer_error_quark(), FL_RENDERER_ERROR_FAILED,
                "Failed to choose EGL config: %s",
                egl_error_to_string(eglGetError()));
    return FALSE;
  }

  if (n_config == 0) {
    g_set_error(error, fl_renderer_error_quark(), FL_RENDERER_ERROR_FAILED,
                "Failed to find appropriate EGL config: %s",
                egl_error_to_string(eglGetError()));
    return FALSE;
  }

  if (!eglBindAPI(EGL_OPENGL_ES_API)) {
    EGLint egl_error = eglGetError();  // Must be before egl_config_to_string().
    g_autofree gchar* config_string =
        egl_config_to_string(priv->egl_display, priv->egl_config);
    g_set_error(error, fl_renderer_error_quark(), FL_RENDERER_ERROR_FAILED,
                "Failed to bind EGL OpenGL ES API using configuration (%s): %s",
                config_string, egl_error_to_string(egl_error));
    return FALSE;
  }

  return TRUE;
}

// Creates a GDK window that can be rendered to using EGL.
static gboolean setup_gdk_window(FlRenderer* self,
                                 GtkWidget* widget,
                                 GError** error) {
  FlRendererPrivate* priv =
      static_cast<FlRendererPrivate*>(fl_renderer_get_instance_private(self));

  if (priv->egl_display == EGL_NO_DISPLAY) {
    g_set_error(error, fl_renderer_error_quark(), FL_RENDERER_ERROR_FAILED,
                "Can not set up GDK window: EGL display not created");
    return FALSE;
  }

  GtkAllocation allocation;
  gtk_widget_get_allocation(widget, &allocation);

  GdkWindowAttr window_attributes;
  window_attributes.window_type = GDK_WINDOW_CHILD;
  window_attributes.x = allocation.x;
  window_attributes.y = allocation.y;
  window_attributes.width = allocation.width;
  window_attributes.height = allocation.height;
  window_attributes.wclass = GDK_INPUT_OUTPUT;
  window_attributes.event_mask =
      gtk_widget_get_events(widget) | GDK_EXPOSURE_MASK |
      GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK |
      GDK_BUTTON_RELEASE_MASK | GDK_SCROLL_MASK | GDK_SMOOTH_SCROLL_MASK |
      GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK;

  gint window_attributes_mask = GDK_WA_X | GDK_WA_Y;

  if (FL_RENDERER_GET_CLASS(self)->setup_window_attr) {
    if (!FL_RENDERER_GET_CLASS(self)->setup_window_attr(
            self, widget, priv->egl_display, priv->egl_config,
            &window_attributes, &window_attributes_mask, error)) {
      return FALSE;
    }
  }

  GdkWindow* window =
      gdk_window_new(gtk_widget_get_parent_window(widget), &window_attributes,
                     window_attributes_mask);
  gtk_widget_register_window(widget, window);
  gtk_widget_set_window(widget, window);

  if (FL_RENDERER_GET_CLASS(self)->set_window) {
    FL_RENDERER_GET_CLASS(self)->set_window(self, window);
  }

  return TRUE;
}

// Creates the EGL surfaces that Flutter will render to.
static gboolean setup_egl_surfaces(FlRenderer* self, GError** error) {
  FlRendererPrivate* priv =
      static_cast<FlRendererPrivate*>(fl_renderer_get_instance_private(self));

  if (priv->egl_surface != EGL_NO_SURFACE ||
      priv->resource_surface != EGL_NO_SURFACE) {
    g_set_error(error, fl_renderer_error_quark(), FL_RENDERER_ERROR_FAILED,
                "setup_egl_surfaces() called after surfaces already created");
    return FALSE;
  }

  if (!FL_RENDERER_GET_CLASS(self)->create_surfaces(
          self, priv->egl_display, priv->egl_config, &priv->egl_surface,
          &priv->resource_surface, error)) {
    return FALSE;
  }

  EGLint context_attributes[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};

  priv->egl_context = eglCreateContext(priv->egl_display, priv->egl_config,
                                       EGL_NO_CONTEXT, context_attributes);
  priv->resource_context =
      eglCreateContext(priv->egl_display, priv->egl_config, priv->egl_context,
                       context_attributes);
  if (priv->egl_context == EGL_NO_CONTEXT ||
      priv->resource_context == EGL_NO_CONTEXT) {
    EGLint egl_error = eglGetError();  // Must be before egl_config_to_string().
    g_autofree gchar* config_string =
        egl_config_to_string(priv->egl_display, priv->egl_config);
    g_set_error(error, fl_renderer_error_quark(), FL_RENDERER_ERROR_FAILED,
                "Failed to create EGL contexts using configuration (%s): %s",
                config_string, egl_error_to_string(egl_error));
    return FALSE;
  }

  return TRUE;
}

gboolean fl_renderer_start(FlRenderer* self,
                           GtkWidget* widget,
                           GError** error) {
  if (!setup_egl_display(self, error)) {
    return FALSE;
  }

  if (!setup_gdk_window(self, widget, error)) {
    return FALSE;
  }

  if (!setup_egl_surfaces(self, error)) {
    return FALSE;
  }

  return TRUE;
}

void fl_renderer_set_geometry(FlRenderer* self,
                              GdkRectangle* geometry,
                              gint scale) {
  g_return_if_fail(FL_IS_RENDERER(self));

  if (FL_RENDERER_GET_CLASS(self)->set_geometry) {
    FL_RENDERER_GET_CLASS(self)->set_geometry(self, geometry, scale);
  }
}

void* fl_renderer_get_proc_address(FlRenderer* self, const char* name) {
  return reinterpret_cast<void*>(eglGetProcAddress(name));
}

gboolean fl_renderer_make_current(FlRenderer* self, GError** error) {
  FlRendererPrivate* priv =
      static_cast<FlRendererPrivate*>(fl_renderer_get_instance_private(self));

  if (priv->egl_surface == EGL_NO_SURFACE ||
      priv->egl_context == EGL_NO_CONTEXT) {
    g_set_error(error, fl_renderer_error_quark(), FL_RENDERER_ERROR_FAILED,
                "Failed to make EGL context current: No surface created");
    return FALSE;
  }

  if (!eglMakeCurrent(priv->egl_display, priv->egl_surface, priv->egl_surface,
                      priv->egl_context)) {
    g_set_error(error, fl_renderer_error_quark(), FL_RENDERER_ERROR_FAILED,
                "Failed to make EGL context current: %s",
                egl_error_to_string(eglGetError()));
    return FALSE;
  }

  return TRUE;
}

gboolean fl_renderer_make_resource_current(FlRenderer* self, GError** error) {
  FlRendererPrivate* priv =
      static_cast<FlRendererPrivate*>(fl_renderer_get_instance_private(self));

  if (priv->resource_surface == EGL_NO_SURFACE ||
      priv->resource_context == EGL_NO_CONTEXT) {
    g_set_error(
        error, fl_renderer_error_quark(), FL_RENDERER_ERROR_FAILED,
        "Failed to make EGL resource context current: No surface created");
    return FALSE;
  }

  if (!eglMakeCurrent(priv->egl_display, priv->resource_surface,
                      priv->resource_surface, priv->resource_context)) {
    g_set_error(error, fl_renderer_error_quark(), FL_RENDERER_ERROR_FAILED,
                "Failed to make EGL resource context current: %s",
                egl_error_to_string(eglGetError()));
    return FALSE;
  }

  return TRUE;
}

gboolean fl_renderer_clear_current(FlRenderer* self, GError** error) {
  FlRendererPrivate* priv =
      static_cast<FlRendererPrivate*>(fl_renderer_get_instance_private(self));

  if (!eglMakeCurrent(priv->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
                      EGL_NO_CONTEXT)) {
    g_set_error(error, fl_renderer_error_quark(), FL_RENDERER_ERROR_FAILED,
                "Failed to clear EGL context: %s",
                egl_error_to_string(eglGetError()));
    return FALSE;
  }

  return TRUE;
}

guint32 fl_renderer_get_fbo(FlRenderer* self) {
  // There is only one frame buffer object - always return that.
  return 0;
}

gboolean fl_renderer_present(FlRenderer* self, GError** error) {
  FlRendererPrivate* priv =
      static_cast<FlRendererPrivate*>(fl_renderer_get_instance_private(self));

  if (!eglSwapBuffers(priv->egl_display, priv->egl_surface)) {
    g_set_error(error, fl_renderer_error_quark(), FL_RENDERER_ERROR_FAILED,
                "Failed to swap EGL buffers: %s",
                egl_error_to_string(eglGetError()));
    return FALSE;
  }

  return TRUE;
}
