hostsupport/hostopenvg/src/src/sfDynamicBlitter.cpp
branchbug235_bringup_0
changeset 53 c2ef9095503a
parent 24 a3f46bb01be2
equal deleted inserted replaced
52:39e5f73667ba 53:c2ef9095503a
       
     1 /* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     2  *
       
     3  * Permission is hereby granted, free of charge, to any person obtaining a
       
     4  * copy of this software and /or associated documentation files
       
     5  * (the "Materials "), to deal in the Materials without restriction,
       
     6  * including without limitation the rights to use, copy, modify, merge,
       
     7  * publish, distribute, sublicense, and/or sell copies of the Materials,
       
     8  * and to permit persons to whom the Materials are furnished to do so,
       
     9  * subject to the following conditions:
       
    10  *
       
    11  * The above copyright notice and this permission notice shall be included
       
    12  * in all copies or substantial portions of the Materials.
       
    13  *
       
    14  * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
       
    15  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
       
    16  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
       
    17  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
       
    18  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
       
    19  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR
       
    20  * THE USE OR OTHER DEALINGS IN THE MATERIALS.
       
    21  */
       
    22 
       
    23 #include "sfDynamicBlitter.h"
       
    24 
       
    25 #ifndef __SFBLITTER_H
       
    26 #   include "sfBlitter.h"
       
    27 #endif
       
    28 
       
    29 #ifndef __SFMASK_H
       
    30 #   include "sfMask.h"
       
    31 #endif
       
    32 
       
    33 namespace OpenVGRI {
       
    34 
       
    35 RI_INLINE static bool maskOperationRequiresLoad(VGMaskOperation op)
       
    36 {
       
    37     switch(op)
       
    38     {
       
    39     case VG_CLEAR_MASK:
       
    40     case VG_FILL_MASK:
       
    41     case VG_SET_MASK:
       
    42         return false;
       
    43     default:
       
    44         RI_ASSERT(op == VG_UNION_MASK || op == VG_INTERSECT_MASK || op == VG_SUBTRACT_MASK);
       
    45         return true;
       
    46     }
       
    47 }
       
    48 
       
    49 /**
       
    50  * \brief   Blit rectangular areas between similar or different color format buffers.
       
    51  * \note    Implementation is structured so that the per-pixel branches are minimized
       
    52  *          even if dynamic compilation is not in use.
       
    53  * \todo    For some reason the completely generic integer conversion does not optimize
       
    54  *          fully run-time. Check what causes this!
       
    55  */
       
    56 void executeBlitter(const DynamicBlitter::BlitSignatureState& state, const DynamicBlitter::BlitUniforms& uniforms)
       
    57 {
       
    58     const void* srcPtr = Image::calculateAddress(
       
    59         uniforms.src, state.srcDesc.bitsPerPixel, uniforms.srcX, uniforms.srcY, uniforms.srcStride); 
       
    60     void* dstPtr = Image::calculateAddress(
       
    61         uniforms.dst, state.dstDesc.bitsPerPixel, uniforms.dstX, uniforms.dstY, uniforms.dstStride);
       
    62 
       
    63     // The following flag is useful for debugging. Enabling it will hurt performance.
       
    64 //#define ALWAYS_FORCE_FULL_CONVERSION
       
    65 
       
    66     // Currently the data must be byte-aligned for memcpy optimizations:
       
    67     const int minBpp = RI_INT_MIN(state.srcDesc.bitsPerPixel, state.dstDesc.bitsPerPixel);
       
    68     const bool byteCopy = minBpp >= 8 ? true : false;
       
    69     const bool forceFullConversion = state.isMaskOperation || state.unsafeInput || !byteCopy;
       
    70     
       
    71 #if !defined(ALWAYS_FORCE_FULL_CONVERSION)
       
    72     if (state.srcDesc.isZeroConversion(state.dstDesc) && !forceFullConversion)
       
    73     {
       
    74         const int fullCopyStride = Image::descriptorToStride(state.srcDesc, uniforms.width);
       
    75 
       
    76         if ((uniforms.dstStride != uniforms.srcStride) || (fullCopyStride != uniforms.srcStride)) 
       
    77         {
       
    78             // memcpy individual scanlines.
       
    79             const size_t scanLength = (size_t)RI_INT_ABS(Image::descriptorToStride(state.srcDesc, uniforms.width));
       
    80             for (RIuint32 i = 0; i < uniforms.height; i++)
       
    81             {
       
    82                 memcpy(dstPtr, srcPtr, scanLength);
       
    83                 dstPtr = (void*)((RIuint8*)dstPtr + uniforms.dstStride);
       
    84                 srcPtr = (void*)((RIuint8*)srcPtr + uniforms.srcStride);
       
    85             }
       
    86         } else
       
    87         {
       
    88             // memcpy the whole area
       
    89             memcpy(dstPtr, srcPtr, uniforms.srcStride * uniforms.height);
       
    90         }
       
    91     } else if (state.srcDesc.isShiftConversion(state.dstDesc) && !forceFullConversion)
       
    92     {
       
    93         // \todo Separate to function? Replace with pointer read/write & advance.
       
    94         if (state.srcDesc.isShiftConversionToLower(state.dstDesc))
       
    95         {
       
    96             // Components can be immediately shifted down to lower bit-depth.
       
    97             for (RIuint32 j = 0; j < uniforms.height; j++)
       
    98             {
       
    99                 RIuint8* srcStart = (RIuint8*)srcPtr;
       
   100                 RIuint8* dstStart = (RIuint8*)dstPtr;
       
   101                 RIuint32 srcX = uniforms.srcX;
       
   102                 RIuint32 dstX = uniforms.dstX;
       
   103                 for (RIuint32 i = 0; i < uniforms.width; i++)
       
   104                 {
       
   105                     RIuint32 c = Image::readPackedPixelFromAddress(srcPtr, state.srcDesc.bitsPerPixel, srcX); // \todo srcX!
       
   106                     RIuint32 dc = Color::Descriptor::crossConvertToLower(c, state.srcDesc, state.dstDesc);
       
   107                     Image::writePackedPixelToAddress(dstPtr, state.dstDesc.bitsPerPixel, dstX, dc);
       
   108 
       
   109                     srcPtr = Image::incrementPointer(srcPtr, state.srcDesc.bitsPerPixel, srcX);
       
   110                     dstPtr = (void*)Image::incrementPointer(dstPtr, state.dstDesc.bitsPerPixel, dstX); 
       
   111 
       
   112                     srcX++;
       
   113                     dstX++;
       
   114                 }
       
   115                 srcPtr = (void*)(srcStart + uniforms.srcStride);
       
   116                 dstPtr = (void*)(dstStart + uniforms.dstStride);
       
   117             }
       
   118         }
       
   119         else
       
   120         {
       
   121             // Color components require expansion before shifting to destination color-format */
       
   122             for (RIuint32 j = 0; j < uniforms.height; j++)
       
   123             {
       
   124                 RIuint8* srcStart = (RIuint8*)srcPtr;
       
   125                 RIuint8* dstStart = (RIuint8*)dstPtr;
       
   126                 RIuint32 srcX = uniforms.srcX;
       
   127                 RIuint32 dstX = uniforms.dstX;
       
   128                 for (RIuint32 i = 0; i < uniforms.width; i++)
       
   129                 {
       
   130                     RIuint32 c = Image::readPackedPixelFromAddress(srcPtr, state.srcDesc.bitsPerPixel, srcX);
       
   131                     IntegerColor ic = IntegerColor(c, state.srcDesc);
       
   132                     ic.expandColor(state.srcDesc);
       
   133                     ic.truncateColor(state.dstDesc);
       
   134                     RIuint32 dc = ic.getPackedColor(state.dstDesc);
       
   135                     Image::writePackedPixelToAddress(dstPtr, state.dstDesc.bitsPerPixel, dstX, dc);
       
   136 
       
   137                     srcPtr = Image::incrementPointer(srcPtr, state.srcDesc.bitsPerPixel, srcX);
       
   138                     dstPtr = (void*)Image::incrementPointer(dstPtr, state.dstDesc.bitsPerPixel, dstX); 
       
   139 
       
   140                     srcX++;
       
   141                     dstX++;
       
   142                 }
       
   143                 srcPtr = (void*)(srcStart + uniforms.srcStride);
       
   144                 dstPtr = (void*)(dstStart + uniforms.dstStride);
       
   145             }
       
   146         }
       
   147     } else
       
   148 #endif
       
   149     {
       
   150         /* This block should handle the rest (and all) of the color-conversion cases. */
       
   151         for (RIuint32 j = 0; j < uniforms.height; j++)
       
   152         {
       
   153             RIuint8* srcStart = (RIuint8*)srcPtr;
       
   154             RIuint8* dstStart = (RIuint8*)dstPtr;
       
   155             RIuint32 srcX = uniforms.srcX;
       
   156             RIuint32 dstX = uniforms.dstX;
       
   157             for (RIuint32 i = 0; i < uniforms.width; i++)
       
   158             {
       
   159                 RIuint32 c = Image::readPackedPixelFromAddress(srcPtr, state.srcDesc.bitsPerPixel, srcX);
       
   160                 IntegerColor ic;
       
   161                 RIuint32 dc;
       
   162                 
       
   163                 if (!state.isMaskOperation)
       
   164                 {
       
   165                     ic = IntegerColor(c, state.srcDesc);
       
   166                     if (state.unsafeInput)
       
   167                         ic.clampToAlpha();
       
   168 
       
   169                     ic.convertToFrom(state.dstDesc, state.srcDesc, false);
       
   170                     dc = ic.getPackedColor(state.dstDesc);
       
   171                 }
       
   172                 else
       
   173                 {
       
   174                     // Apply the given mask operation between two surfaces.
       
   175                     IntegerColor id;
       
   176 
       
   177                     if (maskOperationRequiresLoad(state.maskOperation))
       
   178                     {
       
   179                         ic.fromPackedMask(c, state.srcDesc);
       
   180                         ic.expandMask(state.srcDesc);
       
   181 
       
   182                         IntegerColor id;
       
   183 
       
   184                         RIuint32 d = Image::readPackedPixelFromAddress(dstPtr, state.dstDesc.bitsPerPixel, dstX);
       
   185                         id.fromPackedMask(d, state.dstDesc);
       
   186                         id.expandColor(state.dstDesc);
       
   187 
       
   188                         RIuint32 coverage = ic.a + (ic.a >> 7);
       
   189                         ic = intMaskOperation(coverage, id, state.maskOperation);
       
   190                     }
       
   191                     else
       
   192                     {
       
   193                         // Other ops handled with memset, not blitter
       
   194                         RI_ASSERT(state.maskOperation == VG_SET_MASK); 
       
   195                         ic.fromPackedMask(c, state.srcDesc);
       
   196                         //ic.expandMask(state.srcDesc);
       
   197                         ic.convertToFrom(state.dstDesc, state.srcDesc, true);
       
   198                     }
       
   199                     dc = ic.getPackedMaskColor(state.dstDesc);
       
   200                 }
       
   201 
       
   202                 Image::writePackedPixelToAddress(dstPtr, state.dstDesc.bitsPerPixel, dstX, dc);
       
   203 
       
   204                 srcPtr = Image::incrementPointer(srcPtr, state.srcDesc.bitsPerPixel, srcX);
       
   205                 dstPtr = (void*)Image::incrementPointer(dstPtr, state.dstDesc.bitsPerPixel, dstX); 
       
   206 
       
   207                 srcX++;
       
   208                 dstX++;
       
   209             }
       
   210             srcPtr = (void*)(srcStart + uniforms.srcStride);
       
   211             dstPtr = (void*)(dstStart + uniforms.dstStride);
       
   212         }
       
   213     }
       
   214 }
       
   215 
       
   216 }
       
   217