20 #include <winpr/assert.h>
21 #include <winpr/cast.h>
22 #include <winpr/platform.h>
23 #include <freerdp/config.h>
25 #include "../nsc_types.h"
28 #include "../../core/simd.h"
30 #if defined(SSE_AVX_INTRINSICS_ENABLED)
35 #include <xmmintrin.h>
36 #include <emmintrin.h>
38 #include <freerdp/codec/color.h>
39 #include <winpr/crt.h>
40 #include <winpr/sysinfo.h>
42 static BOOL nsc_encode_argb_to_aycocg_sse2(NSC_CONTEXT* context,
const BYTE* data, UINT32 scanline)
46 if (!context || !data || (scanline == 0))
49 const UINT16 tempWidth = ROUND_UP_TO(context->width, 8);
50 const UINT16 rw = (context->ChromaSubsamplingLevel > 0 ? tempWidth : context->width);
52 const BYTE ccl = WINPR_ASSERTING_INT_CAST(BYTE, context->ColorLossLevel);
54 for (; y < context->height; y++)
56 const BYTE* src = data + (context->height - 1 - y) * scanline;
57 BYTE* yplane = context->priv->PlaneBuffers[0] + y * rw;
58 BYTE* coplane = context->priv->PlaneBuffers[1] + y * rw;
59 BYTE* cgplane = context->priv->PlaneBuffers[2] + y * rw;
60 BYTE* aplane = context->priv->PlaneBuffers[3] + y * context->width;
62 for (UINT16 x = 0; x < context->width; x += 8)
64 __m128i r_val = { 0 };
65 __m128i g_val = { 0 };
66 __m128i b_val = { 0 };
67 __m128i a_val = { 0 };
69 switch (context->format)
71 case PIXEL_FORMAT_BGRX32:
72 b_val = _mm_set_epi16(*(src + 28), *(src + 24), *(src + 20), *(src + 16),
73 *(src + 12), *(src + 8), *(src + 4), *src);
74 g_val = _mm_set_epi16(*(src + 29), *(src + 25), *(src + 21), *(src + 17),
75 *(src + 13), *(src + 9), *(src + 5), *(src + 1));
76 r_val = _mm_set_epi16(*(src + 30), *(src + 26), *(src + 22), *(src + 18),
77 *(src + 14), *(src + 10), *(src + 6), *(src + 2));
78 a_val = _mm_set1_epi16(0xFF);
82 case PIXEL_FORMAT_BGRA32:
83 b_val = _mm_set_epi16(*(src + 28), *(src + 24), *(src + 20), *(src + 16),
84 *(src + 12), *(src + 8), *(src + 4), *src);
85 g_val = _mm_set_epi16(*(src + 29), *(src + 25), *(src + 21), *(src + 17),
86 *(src + 13), *(src + 9), *(src + 5), *(src + 1));
87 r_val = _mm_set_epi16(*(src + 30), *(src + 26), *(src + 22), *(src + 18),
88 *(src + 14), *(src + 10), *(src + 6), *(src + 2));
89 a_val = _mm_set_epi16(*(src + 31), *(src + 27), *(src + 23), *(src + 19),
90 *(src + 15), *(src + 11), *(src + 7), *(src + 3));
94 case PIXEL_FORMAT_RGBX32:
95 r_val = _mm_set_epi16(*(src + 28), *(src + 24), *(src + 20), *(src + 16),
96 *(src + 12), *(src + 8), *(src + 4), *src);
97 g_val = _mm_set_epi16(*(src + 29), *(src + 25), *(src + 21), *(src + 17),
98 *(src + 13), *(src + 9), *(src + 5), *(src + 1));
99 b_val = _mm_set_epi16(*(src + 30), *(src + 26), *(src + 22), *(src + 18),
100 *(src + 14), *(src + 10), *(src + 6), *(src + 2));
101 a_val = _mm_set1_epi16(0xFF);
105 case PIXEL_FORMAT_RGBA32:
106 r_val = _mm_set_epi16(*(src + 28), *(src + 24), *(src + 20), *(src + 16),
107 *(src + 12), *(src + 8), *(src + 4), *src);
108 g_val = _mm_set_epi16(*(src + 29), *(src + 25), *(src + 21), *(src + 17),
109 *(src + 13), *(src + 9), *(src + 5), *(src + 1));
110 b_val = _mm_set_epi16(*(src + 30), *(src + 26), *(src + 22), *(src + 18),
111 *(src + 14), *(src + 10), *(src + 6), *(src + 2));
112 a_val = _mm_set_epi16(*(src + 31), *(src + 27), *(src + 23), *(src + 19),
113 *(src + 15), *(src + 11), *(src + 7), *(src + 3));
117 case PIXEL_FORMAT_BGR24:
118 b_val = _mm_set_epi16(*(src + 21), *(src + 18), *(src + 15), *(src + 12),
119 *(src + 9), *(src + 6), *(src + 3), *src);
120 g_val = _mm_set_epi16(*(src + 22), *(src + 19), *(src + 16), *(src + 13),
121 *(src + 10), *(src + 7), *(src + 4), *(src + 1));
122 r_val = _mm_set_epi16(*(src + 23), *(src + 20), *(src + 17), *(src + 14),
123 *(src + 11), *(src + 8), *(src + 5), *(src + 2));
124 a_val = _mm_set1_epi16(0xFF);
128 case PIXEL_FORMAT_RGB24:
129 r_val = _mm_set_epi16(*(src + 21), *(src + 18), *(src + 15), *(src + 12),
130 *(src + 9), *(src + 6), *(src + 3), *src);
131 g_val = _mm_set_epi16(*(src + 22), *(src + 19), *(src + 16), *(src + 13),
132 *(src + 10), *(src + 7), *(src + 4), *(src + 1));
133 b_val = _mm_set_epi16(*(src + 23), *(src + 20), *(src + 17), *(src + 14),
134 *(src + 11), *(src + 8), *(src + 5), *(src + 2));
135 a_val = _mm_set1_epi16(0xFF);
138 case PIXEL_FORMAT_BGR16:
139 b_val = _mm_set_epi16(WINPR_ASSERTING_INT_CAST(INT16, ((*(src + 15)) & 0xF8) |
140 ((*(src + 15)) >> 5)),
141 WINPR_ASSERTING_INT_CAST(INT16, ((*(src + 13)) & 0xF8) |
142 ((*(src + 13)) >> 5)),
143 WINPR_ASSERTING_INT_CAST(INT16, ((*(src + 11)) & 0xF8) |
144 ((*(src + 11)) >> 5)),
145 WINPR_ASSERTING_INT_CAST(INT16, ((*(src + 9)) & 0xF8) |
146 ((*(src + 9)) >> 5)),
147 WINPR_ASSERTING_INT_CAST(INT16, ((*(src + 7)) & 0xF8) |
148 ((*(src + 7)) >> 5)),
149 WINPR_ASSERTING_INT_CAST(INT16, ((*(src + 5)) & 0xF8) |
150 ((*(src + 5)) >> 5)),
151 WINPR_ASSERTING_INT_CAST(INT16, ((*(src + 3)) & 0xF8) |
152 ((*(src + 3)) >> 5)),
153 WINPR_ASSERTING_INT_CAST(INT16, ((*(src + 1)) & 0xF8) |
154 ((*(src + 1)) >> 5)));
155 g_val = _mm_set_epi16(
156 WINPR_ASSERTING_INT_CAST(INT16, (((*(src + 15)) & 0x07) << 5) |
157 (((*(src + 14)) & 0xE0) >> 3)),
158 WINPR_ASSERTING_INT_CAST(INT16, (((*(src + 13)) & 0x07) << 5) |
159 (((*(src + 12)) & 0xE0) >> 3)),
160 WINPR_ASSERTING_INT_CAST(INT16, (((*(src + 11)) & 0x07) << 5) |
161 (((*(src + 10)) & 0xE0) >> 3)),
162 WINPR_ASSERTING_INT_CAST(INT16, (((*(src + 9)) & 0x07) << 5) |
163 (((*(src + 8)) & 0xE0) >> 3)),
164 WINPR_ASSERTING_INT_CAST(INT16, (((*(src + 7)) & 0x07) << 5) |
165 (((*(src + 6)) & 0xE0) >> 3)),
166 WINPR_ASSERTING_INT_CAST(INT16, (((*(src + 5)) & 0x07) << 5) |
167 (((*(src + 4)) & 0xE0) >> 3)),
168 WINPR_ASSERTING_INT_CAST(INT16, (((*(src + 3)) & 0x07) << 5) |
169 (((*(src + 2)) & 0xE0) >> 3)),
170 WINPR_ASSERTING_INT_CAST(INT16, (((*(src + 1)) & 0x07) << 5) |
171 (((*src) & 0xE0) >> 3)));
172 r_val = _mm_set_epi16(
173 WINPR_ASSERTING_INT_CAST(INT16, (((*(src + 14)) & 0x1F) << 3) |
174 (((*(src + 14)) >> 2) & 0x07)),
175 WINPR_ASSERTING_INT_CAST(INT16, (((*(src + 12)) & 0x1F) << 3) |
176 (((*(src + 12)) >> 2) & 0x07)),
177 WINPR_ASSERTING_INT_CAST(INT16, (((*(src + 10)) & 0x1F) << 3) |
178 (((*(src + 10)) >> 2) & 0x07)),
179 WINPR_ASSERTING_INT_CAST(INT16, (((*(src + 8)) & 0x1F) << 3) |
180 (((*(src + 8)) >> 2) & 0x07)),
181 WINPR_ASSERTING_INT_CAST(INT16, (((*(src + 6)) & 0x1F) << 3) |
182 (((*(src + 6)) >> 2) & 0x07)),
183 WINPR_ASSERTING_INT_CAST(INT16, (((*(src + 4)) & 0x1F) << 3) |
184 (((*(src + 4)) >> 2) & 0x07)),
185 WINPR_ASSERTING_INT_CAST(INT16, (((*(src + 2)) & 0x1F) << 3) |
186 (((*(src + 2)) >> 2) & 0x07)),
187 WINPR_ASSERTING_INT_CAST(INT16,
188 (((*src) & 0x1F) << 3) | (((*src) >> 2) & 0x07)));
189 a_val = _mm_set1_epi16(0xFF);
193 case PIXEL_FORMAT_RGB16:
194 r_val = _mm_set_epi16(
195 WINPR_ASSERTING_INT_CAST(INT16, ((src[15] & 0xF8) | (src[15] >> 5))),
196 WINPR_ASSERTING_INT_CAST(INT16, ((src[13] & 0xF8) | (src[13] >> 5))),
197 WINPR_ASSERTING_INT_CAST(INT16, ((src[11] & 0xF8) | (src[11] >> 5))),
198 WINPR_ASSERTING_INT_CAST(INT16, ((src[9] & 0xF8) | (src[9] >> 5))),
199 WINPR_ASSERTING_INT_CAST(INT16, ((src[7] & 0xF8) | (src[7] >> 5))),
200 WINPR_ASSERTING_INT_CAST(INT16, ((src[5] & 0xF8) | (src[5] >> 5))),
201 WINPR_ASSERTING_INT_CAST(INT16, ((src[3] & 0xF8) | (src[3] >> 5))),
202 WINPR_ASSERTING_INT_CAST(INT16, ((src[1] & 0xF8) | (src[1] >> 5))));
203 g_val = _mm_set_epi16(
204 WINPR_ASSERTING_INT_CAST(INT16, (((*(src + 15)) & 0x07) << 5) |
205 (((*(src + 14)) & 0xE0) >> 3)),
206 WINPR_ASSERTING_INT_CAST(INT16, (((*(src + 13)) & 0x07) << 5) |
207 (((*(src + 12)) & 0xE0) >> 3)),
208 WINPR_ASSERTING_INT_CAST(INT16, (((*(src + 11)) & 0x07) << 5) |
209 (((*(src + 10)) & 0xE0) >> 3)),
210 WINPR_ASSERTING_INT_CAST(INT16, (((*(src + 9)) & 0x07) << 5) |
211 (((*(src + 8)) & 0xE0) >> 3)),
212 WINPR_ASSERTING_INT_CAST(INT16, (((*(src + 7)) & 0x07) << 5) |
213 (((*(src + 6)) & 0xE0) >> 3)),
214 WINPR_ASSERTING_INT_CAST(INT16, (((*(src + 5)) & 0x07) << 5) |
215 (((*(src + 4)) & 0xE0) >> 3)),
216 WINPR_ASSERTING_INT_CAST(INT16, (((*(src + 3)) & 0x07) << 5) |
217 (((*(src + 2)) & 0xE0) >> 3)),
218 WINPR_ASSERTING_INT_CAST(INT16, (((*(src + 1)) & 0x07) << 5) |
219 (((*src) & 0xE0) >> 3)));
220 b_val = _mm_set_epi16(
221 WINPR_ASSERTING_INT_CAST(INT16, (((*(src + 14)) & 0x1F) << 3) |
222 (((*(src + 14)) >> 2) & 0x07)),
223 WINPR_ASSERTING_INT_CAST(INT16, (((*(src + 12)) & 0x1F) << 3) |
224 (((*(src + 12)) >> 2) & 0x07)),
225 WINPR_ASSERTING_INT_CAST(INT16, (((*(src + 10)) & 0x1F) << 3) |
226 (((*(src + 10)) >> 2) & 0x07)),
227 WINPR_ASSERTING_INT_CAST(INT16, (((*(src + 8)) & 0x1F) << 3) |
228 (((*(src + 8)) >> 2) & 0x07)),
229 WINPR_ASSERTING_INT_CAST(INT16, (((*(src + 6)) & 0x1F) << 3) |
230 (((*(src + 6)) >> 2) & 0x07)),
231 WINPR_ASSERTING_INT_CAST(INT16, (((*(src + 4)) & 0x1F) << 3) |
232 (((*(src + 4)) >> 2) & 0x07)),
233 WINPR_ASSERTING_INT_CAST(INT16, (((*(src + 2)) & 0x1F) << 3) |
234 (((*(src + 2)) >> 2) & 0x07)),
235 WINPR_ASSERTING_INT_CAST(INT16,
236 (((*src) & 0x1F) << 3) | (((*src) >> 2) & 0x07)));
237 a_val = _mm_set1_epi16(0xFF);
241 case PIXEL_FORMAT_A4:
245 for (
int shift = 7; shift >= 0; shift--)
247 idx[shift] = ((*src) >> shift) & 1;
248 idx[shift] |= (((*(src + 1)) >> shift) & 1) << 1;
249 idx[shift] |= (((*(src + 2)) >> shift) & 1) << 2;
250 idx[shift] |= (((*(src + 3)) >> shift) & 1) << 3;
254 r_val = _mm_set_epi16(context->palette[idx[0]], context->palette[idx[1]],
255 context->palette[idx[2]], context->palette[idx[3]],
256 context->palette[idx[4]], context->palette[idx[5]],
257 context->palette[idx[6]], context->palette[idx[7]]);
259 _mm_set_epi16(context->palette[idx[0] + 1], context->palette[idx[1] + 1],
260 context->palette[idx[2] + 1], context->palette[idx[3] + 1],
261 context->palette[idx[4] + 1], context->palette[idx[5] + 1],
262 context->palette[idx[6] + 1], context->palette[idx[7] + 1]);
264 _mm_set_epi16(context->palette[idx[0] + 2], context->palette[idx[1] + 2],
265 context->palette[idx[2] + 2], context->palette[idx[3] + 2],
266 context->palette[idx[4] + 2], context->palette[idx[5] + 2],
267 context->palette[idx[6] + 2], context->palette[idx[7] + 2]);
271 a_val = _mm_set1_epi16(0xFF);
274 case PIXEL_FORMAT_RGB8:
276 r_val = _mm_set_epi16(context->palette[(*(src + 7ULL)) * 3ULL],
277 context->palette[(*(src + 6ULL)) * 3ULL],
278 context->palette[(*(src + 5ULL)) * 3ULL],
279 context->palette[(*(src + 4ULL)) * 3ULL],
280 context->palette[(*(src + 3ULL)) * 3ULL],
281 context->palette[(*(src + 2ULL)) * 3ULL],
282 context->palette[(*(src + 1ULL)) * 3ULL],
283 context->palette[(*src) * 3ULL]);
284 g_val = _mm_set_epi16(context->palette[(*(src + 7ULL)) * 3ULL + 1ULL],
285 context->palette[(*(src + 6ULL)) * 3ULL + 1ULL],
286 context->palette[(*(src + 5ULL)) * 3ULL + 1ULL],
287 context->palette[(*(src + 4ULL)) * 3ULL + 1ULL],
288 context->palette[(*(src + 3ULL)) * 3ULL + 1ULL],
289 context->palette[(*(src + 2ULL)) * 3ULL + 1ULL],
290 context->palette[(*(src + 1ULL)) * 3ULL + 1ULL],
291 context->palette[(*src) * 3ULL + 1ULL]);
292 b_val = _mm_set_epi16(context->palette[(*(src + 7ULL)) * 3ULL + 2ULL],
293 context->palette[(*(src + 6ULL)) * 3ULL + 2ULL],
294 context->palette[(*(src + 5ULL)) * 3ULL + 2ULL],
295 context->palette[(*(src + 4ULL)) * 3ULL + 2ULL],
296 context->palette[(*(src + 3ULL)) * 3ULL + 2ULL],
297 context->palette[(*(src + 2ULL)) * 3ULL + 2ULL],
298 context->palette[(*(src + 1ULL)) * 3ULL + 2ULL],
299 context->palette[(*src) * 3ULL + 2ULL]);
303 a_val = _mm_set1_epi16(0xFF);
307 r_val = g_val = b_val = a_val = _mm_set1_epi16(0);
311 __m128i y_val = _mm_srai_epi16(r_val, 2);
312 y_val = _mm_add_epi16(y_val, _mm_srai_epi16(g_val, 1));
313 y_val = _mm_add_epi16(y_val, _mm_srai_epi16(b_val, 2));
314 __m128i co_val = _mm_sub_epi16(r_val, b_val);
315 co_val = _mm_srai_epi16(co_val, ccl);
316 __m128i cg_val = _mm_sub_epi16(g_val, _mm_srai_epi16(r_val, 1));
317 cg_val = _mm_sub_epi16(cg_val, _mm_srai_epi16(b_val, 1));
318 cg_val = _mm_srai_epi16(cg_val, ccl);
319 y_val = _mm_packus_epi16(y_val, y_val);
320 _mm_storeu_si128((__m128i*)yplane, y_val);
321 co_val = _mm_packs_epi16(co_val, co_val);
322 _mm_storeu_si128((__m128i*)coplane, co_val);
323 cg_val = _mm_packs_epi16(cg_val, cg_val);
324 _mm_storeu_si128((__m128i*)cgplane, cg_val);
325 a_val = _mm_packus_epi16(a_val, a_val);
326 _mm_storeu_si128((__m128i*)aplane, a_val);
333 if (context->ChromaSubsamplingLevel > 0 && (context->width % 2) == 1)
335 context->priv->PlaneBuffers[0][y * rw + context->width] =
336 context->priv->PlaneBuffers[0][y * rw + context->width - 1];
337 context->priv->PlaneBuffers[1][y * rw + context->width] =
338 context->priv->PlaneBuffers[1][y * rw + context->width - 1];
339 context->priv->PlaneBuffers[2][y * rw + context->width] =
340 context->priv->PlaneBuffers[2][y * rw + context->width - 1];
344 if (context->ChromaSubsamplingLevel > 0 && (y % 2) == 1)
346 BYTE* yplane = context->priv->PlaneBuffers[0] + y * rw;
347 BYTE* coplane = context->priv->PlaneBuffers[1] + y * rw;
348 BYTE* cgplane = context->priv->PlaneBuffers[2] + y * rw;
349 CopyMemory(yplane, yplane - rw, rw);
350 CopyMemory(coplane, coplane - rw, rw);
351 CopyMemory(cgplane, cgplane - rw, rw);
357 static void nsc_encode_subsampling_sse2(NSC_CONTEXT* context)
361 INT8* co_src0 = NULL;
362 INT8* co_src1 = NULL;
363 INT8* cg_src0 = NULL;
364 INT8* cg_src1 = NULL;
365 UINT32 tempWidth = 0;
366 UINT32 tempHeight = 0;
369 __m128i mask = _mm_set1_epi16(0xFF);
370 tempWidth = ROUND_UP_TO(context->width, 8);
371 tempHeight = ROUND_UP_TO(context->height, 2);
373 for (
size_t y = 0; y < tempHeight >> 1; y++)
375 co_dst = context->priv->PlaneBuffers[1] + y * (tempWidth >> 1);
376 cg_dst = context->priv->PlaneBuffers[2] + y * (tempWidth >> 1);
377 co_src0 = (INT8*)context->priv->PlaneBuffers[1] + (y << 1) * tempWidth;
378 co_src1 = co_src0 + tempWidth;
379 cg_src0 = (INT8*)context->priv->PlaneBuffers[2] + (y << 1) * tempWidth;
380 cg_src1 = cg_src0 + tempWidth;
382 for (UINT32 x = 0; x < tempWidth >> 1; x += 8)
384 t = _mm_loadu_si128((__m128i*)co_src0);
385 t = _mm_avg_epu8(t, _mm_loadu_si128((__m128i*)co_src1));
386 val = _mm_and_si128(_mm_srli_si128(t, 1), mask);
387 val = _mm_avg_epu16(val, _mm_and_si128(t, mask));
388 val = _mm_packus_epi16(val, val);
389 _mm_storeu_si128((__m128i*)co_dst, val);
393 t = _mm_loadu_si128((__m128i*)cg_src0);
394 t = _mm_avg_epu8(t, _mm_loadu_si128((__m128i*)cg_src1));
395 val = _mm_and_si128(_mm_srli_si128(t, 1), mask);
396 val = _mm_avg_epu16(val, _mm_and_si128(t, mask));
397 val = _mm_packus_epi16(val, val);
398 _mm_storeu_si128((__m128i*)cg_dst, val);
406 static BOOL nsc_encode_sse2(NSC_CONTEXT* context,
const BYTE* data, UINT32 scanline)
408 if (!nsc_encode_argb_to_aycocg_sse2(context, data, scanline))
411 if (context->ChromaSubsamplingLevel > 0)
412 nsc_encode_subsampling_sse2(context);
418 void nsc_init_sse2(NSC_CONTEXT* context)
420 #if defined(SSE_AVX_INTRINSICS_ENABLED)
421 if (!IsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE))
424 PROFILER_RENAME(context->priv->prof_nsc_encode,
"nsc_encode_sse2")
425 context->encode = nsc_encode_sse2;
427 WINPR_UNUSED(context);