// Copyright 2016 The Fuchsia 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 <string.h>
#include <zircon/process.h>
#include <zircon/syscalls.h>

#include <gfx/gfx.h>

#include "vc.h"

void vc_gfx_draw_char(vc_gfx_t* gfx, vc_t* vc, vc_char_t ch, unsigned x, unsigned y, bool invert) {
  uint8_t fg_color = vc_char_get_fg_color(ch);
  uint8_t bg_color = vc_char_get_bg_color(ch);
  if (invert) {
    // Swap the colors.
    uint8_t temp = fg_color;
    fg_color = bg_color;
    bg_color = temp;
  }
  gfx_putchar(gfx->vc_gfx, vc->font, vc_char_get_char(ch), x * vc->charw, y * vc->charh,
              palette_to_color(vc, fg_color), palette_to_color(vc, bg_color));
}

void vc_free_gfx(vc_gfx_t* gfx) {
  if (gfx->vc_gfx) {
    gfx_surface_destroy(gfx->vc_gfx);
    gfx->vc_gfx = NULL;
  }
  if (gfx->vc_status_bar_gfx) {
    gfx_surface_destroy(gfx->vc_status_bar_gfx);
    gfx->vc_status_bar_gfx = NULL;
  }
#if BUILD_FOR_TEST
  if (gfx->vc_test_gfx) {
    gfx_surface_destroy(gfx->vc_test_gfx);
    gfx->vc_test_gfx = NULL;
  }
#endif
  if (gfx->vc_gfx_mem) {
    zx_vmar_unmap(zx_vmar_root_self(), gfx->vc_gfx_mem, gfx->vc_gfx_size);
    gfx->vc_gfx_mem = 0;
  }
  if (gfx->vc_gfx_vmo) {
    zx_handle_close(gfx->vc_gfx_vmo);
    gfx->vc_gfx_vmo = ZX_HANDLE_INVALID;
  }
  if (gfx->vc_hw_gfx_mem) {
    zx_vmar_unmap(zx_vmar_root_self(), gfx->vc_hw_gfx_mem, gfx->vc_gfx_size);
    gfx->vc_hw_gfx_mem = 0;
  }
}

#if BUILD_FOR_TEST

zx_status_t vc_init_gfx(vc_gfx_t* gfx, gfx_surface* test) {
  const gfx_font* font = vc_get_font();
  gfx->vc_font = font;

  gfx->vc_test_gfx = test;

  // Initialize the status bar.
  gfx->vc_status_bar_gfx =
      gfx_create_surface(NULL, test->width, font->height, test->stride, test->format, 0);
  if (!gfx->vc_status_bar_gfx) {
    return ZX_ERR_NO_MEMORY;
  }

  // Initialize the main surface.
  gfx->vc_gfx = gfx_create_surface(NULL, test->width, test->height, test->stride, test->format, 0);
  if (!gfx->vc_gfx) {
    gfx_surface_destroy(gfx->vc_status_bar_gfx);
    gfx->vc_status_bar_gfx = NULL;
    return ZX_ERR_NO_MEMORY;
  }

  g_status_width = gfx->vc_gfx->width / font->width;

  return ZX_OK;
}

void vc_gfx_invalidate_all(vc_gfx_t* gfx, vc_t* vc) {
  gfx_copylines(gfx->vc_test_gfx, gfx->vc_status_bar_gfx, 0, 0, gfx->vc_status_bar_gfx->height);
  gfx_copylines(gfx->vc_test_gfx, gfx->vc_gfx, 0, gfx->vc_status_bar_gfx->height,
                gfx->vc_gfx->height - gfx->vc_status_bar_gfx->height);
}

void vc_gfx_invalidate_status(vc_gfx_t* gfx) {
  gfx_copylines(gfx->vc_test_gfx, gfx->vc_status_bar_gfx, 0, 0, gfx->vc_status_bar_gfx->height);
}

void vc_gfx_invalidate(vc_gfx_t* gfx, vc_t* vc, unsigned x, unsigned y, unsigned w, unsigned h) {
  unsigned desty = gfx->vc_status_bar_gfx->height + y * vc->charh;
  if ((x == 0) && (w == vc->columns)) {
    gfx_copylines(gfx->vc_test_gfx, gfx->vc_gfx, y * vc->charh, desty, h * vc->charh);
  } else {
    gfx_blend(gfx->vc_test_gfx, gfx->vc_gfx, x * vc->charw, y * vc->charh, w * vc->charw,
              h * vc->charh, x * vc->charw, desty);
  }
}

void vc_gfx_invalidate_region(vc_gfx_t* gfx, vc_t* vc, unsigned x, unsigned y, unsigned w,
                              unsigned h) {
  unsigned desty = gfx->vc_status_bar_gfx->height + y;
  if ((x == 0) && (w == vc->columns)) {
    gfx_copylines(gfx->vc_test_gfx, gfx->vc_gfx, y, desty, h);
  } else {
    gfx_blend(gfx->vc_test_gfx, gfx->vc_gfx, x, y, w, h, x, desty);
  }
}
#else

