10f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com//
20f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
30f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com// Use of this source code is governed by a BSD-style license that can be
40f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com// found in the LICENSE file.
50f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com//
60f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com
78fd34bd649a855dab9f5dc3505e40ecb14a01d70daniel@transgaming.com// vertexconversion.h: A library of vertex conversion classes that can be used to build
80f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com// the FormatConverter objects used by the buffer conversion system.
90f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com
108fd34bd649a855dab9f5dc3505e40ecb14a01d70daniel@transgaming.com#ifndef LIBGLESV2_VERTEXCONVERSION_H_
118fd34bd649a855dab9f5dc3505e40ecb14a01d70daniel@transgaming.com#define LIBGLESV2_VERTEXCONVERSION_H_
120f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com
130b7eef7c469bf717f7e1b57c6273f00d88e8b1d9Geoff Lang#include <limits>
140b7eef7c469bf717f7e1b57c6273f00d88e8b1d9Geoff Lang#include <cstdint>
150b7eef7c469bf717f7e1b57c6273f00d88e8b1d9Geoff Lang#include <cstddef>
160b7eef7c469bf717f7e1b57c6273f00d88e8b1d9Geoff Lang
17312404870905e1eff46e21632c1c2f2143af4694daniel@transgaming.comnamespace rx
180f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com{
190f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com
200f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com// Conversion types:
210f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com// static const bool identity: true if this is an identity transform, false otherwise
220f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com// static U convert(T): convert a single element from the input type to the output type
230f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com// typedef ... OutputType: the type produced by this conversion
240f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com
250f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.comtemplate <class T>
260f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.comstruct Identity
270f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com{
280f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    static const bool identity = true;
290f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com
300f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    typedef T OutputType;
310f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com
320f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    static T convert(T x)
330f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    {
340f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com        return x;
350f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    }
360f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com};
370f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com
380f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.comtemplate <class FromT, class ToT>
390f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.comstruct Cast
400f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com{
410f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    static const bool identity = false;
420f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com
430f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    typedef ToT OutputType;
440f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com
450f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    static ToT convert(FromT x)
460f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    {
470f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com        return static_cast<ToT>(x);
480f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    }
490f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com};
500f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com
510f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.comtemplate <class T>
520f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.comstruct Cast<T, T>
530f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com{
540f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    static const bool identity = true;
550f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com
560f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    typedef T OutputType;
570f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com
580f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    static T convert(T x)
590f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    {
600f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com        return static_cast<T>(x);
610f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    }
620f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com};
630f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com
640f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.comtemplate <class T>
650f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.comstruct Normalize
660f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com{
670f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    static const bool identity = false;
680f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com
690f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    typedef float OutputType;
700f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com
710f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    static float convert(T x)
720f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    {
730f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com        typedef std::numeric_limits<T> NL;
740f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com        float f = static_cast<float>(x);
750f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com
760f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com        if (NL::is_signed)
770f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com        {
780f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com            // const float => VC2008 computes it at compile time
790f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com            // static const float => VC2008 computes it the first time we get here, stores it to memory with static guard and all that.
800f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com            const float divisor = 1.0f/(2*static_cast<float>(NL::max())+1);
810f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com            return (2*f+1)*divisor;
820f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com        }
830f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com        else
840f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com        {
850f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com            return f/NL::max();
860f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com        }
870f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    }
880f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com};
890f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com
900f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.comtemplate <class FromType, std::size_t ScaleBits>
910f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.comstruct FixedToFloat
920f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com{
930f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    static const bool identity = false;
940f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com
950f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    typedef float OutputType;
960f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com
970f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    static float convert(FromType x)
980f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    {
990f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com        const float divisor = 1.0f / static_cast<float>(static_cast<FromType>(1) << ScaleBits);
1000f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com        return static_cast<float>(x) * divisor;
1010f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    }
1020f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com};
1030f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com
1040f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com// Widen types:
1050f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com// static const unsigned int initialWidth: number of components before conversion
1060f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com// static const unsigned int finalWidth: number of components after conversion
1070f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com
1080f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com// Float is supported at any size.
1090f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.comtemplate <std::size_t N>
1100f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.comstruct NoWiden
1110f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com{
1120f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    static const std::size_t initialWidth = N;
1130f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    static const std::size_t finalWidth = N;
1140f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com};
1150f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com
1160f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com// SHORT, norm-SHORT, norm-UNSIGNED_SHORT are supported but only with 2 or 4 components
1170f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.comtemplate <std::size_t N>
1180f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.comstruct WidenToEven
1190f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com{
1200f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    static const std::size_t initialWidth = N;
1210f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    static const std::size_t finalWidth = N+(N&1);
1220f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com};
1230f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com
12413881545ced98cd2ec7b175389c95bf23574bf53daniel@transgaming.comtemplate <std::size_t N>
1250f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.comstruct WidenToFour
1260f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com{
1270f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    static const std::size_t initialWidth = N;
1280f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    static const std::size_t finalWidth = 4;
1290f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com};
1300f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com
1310f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com// Most types have 0 and 1 that are just that.
1320f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.comtemplate <class T>
1330f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.comstruct SimpleDefaultValues
1340f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com{
1350f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    static T zero() { return static_cast<T>(0); }
1360f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    static T one() { return static_cast<T>(1); }
1370f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com};
1380f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com
1390f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com// But normalised types only store [0,1] or [-1,1] so 1.0 is represented by the max value.
1400f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.comtemplate <class T>
1410f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.comstruct NormalizedDefaultValues
1420f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com{
1430f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    static T zero() { return static_cast<T>(0); }
1440f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    static T one() { return std::numeric_limits<T>::max(); }
1450f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com};
1460f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com
1470f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com// Converter:
1480f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com// static const bool identity: true if this is an identity transform (with no widening)
1490f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com// static const std::size_t finalSize: number of bytes per output vertex
1500f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com// 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.
1510f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com
1520f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.comtemplate <class InT, class WidenRule, class Converter, class DefaultValueRule = SimpleDefaultValues<InT> >
1530f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.comstruct VertexDataConverter
1540f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com{
1550f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    typedef typename Converter::OutputType OutputType;
1560f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    typedef InT InputType;
1570f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com
1580f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    static const bool identity = (WidenRule::initialWidth == WidenRule::finalWidth) && Converter::identity;
1590f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    static const std::size_t finalSize = WidenRule::finalWidth * sizeof(OutputType);
1600f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com
16145965b102fbff399c3e39aeeabf55f146c75caabGeoff Lang    static void convertArray(const uint8_t *input, size_t stride, size_t n, uint8_t *output)
1620f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    {
16345965b102fbff399c3e39aeeabf55f146c75caabGeoff Lang        OutputType *out = reinterpret_cast<OutputType*>(output);
16445965b102fbff399c3e39aeeabf55f146c75caabGeoff Lang
1650f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com        for (std::size_t i = 0; i < n; i++)
1660f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com        {
16745965b102fbff399c3e39aeeabf55f146c75caabGeoff Lang            const InputType *ein = reinterpret_cast<const InputType*>(input + i * stride);
1680f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com
1690f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com            copyComponent(out, ein, 0, static_cast<OutputType>(DefaultValueRule::zero()));
1700f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com            copyComponent(out, ein, 1, static_cast<OutputType>(DefaultValueRule::zero()));
1710f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com            copyComponent(out, ein, 2, static_cast<OutputType>(DefaultValueRule::zero()));
1720f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com            copyComponent(out, ein, 3, static_cast<OutputType>(DefaultValueRule::one()));
1730f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com
1740f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com            out += WidenRule::finalWidth;
1750f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com        }
1760f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    }
1770f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com
1780f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com  private:
1790f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    static void copyComponent(OutputType *out, const InputType *in, std::size_t elementindex, OutputType defaultvalue)
1800f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    {
1810f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com        if (WidenRule::finalWidth > elementindex)
1820f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com        {
1830f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com            if (WidenRule::initialWidth > elementindex)
1840f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com            {
185c21c227174ae9b23d4b719ca42694646d8dea122daniel@transgaming.com                out[elementindex] = Converter::convert(in[elementindex]);
1860f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com            }
1870f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com            else
1880f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com            {
189c21c227174ae9b23d4b719ca42694646d8dea122daniel@transgaming.com                out[elementindex] = defaultvalue;
1900f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com            }
1910f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com        }
1920f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com    }
1930f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com};
1940f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com
1950f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com}
1960f7aaf530b2aad644d4aab01c493517dedf3f62fdaniel@transgaming.com
1978fd34bd649a855dab9f5dc3505e40ecb14a01d70daniel@transgaming.com#endif   // LIBGLESV2_VERTEXCONVERSION_H_
198