hostsupport/hostopenvg/src/riRasterizer.h
author Matt Plumtree <matt.plumtree@nokia.com>
Mon, 08 Nov 2010 15:39:31 +0000
branchbug235_bringup_0
changeset 73 11fc086941ac
parent 53 c2ef9095503a
permissions -rw-r--r--
Add host build extension component to package. Avoid using SSE2 with GCC builds for the moment - possibly broken on 3.4.5

#ifndef __RIRASTERIZER_H
#define __RIRASTERIZER_H

/*------------------------------------------------------------------------
 *
 * OpenVG 1.1 Reference Implementation
 * -----------------------------------
 *
 * Copyright (c) 2007 The Khronos Group Inc.
 * Portions copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and /or associated documentation files
 * (the "Materials "), to deal in the Materials without restriction,
 * including without limitation the rights to use, copy, modify, merge,
 * publish, distribute, sublicense, and/or sell copies of the Materials,
 * and to permit persons to whom the Materials are furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Materials.
 *
 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR
 * THE USE OR OTHER DEALINGS IN THE MATERIALS.
 *
 *//**
 * \file
 * \brief   Rasterizer class.
 * \note
 *//*-------------------------------------------------------------------*/

#ifndef __RIMATH_H
#include "riMath.h"
#endif

#ifndef __RIARRAY_H
#include "riArray.h"
#endif

#ifndef __RIPIXELPIPE_H
#include "riPixelPipe.h"
#endif

// TESTING ONLY!!
#include "sfDynamicPixelPipe.h"

#if defined(RI_DEBUG)
#    include <stdio.h>
#endif
// \todo SSE2 probably has everything necessary and matches the minimum platform requirements.
// SSE4 is probably too new. SSE3?
// \note This will cause the code to not compile on MSVC...

#if defined(USE_SSE2)
// \todo only the last include is needed: QT creator does not find types if others not included.
#   include <mmintrin.h>
#   include <xmmintrin.h>
#   include <emmintrin.h>
#endif

//=======================================================================

namespace OpenVGRI
{

/*-------------------------------------------------------------------*//*!
* \brief    Scalar and vector data types used by the rasterizer.
* \param
* \return
* \note
*//*-------------------------------------------------------------------*/

typedef RIfloat RScalar;    //change this if you want to have different precision for rasterizer scalars and RIfloat

struct RVector2
{
    RI_INLINE RVector2()                            { }
    RI_INLINE RVector2(const Vector2& v)            { x = v.x; y = v.y; }
    RI_INLINE RVector2(RIfloat vx, RIfloat vy)      { x = vx; y = vy; }
    RI_INLINE void set(RIfloat vx, RIfloat vy)      { x = vx; y = vy; }
    RScalar     x;
    RScalar     y;
};

struct IVector2
{
    RI_INLINE IVector2() {}
    RI_INLINE IVector2(const IVector2& v) { x = v.x; y = v.y; }
    RI_INLINE IVector2(const Vector2& v) { x = (int)v.x; y = (int) v.y; }
    RI_INLINE IVector2(int vx, int vy) { x = vx; y = vy; }
    RI_INLINE void set(int vx, int vy) { x = vx; y = vy; }
    int x;
    int y;
};

struct Span
{
    RIuint16 x0;
    RIuint16 y;
    RIuint16 len;
    RIuint8  coverage;
    RIuint8  pad; // align to 8 bytes. \temp Use qualifiers instead?
};

/*-------------------------------------------------------------------*//*!
* \brief    Converts a set of edges to coverage values for each pixel and
*           calls PixelPipe::pixelPipe for painting a pixel.
* \param
* \return
* \note
*//*-------------------------------------------------------------------*/

class Rasterizer
{
public:
    Rasterizer();   //throws bad_alloc
    ~Rasterizer();

    void        setup(int vpx, int vpy, int vpwidth, int vpheight, VGFillRule fillRule, const PixelPipe* pixelPipe);
    void        setScissor(const Array<Rectangle>& scissors);   //throws bad_alloc
    void        setScissoring(bool enabled);

    void        clear();
    void        addEdge(const Vector2& v0, const Vector2& v1);  //throws bad_alloc

    RI_INLINE void setAntiAliasing(bool enable) { m_aa = enable; }
    void        fill(); //throws bad_alloc

    void        getBBox(int& sx, int& sy, int& ex, int& ey) const       { sx = m_covMinx; sy = m_covMiny; ex = m_covMaxx; ey = m_covMaxy; }

public:
    enum { SAMPLE_BITS = 3 };
    enum { Y_BITS = SAMPLE_BITS };
    enum { MAX_COVERAGE = 1<<SAMPLE_BITS };

