hostsupport/hostopenvg/src/src/riPixelPipe.cpp
branchbug235_bringup_0
changeset 54 067180f57b12
parent 53 c2ef9095503a
child 55 09263774e342
equal deleted inserted replaced
53:c2ef9095503a 54:067180f57b12
     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 Paint and pixel pipe functionality.
       
    31  * \note
       
    32  *//*-------------------------------------------------------------------*/
       
    33 
       
    34 #ifndef __RIPIXELPIPE_H
       
    35 #   include "riPixelPipe.h"
       
    36 #endif
       
    37 #ifndef __RIRASTERIZER_H
       
    38 #   include "riRasterizer.h"
       
    39 #endif
       
    40 #ifndef __SFDYNAMICPIXELPIPE_H
       
    41 #   include "sfDynamicPixelPipe.h"
       
    42 #endif
       
    43 #ifndef __SFCOMPILER_H
       
    44 #   include "sfCompiler.h"
       
    45 #endif
       
    46 
       
    47 //==============================================================================================
       
    48 
       
    49 namespace OpenVGRI
       
    50 {
       
    51 
       
    52 /*-------------------------------------------------------------------*//*!
       
    53 * \brief    Paint constructor.
       
    54 * \param
       
    55 * \return
       
    56 * \note
       
    57 *//*-------------------------------------------------------------------*/
       
    58 
       
    59 Paint::Paint() :
       
    60     m_paintType(VG_PAINT_TYPE_COLOR),
       
    61     m_paintColor(0,0,0,1,Color::sRGBA_PRE),
       
    62     m_inputPaintColor(0,0,0,1,Color::sRGBA),
       
    63     m_colorRampSpreadMode(VG_COLOR_RAMP_SPREAD_PAD),
       
    64     m_colorRampStops(),
       
    65     m_inputColorRampStops(),
       
    66     m_colorRampPremultiplied(VG_TRUE),
       
    67     m_inputLinearGradientPoint0(0,0),
       
    68     m_inputLinearGradientPoint1(1,0),
       
    69     m_inputRadialGradientCenter(0,0),
       
    70     m_inputRadialGradientFocalPoint(0,0),
       
    71     m_inputRadialGradientRadius(1.0f),
       
    72     m_linearGradientPoint0(0,0),
       
    73     m_linearGradientPoint1(1,0),
       
    74     m_radialGradientCenter(0,0),
       
    75     m_radialGradientFocalPoint(0,0),
       
    76     m_radialGradientRadius(1.0f),
       
    77     m_patternTilingMode(VG_TILE_FILL),
       
    78     m_pattern(NULL),
       
    79     m_referenceCount(0),
       
    80     m_lutFormat((VGImageFormat)-1),
       
    81     m_gradientStopsChanged(true)
       
    82 {
       
    83     Paint::GradientStop gs;
       
    84     gs.offset = 0.0f;
       
    85     gs.color.set(0,0,0,1,Color::sRGBA);
       
    86     m_colorRampStops.push_back(gs); //throws bad_alloc
       
    87     gs.offset = 1.0f;
       
    88     gs.color.set(1,1,1,1,Color::sRGBA);
       
    89     m_colorRampStops.push_back(gs); //throws bad_alloc
       
    90 }
       
    91 
       
    92 /*-------------------------------------------------------------------*//*!
       
    93 * \brief    Paint destructor.
       
    94 * \param
       
    95 * \return
       
    96 * \note
       
    97 *//*-------------------------------------------------------------------*/
       
    98 
       
    99 Paint::~Paint()
       
   100 {
       
   101     RI_ASSERT(m_referenceCount == 0);
       
   102     if(m_pattern)
       
   103     {
       
   104         m_pattern->removeInUse();
       
   105         if(!m_pattern->removeReference())
       
   106             RI_DELETE(m_pattern);
       
   107     }
       
   108 }
       
   109 
       
   110 static Color readStopColor(const Array<Paint::GradientStop>& colorRampStops, int i, VGboolean colorRampPremultiplied)
       
   111 {
       
   112     RI_ASSERT(i >= 0 && i < colorRampStops.size());
       
   113     Color c = colorRampStops[i].color;
       
   114     RI_ASSERT(c.getInternalFormat() == Color::sRGBA);
       
   115     if(colorRampPremultiplied)
       
   116         c.premultiply();
       
   117     return c;
       
   118 }
       
   119 
       
   120 void Paint::setGradientStops(Array<GradientStop>& inputStops, Array<GradientStop>& stops)
       
   121 {
       
   122     m_colorRampStops.swap(stops);
       
   123     m_inputColorRampStops.swap(inputStops);
       
   124     m_gradientStopsChanged = true;
       
   125 }
       
   126 
       
   127 void Paint::setLinearGradient(const Vector2& p0, const Vector2& p1)
       
   128 {
       
   129     m_linearGradientPoint0 = p0;
       
   130     m_linearGradientPoint1 = p1;
       
   131 }
       
   132 
       
   133 void Paint::setRadialGradient(const Vector2& c, const Vector2& f, VGfloat r)
       
   134 {
       
   135     m_radialGradientCenter = c;
       
   136     m_radialGradientFocalPoint = f;
       
   137     m_radialGradientRadius = r;
       
   138 }
       
   139 
       
   140 bool Paint::linearDegenerate() const
       
   141 {
       
   142     return m_linearGradientPoint0 == m_linearGradientPoint1 ? true : false;
       
   143 }
       
   144 
       
   145 bool Paint::radialDegenerate() const
       
   146 {
       
   147     return m_radialGradientRadius == 0.0f ? true : false;
       
   148 }
       
   149 
       
   150 /**
       
   151  * \brief   Returns either the VG_PAINT_COLOR, or evaluated gradient value when the
       
   152  *          gradient is degenerate.
       
   153  */
       
   154 Color Paint::getSolidColor() const
       
   155 {
       
   156     if (m_paintType == VG_PAINT_TYPE_PATTERN)
       
   157     {
       
   158         RI_ASSERT(m_pattern == NULL);
       
   159         return m_paintColor;
       
   160     }
       
   161 
       
   162     if (m_paintType == VG_PAINT_TYPE_COLOR)
       
   163         return m_paintColor;
       
   164 
       
   165     RI_ASSERT(linearDegenerate() || radialDegenerate());
       
   166 
       
   167     // Determine the color at the end of the gradient
       
   168     RIfloat gs, ge;
       
   169     if (m_colorRampSpreadMode == VG_COLOR_RAMP_SPREAD_PAD)
       
   170     {
       
   171         gs = 1.0f - 1/256.0f;
       
   172         ge = 1.0f;
       
   173     } else if (m_colorRampSpreadMode == VG_COLOR_RAMP_SPREAD_REPEAT)
       
   174     {
       
   175         gs = 0.0f;
       
   176         ge = 1/256.0f;
       
   177     } else
       
   178     {
       
   179         gs = 1.0f - 1/256.0f;
       
   180         ge = 1.0f;
       
   181     }
       
   182     Color c = integrateColorRamp(gs, ge);
       
   183     return c * 256.0f;
       
   184 }
       
   185 
       
   186 /*-------------------------------------------------------------------*//*!
       
   187 * \brief    Returns the average color within an offset range in the color ramp.
       
   188 * \param
       
   189 * \return
       
   190 * \note
       
   191 *//*-------------------------------------------------------------------*/
       
   192 
       
   193 Color Paint::integrateColorRamp(RIfloat gmin, RIfloat gmax) const
       
   194 {
       
   195     RI_ASSERT(gmin <= gmax);
       
   196     RI_ASSERT(gmin >= 0.0f && gmin <= 1.0f);
       
   197     RI_ASSERT(gmax >= 0.0f && gmax <= 1.0f);
       
   198     RI_ASSERT(m_colorRampStops.size() >= 2);   //there are at least two stops
       
   199 
       
   200     Color currC(0,0,0,0,m_colorRampPremultiplied ? Color::sRGBA_PRE : Color::sRGBA);
       
   201 
       
   202     if(gmin == 1.0f || gmax == 0.0f)
       
   203         return currC;
       
   204 
       
   205     int i = 0;
       
   206 
       
   207     for(; i < m_colorRampStops.size()-1; i++)
       
   208     {
       
   209         if(gmin >= m_colorRampStops[i].offset && gmin < m_colorRampStops[i+1].offset)
       
   210         {
       
   211             RIfloat s = m_colorRampStops[i].offset;
       
   212             RIfloat e = m_colorRampStops[i+1].offset;
       
   213             RI_ASSERT(s < e);
       
   214             RIfloat g = (gmin - s) / (e - s);
       
   215 
       
   216             Color sc = readStopColor(m_colorRampStops, i, m_colorRampPremultiplied);
       
   217             Color ec = readStopColor(m_colorRampStops, i+1, m_colorRampPremultiplied);
       
   218             Color rc = (1.0f-g) * sc + g * ec;
       
   219 
       
   220             //subtract the average color from the start of the stop to gmin
       
   221             Color dc = 0.5f*(gmin - s)*(sc + rc);
       
   222             currC -= dc; 
       
   223             break;
       
   224         }
       
   225     }
       
   226 
       
   227     for(;i < m_colorRampStops.size()-1; i++)
       
   228     {
       
   229         RIfloat s = m_colorRampStops[i].offset;
       
   230         RIfloat e = m_colorRampStops[i+1].offset;
       
   231         RI_ASSERT(s <= e);
       
   232 
       
   233         Color sc = readStopColor(m_colorRampStops, i, m_colorRampPremultiplied);
       
   234         Color ec = readStopColor(m_colorRampStops, i+1, m_colorRampPremultiplied);
       
   235 
       
   236         //average of the stop
       
   237         Color dc = 0.5f*(e-s)*(sc + ec);
       
   238         currC += dc; 
       
   239 
       
   240         if(gmax >= m_colorRampStops[i].offset && gmax < m_colorRampStops[i+1].offset)
       
   241         {
       
   242             RIfloat g = (gmax - s) / (e - s);
       
   243             Color rc = (1.0f-g) * sc + g * ec;
       
   244 
       
   245             //subtract the average color from gmax to the end of the stop
       
   246             dc = 0.5f*(e - gmax)*(rc + ec);
       
   247             currC -= dc;
       
   248             break;
       
   249         }
       
   250     }
       
   251 
       
   252     return currC;
       
   253 }
       
   254 
       
   255 /**
       
   256  * \brief   Generates gradient color-ramp lookup values.
       
   257  *
       
   258  * \param   targetFormat    Destination or image format to associate LUT with.
       
   259  * \patam   drawImage       true if paint is evaluated along drawImage.
       
   260  *
       
   261  * \note    Must be called prior to rendering, and after the destination
       
   262  *          format is known. The destination format is either destination 
       
   263  *          surface format, or the image format in case of image rendering
       
   264  *          operation.
       
   265  */
       
   266 void Paint::generateLUT(PixelPipe& pipe, VGImageFormat preferredFormat)
       
   267 {
       
   268     const RIfloat gstep = 1.0f / (GRADIENT_LUT_COUNT);
       
   269     const RIfloat rcp = (RIfloat)(GRADIENT_LUT_COUNT);
       
   270     RIfloat gsx;
       
   271     gsx = 0.0f;
       
   272     
       
   273     if (!pipe.colorTransformChanged() && !m_gradientStopsChanged && (preferredFormat == m_lutFormat))
       
   274         return; // Already in correct format
       
   275 
       
   276     const bool inputPremultiplied = m_colorRampPremultiplied == VG_TRUE ? true : false;
       
   277 
       
   278     // Colortransform premultiplies color.
       
   279     const Color::Descriptor srcDesc = Color::formatToDescriptorConst(
       
   280         inputPremultiplied || pipe.hasColorTransform() ? VG_sRGBA_8888_PRE : VG_sRGBA_8888);
       
   281 
       
   282     const Color::Descriptor dstDesc = Color::formatToDescriptorConst(preferredFormat);
       
   283 
       
   284     // Create a pre-calculated LUT.
       
   285     for (int i = 0; i < GRADIENT_LUT_COUNT; i++)
       
   286     {
       
   287         // \todo Open up the integrator and/or use also integers.
       
   288         Color c = integrateColorRamp(gsx, gsx + gstep);
       
   289         c *= rcp;
       
   290 
       
   291         // \todo Changing the mode must be tracked somehow!
       
   292         if (pipe.getImageMode() != VG_DRAW_IMAGE_MULTIPLY)
       
   293             pipe.colorTransform(c);
       
   294 
       
   295         IntegerColor ic = IntegerColor(c);
       
   296         ic.convertToFrom(dstDesc, srcDesc, false);
       
   297         m_gradientLUT[i] = ic;
       
   298 
       
   299         gsx += gstep;
       
   300     }
       
   301 
       
   302     m_gradientStopsChanged = false;
       
   303     m_lutFormat = Color::descriptorToVGImageFormat(dstDesc);
       
   304     pipe.setColorTransformChanged(false);
       
   305 
       
   306     RI_ASSERT(m_lutFormat == preferredFormat);
       
   307 }
       
   308 
       
   309 /*-------------------------------------------------------------------*//*!
       
   310 * \brief    PixelPipe constructor.
       
   311 * \param
       
   312 * \return
       
   313 * \note
       
   314 *//*-------------------------------------------------------------------*/
       
   315 
       
   316 PixelPipe::PixelPipe() :
       
   317     m_drawable(NULL),
       
   318     m_image(NULL),
       
   319     m_paint(NULL),
       
   320     m_defaultPaint(),
       
   321     m_blendMode(VG_BLEND_SRC_OVER),
       
   322     m_imageMode(VG_DRAW_IMAGE_NORMAL),
       
   323     m_imageQuality(VG_IMAGE_QUALITY_FASTER),
       
   324     m_tileFillColor(0,0,0,0,Color::sRGBA),
       
   325     m_colorTransform(false),
       
   326     m_colorTransformValues(),
       
   327     m_iColorTransformValues(),
       
   328     m_surfaceToPaintMatrix(),
       
   329     m_surfaceToImageMatrix(),
       
   330     m_paintToSurfaceMatrix(),
       
   331     m_maskOperation(VG_SET_MASK),
       
   332     m_renderToMask(false),
       
   333     m_colorTransformChanged(true)
       
   334 {
       
   335     for(int i=0;i<8;i++)
       
   336     {
       
   337         m_colorTransformValues[i] = (i < 4) ? 1.0f : 0.0f;
       
   338         m_iColorTransformValues[i] = (i < 4) ? (COLOR_TRANSFORM_ONE) : 0;
       
   339     }
       
   340 }
       
   341 
       
   342 
       
   343 /*-------------------------------------------------------------------*//*!
       
   344 * \brief    PixelPipe destructor.
       
   345 * \param
       
   346 * \return
       
   347 * \note
       
   348 *//*-------------------------------------------------------------------*/
       
   349 
       
   350 PixelPipe::~PixelPipe()
       
   351 {
       
   352 }
       
   353 
       
   354 /*-------------------------------------------------------------------*//*!
       
   355 * \brief    Sets the rendering surface.
       
   356 * \param
       
   357 * \return
       
   358 * \note
       
   359 *//*-------------------------------------------------------------------*/
       
   360 
       
   361 void PixelPipe::setDrawable(Drawable* drawable)
       
   362 {
       
   363     RI_ASSERT(drawable);
       
   364     m_drawable = drawable;
       
   365 }
       
   366 
       
   367 /*-------------------------------------------------------------------*//*!
       
   368 * \brief    Sets the blend mode.
       
   369 * \param
       
   370 * \return
       
   371 * \note
       
   372 *//*-------------------------------------------------------------------*/
       
   373 
       
   374 void PixelPipe::setBlendMode(VGBlendMode blendMode)
       
   375 {
       
   376     RI_ASSERT(blendMode >= VG_BLEND_SRC && blendMode <= VG_BLEND_ADDITIVE);
       
   377     m_blendMode = blendMode;
       
   378 }
       
   379 
       
   380 /*-------------------------------------------------------------------*//*!
       
   381 * \brief    Sets the mask image. NULL disables masking.
       
   382 * \param
       
   383 * \return
       
   384 * \note
       
   385 *//*-------------------------------------------------------------------*/
       
   386 
       
   387 void PixelPipe::setMask(bool masking)
       
   388 {
       
   389     m_masking = masking;
       
   390 }
       
   391 
       
   392 /*-------------------------------------------------------------------*//*!
       
   393 * \brief    Sets the image to be drawn. NULL disables image drawing.
       
   394 * \param
       
   395 * \return
       
   396 * \note
       
   397 *//*-------------------------------------------------------------------*/
       
   398 
       
   399 void PixelPipe::setImage(Image* image, VGImageMode imageMode)
       
   400 {
       
   401     RI_ASSERT(imageMode == VG_DRAW_IMAGE_NORMAL || imageMode == VG_DRAW_IMAGE_MULTIPLY || imageMode == VG_DRAW_IMAGE_STENCIL);
       
   402     m_image = image;
       
   403     m_imageMode = imageMode;
       
   404 }
       
   405 
       
   406 /*-------------------------------------------------------------------*//*!
       
   407 * \brief    Sets the surface-to-paint matrix.
       
   408 * \param
       
   409 * \return
       
   410 * \note
       
   411 *//*-------------------------------------------------------------------*/
       
   412 
       
   413 void PixelPipe::setSurfaceToPaintMatrix(const Matrix3x3& surfaceToPaintMatrix)
       
   414 {
       
   415     m_surfaceToPaintMatrix = surfaceToPaintMatrix;
       
   416 }
       
   417 
       
   418 /*-------------------------------------------------------------------*//*!
       
   419 * \brief    Sets the surface-to-image matrix.
       
   420 * \param
       
   421 * \return
       
   422 * \note
       
   423 *//*-------------------------------------------------------------------*/
       
   424 
       
   425 void PixelPipe::setSurfaceToImageMatrix(const Matrix3x3& surfaceToImageMatrix)
       
   426 {
       
   427     m_surfaceToImageMatrix = surfaceToImageMatrix;
       
   428 }
       
   429 
       
   430 /*-------------------------------------------------------------------*//*!
       
   431 * \brief    Sets image quality.
       
   432 * \param
       
   433 * \return
       
   434 * \note
       
   435 *//*-------------------------------------------------------------------*/
       
   436 
       
   437 void PixelPipe::setImageQuality(VGImageQuality imageQuality)
       
   438 {
       
   439     RI_ASSERT(imageQuality == VG_IMAGE_QUALITY_NONANTIALIASED || imageQuality == VG_IMAGE_QUALITY_FASTER || imageQuality == VG_IMAGE_QUALITY_BETTER);
       
   440     m_imageQuality = imageQuality;
       
   441 }
       
   442 
       
   443 /*-------------------------------------------------------------------*//*!
       
   444 * \brief    Sets fill color for VG_TILE_FILL tiling mode (pattern only).
       
   445 * \param
       
   446 * \return
       
   447 * \note
       
   448 *//*-------------------------------------------------------------------*/
       
   449 
       
   450 void PixelPipe::setTileFillColor(const Color& c)
       
   451 {
       
   452     m_tileFillColor = c;
       
   453     m_tileFillColor.clamp();
       
   454 }
       
   455 
       
   456 /*-------------------------------------------------------------------*//*!
       
   457 * \brief    Sets paint.
       
   458 * \param
       
   459 * \return
       
   460 * \note
       
   461 *//*-------------------------------------------------------------------*/
       
   462 
       
   463 void PixelPipe::setPaint(Paint* paint)
       
   464 {
       
   465     // \temp Only call this right before filling a polygon.
       
   466     m_paint = paint;
       
   467 
       
   468     if(!m_paint)
       
   469         m_paint = &m_defaultPaint;
       
   470 
       
   471     if(m_paint->m_pattern)
       
   472         m_tileFillColor.convert(m_paint->m_pattern->getDescriptor().internalFormat);
       
   473 
       
   474 }
       
   475 
       
   476 /*-------------------------------------------------------------------*//*!
       
   477 * \brief    Color transform.
       
   478 * \param
       
   479 * \return
       
   480 * \note
       
   481 *//*-------------------------------------------------------------------*/
       
   482 
       
   483 void PixelPipe::setColorTransform(bool enable, RIfloat values[8])
       
   484 {
       
   485     m_colorTransform = enable;
       
   486     for(int i=0;i<4;i++)
       
   487     {
       
   488         m_colorTransformValues[i] = RI_CLAMP(values[i], -127.0f, 127.0f);
       
   489         m_colorTransformValues[i+4] = RI_CLAMP(values[i+4], -1.0f, 1.0f);
       
   490         m_iColorTransformValues[i] = RI_ROUND_TO_INT(m_colorTransformValues[i]*(RIfloat)COLOR_TRANSFORM_ONE);
       
   491         m_iColorTransformValues[i+4] = RI_ROUND_TO_INT(m_colorTransformValues[i+4]*255.0f);
       
   492     }
       
   493     m_colorTransformChanged = true;
       
   494 }
       
   495 
       
   496 const Image* PixelPipe::getRenderTargetImage() const
       
   497 {
       
   498     if (m_renderToMask)
       
   499         return m_drawable->getMaskBuffer()->getImage();
       
   500 
       
   501     return m_drawable->getColorBuffer()->getImage();
       
   502 }
       
   503 
       
   504 /**
       
   505  * \brief   Determine an appropriate VGImageFormat to use for lookup tables.
       
   506  * \todo    Should return descriptor instead?
       
   507  */
       
   508 VGImageFormat PixelPipe::getPreferredLUTFormat() const
       
   509 {
       
   510     const Image* target = getRenderTargetImage();
       
   511     const Color::Descriptor& targetDesc = target->getDescriptor();
       
   512 
       
   513     if (m_renderToMask)
       
   514     {
       
   515         RI_ASSERT(!m_image);
       
   516         if (targetDesc.isNonlinear())
       
   517             return VG_sRGBA_8888_PRE;
       
   518         else
       
   519             return VG_lRGBA_8888_PRE;
       
   520     }
       
   521 
       
   522     if (m_image && m_imageMode == VG_DRAW_IMAGE_MULTIPLY)
       
   523         return VG_sRGBA_8888_PRE; // ?
       
   524 
       
   525     // Prefer premultiplied formats
       
   526     // \note Can also generate non-premultiplied if no sampling/other operation and destination
       
   527     // is in linear format.
       
   528     // \note Do not use VGImageFormat, because using (s/l)LA88 is possible with
       
   529     // luminance destination formats.
       
   530     if (targetDesc.isNonlinear())
       
   531         return VG_sRGBA_8888_PRE;
       
   532     else
       
   533         return VG_lRGBA_8888_PRE;
       
   534 }
       
   535 
       
   536 void PixelPipe::prepareSolidFill()
       
   537 {
       
   538     if (!(m_drawable && m_paint))
       
   539         return;
       
   540         
       
   541     Color c = m_paint->getSolidColor();
       
   542     //Color c = m_paint->m_paintColor;
       
   543     
       
   544     if (!m_image || m_imageMode != VG_DRAW_IMAGE_MULTIPLY)
       
   545         colorTransform(c); // Output will be premultiplied
       
   546     // Generate internal color
       
   547     Color::Descriptor blendDesc = getRenderTargetImage()->getDescriptor();
       
   548 
       
   549     // MULTIPLY uses the color as-is.
       
   550     if (m_imageMode != VG_DRAW_IMAGE_MULTIPLY) c.convert(blendDesc.internalFormat);
       
   551 
       
   552     IntegerColor ic = IntegerColor(c);
       
   553     blendDesc.internalFormat = (Color::InternalFormat)(blendDesc.internalFormat | (Color::PREMULTIPLIED));
       
   554 
       
   555     if (m_imageMode != VG_DRAW_IMAGE_MULTIPLY) c.convert(blendDesc.internalFormat);
       
   556     
       
   557     IntegerColor blendColor = IntegerColor(c);
       
   558 
       
   559     if (m_imageMode == VG_DRAW_IMAGE_STENCIL)
       
   560         blendColor.asFixedPoint(c); // Enhance the precision a bit
       
   561     
       
   562     // \todo No need to pack the color if solid fill is not possible
       
   563     if (!m_renderToMask)
       
   564         ic.truncateColor(getRenderTargetImage()->getDescriptor());
       
   565     else
       
   566         ic.truncateMask(getRenderTargetImage()->getDescriptor());
       
   567 
       
   568     RIuint32 p = ic.getPackedColor(getRenderTargetImage()->getDescriptor());
       
   569 
       
   570     m_spanUniforms.solidColor = blendColor; // This must be premultiplied
       
   571     m_spanUniforms.packedSolidColor = p; // This must be exactly the dst color
       
   572 }
       
   573 
       
   574 void PixelPipe::prepareCoverageFill()
       
   575 {
       
   576     IntegerColor ic = IntegerColor(255, 255, 255, 255);
       
   577     RIuint32 p = ic.getPackedColor(m_drawable->getMaskBuffer()->getDescriptor());
       
   578 
       
   579     m_spanUniforms.solidColor = ic;
       
   580     m_spanUniforms.packedSolidColor = p;
       
   581 }
       
   582 
       
   583 void PixelPipe::prepareLinearGradient()
       
   584 {
       
   585     const Matrix3x3& s2p = m_surfaceToPaintMatrix;
       
   586 
       
   587     Vector2 zero(0,0);
       
   588     Vector2 p0 = m_paint->m_linearGradientPoint0;
       
   589     Vector2 p1 = m_paint->m_linearGradientPoint1;
       
   590     Vector2 delta = p1 - p0;
       
   591 
       
   592     zero = affineTransform(s2p, zero);
       
   593 
       
   594     RIfloat d = (delta.x * delta.x) + (delta.y * delta.y);
       
   595     RIfloat gdx = (s2p[0][0] * delta.x + s2p[1][0] * delta.y) / d;
       
   596     RIfloat gdy = (s2p[0][1] * delta.x + s2p[1][1] * delta.y) / d;
       
   597     RIfloat cx = (zero.x-p0.x) * (delta.x);
       
   598     RIfloat cy = (zero.y-p0.y) * (delta.y);
       
   599     RIfloat c = (cx + cy) / d;
       
   600 
       
   601     m_spanUniforms.dgdx = RI_FLOAT_TO_FX(gdx, PixelPipe::GRADIENT_BITS);
       
   602     m_spanUniforms.dgdy = RI_FLOAT_TO_FX(gdy, PixelPipe::GRADIENT_BITS);
       
   603     m_spanUniforms.lgc = RI_FLOAT_TO_FX(c + 0.5*(gdx + gdy), PixelPipe::GRADIENT_BITS);
       
   604 
       
   605     m_spanUniforms.gradientLookup = m_paint->getGradientLUT();
       
   606 }
       
   607 
       
   608 void PixelPipe::prepareRadialGradient()
       
   609 {
       
   610     const Matrix3x3& s2p = m_surfaceToPaintMatrix;
       
   611 
       
   612     Vector2 c = m_paint->m_radialGradientCenter;
       
   613     Vector2 f = m_paint->m_radialGradientFocalPoint;
       
   614     RGScalar r = m_paint->m_radialGradientRadius;
       
   615 
       
   616     Vector2 zero(0,0);
       
   617     Vector2 pzero = affineTransform(s2p, zero);
       
   618 
       
   619     Vector2 fp = f - c;
       
   620 
       
   621     RGScalar q = fp.length();
       
   622 
       
   623     if (q > r)
       
   624     {
       
   625         const RIfloat scale = 0.99f;
       
   626         fp.normalize();
       
   627         fp *= r * scale;
       
   628         f = fp + c;
       
   629     } 
       
   630 
       
   631     RGScalar r1sqr = RI_SQR(r);
       
   632     RGScalar d = r1sqr - dot(fp, fp);
       
   633 
       
   634     m_spanUniforms.rdxdx = s2p[0][0];
       
   635     m_spanUniforms.rdxdy = s2p[0][1];
       
   636     m_spanUniforms.rdydx = s2p[1][0];
       
   637     m_spanUniforms.rdydy = s2p[1][1];
       
   638 
       
   639     m_spanUniforms.rsqrp = r1sqr / RI_SQR(d);
       
   640     m_spanUniforms.rfxp = fp.x / d;
       
   641     m_spanUniforms.rfyp = fp.y / d;
       
   642     m_spanUniforms.rx0 = pzero.x - f.x + 0.5f*(m_spanUniforms.rdxdx + m_spanUniforms.rdxdy);
       
   643     m_spanUniforms.ry0 = pzero.y - f.y + 0.5f*(m_spanUniforms.rdydy + m_spanUniforms.rdydx);
       
   644 
       
   645     m_spanUniforms.gradientLookup = m_paint->getGradientLUT();
       
   646 }
       
   647 
       
   648 void PixelPipe::preparePattern()
       
   649 {
       
   650     // Patterns only support affine transforms
       
   651     const Matrix3x3& s2p = m_surfaceToPaintMatrix;
       
   652     const RIfloat patternWidth = (RIfloat)m_paint->m_pattern->getWidth();
       
   653     const RIfloat patternHeight = (RIfloat)m_paint->m_pattern->getHeight();
       
   654     const Vector2 zero(0, 0);
       
   655     Vector2 pzero = affineTransform(s2p, zero); 
       
   656 
       
   657     m_spanUniforms.paint_x0 = RI_ROUND_TO_INT((pzero.x/patternWidth)*(1<<GRADIENT_BITS));
       
   658     m_spanUniforms.paint_y0 = RI_ROUND_TO_INT((pzero.y/patternHeight)*(1<<GRADIENT_BITS));
       
   659     m_spanUniforms.paint_dxdx = RI_ROUND_TO_INT((s2p[0][0]/patternWidth)*(1<<GRADIENT_BITS));
       
   660     m_spanUniforms.paint_dxdy = RI_ROUND_TO_INT((s2p[0][1]/patternHeight)*(1<<GRADIENT_BITS));
       
   661     m_spanUniforms.paint_dydx = RI_ROUND_TO_INT((s2p[1][0]/patternWidth)*(1<<GRADIENT_BITS));
       
   662     m_spanUniforms.paint_dydy = RI_ROUND_TO_INT((s2p[1][1]/patternHeight)*(1<<GRADIENT_BITS));
       
   663 
       
   664     m_spanUniforms.paint_x0 += (m_spanUniforms.paint_dxdx + m_spanUniforms.paint_dxdy) / 2;
       
   665     m_spanUniforms.paint_y0 += (m_spanUniforms.paint_dydy + m_spanUniforms.paint_dydx) / 2;
       
   666 
       
   667     m_spanUniforms.patternPtr = m_paint->m_pattern->getData(); 
       
   668     m_spanUniforms.patternStride = m_paint->m_pattern->getStride();
       
   669     m_spanUniforms.paint_width = m_paint->m_pattern->getWidth();
       
   670     m_spanUniforms.paint_height = m_paint->m_pattern->getHeight();
       
   671 
       
   672     m_signatureState.patternDesc = m_paint->m_pattern->getDescriptor();
       
   673 
       
   674     m_spanUniforms.tileFillColor = IntegerColor(m_tileFillColor);
       
   675     // The tile fill-color must be shifted down to same bit-depth (see integer samplers)
       
   676     m_spanUniforms.tileFillColor.truncateColor(m_signatureState.patternDesc);
       
   677 
       
   678 }
       
   679 
       
   680 RI_INLINE static RIfloat floatEqu(RIfloat a, RIfloat b, RIfloat e)
       
   681 {
       
   682     // \note This should be sufficient for our use-cases;
       
   683     return (RI_ABS(a - b) < e);
       
   684 }
       
   685 
       
   686 RI_INLINE static RIfloat distToInt(RIfloat f)
       
   687 {
       
   688     const RIfloat intF = RI_ROUND_TO_INT(f);
       
   689     return RI_ABS(intF - f);
       
   690 }
       
   691 
       
   692 /**
       
   693  * \brief   Check if transform is 90 degree rotation, or flip and nothing else.
       
   694  */
       
   695 RI_INLINE static bool orthoNormalCoAxialTransform(const Matrix3x3& t, bool aa)
       
   696 {
       
   697     const RIfloat epsilonCoord = 1/255.0f; // 1/127.0f;
       
   698     const RIfloat epsilonGradient = epsilonCoord * epsilonCoord; // \todo Too strict?
       
   699     const RIfloat absPatterns[2][4] = {
       
   700         {1.0f, 0.0f, 0.0f, 1.0f},
       
   701         {0.0f, 1.0f, 1.0f, 0.0f} };
       
   702 
       
   703     if (!t.isAffine())
       
   704         return false;
       
   705 
       
   706     // \todo This rule only applies if filtering is in use?
       
   707     if (aa)
       
   708         if (!floatEqu(distToInt(t[0][2]), 0.0f, epsilonCoord) || !floatEqu(distToInt(t[1][2]), 0.0f, epsilonCoord))
       
   709             return false;
       
   710 
       
   711     Matrix3x3 u = t;
       
   712     
       
   713     for (int j = 0; j < 2; j++)
       
   714         for (int i = 0; i < 2; i++)
       
   715             u[j][i] = RI_ABS(u[j][i]);
       
   716 
       
   717     bool found;
       
   718 
       
   719     for (int m = 0; m < 2; m++)
       
   720     {
       
   721         found = true;
       
   722         for (int j = 0; j < 2; j++)
       
   723         {
       
   724             for (int i = 0; i < 2; i++)
       
   725             {
       
   726                 //if (u[j][i] != absPatterns[m][i+j*2])
       
   727                 if (!floatEqu(u[j][i], absPatterns[m][i+j*2], epsilonGradient))
       
   728                 {
       
   729                     found = false;
       
   730                     break;
       
   731                 }
       
   732             }
       
   733             if (!found) break;
       
   734         }
       
   735         if (found) break;
       
   736     }
       
   737 
       
   738     return found;
       
   739 }
       
   740 
       
   741 void PixelPipe::prepareImage(bool aa)
       
   742 {
       
   743     if (!m_image)
       
   744     {
       
   745         m_signatureState.imageGradientType = GRADIENT_TYPE_INTEGER;
       
   746         return;
       
   747     }
       
   748 
       
   749     RI_ASSERT(m_image);
       
   750     m_spanUniforms.imagePtr = m_image->getData();
       
   751     m_spanUniforms.imageStride = m_image->getStride();
       
   752     
       
   753     if (m_image->getParent() != NULL)
       
   754     {
       
   755         // Adjust the pointer.
       
   756         int x, y;
       
   757         m_image->getStorageOffset(x, y);
       
   758         m_spanUniforms.imagePtr = Image::calculateAddress(
       
   759             m_spanUniforms.imagePtr, m_image->getDescriptor().bitsPerPixel, x, y, m_spanUniforms.imageStride);
       
   760     }
       
   761 
       
   762     // \todo This function writes to derived state also.
       
   763     // \todo Plenty of fast-paths possible!
       
   764     const Matrix3x3& s2i = m_surfaceToImageMatrix;
       
   765     
       
   766     Vector3 zero(0,0,1);
       
   767     Vector3 pzero;
       
   768 
       
   769     bool fastImage = orthoNormalCoAxialTransform(s2i, aa);
       
   770     
       
   771     pzero = s2i * zero;
       
   772 
       
   773     if (fastImage)
       
   774     {
       
   775         RI_ASSERT(pzero.z == 1.0f);
       
   776         m_spanUniforms.image_idxdx = RI_ROUND_TO_INT(s2i[0][0]);
       
   777         m_spanUniforms.image_idxdy = RI_ROUND_TO_INT(s2i[0][1]);
       
   778         m_spanUniforms.image_idydx = RI_ROUND_TO_INT(s2i[1][0]);
       
   779         m_spanUniforms.image_idydy = RI_ROUND_TO_INT(s2i[1][1]);
       
   780         m_spanUniforms.image_ix0 = RI_FLOOR(pzero.x + 0.5f*(s2i[0][0]+s2i[0][1]));
       
   781         m_spanUniforms.image_iy0 = RI_FLOOR(pzero.y + 0.5f*(s2i[1][1]+s2i[1][0]));
       
   782 
       
   783         // Adjust sample-center when using (exactly) integer coordinates.
       
   784         
       
   785 #if 0
       
   786         if (m_spanUniforms.image_idxdx < 0 || m_spanUniforms.image_idxdy < 0)
       
   787             m_spanUniforms.image_ix0--;
       
   788     
       
   789         if (m_spanUniforms.image_idydy < 0 || m_spanUniforms.image_idydx < 0)
       
   790             m_spanUniforms.image_iy0--;
       
   791 #endif
       
   792 
       
   793         m_signatureState.imageGradientType = GRADIENT_TYPE_INTEGER;
       
   794     } 
       
   795     else if (s2i.isAffine())
       
   796     {
       
   797         RI_ASSERT(pzero.z == 1.0f); 
       
   798         const RIfloat imageWidth = m_image->getWidth();
       
   799         const RIfloat imageHeight = m_image->getHeight();
       
   800         
       
   801         m_spanUniforms.image_idxdx = RI_ROUND_TO_INT((s2i[0][0]/imageWidth)*(1<<GRADIENT_BITS));
       
   802         m_spanUniforms.image_idxdy = RI_ROUND_TO_INT((s2i[0][1]/imageHeight)*(1<<GRADIENT_BITS));
       
   803         m_spanUniforms.image_idydx = RI_ROUND_TO_INT((s2i[1][0]/imageWidth)*(1<<GRADIENT_BITS));
       
   804         m_spanUniforms.image_idydy = RI_ROUND_TO_INT((s2i[1][1]/imageHeight)*(1<<GRADIENT_BITS));
       
   805         m_spanUniforms.image_ix0 = RI_ROUND_TO_INT((pzero.x/imageWidth)*(1<<GRADIENT_BITS));
       
   806         m_spanUniforms.image_iy0 = RI_ROUND_TO_INT((pzero.y/imageHeight)*(1<<GRADIENT_BITS));
       
   807 
       
   808         m_spanUniforms.image_ix0 += (m_spanUniforms.image_idxdx + m_spanUniforms.image_idxdy)/2;
       
   809         m_spanUniforms.image_iy0 += (m_spanUniforms.image_idydy + m_spanUniforms.image_idydx)/2;
       
   810 
       
   811         m_spanUniforms.image_iWidth = (RIint32)imageWidth;
       
   812         m_spanUniforms.image_iHeight = (RIint32)imageHeight;
       
   813 
       
   814         m_signatureState.imageGradientType = GRADIENT_TYPE_FIXED;
       
   815     } 
       
   816     else
       
   817     {
       
   818         // Use floats.
       
   819         m_spanUniforms.image_fx0 = pzero.x;
       
   820         m_spanUniforms.image_fy0 = pzero.y;
       
   821         m_spanUniforms.image_fw0 = pzero.z;
       
   822         m_spanUniforms.image_fdxdx = s2i[0][0];
       
   823         m_spanUniforms.image_fdxdy = s2i[0][1];
       
   824         m_spanUniforms.image_fdydx = s2i[1][0];
       
   825         m_spanUniforms.image_fdydy = s2i[1][1];
       
   826         m_spanUniforms.image_fdwdx = s2i[2][0];
       
   827         m_spanUniforms.image_fdwdy = s2i[2][1];
       
   828 
       
   829         m_spanUniforms.image_fx0 += 0.5f * (m_spanUniforms.image_fdxdx + m_spanUniforms.image_fdxdy);
       
   830         m_spanUniforms.image_fy0 += 0.5f * (m_spanUniforms.image_fdydy + m_spanUniforms.image_fdydx);
       
   831         m_spanUniforms.image_fw0 += 0.5f * (m_spanUniforms.image_fdwdx + m_spanUniforms.image_fdwdy);
       
   832 
       
   833         m_spanUniforms.image_fWidth = (RIfloat)m_image->getWidth();
       
   834         m_spanUniforms.image_fHeight = (RIfloat)m_image->getHeight();
       
   835 
       
   836         m_signatureState.imageGradientType = GRADIENT_TYPE_FLOAT;
       
   837     }
       
   838 
       
   839     m_signatureState.imageDesc = m_image->getDescriptor();
       
   840 }
       
   841 
       
   842 static PixelPipe::TilingMode tilingModeOfImageTilingMode(VGTilingMode it)
       
   843 {
       
   844     switch(it)
       
   845     {
       
   846     case VG_TILE_PAD:
       
   847         return PixelPipe::TILING_MODE_PAD;
       
   848     case VG_TILE_REPEAT:
       
   849         return PixelPipe::TILING_MODE_REPEAT;
       
   850     case VG_TILE_REFLECT:
       
   851         return PixelPipe::TILING_MODE_REFLECT;
       
   852     default:
       
   853         RI_ASSERT(it == VG_TILE_FILL);
       
   854         return PixelPipe::TILING_MODE_FILL;
       
   855     }
       
   856 }
       
   857 
       
   858 static PixelPipe::TilingMode tilingModeOfSpreadMode(VGColorRampSpreadMode sm)
       
   859 {
       
   860     switch(sm)
       
   861     {
       
   862     case VG_COLOR_RAMP_SPREAD_PAD:
       
   863         return PixelPipe::TILING_MODE_PAD;
       
   864     case VG_COLOR_RAMP_SPREAD_REPEAT:
       
   865         return PixelPipe::TILING_MODE_REPEAT;
       
   866     default:
       
   867         RI_ASSERT(sm == VG_COLOR_RAMP_SPREAD_REFLECT);
       
   868         return PixelPipe::TILING_MODE_REFLECT;
       
   869     }
       
   870 }
       
   871 
       
   872 static PixelPipe::TilingMode tilingModeOfPaint(const Paint* paint)
       
   873 {
       
   874     switch(paint->m_paintType)
       
   875     {
       
   876     case VG_PAINT_TYPE_COLOR:
       
   877         return PixelPipe::TILING_MODE_PAD;
       
   878     case VG_PAINT_TYPE_LINEAR_GRADIENT:
       
   879     case VG_PAINT_TYPE_RADIAL_GRADIENT:
       
   880         return tilingModeOfSpreadMode(paint->m_colorRampSpreadMode);
       
   881     default:
       
   882         RI_ASSERT(paint->m_paintType == VG_PAINT_TYPE_PATTERN);
       
   883         return tilingModeOfImageTilingMode(paint->m_patternTilingMode);
       
   884     }
       
   885 }
       
   886 
       
   887 void PixelPipe::prepareRenderToMask()
       
   888 {
       
   889     RI_ASSERT(m_drawable->getMaskBuffer());
       
   890 
       
   891     m_signatureState.dstDesc = m_drawable->getMaskBuffer()->getDescriptor();
       
   892     //RI_ASSERT(m_signatureState.dstFormat >= 0 && m_signatureState.dstFormat <= VG_lABGR_8888_PRE);
       
   893 
       
   894     m_signatureState.maskOperation = m_maskOperation;
       
   895 }
       
   896 
       
   897 void PixelPipe::prepareSignatureState()
       
   898 {
       
   899     m_signatureState.isRenderToMask = m_renderToMask;
       
   900 
       
   901     if (m_signatureState.isRenderToMask)
       
   902     {
       
   903         prepareRenderToMask();
       
   904         return;
       
   905     }
       
   906 
       
   907     m_signatureState.blendMode = getBlendMode();
       
   908 
       
   909     m_signatureState.hasColorTransform = this->m_colorTransform;
       
   910 
       
   911     m_signatureState.paintType = getPaintType();
       
   912     
       
   913     m_signatureState.paintTilingMode = tilingModeOfPaint(m_paint);
       
   914     // \todo Derive these from the quality settings somehow.
       
   915     // Linear and nearest should work atm.
       
   916     m_signatureState.paintSampler = SAMPLER_TYPE_NEAREST;
       
   917     m_signatureState.imageSampler = SAMPLER_TYPE_NEAREST;
       
   918 
       
   919     m_signatureState.hasMasking = isMasking() && (m_drawable->getMaskBuffer() != NULL);
       
   920     
       
   921     m_signatureState.hasImage = m_image ? true : false;
       
   922     m_signatureState.unsafeImageInput = !m_image ? false : m_image->isUnsafe();
       
   923     m_signatureState.imageMode = m_imageMode;
       
   924 
       
   925     // Formats. Note that fields that are not filled in / used get set to a derived state in a 
       
   926     // separate function!
       
   927 
       
   928     if (m_signatureState.paintType == (RIuint32)VG_PAINT_TYPE_COLOR)
       
   929     {
       
   930         RI_ASSERT(m_paint);
       
   931         if (m_paint->getSolidColor().a == 1.0)
       
   932             m_signatureState.fillColorTransparent = false;
       
   933         else
       
   934             m_signatureState.fillColorTransparent = true;
       
   935     }
       
   936 
       
   937     m_signatureState.dstDesc = m_drawable->getColorBuffer()->getDescriptor();
       
   938 
       
   939     // \todo Why isn't the imagedescriptor set here?
       
   940     if (m_signatureState.hasMasking)
       
   941     {
       
   942         m_signatureState.maskDesc = m_drawable->getMaskBuffer()->getDescriptor();
       
   943     }
       
   944 
       
   945 }
       
   946 
       
   947 /**
       
   948  * \brief   Remove redundancy from the pixel-pipeline state so that less
       
   949  *          pipelines are generated.
       
   950  */
       
   951 static void determineDerivedState(PixelPipe::SignatureState& derivedState, const PixelPipe::SignatureState& originalState)
       
   952 {
       
   953     derivedState = originalState;
       
   954 
       
   955     if (derivedState.isRenderToMask)
       
   956     {
       
   957         // Set a lot of defaults:
       
   958         derivedState.blendMode = VG_BLEND_SRC;
       
   959         derivedState.imageMode = VG_DRAW_IMAGE_NORMAL;
       
   960         derivedState.paintType = VG_PAINT_TYPE_COLOR;
       
   961 
       
   962         derivedState.hasImage = false;
       
   963         derivedState.hasMasking = false;
       
   964         derivedState.hasColorTransform = false;
       
   965     }
       
   966 
       
   967     if (derivedState.paintType == VG_PAINT_TYPE_COLOR)
       
   968     {
       
   969         derivedState.paintTilingMode = PixelPipe::TILING_MODE_PAD;
       
   970         derivedState.paintSampler = PixelPipe::SAMPLER_TYPE_NEAREST;
       
   971         // \todo Opaque solid colors can benefit from simpler coverage-blending
       
   972         // becase SRC_OVER == SRC. This information has to be present in
       
   973         // the derivedState (and not just uniform).
       
   974     }
       
   975 
       
   976     if (!derivedState.hasImage)
       
   977     {
       
   978         derivedState.imageMode = VG_DRAW_IMAGE_NORMAL;
       
   979         derivedState.imageSampler = PixelPipe::SAMPLER_TYPE_NEAREST;
       
   980         derivedState.imageGradientType = PixelPipe::GRADIENT_TYPE_INTEGER;
       
   981         derivedState.imageDesc = Color::Descriptor::getDummyDescriptor();
       
   982     } else if (derivedState.imageMode == VG_DRAW_IMAGE_NORMAL)
       
   983     {
       
   984         // If paint is not generated, use a common enum
       
   985         derivedState.paintType = VG_PAINT_TYPE_COLOR;
       
   986     }
       
   987 
       
   988     if (derivedState.paintType != VG_PAINT_TYPE_PATTERN)
       
   989     {
       
   990         derivedState.patternDesc = Color::Descriptor::getDummyDescriptor();
       
   991     }
       
   992 
       
   993     if (!derivedState.isRenderToMask)
       
   994         derivedState.maskOperation = VG_CLEAR_MASK;
       
   995 
       
   996     if (!derivedState.hasMasking)
       
   997     {
       
   998         derivedState.maskDesc = Color::Descriptor::getDummyDescriptor();
       
   999     }
       
  1000 }
       
  1001 
       
  1002 
       
  1003 /**
       
  1004  * \brief   Determine per-scanconversion constant state.
       
  1005  * \todo    NOTE! This also prepares the derived state at the moment.
       
  1006  */
       
  1007 void PixelPipe::prepareSpanUniforms(bool aa)
       
  1008 {
       
  1009     prepareSignatureState();
       
  1010 
       
  1011     if (m_signatureState.hasColorTransform)
       
  1012         m_spanUniforms.colorTransformValues = m_iColorTransformValues;
       
  1013 
       
  1014     RI_ASSERT(m_drawable->getColorBuffer());
       
  1015 
       
  1016     const Image* dst;
       
  1017 
       
  1018     if (!m_signatureState.isRenderToMask)
       
  1019         dst = m_drawable->getColorBuffer()->getImage();
       
  1020     else
       
  1021         dst = m_drawable->getMaskBuffer()->getImage();
       
  1022     
       
  1023     m_spanUniforms.dstPtr = dst->getData();
       
  1024     m_spanUniforms.dstStride = dst->getStride();
       
  1025 
       
  1026     if (m_drawable->getMaskBuffer())
       
  1027     {
       
  1028         m_spanUniforms.maskPtr = m_drawable->getMaskBuffer()->m_image->getData();
       
  1029         m_spanUniforms.maskStride = m_drawable->getMaskBuffer()->m_image->getStride();
       
  1030     }
       
  1031     else
       
  1032     {
       
  1033         m_spanUniforms.maskPtr = NULL;
       
  1034         m_spanUniforms.maskStride = 0;
       
  1035     }
       
  1036 
       
  1037     if (!m_renderToMask)
       
  1038     {
       
  1039         VGImageFormat prefPaintFormat = getPreferredLUTFormat();
       
  1040 
       
  1041         switch (getPaintType())
       
  1042         {
       
  1043             case VG_PAINT_TYPE_COLOR:
       
  1044                 prepareSolidFill();
       
  1045                 break;
       
  1046             case VG_PAINT_TYPE_LINEAR_GRADIENT:
       
  1047                 m_paint->generateLUT(*this, prefPaintFormat);
       
  1048                 prepareLinearGradient(); 
       
  1049                 break;
       
  1050             case VG_PAINT_TYPE_RADIAL_GRADIENT:
       
  1051                 m_paint->generateLUT(*this, prefPaintFormat);
       
  1052                 prepareRadialGradient();
       
  1053                 break;
       
  1054             default:
       
  1055                 RI_ASSERT(getPaintType() == VG_PAINT_TYPE_PATTERN);
       
  1056                 preparePattern();
       
  1057                 break;
       
  1058         }
       
  1059     }
       
  1060     else
       
  1061     {
       
  1062         prepareCoverageFill();
       
  1063     }
       
  1064 
       
  1065     prepareImage(aa);
       
  1066 
       
  1067     // Must be done last:
       
  1068     determineDerivedState(m_derivedState, m_signatureState);
       
  1069 }
       
  1070 
       
  1071 
       
  1072 /*-------------------------------------------------------------------*//*!
       
  1073 * \brief    Computes the linear gradient function at (x,y).
       
  1074 * \param
       
  1075 * \return
       
  1076 * \note
       
  1077 *//*-------------------------------------------------------------------*/
       
  1078 void PixelPipe::linearGradient(RIfloat& g, RIfloat& rho, RIfloat x, RIfloat y) const
       
  1079 {
       
  1080     RI_ASSERT(m_paint);
       
  1081     Vector2 u = m_paint->m_linearGradientPoint1 - m_paint->m_linearGradientPoint0;
       
  1082     RIfloat usq = dot(u,u);
       
  1083     if( usq <= 0.0f )
       
  1084     {   //points are equal, gradient is always 1.0f
       
  1085         g = 1.0f;
       
  1086         rho = 0.0f;
       
  1087         return;
       
  1088     }
       
  1089     RIfloat oou = 1.0f / usq;
       
  1090 
       
  1091     Vector2 p(x, y);
       
  1092     p = affineTransform(m_surfaceToPaintMatrix, p);
       
  1093     p -= m_paint->m_linearGradientPoint0;
       
  1094     RI_ASSERT(usq >= 0.0f);
       
  1095     g = dot(p, u) * oou;
       
  1096     RIfloat dgdx = oou * u.x * m_surfaceToPaintMatrix[0][0] + oou * u.y * m_surfaceToPaintMatrix[1][0];
       
  1097     RIfloat dgdy = oou * u.x * m_surfaceToPaintMatrix[0][1] + oou * u.y * m_surfaceToPaintMatrix[1][1];
       
  1098     rho = (RIfloat)sqrt(dgdx*dgdx + dgdy*dgdy);
       
  1099     RI_ASSERT(rho >= 0.0f);
       
  1100 }
       
  1101 
       
  1102 /*-------------------------------------------------------------------*//*!
       
  1103 * \brief    Computes the radial gradient function at (x,y).
       
  1104 * \param
       
  1105 * \return
       
  1106 * \note
       
  1107 *//*-------------------------------------------------------------------*/
       
  1108 
       
  1109 void PixelPipe::radialGradient(RIfloat &g, RIfloat &rho, RIfloat x, RIfloat y) const
       
  1110 {
       
  1111     RI_ASSERT(m_paint);
       
  1112     if( m_paint->m_radialGradientRadius <= 0.0f )
       
  1113     {
       
  1114         g = 1.0f;
       
  1115         rho = 0.0f;
       
  1116         return;
       
  1117     }
       
  1118 
       
  1119     RIfloat r = m_paint->m_radialGradientRadius;
       
  1120     Vector2 c = m_paint->m_radialGradientCenter;
       
  1121     Vector2 f = m_paint->m_radialGradientFocalPoint;
       
  1122     Vector2 gx(m_surfaceToPaintMatrix[0][0], m_surfaceToPaintMatrix[1][0]);
       
  1123     Vector2 gy(m_surfaceToPaintMatrix[0][1], m_surfaceToPaintMatrix[1][1]);
       
  1124 
       
  1125     Vector2 fp = f - c;
       
  1126 
       
  1127     //clamp the focal point inside the gradient circle
       
  1128     RIfloat fpLen = fp.length();
       
  1129     if( fpLen > 0.999f * r )
       
  1130         fp *= 0.999f * r / fpLen;
       
  1131 
       
  1132     RIfloat D = -1.0f / (dot(fp,fp) - r*r);
       
  1133     Vector2 p(x, y);
       
  1134     p = affineTransform(m_surfaceToPaintMatrix, p) - c;
       
  1135     Vector2 d = p - fp;
       
  1136     RIfloat s = (RIfloat)sqrt(r*r*dot(d,d) - RI_SQR(p.x*fp.y - p.y*fp.x));
       
  1137     g = (dot(fp,d) + s) * D;
       
  1138     if(RI_ISNAN(g))
       
  1139         g = 0.0f;
       
  1140     RIfloat dgdx = D*dot(fp,gx) + (r*r*dot(d,gx) - (gx.x*fp.y - gx.y*fp.x)*(p.x*fp.y - p.y*fp.x)) * (D / s);
       
  1141     RIfloat dgdy = D*dot(fp,gy) + (r*r*dot(d,gy) - (gy.x*fp.y - gy.y*fp.x)*(p.x*fp.y - p.y*fp.x)) * (D / s);
       
  1142     rho = (RIfloat)sqrt(dgdx*dgdx + dgdy*dgdy);
       
  1143     if(RI_ISNAN(rho))
       
  1144         rho = 0.0f;
       
  1145     RI_ASSERT(rho >= 0.0f);
       
  1146 }
       
  1147 
       
  1148 /*-------------------------------------------------------------------*//*!
       
  1149 * \brief    Maps a gradient function value to a color.
       
  1150 * \param
       
  1151 * \return
       
  1152 * \note
       
  1153 *//*-------------------------------------------------------------------*/
       
  1154 
       
  1155 Color PixelPipe::colorRamp(RIfloat gradient, RIfloat rho) const
       
  1156 {
       
  1157     RI_ASSERT(m_paint);
       
  1158     RI_ASSERT(rho >= 0.0f);
       
  1159 
       
  1160     Color c(0,0,0,0,m_paint->m_colorRampPremultiplied ? Color::sRGBA_PRE : Color::sRGBA);
       
  1161     Color avg;
       
  1162 
       
  1163     if(rho == 0.0f)
       
  1164     {   //filter size is zero or gradient is degenerate
       
  1165         switch(m_paint->m_colorRampSpreadMode)
       
  1166         {
       
  1167         case VG_COLOR_RAMP_SPREAD_PAD:
       
  1168             gradient = RI_CLAMP(gradient, 0.0f, 1.0f);
       
  1169             break;
       
  1170         case VG_COLOR_RAMP_SPREAD_REFLECT:
       
  1171         {
       
  1172             RIfloat g = RI_MOD(gradient, 2.0f);
       
  1173             gradient = (g < 1.0f) ? g : 2.0f - g;
       
  1174             break;
       
  1175         }
       
  1176         default:
       
  1177             RI_ASSERT(m_paint->m_colorRampSpreadMode == VG_COLOR_RAMP_SPREAD_REPEAT);
       
  1178             gradient = gradient - (RIfloat)floor(gradient);
       
  1179             break;
       
  1180         }
       
  1181         RI_ASSERT(gradient >= 0.0f && gradient <= 1.0f);
       
  1182 
       
  1183         for(int i=0;i<m_paint->m_colorRampStops.size()-1;i++)
       
  1184         {
       
  1185             if(gradient >= m_paint->m_colorRampStops[i].offset && gradient < m_paint->m_colorRampStops[i+1].offset)
       
  1186             {
       
  1187                 RIfloat s = m_paint->m_colorRampStops[i].offset;
       
  1188                 RIfloat e = m_paint->m_colorRampStops[i+1].offset;
       
  1189                 RI_ASSERT(s < e);
       
  1190                 RIfloat g = RI_CLAMP((gradient - s) / (e - s), 0.0f, 1.0f); //clamp needed due to numerical inaccuracies
       
  1191 
       
  1192                 Color sc = readStopColor(m_paint->m_colorRampStops, i, m_paint->m_colorRampPremultiplied);
       
  1193                 Color ec = readStopColor(m_paint->m_colorRampStops, i+1, m_paint->m_colorRampPremultiplied);
       
  1194                 return (1.0f-g) * sc + g * ec;  //return interpolated value
       
  1195             }
       
  1196         }
       
  1197         return readStopColor(m_paint->m_colorRampStops, m_paint->m_colorRampStops.size()-1, m_paint->m_colorRampPremultiplied);
       
  1198     }
       
  1199 
       
  1200     RIfloat gmin = gradient - rho*0.5f;         //filter starting from the gradient point (if starts earlier, radial gradient center will be an average of the first and the last stop, which doesn't look good)
       
  1201     RIfloat gmax = gradient + rho*0.5f;
       
  1202 
       
  1203     switch(m_paint->m_colorRampSpreadMode)
       
  1204     {
       
  1205     case VG_COLOR_RAMP_SPREAD_PAD:
       
  1206     {
       
  1207         if(gmin < 0.0f)
       
  1208             c += (RI_MIN(gmax, 0.0f) - gmin) * readStopColor(m_paint->m_colorRampStops, 0, m_paint->m_colorRampPremultiplied);
       
  1209         if(gmax > 1.0f)
       
  1210             c += (gmax - RI_MAX(gmin, 1.0f)) * readStopColor(m_paint->m_colorRampStops, m_paint->m_colorRampStops.size()-1, m_paint->m_colorRampPremultiplied);
       
  1211         gmin = RI_CLAMP(gmin, 0.0f, 1.0f);
       
  1212         gmax = RI_CLAMP(gmax, 0.0f, 1.0f);
       
  1213         c += m_paint->integrateColorRamp(gmin, gmax);
       
  1214         c *= 1.0f/rho;
       
  1215         c.clamp();  //clamp needed due to numerical inaccuracies
       
  1216         return c;
       
  1217     }
       
  1218 
       
  1219     case VG_COLOR_RAMP_SPREAD_REFLECT:
       
  1220     {
       
  1221         avg = m_paint->integrateColorRamp(0.0f, 1.0f);
       
  1222         RIfloat gmini = (RIfloat)floor(gmin);
       
  1223         RIfloat gmaxi = (RIfloat)floor(gmax);
       
  1224         c = (gmaxi + 1.0f - gmini) * avg;       //full ramps
       
  1225 
       
  1226         //subtract beginning
       
  1227         if(((int)gmini) & 1)
       
  1228             c -= m_paint->integrateColorRamp(RI_CLAMP(1.0f - (gmin - gmini), 0.0f, 1.0f), 1.0f);
       
  1229         else
       
  1230             c -= m_paint->integrateColorRamp(0.0f, RI_CLAMP(gmin - gmini, 0.0f, 1.0f));
       
  1231 
       
  1232         //subtract end
       
  1233         if(((int)gmaxi) & 1)
       
  1234             c -= m_paint->integrateColorRamp(0.0f, RI_CLAMP(1.0f - (gmax - gmaxi), 0.0f, 1.0f));
       
  1235         else
       
  1236             c -= m_paint->integrateColorRamp(RI_CLAMP(gmax - gmaxi, 0.0f, 1.0f), 1.0f);
       
  1237         break;
       
  1238     }
       
  1239 
       
  1240     default:
       
  1241     {
       
  1242         RI_ASSERT(m_paint->m_colorRampSpreadMode == VG_COLOR_RAMP_SPREAD_REPEAT);
       
  1243         avg = m_paint->integrateColorRamp(0.0f, 1.0f);
       
  1244         RIfloat gmini = (RIfloat)floor(gmin);
       
  1245         RIfloat gmaxi = (RIfloat)floor(gmax);
       
  1246         c = (gmaxi + 1.0f - gmini) * avg;       //full ramps
       
  1247         c -= m_paint->integrateColorRamp(0.0f, RI_CLAMP(gmin - gmini, 0.0f, 1.0f));  //subtract beginning
       
  1248         c -= m_paint->integrateColorRamp(RI_CLAMP(gmax - gmaxi, 0.0f, 1.0f), 1.0f);  //subtract end
       
  1249         break;
       
  1250     }
       
  1251     }
       
  1252 
       
  1253     //divide color by the length of the range
       
  1254     c *= 1.0f / rho;
       
  1255     c.clamp();  //clamp needed due to numerical inaccuracies
       
  1256 
       
  1257     //hide aliasing by fading to the average color
       
  1258     const RIfloat fadeStart = 0.5f;
       
  1259     const RIfloat fadeMultiplier = 2.0f;    //the larger, the earlier fade to average is done
       
  1260 
       
  1261     if(rho < fadeStart)
       
  1262         return c;
       
  1263 
       
  1264     RIfloat ratio = RI_MIN((rho - fadeStart) * fadeMultiplier, 1.0f);
       
  1265     return ratio * avg + (1.0f - ratio) * c;
       
  1266 }
       
  1267 
       
  1268 /*-------------------------------------------------------------------*//*!
       
  1269 * \brief    Computes blend.
       
  1270 * \param
       
  1271 * \return
       
  1272 * \note     premultiplied blending formulas
       
  1273             //src
       
  1274             a = asrc
       
  1275             r = rsrc
       
  1276             //src over
       
  1277             a = asrc + adst * (1-asrc)
       
  1278             r = rsrc + rdst * (1-asrc)
       
  1279             //dst over
       
  1280             a = asrc * (1-adst) + adst
       
  1281             r = rsrc * (1-adst) + adst
       
  1282             //src in
       
  1283             a = asrc * adst
       
  1284             r = rsrc * adst
       
  1285             //dst in
       
  1286             a = adst * asrc
       
  1287             r = rdst * asrc
       
  1288             //multiply
       
  1289             a = asrc + adst * (1-asrc)
       
  1290             r = rsrc * (1-adst) + rdst * (1-asrc) + rsrc * rdst
       
  1291             //screen
       
  1292             a = asrc + adst * (1-asrc)
       
  1293             r = rsrc + rdst - rsrc * rdst
       
  1294             //darken
       
  1295             a = asrc + adst * (1-asrc)
       
  1296             r = MIN(rsrc + rdst * (1-asrc), rdst + rsrc * (1-adst))
       
  1297             //lighten
       
  1298             a = asrc + adst * (1-asrc)
       
  1299             r = MAX(rsrc + rdst * (1-asrc), rdst + rsrc * (1-adst))
       
  1300             //additive
       
  1301             a = MIN(asrc+adst,1)
       
  1302             r = rsrc + rdst
       
  1303 *//*-------------------------------------------------------------------*/
       
  1304 
       
  1305 
       
  1306 
       
  1307 Color PixelPipe::blend(const Color& s, RIfloat ar, RIfloat ag, RIfloat ab, const Color& d, VGBlendMode blendMode) const
       
  1308 {
       
  1309     //apply blending in the premultiplied format
       
  1310     Color r(0,0,0,0,d.getInternalFormat());
       
  1311     RI_ASSERT(s.a >= 0.0f && s.a <= 1.0f);
       
  1312     RI_ASSERT(s.r >= 0.0f && s.r <= s.a && s.r <= ar);
       
  1313     RI_ASSERT(s.g >= 0.0f && s.g <= s.a && s.g <= ag);
       
  1314     RI_ASSERT(s.b >= 0.0f && s.b <= s.a && s.b <= ab);
       
  1315     RI_ASSERT(d.a >= 0.0f && d.a <= 1.0f);
       
  1316     RI_ASSERT(d.r >= 0.0f && d.r <= d.a);
       
  1317     RI_ASSERT(d.g >= 0.0f && d.g <= d.a);
       
  1318     RI_ASSERT(d.b >= 0.0f && d.b <= d.a);
       
  1319     switch(blendMode)
       
  1320     {
       
  1321     case VG_BLEND_SRC:
       
  1322         r = s;
       
  1323         break;
       
  1324 
       
  1325     case VG_BLEND_SRC_OVER:
       
  1326         r.r = s.r + d.r * (1.0f - ar);
       
  1327         r.g = s.g + d.g * (1.0f - ag);
       
  1328         r.b = s.b + d.b * (1.0f - ab);
       
  1329         r.a = s.a + d.a * (1.0f - s.a);
       
  1330         break;
       
  1331 
       
  1332     case VG_BLEND_DST_OVER:
       
  1333         r.r = s.r * (1.0f - d.a) + d.r;
       
  1334         r.g = s.g * (1.0f - d.a) + d.g;
       
  1335         r.b = s.b * (1.0f - d.a) + d.b;
       
  1336         r.a = s.a * (1.0f - d.a) + d.a;
       
  1337         break;
       
  1338 
       
  1339     case VG_BLEND_SRC_IN:
       
  1340         r.r = s.r * d.a;
       
  1341         r.g = s.g * d.a;
       
  1342         r.b = s.b * d.a;
       
  1343         r.a = s.a * d.a;
       
  1344         break;
       
  1345 
       
  1346     case VG_BLEND_DST_IN:
       
  1347         r.r = d.r * ar;
       
  1348         r.g = d.g * ag;
       
  1349         r.b = d.b * ab;
       
  1350         r.a = d.a * s.a;
       
  1351         break;
       
  1352 
       
  1353     case VG_BLEND_MULTIPLY:
       
  1354         r.r = s.r * (1.0f - d.a + d.r) + d.r * (1.0f - ar);
       
  1355         r.g = s.g * (1.0f - d.a + d.g) + d.g * (1.0f - ag);
       
  1356         r.b = s.b * (1.0f - d.a + d.b) + d.b * (1.0f - ab);
       
  1357         r.a = s.a + d.a * (1.0f - s.a);
       
  1358         break;
       
  1359 
       
  1360     case VG_BLEND_SCREEN:
       
  1361         r.r = s.r + d.r * (1.0f - s.r);
       
  1362         r.g = s.g + d.g * (1.0f - s.g);
       
  1363         r.b = s.b + d.b * (1.0f - s.b);
       
  1364         r.a = s.a + d.a * (1.0f - s.a);
       
  1365         break;
       
  1366 
       
  1367     case VG_BLEND_DARKEN:
       
  1368         r.r = RI_MIN(s.r + d.r * (1.0f - ar), d.r + s.r * (1.0f - d.a));
       
  1369         r.g = RI_MIN(s.g + d.g * (1.0f - ag), d.g + s.g * (1.0f - d.a));
       
  1370         r.b = RI_MIN(s.b + d.b * (1.0f - ab), d.b + s.b * (1.0f - d.a));
       
  1371         r.a = s.a + d.a * (1.0f - s.a);
       
  1372         break;
       
  1373 
       
  1374     case VG_BLEND_LIGHTEN:
       
  1375         r.r = RI_MAX(s.r + d.r * (1.0f - ar), d.r + s.r * (1.0f - d.a));
       
  1376         r.g = RI_MAX(s.g + d.g * (1.0f - ag), d.g + s.g * (1.0f - d.a));
       
  1377         r.b = RI_MAX(s.b + d.b * (1.0f - ab), d.b + s.b * (1.0f - d.a));
       
  1378         //although the statement below is equivalent to r.a = s.a + d.a * (1.0f - s.a)
       
  1379         //in practice there can be a very slight difference because
       
  1380         //of the max operation in the blending formula that may cause color to exceed alpha.
       
  1381         //Because of this, we compute the result both ways and return the maximum.
       
  1382         r.a = RI_MAX(s.a + d.a * (1.0f - s.a), d.a + s.a * (1.0f - d.a));
       
  1383         break;
       
  1384 
       
  1385     default:
       
  1386         RI_ASSERT(blendMode == VG_BLEND_ADDITIVE);
       
  1387         r.r = RI_MIN(s.r + d.r, 1.0f);
       
  1388         r.g = RI_MIN(s.g + d.g, 1.0f);
       
  1389         r.b = RI_MIN(s.b + d.b, 1.0f);
       
  1390         r.a = RI_MIN(s.a + d.a, 1.0f);
       
  1391         break;
       
  1392     }
       
  1393     return r;
       
  1394 }
       
  1395 
       
  1396 /*-------------------------------------------------------------------*//*!
       
  1397 * \brief    Applies color transform.
       
  1398 * \param
       
  1399 * \return
       
  1400 * \note
       
  1401 *//*-------------------------------------------------------------------*/
       
  1402 
       
  1403 void PixelPipe::colorTransform(Color& c) const
       
  1404 {
       
  1405     if(m_colorTransform)
       
  1406     {
       
  1407         c.unpremultiply();
       
  1408         c.luminanceToRGB();
       
  1409         c.r = c.r * m_colorTransformValues[0] + m_colorTransformValues[4];
       
  1410         c.g = c.g * m_colorTransformValues[1] + m_colorTransformValues[5];
       
  1411         c.b = c.b * m_colorTransformValues[2] + m_colorTransformValues[6];
       
  1412         c.a = c.a * m_colorTransformValues[3] + m_colorTransformValues[7];
       
  1413         c.clamp();
       
  1414         c.premultiply();
       
  1415     }
       
  1416 }
       
  1417 
       
  1418 void PixelPipe::fillSpans(PPVariants& variants, const Span* spans, int nSpans) const
       
  1419 {
       
  1420 #if 1
       
  1421     PPCompiler& compiler = PPCompiler::getCompiler();
       
  1422 
       
  1423     PPCompiler::PixelPipeHandle handle = compiler.compilePixelPipeline(m_derivedState);
       
  1424     if (handle)
       
  1425     {
       
  1426         PixelPipeFunction func = compiler.getPixelPipePtr(handle);
       
  1427         RI_ASSERT(func);
       
  1428         func(m_spanUniforms, variants, spans, nSpans);
       
  1429         compiler.releasePixelPipeline(handle);
       
  1430     } else
       
  1431 #endif
       
  1432     {
       
  1433         executePixelPipeline(m_derivedState, m_spanUniforms, variants, spans, nSpans);
       
  1434     }
       
  1435 }
       
  1436 
       
  1437 //=======================================================================
       
  1438 
       
  1439 }   //namespace OpenVGRI
       
  1440