zx_status_t vc_init_gfx(vc_gfx_t* gfx, zx_handle_t fb_vmo, int32_t width, int32_t height,
                        zx_pixel_format_t format, int32_t stride) {
  const gfx_font* font = vc_get_font();
  gfx->vc_font = font;

  gfx->vc_gfx_size = stride * ZX_PIXEL_FORMAT_BYTES(format) * height;

  zx_status_t r;
  // If we can't efficiently read from the framebuffer VMO, create a secondary
  // surface using a regular VMO and blit contents between the two.
  if ((r = zx_vmo_set_cache_policy(fb_vmo, ZX_CACHE_POLICY_CACHED)) == ZX_ERR_BAD_STATE) {
    if ((r = zx_vmar_map(zx_vmar_root_self(), ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, 0, fb_vmo, 0,
                         gfx->vc_gfx_size, &gfx->vc_hw_gfx_mem)) < 0) {
      goto fail;
    }

    if ((gfx->vc_hw_gfx = gfx_create_surface((void*)gfx->vc_hw_gfx_mem, width, height, stride,
                                             format, 0)) == NULL) {
      r = ZX_ERR_INTERNAL;
      goto fail;
    }

    if ((r = zx_vmo_create(gfx->vc_gfx_size, 0, &fb_vmo)) < 0) {
      goto fail;
    }
  } else if (r != ZX_OK) {
    goto fail;
  }

  uintptr_t ptr;
  gfx->vc_gfx_vmo = fb_vmo;
  if ((r = zx_vmar_map(zx_vmar_root_self(), ZX_VM_PERM_READ | ZX_VM_PERM_WRITE, 0, gfx->vc_gfx_vmo,
                       0, gfx->vc_gfx_size, &gfx->vc_gfx_mem)) < 0) {
    goto fail;
  }

  r = ZX_ERR_NO_MEMORY;
  // Initialize the status bar.
  if ((gfx->vc_status_bar_gfx = gfx_create_surface((void*)gfx->vc_gfx_mem, width, font->height,
                                                   stride, format, 0)) == NULL) {
    goto fail;
  }

  // Initialize the main surface.
  ptr = gfx->vc_gfx_mem + stride * font->height * ZX_PIXEL_FORMAT_BYTES(format);
  if ((gfx->vc_gfx = gfx_create_surface((void*)ptr, width, height - font->height, stride, format,
                                        0)) == NULL) {
    goto fail;
  }

  g_status_width = gfx->vc_gfx->width / font->width;

  return ZX_OK;

fail:
  vc_free_gfx(gfx);
  return r;
}

void vc_gfx_invalidate_mem(vc_gfx_t* gfx, size_t offset, size_t size) {
  void* ptr;
  if (gfx->vc_hw_gfx_mem) {
    void* data_ptr = reinterpret_cast<void*>(gfx->vc_gfx_mem + offset);
    ptr = reinterpret_cast<void*>(gfx->vc_hw_gfx_mem + offset);
    memcpy(ptr, data_ptr, size);
  } else {
    ptr = reinterpret_cast<void*>(gfx->vc_gfx_mem + offset);
  }
  zx_cache_flush(ptr, size, ZX_CACHE_FLUSH_DATA);
}

void vc_gfx_invalidate_all(vc_gfx_t* gfx, vc_t* vc) {
  if (g_vc_owns_display || vc->active) {
    vc_gfx_invalidate_mem(gfx, 0, gfx->vc_gfx_size);
  }
}

void vc_gfx_invalidate_status(vc_gfx_t* gfx) {
  vc_gfx_invalidate_mem(gfx, 0,
                        gfx->vc_status_bar_gfx->stride * gfx->vc_status_bar_gfx->height *
                            gfx->vc_status_bar_gfx->pixelsize);
}

// pixel coords
void vc_gfx_invalidate_region(vc_gfx_t* gfx, vc_t* vc, unsigned x, unsigned y, unsigned w,
                              unsigned h) {
  if (!g_vc_owns_display || !vc->active) {
    return;
  }
  uint32_t flush_size = w * gfx->vc_gfx->pixelsize;
  size_t offset = gfx->vc_gfx->stride * (vc->charh + y) * gfx->vc_gfx->pixelsize;
  for (unsigned i = 0; i < h; i++, offset += (gfx->vc_gfx->stride * gfx->vc_gfx->pixelsize)) {
    vc_gfx_invalidate_mem(gfx, offset, flush_size);
  }
}

// text coords
void vc_gfx_invalidate(vc_gfx_t* gfx, vc_t* vc, unsigned x, unsigned y, unsigned w, unsigned h) {
  vc_gfx_invalidate_region(gfx, vc, x * vc->charw, y * vc->charh, w * vc->charw, h * vc->charh);
}
#endif
