hostsupport/hostopenvg/src/riRasterizer.cpp
branchbug235_bringup_0
changeset 53 c2ef9095503a
parent 24 a3f46bb01be2
child 69 3f914c77c2e9
equal deleted inserted replaced
52:39e5f73667ba 53:c2ef9095503a
       
     1 /*------------------------------------------------------------------------
       
     2  *
       
     3  * OpenVG 1.1 Reference Implementation
       
     4  * -----------------------------------
       
     5  *
       
     6  * Copyright (c) 2007 The Khronos Group Inc.
       
     7  * Portions copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     8  *
       
     9  * Permission is hereby granted, free of charge, to any person obtaining a
       
    10  * copy of this software and /or associated documentation files
       
    11  * (the "Materials "), to deal in the Materials without restriction,
       
    12  * including without limitation the rights to use, copy, modify, merge,
       
    13  * publish, distribute, sublicense, and/or sell copies of the Materials,
       
    14  * and to permit persons to whom the Materials are furnished to do so,
       
    15  * subject to the following conditions:
       
    16  *
       
    17  * The above copyright notice and this permission notice shall be included
       
    18  * in all copies or substantial portions of the Materials.
       
    19  *
       
    20  * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
       
    21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
       
    22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
       
    23  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
       
    24  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
       
    25  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR
       
    26  * THE USE OR OTHER DEALINGS IN THE MATERIALS.
       
    27  *
       
    28  *//**
       
    29  * \file
       
    30  * \brief	Implementation of polygon rasterizer.
       
    31  * \note
       
    32  *//*-------------------------------------------------------------------*/
       
    33 
       
    34 #include "riRasterizer.h"
       
    35 
       
    36 // TEMP!
       
    37 #ifndef __SFCOMPILER_H
       
    38 #   include "sfCompiler.h"
       
    39 #endif
       
    40 
       
    41 
       
    42 namespace OpenVGRI
       
    43 {
       
    44 
       
    45 /*-------------------------------------------------------------------*//*!
       
    46 * \brief	Rasterizer constructor.
       
    47 * \param
       
    48 * \return
       
    49 * \note
       
    50 *//*-------------------------------------------------------------------*/
       
    51 
       
    52 Rasterizer::Rasterizer() :
       
    53     m_covBuffer(NULL),
       
    54     m_covBufferSz(0),
       
    55     m_edges(),
       
    56     m_scissorEdges(),
       
    57     m_scissor(false),
       
    58     m_aa(true),
       
    59     m_vpx(0),
       
    60     m_vpy(0),
       
    61     m_vpwidth(0),
       
    62     m_vpheight(0),
       
    63     m_fillRule(VG_EVEN_ODD),
       
    64     m_pixelPipe(NULL),
       
    65     m_nSpans(0)
       
    66 {}
       
    67 
       
    68 /*-------------------------------------------------------------------*//*!
       
    69 * \brief	Rasterizer destructor.
       
    70 * \param
       
    71 * \return
       
    72 * \note
       
    73 *//*-------------------------------------------------------------------*/
       
    74 
       
    75 Rasterizer::~Rasterizer()
       
    76 {
       
    77     if(m_covBuffer)
       
    78         RI_DELETE_ARRAY(m_covBuffer);
       
    79 }
       
    80 
       
    81 /*-------------------------------------------------------------------*//*!
       
    82 * \brief	Removes all appended edges.
       
    83 * \param
       
    84 * \return
       
    85 * \note
       
    86 *//*-------------------------------------------------------------------*/
       
    87 
       
    88 #define EDGE_TERMINATOR 0xFFFFFFFFu
       
    89 
       
    90 void Rasterizer::clear()
       
    91 {
       
    92     //m_edges.clear();
       
    93     for (int i = 0; i < m_edges.size(); i++)
       
    94         m_edges[i] = EDGE_TERMINATOR;
       
    95 
       
    96     m_edgePool.clear();
       
    97 
       
    98     m_edgeMin.set(0x7fffffffu, 0x7fffffffu);
       
    99     m_edgeMax.set(0x80000000, 0x80000000);
       
   100 }
       
   101 
       
   102 /*-------------------------------------------------------------------*//*!
       
   103 * \brief	Appends an edge to the rasterizer.
       
   104 * \param
       
   105 * \return
       
   106 * \note
       
   107 *//*-------------------------------------------------------------------*/
       
   108 
       
   109 void Rasterizer::addBBox(const IVector2& v)
       
   110 {
       
   111     if(v.x < m_edgeMin.x) m_edgeMin.x = v.x;
       
   112     if(v.y < m_edgeMin.y) m_edgeMin.y = v.y;
       
   113     if(v.x > m_edgeMax.x) m_edgeMax.x = v.x;
       
   114     if(v.y > m_edgeMax.y) m_edgeMax.y = v.y;
       
   115 }
       
   116 
       
   117 void Rasterizer::pushEdge(const Edge& edge)
       
   118 {
       
   119     addBBox(edge.v0);
       
   120     addBBox(edge.v1);
       
   121 
       
   122     // Only add processed edges.
       
   123 
       
   124     RI_ASSERT(edge.v0.y >= 0);
       
   125     RI_ASSERT(edge.v0.y < edge.v1.y);	//horizontal edges should have been dropped already
       
   126 
       
   127     ActiveEdge ae;
       
   128     ae.direction = edge.direction;
       
   129 
       
   130     // \todo Adjust for non-AA cases
       
   131     // \todo verySteep is temporary. Either clip to right edge also, or validate that a proper slope can be
       
   132     // calculated here.
       
   133     const int slope	= RI_SAT_SHL((edge.v1.x - edge.v0.x), RASTERIZER_BITS - X_BITS) / (edge.v1.y - edge.v0.y);
       
   134     //const bool verySteep = RI_INT_ABS(edge.v1.x - edge.v0.x) > (1 << (30-RASTERIZER_BITS)) ? true : false;
       
   135     //const int slope	= verySteep ? 1 << 30 : RI_SHL((edge.v1.x - edge.v0.x), RASTERIZER_BITS - X_BITS) / (edge.v1.y - edge.v0.y);
       
   136     // slope: SI.(RASTERIZER_BITS - Y_BITS)
       
   137     const int yF 	= edge.v0.y & Y_MASK;
       
   138     // \todo See verySteep note for this hack also. (Clip to right edge?)
       
   139     const int xRef 	= RI_SAT_SHL(edge.v0.x, RASTERIZER_BITS - X_BITS) - (yF * slope);
       
   140     //const int xRef 	= edge.v0.x > (1<<(30-RASTERIZER_BITS)) ? 1<<30 : RI_SHL(edge.v0.x, RASTERIZER_BITS - X_BITS) - (yF * slope);
       
   141 
       
   142     RI_ASSERT(RI_INT_ABS(edge.v0.y <= 32767));
       
   143     RI_ASSERT(RI_INT_ABS(edge.v1.y <= 32767));
       
   144 
       
   145     ae.yStart 		= (RIint16)edge.v0.y;
       
   146     ae.yEnd 	  	= (RIint16)edge.v1.y;
       
   147     ae.xRef 		= xRef;
       
   148     ae.slope 		= slope;
       
   149     // Scanline range.
       
   150     ae.minx         = xRef >> RASTERIZER_BITS;
       
   151     ae.maxx         = (xRef + slope * (1<<Y_BITS)) >> RASTERIZER_BITS;
       
   152 
       
   153     if (ae.minx > ae.maxx)
       
   154         RI_ANY_SWAP(ActiveEdge::XCoord, ae.minx, ae.maxx);
       
   155 
       
   156     if (ae.maxx < 0)
       
   157         ae.minx = ae.maxx = LEFT_DISCARD_SHORT;
       
   158 
       
   159     if (m_edges[ae.yStart>>Y_BITS] == EDGE_TERMINATOR)
       
   160         ae.next = EDGE_TERMINATOR;
       
   161     else
       
   162         ae.next = m_edges[ae.yStart>>Y_BITS];
       
   163 
       
   164     m_edgePool.push_back(ae);	//throws bad_alloc
       
   165 
       
   166     RI_ASSERT(m_edgePool.size() > 0);
       
   167     m_edges[ae.yStart>>Y_BITS] = m_edgePool.size()-1;
       
   168 }
       
   169 
       
   170 /**
       
   171  * \brief   Clips an edge and if something remains, adds it to the list of edges.
       
   172  * \todo    Enhance precision: Currently this just uses doubles and gets away with
       
   173  *          it in most cases.
       
   174  */
       
   175 void Rasterizer::clipAndAddEdge(Edge& edge)
       
   176 {
       
   177     //if (m_edges.size() > 48)
       
   178         //return;
       
   179     // Check y-clips
       
   180     // \todo Reduce amount of clips.
       
   181     bool outLeft[2] = {(edge.v0.x < m_vpMinx), (edge.v1.x < m_vpMinx)};
       
   182     bool outRight[2] = {(edge.v0.x > m_vpMaxx), (edge.v1.x > m_vpMaxx)};
       
   183     bool outTop[2] = {(edge.v0.y < m_vpMiny), (edge.v1.y < m_vpMiny)};
       
   184     bool outBottom[2] = {(edge.v0.y > m_vpMaxy), (edge.v1.y > m_vpMaxy)};
       
   185 
       
   186     if (!(outLeft[0] || outLeft[1] || outRight[0] || outRight[1] || outTop[0] || outTop[1] || outBottom[0] || outBottom[1]))
       
   187     {
       
   188         pushEdge(edge);
       
   189         return;
       
   190     }
       
   191 
       
   192     // \todo Make sure that checking out-of-right works with the scanconverter.
       
   193     if ((outBottom[0] && outBottom[1]) || (outTop[0] && outTop[1]))
       
   194         return; // Out of bounds
       
   195 
       
   196     // \todo Clip to right edge of screen.
       
   197     // \todo Make slope-calculation and signs consistent.
       
   198     //
       
   199     if (outTop[0] || outBottom[1])
       
   200     {
       
   201         // Clip to top/bottom.
       
   202         double slope = (double)(edge.v1.x - edge.v0.x)/(edge.v1.y - edge.v0.y);
       
   203 
       
   204         if (outTop[0])
       
   205         {
       
   206             RI_ASSERT(-(RIint64)edge.v0.y >= 0);
       
   207             RIint32 dx = RI_ROUND_TO_INT(-slope * edge.v0.y);
       
   208             edge.v0.y = 0;
       
   209             edge.v0.x += dx;
       
   210         }
       
   211 
       
   212         if (outBottom[1])
       
   213         {
       
   214             RIint32 dy = edge.v1.y - m_vpMaxy;
       
   215             RI_ASSERT(dy >= 0);
       
   216             RIint32 dx = -RI_ROUND_TO_INT(slope * dy);
       
   217             edge.v1.y = m_vpMaxy;
       
   218             edge.v1.x += dx;
       
   219         }
       
   220 
       
   221     }
       
   222 
       
   223     if (edge.v0.y >= edge.v1.y)
       
   224         return;
       
   225 
       
   226     // \todo Recheck left/right.
       
   227     outLeft[0] = (edge.v0.x < m_vpMinx); outLeft[1] = (edge.v1.x < m_vpMinx);
       
   228     outRight[1] = (edge.v0.x > m_vpMaxx); outRight[1] = (edge.v1.x > m_vpMaxx);
       
   229 
       
   230     if (outLeft[0] && outLeft[1])
       
   231     {
       
   232         edge.v0.x = m_vpMinx;
       
   233         edge.v1.x = m_vpMinx;
       
   234         pushEdge(edge);
       
   235         return;
       
   236     }
       
   237     if (outRight[0] && outRight[1])
       
   238     {
       
   239         edge.v0.x = m_vpMaxx;
       
   240         edge.v1.x = m_vpMaxx;
       
   241         pushEdge(edge);
       
   242         return;
       
   243     }
       
   244 
       
   245     // From outside -> screen
       
   246     if (outLeft[0] || outRight[1])
       
   247     {
       
   248         // infinite slope?
       
   249         double slope = (double)((RIint64)edge.v1.y - edge.v0.y)/((RIint64)edge.v1.x - edge.v0.x);
       
   250 
       
   251         if (outLeft[0])
       
   252         {
       
   253             RIint32 dx = edge.v0.x;
       
   254             //RI_ASSERT(dx >= 0);
       
   255             // Note the sign.
       
   256             RIint32 dy = RI_ROUND_TO_INT(-slope * dx);
       
   257 
       
   258             Edge vpart = edge;
       
   259             vpart.v1.y = edge.v0.y + dy;
       
   260             //vpart.v1.x = edge.v0.x; // = 0?
       
   261             // \note This should be flagged instead of setting the smallest possible
       
   262             // value because of extremely gentle slopes may cause bugs:
       
   263             vpart.v1.x = vpart.v0.x = -0x100000;
       
   264 
       
   265             if (vpart.v1.y > vpart.v0.y)
       
   266                 pushEdge(vpart);
       
   267 
       
   268             edge.v0.y += dy;
       
   269             edge.v0.x = 0;
       
   270         }
       
   271     }
       
   272     // From screen -> outside
       
   273     if (outLeft[1] || outRight[0])
       
   274     {
       
   275         // infinite slope?
       
   276         double slope = (double)((RIint64)edge.v1.y - edge.v0.y)/((RIint64)edge.v1.x - edge.v0.x);
       
   277 
       
   278         if (outLeft[1])
       
   279         {
       
   280             RIint32 dx = edge.v0.x;
       
   281             RI_ASSERT(dx >= 0);
       
   282             RIint32 dy = RI_ROUND_TO_INT(-slope * dx);
       
   283 
       
   284             Edge vpart = edge;
       
   285             vpart.v0.y = edge.v0.y + dy;
       
   286             vpart.v1.x = vpart.v0.x = LEFT_DISCARD;
       
   287 
       
   288             if (vpart.v1.y > vpart.v0.y)
       
   289                 pushEdge(vpart);
       
   290 
       
   291             edge.v1.y = edge.v0.y + dy;
       
   292             edge.v1.x = 0;
       
   293         }
       
   294     }
       
   295 
       
   296     if (edge.v0.y >= edge.v1.y)
       
   297         return;
       
   298 
       
   299     // Finally, add the edge:
       
   300     pushEdge(edge);
       
   301 }
       
   302 
       
   303 void Rasterizer::addEdge(const Vector2& v0, const Vector2& v1)
       
   304 {
       
   305     if( m_edges.size() >= RI_MAX_EDGES )
       
   306         throw std::bad_alloc();	//throw an out of memory error if there are too many edges
       
   307 
       
   308     Edge e;
       
   309 
       
   310     {
       
   311         IVector2 i0(RI_ROUND_TO_INT(v0.x * (1<<X_BITS)), RI_ROUND_TO_INT(v0.y * (1<<Y_BITS)));
       
   312         IVector2 i1(RI_ROUND_TO_INT(v1.x * (1<<X_BITS)), RI_ROUND_TO_INT(v1.y * (1<<Y_BITS)));
       
   313 
       
   314         if(i0.y == i1.y)
       
   315             return;	//skip horizontal edges (they don't affect rasterization since we scan horizontally)
       
   316 
       
   317         if (i0.y < i1.y)
       
   318         {
       
   319             // Edge is going upward
       
   320             e.v0 = i0;
       
   321             e.v1 = i1;
       
   322             e.direction = 1;
       
   323         }
       
   324         else
       
   325         {
       
   326             // Edge is going downward
       
   327             e.v0 = i1;
       
   328             e.v1 = i0;
       
   329             e.direction = -1;
       
   330         }
       
   331     }
       
   332 
       
   333     // Clip and insert.
       
   334 
       
   335     clipAndAddEdge(e);
       
   336 }
       
   337 
       
   338 /*-------------------------------------------------------------------*//*!
       
   339 * \brief	Set up rasterizer
       
   340 * \param
       
   341 * \return
       
   342 * \note
       
   343 *//*-------------------------------------------------------------------*/
       
   344 
       
   345 void Rasterizer::setup(int vpx, int vpy, int vpwidth, int vpheight, VGFillRule fillRule, const PixelPipe* pixelPipe)
       
   346 {
       
   347     RI_ASSERT(vpwidth >= 0 && vpheight >= 0);
       
   348     RI_ASSERT(vpx + vpwidth >= vpx && vpy + vpheight >= vpy);
       
   349     RI_ASSERT(fillRule == VG_EVEN_ODD || fillRule == VG_NON_ZERO);
       
   350     RI_ASSERT(pixelPipe);
       
   351 
       
   352     clear();
       
   353 
       
   354     m_vpx = vpx;
       
   355     m_vpy = vpy;
       
   356     m_vpwidth = vpwidth;
       
   357     m_vpheight = vpheight;
       
   358 
       
   359     if (m_vpheight > m_edges.size())
       
   360     {
       
   361         int os = m_edges.size();
       
   362         m_edges.resize(m_vpheight);
       
   363         for (int i = os; i < m_edges.size(); i++)
       
   364             m_edges[i] = EDGE_TERMINATOR;
       
   365     }
       
   366 
       
   367     m_vpMinx = RI_SHL(vpx, X_BITS);
       
   368     m_vpMiny = RI_SHL(vpy, Y_BITS);
       
   369     m_vpMaxx = RI_SHL(vpx + vpwidth, X_BITS);
       
   370     m_vpMaxy = RI_SHL(vpy + vpheight, Y_BITS);
       
   371 
       
   372     m_fillRule = fillRule;
       
   373 
       
   374     RIuint32 fillRuleMask = fillRule == VG_NON_ZERO ? 0xffffffffu : 1;
       
   375     m_fillRuleMask = fillRuleMask;
       
   376 
       
   377     m_pixelPipe = pixelPipe;
       
   378     m_covMinx = vpx+vpwidth;
       
   379     m_covMiny = vpy+vpheight;
       
   380     m_covMaxx = vpx;
       
   381     m_covMaxy = vpy;
       
   382 }
       
   383 
       
   384 /*-------------------------------------------------------------------*//*!
       
   385 * \brief	Sets scissor rectangles.
       
   386 * \param
       
   387 * \return
       
   388 * \note
       
   389 *//*-------------------------------------------------------------------*/
       
   390 
       
   391 void Rasterizer::setScissor(const Array<Rectangle>& scissors)
       
   392 {
       
   393     try
       
   394     {
       
   395         m_scissorEdges.clear();
       
   396         for(int i=0;i<scissors.size();i++)
       
   397         {
       
   398             if(scissors[i].width > 0 && scissors[i].height > 0)
       
   399             {
       
   400                 ScissorEdge e;
       
   401                 e.miny = scissors[i].y;
       
   402                 e.maxy = RI_INT_ADDSATURATE(scissors[i].y, scissors[i].height);
       
   403 
       
   404                 e.x = scissors[i].x;
       
   405                 e.direction = 1;
       
   406                 m_scissorEdges.push_back(e);	//throws bad_alloc
       
   407                 e.x = RI_INT_ADDSATURATE(scissors[i].x, scissors[i].width);
       
   408                 e.direction = -1;
       
   409                 m_scissorEdges.push_back(e);	//throws bad_alloc
       
   410             }
       
   411         }
       
   412     }
       
   413     catch(std::bad_alloc)
       
   414     {
       
   415         m_scissorEdges.clear();
       
   416         throw;
       
   417     }
       
   418 }
       
   419 
       
   420 void Rasterizer::setScissoring(bool enabled)
       
   421 {
       
   422     m_scissor = enabled;
       
   423 }
       
   424 
       
   425 static RI_INLINE void small_memcpy32(void* dst, const void* src, size_t n)
       
   426 {
       
   427     RIuint32 *d = (RIuint32*)dst;
       
   428     const RIuint32 *s = (const RIuint32*)src;
       
   429     while(n)
       
   430     {
       
   431         *d++ = *s++;
       
   432         n-=4;
       
   433     }
       
   434 }
       
   435 
       
   436 // \todo Move this to some debug file or remove.
       
   437 #if defined(USE_SSE2) && !defined(_WIN32)
       
   438 RI_INLINE static void print128(__m128i ll)
       
   439 {
       
   440 #if defined(RI_DEBUG)
       
   441     unsigned long long v[2];
       
   442     _mm_storeu_pd((double*)v, (__m128d)ll);
       
   443     RI_PRINTF("0x%016llx %016llx\n", v[0], v[1]);
       
   444 #else
       
   445     (void)ll;
       
   446 #endif
       
   447 }
       
   448 #endif
       
   449 
       
   450 #if defined(USE_SSE2)
       
   451 RI_INLINE static __m128i mm_mul4x32(const __m128i a, const __m128i b) {
       
   452      __m128i res;
       
   453 #if (_MSC_VER > 1400 )
       
   454      // \todo Simpler way to do this on intel?
       
   455      __m128i m0 = _mm_mul_epu32(a, _mm_shuffle_epi32(b, _MM_SHUFFLE(1, 1, 0, 0)));
       
   456      __m128i m1 = _mm_mul_epu32(a, _mm_shuffle_epi32(b, _MM_SHUFFLE(3, 3, 2, 2)));
       
   457 
       
   458      res = _mm_castps_si128(_mm_shuffle_ps(_mm_castsi128_ps(m0), _mm_castsi128_ps(m1), _MM_SHUFFLE(2, 0, 2, 0)));
       
   459 #else
       
   460      __asm {
       
   461          movdqa xmm1, a;
       
   462          movdqa xmm2, b;
       
   463          pshufd xmm3, xmm2, 80;
       
   464          movdqa xmm0, xmm1;
       
   465 
       
   466          pshufd xmm2, xmm2, 250;
       
   467          pmuludq xmm0, xmm3;
       
   468          pmuludq xmm1, xmm2;
       
   469 
       
   470          shufps xmm0, xmm1, 136;
       
   471          movdqa res, xmm0;
       
   472      }
       
   473 #endif
       
   474      return res;
       
   475 }
       
   476 #endif
       
   477 
       
   478 #if defined(USE_SSE2)
       
   479 RI_INLINE static void mm_get_xmasks(const __m128i& coords, const __m128i& sampleCoords, __m128i& slWindMask, __m128i& pxWindMask)
       
   480 {
       
   481     const __m128i z = _mm_setzero_si128();
       
   482     const __m128i xMask = _mm_cmpeq_epi16(_mm_srai_epi16(coords, Rasterizer::RASTERIZER_BITS), z);
       
   483     const __m128i sCmp = _mm_or_si128(_mm_cmpgt_epi16(sampleCoords, coords), _mm_cmpeq_epi16(sampleCoords, coords));
       
   484     //const __m128i sCmp = _mm_cmplt_epi16(coords, sampleCoords);
       
   485     slWindMask = xMask;
       
   486     pxWindMask = _mm_and_si128(xMask, sCmp);
       
   487 }
       
   488 #endif
       
   489 
       
   490 RI_INLINE static void getVerticalSubpixels(int iY, int yStart, int yEnd, int& py0, int& py1)
       
   491 {
       
   492     const int cy = iY << Rasterizer::Y_BITS;
       
   493     py0 = cy > yStart ? 0 : yStart & Rasterizer::Y_MASK;
       
   494     py1 = (RI_INT_MIN(yEnd, cy + (1<<Rasterizer::Y_BITS)) - 1) & Rasterizer::Y_MASK;
       
   495 }
       
   496 
       
   497 RI_INLINE static void applyLeftEdge(const Rasterizer::ActiveEdge& currAe, Rasterizer::Windings& scanline, int intY)
       
   498 {
       
   499     // Applies the whole edge at a time. Make sure xRight < x for all y.
       
   500     // \todo Remove duplicate code for determining the active samples
       
   501 #if defined(USE_SSE2)
       
   502     int py0, py1;
       
   503 
       
   504     getVerticalSubpixels(intY, currAe.yStart, currAe.yEnd, py0, py1);
       
   505 
       
   506     const __m128i csteps = _mm_set_epi16(7,6,5,4,3,2,1,0);
       
   507 
       
   508     const __m128i ssePy0 = _mm_set1_epi16(py0-1);
       
   509     const __m128i ssePy1 = _mm_set1_epi16(py1+1);
       
   510 
       
   511     const __m128i yMask = _mm_and_si128(_mm_cmpgt_epi16(csteps, ssePy0), _mm_cmplt_epi16(csteps, ssePy1));
       
   512     const __m128i dir = _mm_set1_epi16(currAe.direction);
       
   513 
       
   514     scanline.sseWinding = _mm_add_epi16(scanline.sseWinding, _mm_and_si128(yMask, dir));
       
   515 
       
   516 #else
       
   517     RI_ASSERT(false); // Not implemented yet.
       
   518 #endif
       
   519 }
       
   520 
       
   521 RI_INLINE static void applyLeftEdgeNoAA(const Rasterizer::ActiveEdge& currAe, Rasterizer::Windings& scanline, int intY)
       
   522 {
       
   523     // Applies the whole edge at a time. Make sure xRight < x for all y.
       
   524     // \todo Remove duplicate code for determining the active samples?
       
   525 #if defined(USE_SSE2)
       
   526     int py0, py1;
       
   527 
       
   528     getVerticalSubpixels(intY, currAe.yStart, currAe.yEnd, py0, py1);
       
   529 
       
   530     //const __m128i csteps = _mm_set_epi16(4,4,4,4,4,4,4,4);
       
   531 
       
   532     __m128i yMask;
       
   533 
       
   534     if (py0 <= 4 && py1 >= 4)
       
   535         yMask = _mm_set1_epi8(-1);
       
   536     else
       
   537         yMask = _mm_set1_epi8(0);
       
   538 
       
   539     const __m128i dir = _mm_set1_epi16(currAe.direction);
       
   540 
       
   541     scanline.sseWinding = _mm_add_epi16(scanline.sseWinding, _mm_and_si128(yMask, dir));
       
   542     //scanline.sseWinding = _mm_add_epi32(scanline.sseWinding, dir);
       
   543 
       
   544 #else
       
   545     RI_ASSERT(false); // Not implemented yet.
       
   546 #endif
       
   547 }
       
   548 
       
   549 RI_INLINE void calculateAEWinding(const Rasterizer::ActiveEdge& currAe, Rasterizer::Windings& pixel, Rasterizer::Windings& scanline, int intY, int pixelX)
       
   550 {
       
   551 #define QUEEN_COORD(Y) ((Y<<(Rasterizer::RASTERIZER_BITS - Rasterizer::SAMPLE_BITS)) + (1<<(Rasterizer::RASTERIZER_BITS-Rasterizer::SAMPLE_BITS-1)))
       
   552 
       
   553 #if !defined(USE_SSE2)
       
   554     static const int queenCoords[(1<<Rasterizer::SAMPLE_BITS)] = {
       
   555         QUEEN_COORD(3), QUEEN_COORD(7), QUEEN_COORD(0), QUEEN_COORD(2),
       
   556         QUEEN_COORD(5), QUEEN_COORD(1), QUEEN_COORD(6), QUEEN_COORD(4)
       
   557     };
       
   558 
       
   559     const int ix = pixelX >> Rasterizer::RASTERIZER_BITS;
       
   560     const int cy = intY << Rasterizer::Y_BITS;
       
   561 
       
   562     const int py0 = cy > currAe.yStart ? 0 : currAe.yStart & Rasterizer::Y_MASK;
       
   563     const int py1 = (RI_INT_MIN(currAe.yEnd, cy + (1<<Rasterizer::Y_BITS)) - 1) & Rasterizer::Y_MASK;
       
   564 
       
   565     int edgeX = currAe.xRef + (cy + py0 - (currAe.yStart & ~Rasterizer::Y_MASK)) * currAe.slope;
       
   566 
       
   567     RI_ASSERT(py1 >= py0);
       
   568 
       
   569     for (int s = py0; s <= py1; s++)
       
   570     {
       
   571         const int sampleX = pixelX + queenCoords[s];
       
   572 
       
   573         //compute winding number by evaluating the edge functions of edges to the left of the sampling point
       
   574         if(((edgeX >> Rasterizer::RASTERIZER_BITS) == ix))
       
   575         {
       
   576             if (sampleX >= edgeX)
       
   577             {
       
   578                 pixel.winding[s] += currAe.direction;
       
   579             }
       
   580             scanline.winding[s] += currAe.direction;
       
   581         }
       
   582 
       
   583         edgeX += currAe.slope;
       
   584     }
       
   585 #else
       
   586 
       
   587     __m128i qCoords = _mm_set_epi16(
       
   588         QUEEN_COORD(4), QUEEN_COORD(6), QUEEN_COORD(1), QUEEN_COORD(5),
       
   589         QUEEN_COORD(2), QUEEN_COORD(0), QUEEN_COORD(7), QUEEN_COORD(3));
       
   590 
       
   591     RI_ASSERT(Rasterizer::RASTERIZER_BITS <= 14);
       
   592 
       
   593     // TEROP: Optimize conditions.
       
   594     int py0, py1;
       
   595     getVerticalSubpixels(intY, currAe.yStart, currAe.yEnd, py0, py1);
       
   596 
       
   597     const int cy = intY << Rasterizer::Y_BITS;
       
   598 
       
   599     const __m128i csteps0 = _mm_set_epi32(3,2,1,0);
       
   600     const __m128i csteps1 = _mm_set_epi32(7,6,5,4);
       
   601 
       
   602     const __m128i ssePy0 = _mm_set1_epi32(py0-1);
       
   603     const __m128i ssePy1 = _mm_set1_epi32(py1+1);
       
   604 
       
   605     const __m128i yMask0 = _mm_and_si128(_mm_cmpgt_epi32(csteps0, ssePy0), _mm_cmplt_epi32(csteps0, ssePy1));
       
   606     const __m128i yMask1 = _mm_and_si128(_mm_cmpgt_epi32(csteps1, ssePy0), _mm_cmplt_epi32(csteps1, ssePy1));
       
   607 
       
   608     const int edgeX = currAe.xRef + (cy - (currAe.yStart & ~Rasterizer::Y_MASK)) * currAe.slope;
       
   609     const __m128i xStart = _mm_set1_epi32(edgeX - pixelX);
       
   610 
       
   611     const __m128i xs0 = _mm_set1_epi32(currAe.slope);
       
   612 
       
   613     __m128i xAdd0 = mm_mul4x32(xs0, csteps0);
       
   614     __m128i xAdd1 = mm_mul4x32(xs0, csteps1);
       
   615     __m128i coords0 = _mm_add_epi32(xStart, xAdd0);
       
   616     __m128i coords1 = _mm_add_epi32(xStart, xAdd1);
       
   617     __m128i coords = _mm_packs_epi32(coords0, coords1);
       
   618 
       
   619     __m128i dir = _mm_set1_epi16(currAe.direction);
       
   620     __m128i yMask = _mm_packs_epi32(yMask0, yMask1);
       
   621     __m128i mDir = _mm_and_si128(dir, yMask);
       
   622 
       
   623     __m128i sampleCoords = qCoords;
       
   624 
       
   625     __m128i sw, pw;
       
   626     mm_get_xmasks(coords, sampleCoords, sw, pw);
       
   627 
       
   628     pixel.sseWinding = _mm_add_epi16(pixel.sseWinding, _mm_and_si128(pw, mDir));
       
   629     scanline.sseWinding = _mm_add_epi16(scanline.sseWinding, _mm_and_si128(sw, mDir));
       
   630 #endif
       
   631 
       
   632 #undef QUEEN_COORD
       
   633 
       
   634 }
       
   635 
       
   636 /**
       
   637  * \brief   Calculate winding using one sample only.
       
   638  * \note    This uses most of the same code as the AA-case even though it is not
       
   639  *          necessary (one sample would be enough).
       
   640  */
       
   641 RI_INLINE void calculateAEWindingNoAA(const Rasterizer::ActiveEdge& currAe, Rasterizer::Windings& pixel, Rasterizer::Windings& scanline, int intY, int pixelX)
       
   642 {
       
   643 #if defined(USE_SSE2)
       
   644 
       
   645 #define QUEEN_COORD(Y) ((Y<<(Rasterizer::RASTERIZER_BITS - Rasterizer::SAMPLE_BITS)) + (1<<(Rasterizer::RASTERIZER_BITS-Rasterizer::SAMPLE_BITS-1)))
       
   646     const int half = 1<<(Rasterizer::RASTERIZER_BITS-1);
       
   647 
       
   648     __m128i sampleCoords = _mm_set1_epi16(half);
       
   649 
       
   650     RI_ASSERT(Rasterizer::RASTERIZER_BITS <= 14);
       
   651 
       
   652     const int cy = intY << Rasterizer::Y_BITS;
       
   653 
       
   654     int py0, py1;
       
   655     getVerticalSubpixels(intY, currAe.yStart, currAe.yEnd, py0, py1);
       
   656 
       
   657     __m128i yMask;
       
   658 
       
   659     if (py0 <= 4 && py1 >= 4)
       
   660         yMask = _mm_set1_epi8(-1);
       
   661     else
       
   662         yMask = _mm_set1_epi8(0);
       
   663 
       
   664     const __m128i csteps0 = _mm_set_epi32(4,4,4,4);
       
   665     const __m128i csteps1 = _mm_set_epi32(4,4,4,4);
       
   666 
       
   667     const int edgeX = currAe.xRef + (cy - (currAe.yStart & ~Rasterizer::Y_MASK)) * currAe.slope;
       
   668     const __m128i xStart = _mm_set1_epi32(edgeX - pixelX);
       
   669 
       
   670     const __m128i xs0 = _mm_set1_epi32(currAe.slope);
       
   671 
       
   672     __m128i xAdd0 = mm_mul4x32(xs0, csteps0);
       
   673     __m128i xAdd1 = mm_mul4x32(xs0, csteps1);
       
   674     __m128i coords0 = _mm_add_epi32(xStart, xAdd0);
       
   675     __m128i coords1 = _mm_add_epi32(xStart, xAdd1);
       
   676     __m128i coords = _mm_packs_epi32(coords0, coords1);
       
   677 
       
   678     __m128i dir = _mm_set1_epi16(currAe.direction);
       
   679     __m128i mDir = _mm_and_si128(dir, yMask);
       
   680     //__m128i mDir = dir;
       
   681 
       
   682     __m128i sw, pw;
       
   683     mm_get_xmasks(coords, sampleCoords, sw, pw);
       
   684 
       
   685     pixel.sseWinding = _mm_add_epi16(pixel.sseWinding, _mm_and_si128(pw, mDir));
       
   686     scanline.sseWinding = _mm_add_epi16(scanline.sseWinding, _mm_and_si128(sw, mDir));
       
   687 
       
   688 #undef QUEEN_COORD
       
   689 
       
   690 #else
       
   691     RI_ASSERT(false); // Not implemented.
       
   692 #endif
       
   693 }
       
   694 
       
   695 #if defined(USE_SSE2)
       
   696 RI_INLINE static int mm_winding_to_coverage(const Rasterizer::Windings& pixel, int fillRuleMask)
       
   697 {
       
   698     // This version uses SSE2 counters.
       
   699     __m128i mask = _mm_set1_epi16(fillRuleMask);
       
   700     __m128i t = _mm_and_si128(mask, pixel.sseWinding);
       
   701     __m128i z = _mm_setzero_si128();
       
   702     __m128i isz = _mm_cmpeq_epi16(t, z);
       
   703     __m128i ones = _mm_set1_epi16(1);
       
   704     __m128i res = _mm_add_epi16(ones, isz);
       
   705     __m128i add0 = _mm_add_epi16(res, _mm_shuffle_epi32(res, _MM_SHUFFLE(2, 3, 2, 3)));
       
   706     __m128i add1 = _mm_add_epi16(add0, _mm_shuffle_epi32(add0, _MM_SHUFFLE(1, 1, 1, 1)));
       
   707     __m128i add2 = _mm_add_epi16(add1, _mm_shufflelo_epi16(add1, _MM_SHUFFLE(1, 1, 1, 1)));
       
   708 
       
   709     int nSamples = _mm_cvtsi128_si32(add2) & 0xff;
       
   710     return nSamples;
       
   711 }
       
   712 #endif
       
   713 
       
   714 #define RI_DEBUG
       
   715 #if defined(RI_DEBUG)
       
   716 void maybeDumpEdges(Array<Rasterizer::ActiveEdge> &edgePool)
       
   717 {
       
   718     return;
       
   719     // \note This gives an idea about the edges at the rasterization stage.
       
   720     // Input edges must be output at a different stage.
       
   721     RI_PRINTF("lines = []\n");
       
   722     for (int i = 0 ; i < edgePool.size(); i++)
       
   723     {
       
   724         const int slope = edgePool[i].slope;
       
   725         int x0, x1, y0, y1;
       
   726         y0 = edgePool[i].yStart;
       
   727         y1 = edgePool[i].yEnd;
       
   728         x0 = edgePool[i].xRef + (slope * (y0 & Rasterizer::Y_MASK));
       
   729         x1 = (edgePool[i].xRef + (slope * (y1 - (y0 & ~Rasterizer::Y_MASK))))>>(Rasterizer::RASTERIZER_BITS-Rasterizer::X_BITS);
       
   730         RI_PRINTF("lines += [[%d, %d], [%d, %d]]\n",x0>>(Rasterizer::RASTERIZER_BITS-Rasterizer::X_BITS),y0,x1,y1);
       
   731     }
       
   732 }
       
   733 #endif
       
   734 
       
   735 /*-------------------------------------------------------------------*//*!
       
   736 * \brief	Calls PixelPipe::pixelPipe for each pixel with coverage greater
       
   737 *			than zero.
       
   738 * \param
       
   739 * \return
       
   740 * \note
       
   741 *//*-------------------------------------------------------------------*/
       
   742 void Rasterizer::fill()
       
   743 {
       
   744     if(m_scissor && !m_scissorEdges.size())
       
   745         return;	//scissoring is on, but there are no scissor rectangles => nothing is visible
       
   746 
       
   747     int firstAe = 0;
       
   748 
       
   749     //proceed scanline by scanline
       
   750     //keep track of edges that can intersect the pixel filters of the current scanline (Active Edge Table)
       
   751     //until all pixels of the scanline have been processed
       
   752     //  for all sampling points of the current pixel
       
   753     //    determine the winding number using edge functions
       
   754     //    add filter weight to coverage
       
   755     //  divide coverage by the number of samples
       
   756     //  determine a run of pixels with constant coverage
       
   757     //  call fill callback for each pixel of the run
       
   758 
       
   759     const int fillRuleMask = m_fillRuleMask;
       
   760 
       
   761     int bbminx = (m_edgeMin.x >> X_BITS);
       
   762     int bbminy = (m_edgeMin.y >> Y_BITS);
       
   763     int bbmaxx = (m_edgeMax.x >> X_BITS)+1;
       
   764     int bbmaxy = (m_edgeMax.y >> Y_BITS)+1;
       
   765     int sx = RI_INT_MAX(m_vpx, bbminx);
       
   766     int ex = RI_INT_MIN(m_vpx+m_vpwidth, bbmaxx);
       
   767     int sy = RI_INT_MAX(m_vpy, bbminy);
       
   768     int ey = RI_INT_MIN(m_vpy+m_vpheight, bbmaxy);
       
   769     if(sx < m_covMinx) m_covMinx = sx;
       
   770     if(sy < m_covMiny) m_covMiny = sy;
       
   771     if(ex > m_covMaxx) m_covMaxx = ex;
       
   772     if(ey > m_covMaxy) m_covMaxy = ey;
       
   773 
       
   774 #if 0
       
   775     // Dump edges:
       
   776     static bool dump = true;
       
   777     if (dump)
       
   778     {
       
   779         RI_PRINTF("lines = []\n");
       
   780         for (int ie = 0; dump && ie < m_edgePool.size(); ie++)
       
   781         {
       
   782             RI_PRINTF("lines += [[%d, %d], [%d, %d]]\n",m_edgePool[ie].v0.x, m_edgePool[ie].v0.y, m_edgePool[ie].v1.x, m_edgePool[ie].v1.y);
       
   783         }
       
   784         dump = false;
       
   785     }
       
   786 
       
   787 #endif
       
   788     int debugMagic = 0;
       
   789 
       
   790     m_aet.clear();
       
   791 
       
   792 #if defined(RI_DEBUG)
       
   793     maybeDumpEdges(m_edgePool);
       
   794 #endif
       
   795 
       
   796     //fill the screen
       
   797     for(int j = sy; j < ey; j++)
       
   798     {
       
   799         Windings scanlineWinding;
       
   800         const int cminy = j << Y_BITS;
       
   801 
       
   802         if (m_scissor)
       
   803         {
       
   804             // Gather scissor edges intersecting this scanline
       
   805             // \todo Don't clear, remove unused instead!
       
   806             m_scissorAet.clear();
       
   807 
       
   808             for(int e = 0; e < m_scissorEdges.size(); e++)
       
   809             {
       
   810                 const ScissorEdge& se = m_scissorEdges[e];
       
   811 
       
   812                 if(j >= se.miny && j < se.maxy)
       
   813                     m_scissorAet.push_back(m_scissorEdges[e]);	//throws bad_alloc
       
   814             }
       
   815 
       
   816             //sort scissor AET by edge x
       
   817             if (m_scissor)
       
   818                 m_scissorAet.sort();
       
   819         }
       
   820 
       
   821         // Drop unused edges, update remaining.
       
   822         // \todo Combine with full sweep. Use a sort-friendly edge-discard.
       
   823         for (int iae = firstAe; iae < m_aet.size(); iae++)
       
   824         {
       
   825             ActiveEdge& ae = m_aet[iae];
       
   826 
       
   827             if (cminy >= ae.yEnd)
       
   828             {
       
   829                 m_aet[iae] = m_aet[firstAe];
       
   830                 firstAe++;
       
   831                 continue;
       
   832             }
       
   833 
       
   834             /* Update existing coordinates */
       
   835             // \todo AND instead of shift. See other places also.
       
   836             const int y0 = (ae.yStart & ~Y_MASK);
       
   837             const int x = ae.xRef + ((j << Y_BITS) - y0) * ae.slope;
       
   838             ae.minx = x >> RASTERIZER_BITS;
       
   839             ae.maxx = (x + ae.slope * (1<<Y_BITS)) >> RASTERIZER_BITS;
       
   840 
       
   841             if (ae.minx > ae.maxx)
       
   842                 RI_ANY_SWAP(ActiveEdge::XCoord, ae.minx, ae.maxx);
       
   843 
       
   844             // If the edge is not visible, "mark" it as immediately applicable
       
   845             // \todo Verify that this is the correct procedure.
       
   846 
       
   847            if (ae.maxx < 0)
       
   848                ae.minx = ae.maxx = LEFT_DISCARD_SHORT;
       
   849        }
       
   850 
       
   851         /* Add new edges */
       
   852 
       
   853         RIuint32 aeIndex = m_edges[j];
       
   854         while (aeIndex != EDGE_TERMINATOR)
       
   855         {
       
   856             const ActiveEdge& ae = m_edgePool[aeIndex];
       
   857             m_aet.push_back(ae); // \todo Just copy pointers?
       
   858             aeIndex = ae.next;
       
   859         }
       
   860 
       
   861         if (firstAe >= m_aet.size())
       
   862         {
       
   863             RI_ASSERT(firstAe == m_aet.size());
       
   864             continue;	//no edges on the whole scanline, skip it
       
   865         }
       
   866 
       
   867         //sort AET by edge minx
       
   868         m_aet.sort(firstAe, m_aet.size() - 1);
       
   869 
       
   870         // \todo Optimize adding and updating the edges?
       
   871         if (m_scissor && !m_scissorAet.size())
       
   872             continue;	// Scissoring is on, but there are no scissor rectangles on this scanline.
       
   873 
       
   874         //fill the scanline
       
   875         int scissorWinding = m_scissor ? 0 : 1;	//if scissoring is off, winding is always 1
       
   876         int scissorIndex = 0;
       
   877         int aes = firstAe;
       
   878         int aen = firstAe;
       
   879 
       
   880         RI_ASSERT(sx >= 0);
       
   881 
       
   882 #if 1
       
   883         if (m_aa)
       
   884         {
       
   885             while ((aen < m_aet.size()) && (m_aet[aen].maxx < 0))
       
   886             {
       
   887                 applyLeftEdge(m_aet[aen], scanlineWinding, j);
       
   888                 aen++;
       
   889             }
       
   890         }
       
   891         else
       
   892         {
       
   893             while ((aen < m_aet.size()) && (m_aet[aen].maxx < 0))
       
   894             {
       
   895                 applyLeftEdgeNoAA(m_aet[aen], scanlineWinding, j);
       
   896                 aen++;
       
   897             }
       
   898         }
       
   899 
       
   900 #if defined(RI_DEBUG)
       
   901         for (int a = aen; a < m_aet.size(); a++)
       
   902         {
       
   903             RI_ASSERT(m_aet[a].maxx >= 0);
       
   904         }
       
   905 #endif
       
   906 #endif
       
   907 
       
   908         // \todo Combine this with the first check or reorganize the "clipping".
       
   909         if (aen >= m_aet.size())
       
   910             continue; // No edges within viewport. Can happen atm. when all edges are "left".
       
   911 
       
   912         for(int i = sx; i < ex;)
       
   913         {
       
   914             //find edges that intersect or are to the left of the pixel antialiasing filter
       
   915             while(aes < m_aet.size() && (i + 1) >= m_aet[aes].minx)
       
   916                 aes++;
       
   917             //edges [0,aes[ may have an effect on winding, and need to be evaluated while sampling
       
   918 
       
   919             // RIint8 winding[SF_SAMPLES];
       
   920             Windings pixelWinding;
       
   921 
       
   922             pixelWinding = scanlineWinding;
       
   923 
       
   924             if (m_aa)
       
   925             {
       
   926                 for(int e = aen; e < aes; e++)
       
   927                 {
       
   928                     const ActiveEdge& currAe = m_aet[e];
       
   929                     calculateAEWinding(currAe, pixelWinding, scanlineWinding, j, i << RASTERIZER_BITS);
       
   930                 }
       
   931             }
       
   932             else
       
   933             {
       
   934                 for(int e = aen; e < aes; e++)
       
   935                 {
       
   936                     const ActiveEdge& currAe = m_aet[e];
       
   937                     calculateAEWindingNoAA(currAe, pixelWinding, scanlineWinding, j, i << RASTERIZER_BITS);
       
   938                 }
       
   939             }
       
   940 
       
   941             //compute coverage
       
   942             int coverageSamples = 0;
       
   943 #if !defined(USE_SSE2)
       
   944 
       
   945             for (int s = 0; s < SF_SAMPLES; s++)
       
   946             {
       
   947                 if(pixelWinding.winding[s])
       
   948                 {
       
   949                     coverageSamples++;
       
   950                 }
       
   951             }
       
   952 #else
       
   953            coverageSamples = mm_winding_to_coverage(pixelWinding, fillRuleMask);
       
   954             _mm_empty();
       
   955 #endif
       
   956 
       
   957             //constant coverage optimization:
       
   958             //scan AET from left to right and skip all the edges that are completely to the left of the pixel filter.
       
   959             //since AET is sorted by minx, the edge we stop at is the leftmost of the edges we haven't passed yet.
       
   960             //if that edge is to the right of this pixel, coverage is constant between this pixel and the start of the edge.
       
   961             while(aen < m_aet.size() && m_aet[aen].maxx < i)
       
   962                 aen++;
       
   963 
       
   964             int endSpan = m_vpx + m_vpwidth;	// endSpan is the first pixel NOT part of the span
       
   965 
       
   966             if(aen < m_aet.size())
       
   967             {
       
   968                 endSpan = RI_INT_MAX(i+1, RI_INT_MIN(endSpan, m_aet[aen].minx));
       
   969             }
       
   970 
       
   971             //fill a run of pixels with constant coverage
       
   972             if(coverageSamples)
       
   973             {
       
   974 
       
   975                 if (!m_scissor)
       
   976                 {
       
   977                     int fillStartX = i;	/* Inclusive */
       
   978                     pushSpan(fillStartX, j, (endSpan - fillStartX), coverageSamples);
       
   979                 }
       
   980                 else // (scissor)
       
   981                 {
       
   982                     int fillStartX = i;
       
   983                     //update scissor winding number
       
   984 
       
   985                     /* \todo Sort the scissor edges and skip unnecessary checks when scissors are used */
       
   986                     while (scissorIndex < m_scissorAet.size() && m_scissorAet[scissorIndex].x <= fillStartX)
       
   987                     {
       
   988                         scissorWinding += m_scissorAet[scissorIndex++].direction;
       
   989                     }
       
   990 
       
   991                     while (!scissorWinding && scissorIndex < m_scissorAet.size() && m_scissorAet[scissorIndex].x < endSpan)
       
   992                     {
       
   993                         fillStartX = m_scissorAet[scissorIndex].x;
       
   994                         scissorWinding += m_scissorAet[scissorIndex++].direction;
       
   995                         RI_ASSERT(fillStartX >= i);
       
   996                     }
       
   997 
       
   998                     RI_ASSERT(scissorWinding >= 0);
       
   999 
       
  1000                     int endScissorSpan = endSpan;
       
  1001 
       
  1002                     while (scissorWinding && fillStartX < endSpan && (scissorIndex < m_scissorAet.size()))
       
  1003                     {
       
  1004 
       
  1005                         // Determine the end of renderable area:
       
  1006                         while (scissorWinding && scissorIndex < m_scissorAet.size() && m_scissorAet[scissorIndex].x <= endSpan)
       
  1007                         {
       
  1008                             endScissorSpan = m_scissorAet[scissorIndex].x;
       
  1009                             scissorWinding += m_scissorAet[scissorIndex++].direction;
       
  1010                         }
       
  1011 
       
  1012                         RI_ASSERT(fillStartX >= i);
       
  1013                         RI_ASSERT(endScissorSpan <= endSpan);
       
  1014 
       
  1015                         pushSpan(fillStartX, j, (endScissorSpan - fillStartX), coverageSamples);
       
  1016                         fillStartX = endScissorSpan;
       
  1017                         endScissorSpan = endSpan;
       
  1018 
       
  1019                         // Skip until within drawable area
       
  1020                         while (!scissorWinding && scissorIndex < m_scissorAet.size() && m_scissorAet[scissorIndex].x < endSpan)
       
  1021                         {
       
  1022                             fillStartX = m_scissorAet[scissorIndex].x;
       
  1023                             scissorWinding += m_scissorAet[scissorIndex++].direction;
       
  1024                         }
       
  1025 
       
  1026                     }
       
  1027                 }
       
  1028             }
       
  1029             i = endSpan;
       
  1030         }
       
  1031     }
       
  1032     commitSpans();
       
  1033 #if defined(USE_SSE2)
       
  1034     _mm_empty();
       
  1035 #endif
       
  1036     clear();
       
  1037 }
       
  1038 
       
  1039 RI_INLINE void Rasterizer::commitSpans()
       
  1040 {
       
  1041     if (!m_nSpans)
       
  1042         return;
       
  1043 
       
  1044     m_pixelPipe->fillSpans(m_ppVariants, m_spanCache, m_nSpans);
       
  1045     m_nSpans = 0;
       
  1046 
       
  1047 }
       
  1048 
       
  1049 RI_INLINE void Rasterizer::pushSpan(int x, int y, int len, int coverage)
       
  1050 {
       
  1051     //printf("x: %d, y: %d, len: %d, coverage: %d\n", x, y, len, coverage);
       
  1052     // \todo Check what causes this with scissors
       
  1053     if (len <= 0) return;
       
  1054     //RI_ASSERT(len > 0);
       
  1055 
       
  1056     Span& span = m_spanCache[m_nSpans];
       
  1057 
       
  1058     span.x0 = x;
       
  1059     span.y = y;
       
  1060     span.len = (RIuint16)len;
       
  1061     span.coverage = coverage;
       
  1062 
       
  1063     m_nSpans++;
       
  1064 
       
  1065     if (m_nSpans == N_CACHED_SPANS)
       
  1066     {
       
  1067         commitSpans();
       
  1068     }
       
  1069 }
       
  1070 
       
  1071 //=======================================================================
       
  1072 
       
  1073 }	//namespace OpenVGRI