//
// Copyright 2002 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

// vertexconversion.h: A library of vertex conversion classes that can be used to build
// the FormatConverter objects used by the buffer conversion system.

#ifndef LIBANGLE_RENDERER_D3D_D3D9_VERTEXCONVERSION_H_
#define LIBANGLE_RENDERER_D3D_D3D9_VERTEXCONVERSION_H_

#include <cstddef>
#include <cstdint>
#include <limits>

namespace rx
{

// Conversion types:
// static const bool identity: true if this is an identity transform, false otherwise
// static U convert(T): convert a single element from the input type to the output type
// typedef ... OutputType: the type produced by this conversion

template <class T>
struct Identity
{
    static const bool identity = true;

    typedef T OutputType;

    static T convert(T x) { return x; }
};

template <class FromT, class ToT>
struct Cast
{
    static const bool identity = false;

    typedef ToT OutputType;

    static ToT convert(FromT x) { return static_cast<ToT>(x); }
};

template <class T>
struct Cast<T, T>
{
    static const bool identity = true;

    typedef T OutputType;

    static T convert(T x) { return static_cast<T>(x); }
};

template <class T>
struct Normalize
{
    static const bool identity = false;

    typedef float OutputType;

    static float convert(T x)
    {
        typedef std::numeric_limits<T> NL;
        float f = static_cast<float>(x);

        if (NL::is_signed)
        {
            // const float => VC2008 computes it at compile time
            // static const float => VC2008 computes it the first time we get here, stores it to
            // memory with static guard and all that.
            const float divisor = 1.0f / (2 * static_cast<float>(NL::max()) + 1);
            return (2 * f + 1) * divisor;
        }
        else
        {
            return f / NL::max();
        }
    }
};

template <class FromType, std::size_t ScaleBits>
struct FixedToFloat
{
    static const bool identity = false;

    typedef float OutputType;

    static float convert(FromType x)
    {
        const float divisor = 1.0f / static_cast<float>(static_cast<FromType>(1) << ScaleBits);
        return static_cast<float>(x) * divisor;
    }
};

// Widen types:
// static const unsigned int initialWidth: number of components before conversion
// static const unsigned int finalWidth: number of components after conversion

// Float is supported at any size.
template <std::size_t N>
struct NoWiden
{
    static const std::size_t initialWidth = N;
    static const std::size_t finalWidth   = N;
};

// SHORT, norm-SHORT, norm-UNSIGNED_SHORT are supported but only with 2 or 4 components
template <std::size_t N>
struct WidenToEven
{
    static const std::size_t initialWidth = N;
    static const std::size_t finalWidth   = N + (N & 1);
};

template <std::size_t N>
struct WidenToFour
{
    static const std::size_t initialWidth = N;
    static const std::size_t finalWidth   = 4;
};

// Most types have 0 and 1 that are just that.
template <class T>
struct SimpleDefaultValues
{
    static T zero() { return static_cast<T>(0); }
    static T one() { return static_cast<T>(1); }
};

// But normalised types only store [0,1] or [-1,1] so 1.0 is represented by the max value.
template <class T>
struct NormalizedDefaultValues
{
    static T zero() { return static_cast<T>(0); }
    static T one() { return std::numeric_limits<T>::max(); }
};

// Converter:
// static const bool identity: true if this is an identity transform (with no widening)
// static const std::size_t finalSize: number of bytes per output vertex
// static void convertArray(const void *in, std::size_t stride, std::size_t n, void *out): convert
// an array of vertices. Input may be strided, but output will be unstrided.

template <class InT,
          class WidenRule,
          class Converter,
          class DefaultValueRule = SimpleDefaultValues<InT>>
struct VertexDataConverter
{
    typedef typename Converter::OutputType OutputType;
    typedef InT InputType;

    static const bool identity =
        (WidenRule::initialWidth == WidenRule::finalWidth) && Converter::identity;
    static const std::size_t finalSize = WidenRule::finalWidth * sizeof(OutputType);

    static void convertArray(const uint8_t *input, size_t stride, size_t n, uint8_t *output)
    {
        OutputType *out = reinterpret_cast<OutputType *>(output);

        for (std::size_t i = 0; i < n; i++)
        {
            const InputType *ein = reinterpret_cast<const InputType *>(input + i * stride);

            copyComponent(out, ein, 0, static_cast<OutputType>(DefaultValueRule::zero()));
            copyComponent(out, ein, 1, static_cast<OutputType>(DefaultValueRule::zero()));
            copyComponent(out, ein, 2, static_cast<OutputType>(DefaultValueRule::zero()));
            copyComponent(out, ein, 3, static_cast<OutputType>(DefaultValueRule::one()));

            out += WidenRule::finalWidth;
        }
    }

  private:
    static void copyComponent(OutputType *out,
                              const InputType *in,
                              std::size_t elementindex,
                              OutputType defaultvalue)
    {
        if (WidenRule::finalWidth > elementindex)
        {
            if (WidenRule::initialWidth > elementindex)
            {
                out[elementindex] = Converter::convert(in[elementindex]);
            }
            else
            {
                out[elementindex] = defaultvalue;
            }
        }
    }
};

}  // namespace rx

#endif  // LIBANGLE_RENDERER_D3D_D3D9_VERTEXCONVERSION_H_
