1 /*
2   This module contains some helper functions for the blitter modules.
3 
4   Copyright: Chris Jones
5   License: Boost Software License, Version 1.0
6   Authors: Chris Jones
7 */
8 
9 module dg2d.blitex;
10 
11 import dg2d.misc;
12 import dg2d.rasterizer;
13 
14 immutable __m128i XMZERO = 0;
15 immutable __m128i XMFFFF = 0xFFFF;
16 immutable __m128i XM7FFF = 0x7FFF;
17 immutable __m128i XMABSMASK = 0x7fffffff;
18 immutable __m128i XMSIGNMASK = 0x80000000;
19 
20 public:
21 
22 /*
23   Calculate the gradient index for given repeat mode
24 */
25 
26 __m128i calcRepeatModeIDX(RepeatMode mode)(__m128i ipos, __m128i lutmsk, __m128i lutmsk2)
27 {
28     static if (mode == RepeatMode.Repeat)
29     {
30         return ipos & lutmsk;
31     }
32     else static if (mode == RepeatMode.Pad)
33     {
34         ipos = ipos & _mm_cmpgt_epi32(ipos, XMZERO);
35         return (ipos | _mm_cmpgt_epi32(ipos, lutmsk)) & lutmsk;
36     }
37     else
38     {
39         return (ipos ^ _mm_cmpgt_epi32(ipos & lutmsk2, lutmsk)) & lutmsk;
40     }
41 }
42 
43 /*
44   calculate coverage from winding value
45 */
46 
47 int calcCoverage(WindingRule rule)(int winding)
48 {
49     static if (rule == WindingRule.NonZero)
50     {
51         int tmp = abs(winding)*2;
52         return (tmp > 0xFFFF) ? 0xFFFF : tmp;
53     }
54     else
55     {
56         short tmp = cast(short) winding;
57         return (tmp ^ (tmp >> 15)) * 2;
58     }
59 }
60 
61 /*
62   calculate coverage from winding value
63   incoming 4x int32
64   outgoing 4x int16, in lower 64 bits of return val
65 */
66 
67 __m128i calcCoverage16(WindingRule rule)(__m128i winding)
68 {
69     static if (rule == WindingRule.NonZero)
70     {
71         __m128i absmask = _mm_srai_epi32(winding,31); 
72         __m128i tmp = _mm_xor_si128(winding,absmask); // abs technically off by one, but irrelevant
73         tmp = _mm_packs_epi32(tmp,tmp);               // saturate/pack to int16
74         return _mm_slli_epi16(tmp, 1);                // << to uint16
75     }
76     else
77     {
78         winding = _mm_and_si128(winding,XMFFFF);
79         __m128i mask = _mm_srai_epi16(winding,15);
80         __m128i tmp = _mm_xor_si128(winding,mask);  // if bit 31 set, we xor all other bits
81         tmp = _mm_packs_epi32(tmp,tmp);             // saturate/pack to int16
82         return _mm_slli_epi16(tmp, 1);              // << to uint16
83     } 
84 }
85 
86 /*
87   calculate coverage from winding value
88   incoming 4x int32
89   outgoing 4x int32, coverage is returned in high 16 bits of each 32 bits, 
90 */
91 
92 __m128i calcCoverage32(WindingRule rule)(__m128i winding)
93 {
94     static if (rule == WindingRule.NonZero)
95     {
96         __m128i absmsk = _mm_srai_epi32(winding,31);
97         __m128i tmp = _mm_xor_si128(winding,absmsk); // abs technically off by one, but irrelevant
98         tmp = _mm_packs_epi32(tmp,tmp);              // saturate/pack to int16
99         tmp = _mm_unpacklo_epi16(tmp,tmp);   
100         return _mm_slli_epi16(tmp,1);                // << to top 16 bits of each 32 bit word
101         
102     }
103     else
104     {
105         __m128i mask = _mm_srai_epi16(winding,15);
106         __m128i tmp = _mm_xor_si128(winding,mask);  // if bit 16 set, we xor all other bits
107         return _mm_slli_epi32(tmp, 17);             // << to top 16 bits of each 32 bit word
108     }
109 }
110 
111 
112 /* NEW BLEND DEV WORK
113 
114   put Color0 and Color1, in low 64 bits of R128
115   then unpack low interleaved with itself,
116   so each byte becomes 16 bits => (b << 8) | b 
117   this is the same as multiplying by 257, essentialy converts 0..FF, into 0..FFFF
118 
119   c = _mm_unpacklo_epi8 (c,c);
120 
121   then for alpha...
122 
123   alpha = _mm_shufflelo_epi16!255(c);
124   alpha = _mm_shufflehi_epi16!255(alpha);
125 
126   that gives
127 
128   c = [BB0,GG0,RR0,AA0,BB1,GG1,RR1,AA1]
129   alpha = [AA0,AA0,AA0,AA0,AA1,AA1,AA1,AA1]
130 
131 */
132