1/*
2 * Copyright (c) 2003, 2010, 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
53static 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
125void 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
193void 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
308static 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
371void 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
437void 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
507void 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
586