/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * 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.
 *
 */

/*
 * Hardware Composer Test Library Header
 */

#include <sstream>
#include <string>

#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>

#include <ui/GraphicBuffer.h>

#include <utils/Log.h>
#include <testUtil.h>

#include <hardware/hwcomposer.h>

// Characteristics of known graphic formats
const struct hwcTestGraphicFormat {
    uint32_t format;
    const char *desc;
    uint32_t wMod, hMod; // Width/height mod this value must equal zero
} hwcTestGraphicFormat[] = {
    {HAL_PIXEL_FORMAT_RGBA_8888, "RGBA8888", 1, 1},
    {HAL_PIXEL_FORMAT_RGBX_8888, "RGBX8888", 1, 1},
    {HAL_PIXEL_FORMAT_RGB_888,   "RGB888",   1, 1},
    {HAL_PIXEL_FORMAT_RGB_565,   "RGB565",   1, 1},
    {HAL_PIXEL_FORMAT_BGRA_8888, "BGRA8888", 1, 1},
    {HAL_PIXEL_FORMAT_YV12,      "YV12",     2, 2},
};

// Represent RGB color as fraction of color components.
// Each of the color components are expected in the range [0.0, 1.0]
class ColorFract {
  public:
    ColorFract(): _c1(0.0), _c2(0.0), _c3(0.0) {};
    ColorFract(float c1, float c2, float c3): _c1(c1), _c2(c2), _c3(c3) {};
    float c1(void) const { return _c1; }
    float c2(void) const { return _c2; }
    float c3(void) const { return _c3; }

    operator std::string(); // NOLINT(google-explicit-constructor)

  private:
    float _c1;
    float _c2;
    float _c3;
};

// Represent RGB color as fraction of color components.
// Each of the color components are expected in the range [0.0, 1.0]
class ColorRGB {
  public:
    ColorRGB(): _r(0.0), _g(0.0), _b(0.0) {};
    ColorRGB(float f): _r(f), _g(f), _b(f) {}; // Gray, NOLINT(google-explicit-constructor)
    ColorRGB(float r, float g, float b): _r(r), _g(g), _b(b) {};
    float r(void) const { return _r; }
    float g(void) const { return _g; }
    float b(void) const { return _b; }

  private:
    float _r;
    float _g;
    float _b;
};

// Dimension - width and height of a rectanguler area
class HwcTestDim {
  public:
    HwcTestDim(): _w(0), _h(0) {};
    HwcTestDim(uint32_t w, uint32_t h) : _w(w), _h(h) {}
    uint32_t width(void) const { return _w; }
    uint32_t height(void) const { return _h; }
    void setWidth(uint32_t w) { _w = w; }
    void setHeight(uint32_t h) { _h = h; }

    operator std::string(); // NOLINT(google-explicit-constructor)
    operator hwc_rect() const; // NOLINT(google-explicit-constructor)

  private:
    uint32_t _w;
    uint32_t _h;
};

// Function Prototypes
void hwcTestInitDisplay(bool verbose, EGLDisplay *dpy, EGLSurface *surface,
    EGLint *width, EGLint *height);
void hwcTestOpenHwc(hwc_composer_device_1_t **hwcDevicePtr);
const struct hwcTestGraphicFormat *hwcTestGraphicFormatLookup(const char *desc);
const struct hwcTestGraphicFormat *hwcTestGraphicFormatLookup(uint32_t id);
const char *hwcTestGraphicFormat2str(uint32_t format);
std::string hwcTestRect2str(const struct hwc_rect& rect);

hwc_display_contents_1_t *hwcTestCreateLayerList(size_t numLayers);
void hwcTestFreeLayerList(hwc_display_contents_1_t *list);
void hwcTestDisplayList(hwc_display_contents_1_t *list);
void hwcTestDisplayListPrepareModifiable(hwc_display_contents_1_t *list);
void hwcTestDisplayListHandles(hwc_display_contents_1_t *list);

uint32_t hwcTestColor2Pixel(uint32_t format, ColorFract color, float alpha);
void hwcTestColorConvert(uint32_t fromFormat, uint32_t toFormat,
                  ColorFract& color);
void hwcTestSetPixel(android::GraphicBuffer *gBuf, unsigned char *buf,
                     uint32_t x, uint32_t y, uint32_t pixel);
void hwcTestFillColor(android::GraphicBuffer *gBuf, ColorFract color,
                      float alpha);
void hwcTestFillColorHBlend(android::GraphicBuffer *gBuf,
                            uint32_t colorFormat,
                            ColorFract startColor, ColorFract endColor);
ColorFract hwcTestParseColor(std::istringstream& in, bool& error);
struct hwc_rect hwcTestParseHwcRect(std::istringstream& in, bool& error);
HwcTestDim hwcTestParseDim(std::istringstream& in, bool& error);
