// Copyright 2016 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <directfb.h>

#include "starboard/blitter.h"
#include "starboard/common/log.h"
#include "starboard/memory.h"
#include "starboard/shared/directfb/blitter_internal.h"

namespace {
int WordToByteOrder(int bytes_per_pixel, int byte_index) {
// Since DirectFB stores color in word-order but we wish to output in
// byte-order format, we perform that conversion here.
#if SB_IS_LITTLE_ENDIAN
  return bytes_per_pixel - 1 - byte_index;
#else
  return byte_index;
#endif
}

void SwizzlePixels(void* in_data,
                   void* out_data,
                   int width,
                   int height,
                   int in_bytes_per_pixel,
                   int in_pitch_in_bytes,
                   int out_pitch_in_bytes,
                   int channel_1,
                   int channel_2,
                   int channel_3,
                   int channel_4) {
  uint8_t* in_data_bytes = static_cast<uint8_t*>(in_data);
  uint8_t* out_data_bytes = static_cast<uint8_t*>(out_data);

  bool needs_swizzle = true;
  if (WordToByteOrder(in_bytes_per_pixel, channel_1) == 0 &&
      WordToByteOrder(in_bytes_per_pixel, channel_2) == 1 &&
      WordToByteOrder(in_bytes_per_pixel, channel_3) == 2 &&
      WordToByteOrder(in_bytes_per_pixel, channel_4) == 3) {
    SB_DCHECK(in_bytes_per_pixel == 4);
    needs_swizzle = false;
  }

  for (int y = 0; y < height; ++y) {
    if (needs_swizzle) {
      for (int x = 0; x < width; ++x) {
        out_data_bytes[0] =
            in_data_bytes[WordToByteOrder(in_bytes_per_pixel, channel_1)];
        out_data_bytes[1] =
            in_data_bytes[WordToByteOrder(in_bytes_per_pixel, channel_2)];
        out_data_bytes[2] =
            in_data_bytes[WordToByteOrder(in_bytes_per_pixel, channel_3)];
        out_data_bytes[3] =
            in_data_bytes[WordToByteOrder(in_bytes_per_pixel, channel_4)];

        out_data_bytes += 4;
        in_data_bytes += in_bytes_per_pixel;
      }

      // Increment through the gab between the input data pitch and its
      // width * bpp.
      in_data_bytes += in_pitch_in_bytes - width * in_bytes_per_pixel;
      out_data_bytes += out_pitch_in_bytes - width * 4;
    } else {
      SbMemoryCopy(out_data_bytes, in_data_bytes, width * 4);
      in_data_bytes += in_pitch_in_bytes;
      out_data_bytes += out_pitch_in_bytes;
    }
  }
}
}  // namespace

bool SbBlitterDownloadSurfacePixels(SbBlitterSurface surface,
                                    SbBlitterPixelDataFormat pixel_format,
                                    int pitch_in_bytes,
                                    void* out_pixel_data) {
  if (!SbBlitterIsSurfaceValid(surface)) {
    SB_DLOG(ERROR) << __FUNCTION__ << ": Invalid surface.";
    return false;
  }
  if (out_pixel_data == NULL) {
    SB_DLOG(ERROR) << __FUNCTION__ << ": |out_pixel_data| cannot be NULL.";
    return false;
  }
  if (!SbBlitterIsPixelFormatSupportedByDownloadSurfacePixels(surface,
                                                              pixel_format)) {
    SB_DLOG(ERROR) << __FUNCTION__ << ": Unsupported pixel format.";
    return false;
  }
  if (pitch_in_bytes <
      surface->info.width * SbBlitterBytesPerPixelForFormat(pixel_format)) {
    SB_DLOG(ERROR)
        << __FUNCTION__
        << ": Output pitch must be at least as large as (width * BPP).";
    return false;
  }

  {
    // Wait for all previously flushed draw calls to be executed.
    starboard::ScopedLock lock(surface->device->mutex);
    if (surface->device->dfb->WaitIdle(surface->device->dfb) != DFB_OK) {
      SB_DLOG(ERROR) << __FUNCTION__ << ": WaitIdle() failed.";
      return false;
    }
  }

  IDirectFBSurface* dfb_surface = surface->surface;

  DFBSurfacePixelFormat surface_pixel_format;
  dfb_surface->GetPixelFormat(dfb_surface, &surface_pixel_format);

  // Lock the surface's pixels and then copy them out into the user's provided
  // memory.  Swizzel the pixel's bytes as we copy them out, if necessary.
  void* data;
  int surface_pitch_in_bytes;
  if (dfb_surface->Lock(dfb_surface, DSLF_READ, &data,
                        &surface_pitch_in_bytes) != DFB_OK) {
    SB_DLOG(ERROR) << __FUNCTION__ << ": Error calling Lock().";
    return false;
  }

  switch (DFB_PIXELFORMAT_INDEX(surface_pixel_format)) {
    case DFB_PIXELFORMAT_INDEX(DSPF_ARGB): {
      switch (pixel_format) {
        case kSbBlitterPixelDataFormatARGB8: {
          SwizzlePixels(data, out_pixel_data, surface->info.width,
                        surface->info.height, 4, surface_pitch_in_bytes,
                        pitch_in_bytes, 0, 1, 2, 3);
        } break;
        case kSbBlitterPixelDataFormatBGRA8: {
          SwizzlePixels(data, out_pixel_data, surface->info.width,
                        surface->info.height, 4, surface_pitch_in_bytes,
                        pitch_in_bytes, 3, 2, 1, 0);
        } break;
        case kSbBlitterPixelDataFormatRGBA8: {
          SwizzlePixels(data, out_pixel_data, surface->info.width,
                        surface->info.height, 4, surface_pitch_in_bytes,
                        pitch_in_bytes, 1, 2, 3, 0);
        } break;
        default: { SB_NOTREACHED(); }
      }
    } break;

    case DFB_PIXELFORMAT_INDEX(DSPF_A8): {
      // Convert A8 to either ARGB, BGRA, or RGBA.
      SwizzlePixels(data, out_pixel_data, surface->info.width,
                    surface->info.height, 1, surface_pitch_in_bytes,
                    pitch_in_bytes, 0, 0, 0, 0);
    } break;

    default: {
      SB_DLOG(ERROR) << __FUNCTION__ << ": Unsupported pixel format index ("
                     << DFB_PIXELFORMAT_INDEX(surface_pixel_format) << ").";
      dfb_surface->Unlock(dfb_surface);
      return false;
    }
  }

  // Okay the copy is complete, unlock the pixels and carry on.
  dfb_surface->Unlock(dfb_surface);

  return true;
}
