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