1 /*
   2  * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #if !defined(JAVA2D_NO_MLIB) || defined(MLIB_ADD_SUFF)
  27 
  28 #include <vis_AlphaMacros.h>
  29 
  30 /***************************************************************/
  31 
  32 /* ##############################################################
  33  * IntArgbSrcMaskFill()
  34  * FourByteAbgrSrcMaskFill()
  35  */
  36 
  37 #define MASK_FILL(rr, pathA, dstA, dstARGB)         \
  38 {                                                   \
  39     mlib_d64 t0, t1;                                \
  40                                                     \
  41     dstA = MUL8_INT(dstA, 0xff - pathA);            \
  42                                                     \
  43     t0 = MUL8_VIS(cnstARGB0, pathA);                \
  44     t1 = MUL8_VIS(dstARGB, dstA);                   \
  45     rr = vis_fpadd16(t0, t1);                       \
  46                                                     \
  47     dstA = dstA + mul8_cnstA[pathA];                \
  48     DIV_ALPHA(rr, dstA);                            \
  49 }
  50 
  51 /***************************************************************/
  52 
  53 static void IntArgbSrcMaskFill_line(mlib_f32 *dst_ptr,
  54                                     mlib_u8  *pMask,
  55                                     mlib_s32 width,
  56                                     mlib_d64 fgARGB,
  57                                     mlib_f32 cnstARGB0,
  58                                     mlib_u8  *mul8_cnstA,
  59                                     mlib_u8  *mul8_tbl)
  60 {
  61     mlib_s32 i, i0;
  62     mlib_s32 pathA0, pathA1, dstA0, dstA1, msk;
  63     mlib_d64 res0, res1, dstARGB;
  64     mlib_f32 dstARGB0;
  65 
  66     i = i0 = 0;
  67 
  68     if ((mlib_s32)dst_ptr & 7) {
  69         pathA0 = pMask[i];
  70 
  71         if (pathA0 == 0xff) {
  72             dst_ptr[i] = vis_read_hi(fgARGB);
  73         } else if (pathA0) {
  74             dstA0 = *(mlib_u8*)(dst_ptr + i);
  75             dstARGB0 = dst_ptr[i];
  76             MASK_FILL(res0, pathA0, dstA0, dstARGB0);
  77             dst_ptr[i] = vis_fpack16(res0);
  78             *(mlib_u8*)(dst_ptr + i) = dstA0;
  79         }
  80 
  81         i0 = 1;
  82     }
  83 
  84 #pragma pipeloop(0)
  85     for (i = i0; i <= width - 2; i += 2) {
  86         pathA0 = pMask[i];
  87         pathA1 = pMask[i + 1];
  88         dstA0 = *(mlib_u8*)(dst_ptr + i);
  89         dstA1 = *(mlib_u8*)(dst_ptr + i + 1);
  90         dstARGB = *(mlib_d64*)(dst_ptr + i);
  91 
  92         MASK_FILL(res0, pathA0, dstA0, vis_read_hi(dstARGB));
  93         MASK_FILL(res1, pathA1, dstA1, vis_read_lo(dstARGB));
  94 
  95         res0 = vis_fpack16_pair(res0, res1);
  96 
  97         msk = (((-pathA0) & (1 << 11)) | ((-pathA1) & (1 << 10))) >> 10;
  98         vis_pst_32(res0, dst_ptr + i, msk);
  99 
 100         *(mlib_u8*)(dst_ptr + i    ) = dstA0;
 101         *(mlib_u8*)(dst_ptr + i + 1) = dstA1;
 102 
 103         msk = (((254 - pathA0) & (1 << 11)) |
 104                ((254 - pathA1) & (1 << 10))) >> 10;
 105         vis_pst_32(fgARGB, dst_ptr + i, msk);
 106     }
 107 
 108     if (i < width) {
 109         pathA0 = pMask[i];
 110 
 111         if (pathA0 == 0xff) {
 112             dst_ptr[i] = vis_read_hi(fgARGB);
 113         } else if (pathA0) {
 114             dstA0 = *(mlib_u8*)(dst_ptr + i);
 115             dstARGB0 = dst_ptr[i];
 116             MASK_FILL(res0, pathA0, dstA0, dstARGB0);
 117             dst_ptr[i] = vis_fpack16(res0);
 118             *(mlib_u8*)(dst_ptr + i) = dstA0;
 119         }
 120     }
 121 }
 122 
 123 /***************************************************************/
 124 
 125 void ADD_SUFF(IntArgbSrcMaskFill)(void *rasBase,
 126                                   jubyte *pMask,
 127                                   jint maskOff,
 128                                   jint maskScan,
 129                                   jint width,
 130                                   jint height,
 131                                   jint fgColor,
 132                                   SurfaceDataRasInfo *pRasInfo,
 133                                   NativePrimitive *pPrim,
 134                                   CompositeInfo *pCompInfo)
 135 {
 136     mlib_s32 cnstA, cnstR, cnstG, cnstB;
 137     mlib_s32 rasScan = pRasInfo->scanStride;
 138     mlib_f32 cnstARGB0;
 139     mlib_d64 fgARGB;
 140     mlib_u8  *mul8_cnstA;
 141     mlib_s32 j;
 142 
 143     cnstA = (fgColor >> 24) & 0xff;
 144     cnstR = (fgColor >> 16) & 0xff;
 145     cnstG = (fgColor >>  8) & 0xff;
 146     cnstB = (fgColor      ) & 0xff;
 147 
 148     if (cnstA == 0) {
 149         fgColor = 0;
 150     }
 151 
 152     if (pMask == NULL) {
 153         void *pBase = pRasInfo->rasBase;
 154         pRasInfo->rasBase = rasBase;
 155         ADD_SUFF(AnyIntSetRect)(pRasInfo,
 156                                 0, 0, width, height,
 157                                 fgColor, pPrim, pCompInfo);
 158         pRasInfo->rasBase = pBase;
 159         return;
 160     }
 161 
 162     mul8_cnstA = mul8table[cnstA];
 163     if (cnstA != 0xff) {
 164         cnstR = mul8_cnstA[cnstR];
 165         cnstG = mul8_cnstA[cnstG];
 166         cnstB = mul8_cnstA[cnstB];
 167     }
 168 
 169     cnstARGB0 = F32_FROM_U8x4(cnstA, cnstR, cnstG, cnstB);
 170 
 171     fgARGB = vis_to_double_dup(fgColor);
 172 
 173     pMask += maskOff;
 174 
 175     if (rasScan == 4*width && maskScan == width) {
 176         width *= height;
 177         height = 1;
 178     }
 179 
 180     vis_write_gsr(7 << 3);
 181 
 182     for (j = 0; j < height; j++) {
 183         IntArgbSrcMaskFill_line(rasBase, pMask, width, fgARGB, cnstARGB0,
 184                                 mul8_cnstA, (void*)mul8table);
 185 
 186         PTR_ADD(rasBase, rasScan);
 187         PTR_ADD(pMask, maskScan);
 188     }
 189 }
 190 
 191 /***************************************************************/
 192 
 193 void ADD_SUFF(FourByteAbgrSrcMaskFill)(void *rasBase,
 194                                        jubyte *pMask,
 195                                        jint maskOff,
 196                                        jint maskScan,
 197                                        jint width,
 198                                        jint height,
 199                                        jint fgColor,
 200                                        SurfaceDataRasInfo *pRasInfo,
 201                                        NativePrimitive *pPrim,
 202                                        CompositeInfo *pCompInfo)
 203 {
 204     mlib_d64 buff[BUFF_SIZE/2];
 205     void     *pbuff = buff;
 206     mlib_s32 cnstA, cnstR, cnstG, cnstB;
 207     mlib_s32 rasScan = pRasInfo->scanStride;
 208     mlib_f32 cnstARGB0;
 209     mlib_d64 fgARGB;
 210     mlib_u8  *mul8_cnstA;
 211     mlib_s32 j;
 212 
 213     cnstA = (mlib_u32)fgColor >> 24;
 214     cnstR = (fgColor >> 16) & 0xff;
 215     cnstG = (fgColor >>  8) & 0xff;
 216     cnstB = (fgColor      ) & 0xff;
 217 
 218     if (pMask == NULL) {
 219         void *pBase = pRasInfo->rasBase;
 220         pRasInfo->rasBase = rasBase;
 221         if (cnstA == 0) {
 222             fgColor = 0;
 223         } else {
 224             fgColor = (fgColor << 8) | cnstA;
 225         }
 226         ADD_SUFF(Any4ByteSetRect)(pRasInfo,
 227                                   0, 0, width, height,
 228                                   fgColor, pPrim, pCompInfo);
 229         pRasInfo->rasBase = pBase;
 230         return;
 231     }
 232 
 233     mul8_cnstA = mul8table[cnstA];
 234 
 235     if (cnstA == 0) {
 236         fgColor = 0;
 237         cnstR = cnstG = cnstB = 0;
 238     } else {
 239         fgColor = (cnstA << 24) | (cnstB << 16) | (cnstG << 8) | cnstR;
 240         if (cnstA != 0xff) {
 241             cnstR = mul8_cnstA[cnstR];
 242             cnstG = mul8_cnstA[cnstG];
 243             cnstB = mul8_cnstA[cnstB];
 244         }
 245     }
 246 
 247     cnstARGB0 = F32_FROM_U8x4(cnstA, cnstB, cnstG, cnstR);
 248 
 249     fgARGB = vis_to_double_dup(fgColor);
 250 
 251     pMask += maskOff;
 252 
 253     if (((mlib_s32)rasBase | rasScan) & 3) {
 254         if (width > BUFF_SIZE) pbuff = mlib_malloc(width*sizeof(mlib_s32));
 255     } else {
 256         if (rasScan == 4*width && maskScan == width) {
 257             width *= height;
 258             height = 1;
 259         }
 260     }
 261 
 262     vis_write_gsr(7 << 3);
 263 
 264     for (j = 0; j < height; j++) {
 265         if (!((mlib_s32)rasBase & 3)) {
 266             IntArgbSrcMaskFill_line(rasBase, pMask, width, fgARGB, cnstARGB0,
 267                                     mul8_cnstA, (void*)mul8table);
 268         } else {
 269             mlib_ImageCopy_na(rasBase, pbuff, width*sizeof(mlib_s32));
 270             IntArgbSrcMaskFill_line(pbuff, pMask, width, fgARGB, cnstARGB0,
 271                                     mul8_cnstA, (void*)mul8table);
 272             mlib_ImageCopy_na(pbuff, rasBase, width*sizeof(mlib_s32));
 273         }
 274 
 275         PTR_ADD(rasBase, rasScan);
 276         PTR_ADD(pMask, maskScan);
 277     }
 278 
 279     if (pbuff != buff) {
 280         mlib_free(pbuff);
 281     }
 282 }
 283 
 284 /***************************************************************/
 285 
 286 /* ##############################################################
 287  * IntRgbSrcMaskFill()
 288  * IntBgrSrcMaskFill()
 289  */
 290 
 291 #undef  MASK_FILL
 292 #define MASK_FILL(rr, pathA, dstA, dstARGB)         \
 293 {                                                   \
 294     mlib_d64 t0, t1;                                \
 295                                                     \
 296     dstA = 0xff - pathA;                            \
 297                                                     \
 298     t0 = MUL8_VIS(cnstARGB0, pathA);                \
 299     t1 = MUL8_VIS(dstARGB, dstA);                   \
 300     rr = vis_fpadd16(t0, t1);                       \
 301                                                     \
 302     dstA = dstA + mul8_cnstA[pathA];                \
 303     DIV_ALPHA_RGB(rr, dstA);                        \
 304 }
 305 
 306 /***************************************************************/
 307 
 308 static void IntRgbSrcMaskFill_line(mlib_f32 *dst_ptr,
 309                                    mlib_u8  *pMask,
 310                                    mlib_s32 width,
 311                                    mlib_d64 fgARGB,
 312                                    mlib_f32 cnstARGB0,
 313                                    mlib_u8  *mul8_cnstA,
 314                                    mlib_u8  *mul8_tbl)
 315 {
 316     mlib_s32 i, i0;
 317     mlib_s32 pathA0, pathA1, dstA0, dstA1, msk;
 318     mlib_d64 res0, res1, dstARGB;
 319     mlib_f32 dstARGB0;
 320 
 321     i = i0 = 0;
 322 
 323     if ((mlib_s32)dst_ptr & 7) {
 324         pathA0 = pMask[i];
 325 
 326         if (pathA0 == 0xff) {
 327             dst_ptr[i] = vis_read_hi(fgARGB);
 328         } else if (pathA0) {
 329             dstARGB0 = dst_ptr[i];
 330             MASK_FILL(res0, pathA0, dstA0, dstARGB0);
 331             dst_ptr[i] = vis_fpack16(res0);
 332         }
 333 
 334         i0 = 1;
 335     }
 336 
 337 #pragma pipeloop(0)
 338     for (i = i0; i <= width - 2; i += 2) {
 339         pathA0 = pMask[i];
 340         pathA1 = pMask[i + 1];
 341         dstARGB = *(mlib_d64*)(dst_ptr + i);
 342 
 343         MASK_FILL(res0, pathA0, dstA0, vis_read_hi(dstARGB));
 344         MASK_FILL(res1, pathA1, dstA1, vis_read_lo(dstARGB));
 345 
 346         res0 = vis_fpack16_pair(res0, res1);
 347 
 348         msk = (((-pathA0) & (1 << 11)) | ((-pathA1) & (1 << 10))) >> 10;
 349         vis_pst_32(res0, dst_ptr + i, msk);
 350 
 351         msk = (((254 - pathA0) & (1 << 11)) |
 352                ((254 - pathA1) & (1 << 10))) >> 10;
 353         vis_pst_32(fgARGB, dst_ptr + i, msk);
 354     }
 355 
 356     if (i < width) {
 357         pathA0 = pMask[i];
 358 
 359         if (pathA0 == 0xff) {
 360             dst_ptr[i] = vis_read_hi(fgARGB);
 361         } else if (pathA0) {
 362             dstARGB0 = dst_ptr[i];
 363             MASK_FILL(res0, pathA0, dstA0, dstARGB0);
 364             dst_ptr[i] = vis_fpack16(res0);
 365         }
 366     }
 367 }
 368 
 369 /***************************************************************/
 370 
 371 void ADD_SUFF(IntRgbSrcMaskFill)(void *rasBase,
 372                                  jubyte *pMask,
 373                                  jint maskOff,
 374                                  jint maskScan,
 375                                  jint width,
 376                                  jint height,
 377                                  jint fgColor,
 378                                  SurfaceDataRasInfo *pRasInfo,
 379                                  NativePrimitive *pPrim,
 380                                  CompositeInfo *pCompInfo)
 381 {
 382     mlib_s32 cnstA, cnstR, cnstG, cnstB;
 383     mlib_s32 rasScan = pRasInfo->scanStride;
 384     mlib_f32 cnstARGB0;
 385     mlib_d64 fgARGB;
 386     mlib_u8  *mul8_cnstA;
 387     mlib_s32 j;
 388 
 389     cnstA = (fgColor >> 24) & 0xff;
 390     cnstR = (fgColor >> 16) & 0xff;
 391     cnstG = (fgColor >>  8) & 0xff;
 392     cnstB = (fgColor      ) & 0xff;
 393 
 394     if (cnstA == 0) fgColor = 0;
 395 
 396     if (pMask == NULL) {
 397         void *pBase = pRasInfo->rasBase;
 398         pRasInfo->rasBase = rasBase;
 399         ADD_SUFF(AnyIntSetRect)(pRasInfo,
 400                                 0, 0, width, height,
 401                                 fgColor, pPrim, pCompInfo);
 402         pRasInfo->rasBase = pBase;
 403         return;
 404     }
 405 
 406     mul8_cnstA = mul8table[cnstA];
 407     if (cnstA != 0xff) {
 408         cnstR = mul8_cnstA[cnstR];
 409         cnstG = mul8_cnstA[cnstG];
 410         cnstB = mul8_cnstA[cnstB];
 411     }
 412 
 413     cnstARGB0 = F32_FROM_U8x4(cnstA, cnstR, cnstG, cnstB);
 414 
 415     fgARGB = vis_to_double_dup(fgColor);
 416 
 417     pMask += maskOff;
 418 
 419     if (rasScan == 4*width && maskScan == width) {
 420         width *= height;
 421         height = 1;
 422     }
 423 
 424     vis_write_gsr(7 << 3);
 425 
 426     for (j = 0; j < height; j++) {
 427         IntRgbSrcMaskFill_line(rasBase, pMask, width, fgARGB, cnstARGB0,
 428                                mul8_cnstA, (void*)mul8table);
 429 
 430         PTR_ADD(rasBase, rasScan);
 431         PTR_ADD(pMask, maskScan);
 432     }
 433 }
 434 
 435 /***************************************************************/
 436 
 437 void ADD_SUFF(IntBgrSrcMaskFill)(void *rasBase,
 438                                  jubyte *pMask,
 439                                  jint maskOff,
 440                                  jint maskScan,
 441                                  jint width,
 442                                  jint height,
 443                                  jint fgColor,
 444                                  SurfaceDataRasInfo *pRasInfo,
 445                                  NativePrimitive *pPrim,
 446                                  CompositeInfo *pCompInfo)
 447 {
 448     mlib_s32 cnstA, cnstR, cnstG, cnstB;
 449     mlib_s32 rasScan = pRasInfo->scanStride;
 450     mlib_f32 cnstARGB0;
 451     mlib_d64 fgARGB;
 452     mlib_u8  *mul8_cnstA;
 453     mlib_s32 j;
 454 
 455     cnstA = (fgColor >> 24) & 0xff;
 456     cnstR = (fgColor >> 16) & 0xff;
 457     cnstG = (fgColor >>  8) & 0xff;
 458     cnstB = (fgColor      ) & 0xff;
 459 
 460     if (cnstA == 0) {
 461         fgColor = 0;
 462     } else {
 463         fgColor = (cnstB << 16) | (cnstG << 8) | (cnstR);
 464     }
 465 
 466     if (pMask == NULL) {
 467         void *pBase = pRasInfo->rasBase;
 468         pRasInfo->rasBase = rasBase;
 469         ADD_SUFF(AnyIntSetRect)(pRasInfo,
 470                                 0, 0, width, height,
 471                                 fgColor, pPrim, pCompInfo);
 472         pRasInfo->rasBase = pBase;
 473         return;
 474     }
 475 
 476     mul8_cnstA = mul8table[cnstA];
 477     if (cnstA != 0xff) {
 478         cnstR = mul8_cnstA[cnstR];
 479         cnstG = mul8_cnstA[cnstG];
 480         cnstB = mul8_cnstA[cnstB];
 481     }
 482 
 483     cnstARGB0 = F32_FROM_U8x4(cnstA, cnstB, cnstG, cnstR);
 484 
 485     fgARGB = vis_to_double_dup(fgColor);
 486 
 487     pMask += maskOff;
 488 
 489     if (rasScan == 4*width && maskScan == width) {
 490         width *= height;
 491         height = 1;
 492     }
 493 
 494     vis_write_gsr(7 << 3);
 495 
 496     for (j = 0; j < height; j++) {
 497         IntRgbSrcMaskFill_line(rasBase, pMask, width, fgARGB, cnstARGB0,
 498                                mul8_cnstA, (void*)mul8table);
 499 
 500         PTR_ADD(rasBase, rasScan);
 501         PTR_ADD(pMask, maskScan);
 502     }
 503 }
 504 
 505 /***************************************************************/
 506 
 507 void ADD_SUFF(ThreeByteBgrSrcMaskFill)(void *rasBase,
 508                                        jubyte *pMask,
 509                                        jint maskOff,
 510                                        jint maskScan,
 511                                        jint width,
 512                                        jint height,
 513                                        jint fgColor,
 514                                        SurfaceDataRasInfo *pRasInfo,
 515                                        NativePrimitive *pPrim,
 516                                        CompositeInfo *pCompInfo)
 517 {
 518     mlib_d64 buff[BUFF_SIZE/2];
 519     void     *pbuff = buff;
 520     mlib_s32 cnstA, cnstR, cnstG, cnstB;
 521     mlib_s32 rasScan = pRasInfo->scanStride;
 522     mlib_f32 cnstARGB0;
 523     mlib_d64 fgARGB;
 524     mlib_u8  *mul8_cnstA;
 525     mlib_s32 j;
 526 
 527     cnstA = (fgColor >> 24) & 0xff;
 528     cnstR = (fgColor >> 16) & 0xff;
 529     cnstG = (fgColor >>  8) & 0xff;
 530     cnstB = (fgColor      ) & 0xff;
 531 
 532     if (cnstA == 0) {
 533         fgColor = 0;
 534     }
 535 
 536     if (pMask == NULL) {
 537         void *pBase = pRasInfo->rasBase;
 538         pRasInfo->rasBase = rasBase;
 539         ADD_SUFF(Any3ByteSetRect)(pRasInfo,
 540                                   0, 0, width, height,
 541                                   fgColor, pPrim, pCompInfo);
 542         pRasInfo->rasBase = pBase;
 543         return;
 544     }
 545 
 546     mul8_cnstA = mul8table[cnstA];
 547     if (cnstA != 0xff) {
 548         cnstR = mul8_cnstA[cnstR];
 549         cnstG = mul8_cnstA[cnstG];
 550         cnstB = mul8_cnstA[cnstB];
 551     }
 552 
 553     cnstARGB0 = F32_FROM_U8x4(cnstA, cnstR, cnstG, cnstB);
 554 
 555     fgARGB = vis_to_double_dup(fgColor);
 556 
 557     pMask += maskOff;
 558 
 559     if (width > BUFF_SIZE) pbuff = mlib_malloc(width*sizeof(mlib_s32));
 560 
 561     vis_write_gsr(7 << 3);
 562 
 563     for (j = 0; j < height; j++) {
 564         ADD_SUFF(ThreeByteBgrToIntArgbConvert)(rasBase, pbuff, width, 1,
 565                                                pRasInfo, pRasInfo,
 566                                                pPrim, pCompInfo);
 567 
 568         IntRgbSrcMaskFill_line(pbuff, pMask, width, fgARGB, cnstARGB0,
 569                                mul8_cnstA, (void*)mul8table);
 570 
 571         IntArgbToThreeByteBgrConvert(pbuff, rasBase, width, 1,
 572                                      pRasInfo, pRasInfo, pPrim, pCompInfo);
 573 
 574         PTR_ADD(rasBase, rasScan);
 575         PTR_ADD(pMask, maskScan);
 576     }
 577 
 578     if (pbuff != buff) {
 579         mlib_free(pbuff);
 580     }
 581 }
 582 
 583 /***************************************************************/
 584 
 585 #endif