1 /* sampler template functions */
2
3 #ifndef NO_MEMCPY
4 /*
5 * Unstretched blit of a bgrx texture.
6 */
7 static const uint32_t *
CONCAT2(fetch_memcpy_,FETCH_TYPE)8 CONCAT2(fetch_memcpy_, FETCH_TYPE)(struct lp_linear_elem *elem)
9 {
10 struct lp_linear_sampler *samp = (struct lp_linear_sampler *)elem;
11 const struct lp_jit_texture *texture = samp->texture;
12 const uint32_t *src_row =
13 (const uint32_t *)((const uint8_t *)texture->base +
14 (samp->t >> FIXED16_SHIFT) * texture->row_stride[0]);
15 const int s = samp->s;
16 const int width = samp->width;
17 uint32_t *row = samp->row;
18
19 src_row = &src_row[s >> FIXED16_SHIFT];
20
21 for (int i = 0; i < width; i++) {
22 row[i] = OP(src_row[i]);
23 }
24
25 samp->t += samp->dtdy;
26 return row;
27 }
28 #endif
29
30 /*
31 * Perform nearest filtered lookup of a row of texels. Texture lookup
32 * is assumed to be axis aligned but with arbitrary scaling.
33 *
34 * Texture coordinate interpolation is performed in 16.16 fixed point,
35 * not to be confused with the 1.15 format used by the interpolants.
36 *
37 * After 64 pixels (ie. in the next tile), the starting point will be
38 * recalculated with floating point arithmetic.
39 */
40 static const uint32_t *
CONCAT2(fetch_axis_aligned_,FETCH_TYPE)41 CONCAT2(fetch_axis_aligned_, FETCH_TYPE)(struct lp_linear_elem *elem)
42 {
43 struct lp_linear_sampler *samp = (struct lp_linear_sampler *)elem;
44 const struct lp_jit_texture *texture = samp->texture;
45 const uint32_t *src_row =
46 (const uint32_t *)((const uint8_t *)texture->base +
47 (samp->t >> FIXED16_SHIFT) * texture->row_stride[0]);
48 const int dsdx = samp->dsdx;
49 const int width = samp->width;
50 uint32_t *row = samp->row;
51 int s = samp->s;
52
53 for (int i = 0; i < width; i++) {
54 row[i] = OP(src_row[s>>FIXED16_SHIFT]);
55 s += dsdx;
56 }
57
58 samp->t += samp->dtdy;
59 return row;
60 }
61
62 /* Non-axis aligned, but no clamping or wrapping required
63 */
64 static const uint32_t *
CONCAT2(fetch_,FETCH_TYPE)65 CONCAT2(fetch_, FETCH_TYPE)(struct lp_linear_elem *elem)
66 {
67 struct lp_linear_sampler *samp = (struct lp_linear_sampler *)elem;
68 const struct lp_jit_texture *texture = samp->texture;
69 const uint8_t *src = texture->base;
70 const int stride = texture->row_stride[0];
71 const int dsdx = samp->dsdx;
72 const int dtdx = samp->dtdx;
73 const int width = samp->width;
74 uint32_t *row = samp->row;
75 int s = samp->s;
76 int t = samp->t;
77
78 for (int i = 0; i < width; i++) {
79 const uint8_t *texel = (src +
80 (t>>FIXED16_SHIFT) * stride +
81 (s>>FIXED16_SHIFT) * 4);
82
83 row[i] = OP(*(const uint32_t *)texel);
84
85 s += dsdx;
86 t += dtdx;
87 }
88
89 samp->s += samp->dsdy;
90 samp->t += samp->dtdy;
91 return row;
92 }
93
94 /* Non-axis aligned, clamped.
95 */
96 static const uint32_t *
CONCAT2(fetch_clamp_,FETCH_TYPE)97 CONCAT2(fetch_clamp_, FETCH_TYPE)(struct lp_linear_elem *elem)
98 {
99 struct lp_linear_sampler *samp = (struct lp_linear_sampler *)elem;
100 const struct lp_jit_texture *texture = samp->texture;
101 const uint8_t *src = texture->base;
102 const int stride = texture->row_stride[0];
103 const int tex_height = texture->height - 1;
104 const int tex_width = texture->width - 1;
105 const int dsdx = samp->dsdx;
106 const int dtdx = samp->dtdx;
107 const int width = samp->width;
108 uint32_t *row = samp->row;
109 int s = samp->s;
110 int t = samp->t;
111
112 for (int i = 0; i < width; i++) {
113 int ct = CLAMP(t>>FIXED16_SHIFT, 0, tex_height);
114 int cs = CLAMP(s>>FIXED16_SHIFT, 0, tex_width);
115
116 const uint8_t *texel = src + ct * stride + cs * 4;
117
118 row[i] = OP(*(const uint32_t *)texel);
119
120 s += dsdx;
121 t += dtdx;
122 }
123
124 samp->s += samp->dsdy;
125 samp->t += samp->dtdy;
126 return row;
127 }
128
129 #ifdef OP128
130 static const uint32_t *
CONCAT2(fetch_axis_aligned_linear_,FETCH_TYPE)131 CONCAT2(fetch_axis_aligned_linear_, FETCH_TYPE)(struct lp_linear_elem *elem)
132 {
133 struct lp_linear_sampler *samp = (struct lp_linear_sampler *)elem;
134
135 uint32_t *dst_row = samp->row;
136 const uint32_t *src_row = fetch_axis_aligned_linear_bgra(&samp->base);
137 const int width = samp->width;
138
139 for (int i = 0; i < width; i += 4) {
140 __m128i bgra = *(__m128i *)&src_row[i];
141 __m128i rgba = OP128(bgra);
142 *(__m128i *)&dst_row[i] = rgba;
143 }
144
145 return dst_row;
146 }
147
148 static const uint32_t *
CONCAT2(fetch_clamp_linear_,FETCH_TYPE)149 CONCAT2(fetch_clamp_linear_, FETCH_TYPE)(struct lp_linear_elem *elem)
150 {
151 struct lp_linear_sampler *samp = (struct lp_linear_sampler *)elem;
152 uint32_t *row = samp->row;
153 const int width = samp->width;
154
155 fetch_clamp_linear_bgra(&samp->base);
156
157 for (int i = 0; i < width; i += 4) {
158 __m128i bgra = *(__m128i *)&row[i];
159 __m128i rgba = OP128(bgra);
160 *(__m128i *)&row[i] = rgba;
161 }
162
163 return row;
164 }
165
166 static const uint32_t *
CONCAT2(fetch_linear_,FETCH_TYPE)167 CONCAT2(fetch_linear_, FETCH_TYPE)(struct lp_linear_elem *elem)
168 {
169 struct lp_linear_sampler *samp = (struct lp_linear_sampler *)elem;
170 uint32_t *row = samp->row;
171 const int width = samp->width;
172
173 fetch_linear_bgra(&samp->base);
174
175 for (int i = 0; i < width; i += 4) {
176 __m128i bgra = *(__m128i *)&row[i];
177 __m128i rgba = OP128(bgra);
178 *(__m128i *)&row[i] = rgba;
179 }
180
181 return row;
182 }
183 #endif
184
185 #undef OP
186 #undef OP128
187 #undef FETCH_TYPE
188 #undef NO_MEMCPY
189