    // temp!:
    RIuint32    *m_covBuffer;
    size_t      m_covBufferSz;

private:
    Rasterizer(const Rasterizer&);                      //!< Not allowed.
    const Rasterizer& operator=(const Rasterizer&);     //!< Not allowed.

public:
    struct ScissorEdge
    {
        ScissorEdge() {}
        bool operator<(const ScissorEdge& e) const  { return x < e.x; }
        int         x;
        int         miny;
        int         maxy;
        int         direction;      //1 start, -1 end
    };

    struct Edge
    {
        Edge() {}
        bool operator<(const Edge& e) const { return v0.y < e.v0.y; }
#if defined(RI_DEBUG)
        bool operator<=(const Edge& e) const {return v0.y <= e.v0.y; }
#endif
        IVector2    v0;
        IVector2    v1;
        int         direction;
    };

    struct ActiveEdge
    {
        typedef RIint16 XCoord;
        typedef RIint16 YCoord;

        ActiveEdge() {}
        //bool operator<(const ActiveEdge& e) const   { return minx < e.minx; }
        bool operator<(const ActiveEdge& e) const
        {
            if (minx < e.minx)
                return true;
            if (minx == e.minx)
                return maxx < e.maxx;
            return false;
        }
#if defined(RI_DEBUG)
        bool operator<=(const ActiveEdge& e) const { return minx <= e.minx; }
#endif
        // Fixed-point edge coordinates.
        RIuint32 next; // \todo Pointer?
        int     direction;      //-1 down, 1 up
        int     xRef;
        int     slope;
        XCoord  minx;           // for the current scanline
        XCoord  maxx;           // for the current scanline
        YCoord  yStart;         // for the edge
        YCoord  yEnd;           // for the edge
    };

    enum { SF_SAMPLES = 8 };
    enum { RASTERIZER_BITS = 14 };
    enum { RASTERIZER_MASK = ((1<<RASTERIZER_BITS)-1) };
    enum { Y_MASK = ((1<<Y_BITS)-1) };
    enum { X_BITS = 7 };
    enum { XMASK  = ((1<<X_BITS)-1) };
    enum { LEFT_DISCARD = -0x100000 };
    enum { LEFT_DISCARD_SHORT = -32768 };

    struct Windings
    {
#if !defined(USE_SSE2)
        Windings() {wq = 0;}
        // \todo Use SSE counters or packed counters!
        // \todo 8 samples -> 64 bits == 2 32-bit uints
        union
        {
            RIint8              winding[SF_SAMPLES];
            RIuint32            wd[SF_SAMPLES/4];
            unsigned long long  wq;
        };
#else
        Windings() { sseWinding = _mm_setzero_si128(); }
        __m128i sseWinding;
#endif
     };

private:
    void                pushEdge(const Edge& edge);
    void                clipAndAddEdge(Edge& edge);
    void                addBBox(const IVector2& v);
    RI_INLINE void      pushSpan(int x, int y, int len, int coverage);
    RI_INLINE void      commitSpans();

    //RI_INLINE void      calculateAEWinding(const ActiveEdge& currAe, Windings& pixel, Windings& scanline, int intY, int pixelX);

    Array<ActiveEdge>   m_edgePool;
    Array<RIuint32>     m_edges;
    Array<ScissorEdge>  m_scissorEdges;
    Array<ActiveEdge>   m_aet;
    Array<ScissorEdge>  m_scissorAet;
    bool                m_scissor;

    bool                    m_aa;

    IVector2            m_edgeMin;
    IVector2            m_edgeMax;
    int                 m_covMinx;
    int                 m_covMiny;
    int                 m_covMaxx;
    int                 m_covMaxy;
    int                 m_vpx;
    int                 m_vpy;
    int                 m_vpwidth;
    int                 m_vpheight;
    int                 m_vpMinx;
    int                 m_vpMiny;
    int                 m_vpMaxx;
    int                 m_vpMaxy;
    VGFillRule          m_fillRule;
    RIuint32            m_fillRuleMask;

    const PixelPipe*        m_pixelPipe;
    PixelPipe::PPVariants   m_ppVariants;

    enum { N_CACHED_SPANS = 64 };
    Span                m_spanCache[N_CACHED_SPANS];
    int                 m_nSpans;

};

//=======================================================================

}   //namespace OpenVGRI

//=======================================================================

#endif /* __RIRASTERIZER_H */