michael@0: // michael@0: // Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: // michael@0: michael@0: // vertexconversion.h: A library of vertex conversion classes that can be used to build michael@0: // the FormatConverter objects used by the buffer conversion system. michael@0: michael@0: #ifndef LIBGLESV2_VERTEXCONVERSION_H_ michael@0: #define LIBGLESV2_VERTEXCONVERSION_H_ michael@0: michael@0: namespace rx michael@0: { michael@0: michael@0: // Conversion types: michael@0: // static const bool identity: true if this is an identity transform, false otherwise michael@0: // static U convert(T): convert a single element from the input type to the output type michael@0: // typedef ... OutputType: the type produced by this conversion michael@0: michael@0: template michael@0: struct Identity michael@0: { michael@0: static const bool identity = true; michael@0: michael@0: typedef T OutputType; michael@0: michael@0: static T convert(T x) michael@0: { michael@0: return x; michael@0: } michael@0: }; michael@0: michael@0: template michael@0: struct Cast michael@0: { michael@0: static const bool identity = false; michael@0: michael@0: typedef ToT OutputType; michael@0: michael@0: static ToT convert(FromT x) michael@0: { michael@0: return static_cast(x); michael@0: } michael@0: }; michael@0: michael@0: template michael@0: struct Cast michael@0: { michael@0: static const bool identity = true; michael@0: michael@0: typedef T OutputType; michael@0: michael@0: static T convert(T x) michael@0: { michael@0: return static_cast(x); michael@0: } michael@0: }; michael@0: michael@0: template michael@0: struct Normalize michael@0: { michael@0: static const bool identity = false; michael@0: michael@0: typedef float OutputType; michael@0: michael@0: static float convert(T x) michael@0: { michael@0: typedef std::numeric_limits NL; michael@0: float f = static_cast(x); michael@0: michael@0: if (NL::is_signed) michael@0: { michael@0: // const float => VC2008 computes it at compile time michael@0: // static const float => VC2008 computes it the first time we get here, stores it to memory with static guard and all that. michael@0: const float divisor = 1.0f/(2*static_cast(NL::max())+1); michael@0: return (2*f+1)*divisor; michael@0: } michael@0: else michael@0: { michael@0: return f/NL::max(); michael@0: } michael@0: } michael@0: }; michael@0: michael@0: template michael@0: struct FixedToFloat michael@0: { michael@0: static const bool identity = false; michael@0: michael@0: typedef float OutputType; michael@0: michael@0: static float convert(FromType x) michael@0: { michael@0: const float divisor = 1.0f / static_cast(static_cast(1) << ScaleBits); michael@0: return static_cast(x) * divisor; michael@0: } michael@0: }; michael@0: michael@0: // Widen types: michael@0: // static const unsigned int initialWidth: number of components before conversion michael@0: // static const unsigned int finalWidth: number of components after conversion michael@0: michael@0: // Float is supported at any size. michael@0: template michael@0: struct NoWiden michael@0: { michael@0: static const std::size_t initialWidth = N; michael@0: static const std::size_t finalWidth = N; michael@0: }; michael@0: michael@0: // SHORT, norm-SHORT, norm-UNSIGNED_SHORT are supported but only with 2 or 4 components michael@0: template michael@0: struct WidenToEven michael@0: { michael@0: static const std::size_t initialWidth = N; michael@0: static const std::size_t finalWidth = N+(N&1); michael@0: }; michael@0: michael@0: template michael@0: struct WidenToFour michael@0: { michael@0: static const std::size_t initialWidth = N; michael@0: static const std::size_t finalWidth = 4; michael@0: }; michael@0: michael@0: // Most types have 0 and 1 that are just that. michael@0: template michael@0: struct SimpleDefaultValues michael@0: { michael@0: static T zero() { return static_cast(0); } michael@0: static T one() { return static_cast(1); } michael@0: }; michael@0: michael@0: // But normalised types only store [0,1] or [-1,1] so 1.0 is represented by the max value. michael@0: template michael@0: struct NormalizedDefaultValues michael@0: { michael@0: static T zero() { return static_cast(0); } michael@0: static T one() { return std::numeric_limits::max(); } michael@0: }; michael@0: michael@0: // Converter: michael@0: // static const bool identity: true if this is an identity transform (with no widening) michael@0: // static const std::size_t finalSize: number of bytes per output vertex michael@0: // 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. michael@0: michael@0: template > michael@0: struct VertexDataConverter michael@0: { michael@0: typedef typename Converter::OutputType OutputType; michael@0: typedef InT InputType; michael@0: michael@0: static const bool identity = (WidenRule::initialWidth == WidenRule::finalWidth) && Converter::identity; michael@0: static const std::size_t finalSize = WidenRule::finalWidth * sizeof(OutputType); michael@0: michael@0: static void convertArray(const InputType *in, std::size_t stride, std::size_t n, OutputType *out) michael@0: { michael@0: for (std::size_t i = 0; i < n; i++) michael@0: { michael@0: const InputType *ein = pointerAddBytes(in, i * stride); michael@0: michael@0: copyComponent(out, ein, 0, static_cast(DefaultValueRule::zero())); michael@0: copyComponent(out, ein, 1, static_cast(DefaultValueRule::zero())); michael@0: copyComponent(out, ein, 2, static_cast(DefaultValueRule::zero())); michael@0: copyComponent(out, ein, 3, static_cast(DefaultValueRule::one())); michael@0: michael@0: out += WidenRule::finalWidth; michael@0: } michael@0: } michael@0: michael@0: static void convertArray(const void *in, std::size_t stride, std::size_t n, void *out) michael@0: { michael@0: return convertArray(static_cast(in), stride, n, static_cast(out)); michael@0: } michael@0: michael@0: private: michael@0: // Advance the given pointer by a number of bytes (not pointed-to elements). michael@0: template michael@0: static T *pointerAddBytes(T *basePtr, std::size_t numBytes) michael@0: { michael@0: return reinterpret_cast(reinterpret_cast(basePtr) + numBytes); michael@0: } michael@0: michael@0: static void copyComponent(OutputType *out, const InputType *in, std::size_t elementindex, OutputType defaultvalue) michael@0: { michael@0: if (WidenRule::finalWidth > elementindex) michael@0: { michael@0: if (WidenRule::initialWidth > elementindex) michael@0: { michael@0: out[elementindex] = Converter::convert(in[elementindex]); michael@0: } michael@0: else michael@0: { michael@0: out[elementindex] = defaultvalue; michael@0: } michael@0: } michael@0: } michael@0: }; michael@0: michael@0: } michael@0: michael@0: #endif // LIBGLESV2_VERTEXCONVERSION_H_