FreeRDP
prim_internal.h
1 /* prim_internal.h
2  * vi:ts=4 sw=4
3  *
4  * (c) Copyright 2012 Hewlett-Packard Development Company, L.P.
5  * Licensed under the Apache License, Version 2.0 (the "License"); you may
6  * not use this file except in compliance with the License. You may obtain
7  * a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
8  * Unless required by applicable law or agreed to in writing, software
9  * distributed under the License is distributed on an "AS IS" BASIS,
10  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
11  * or implied. See the License for the specific language governing
12  * permissions and limitations under the License. Algorithms used by
13  * this code may be covered by patents by HP, Microsoft, or other parties.
14  *
15  */
16 
17 #ifndef FREERDP_LIB_PRIM_INTERNAL_H
18 #define FREERDP_LIB_PRIM_INTERNAL_H
19 
20 #include <winpr/platform.h>
21 #include <freerdp/config.h>
22 
23 #include <freerdp/primitives.h>
24 #include <freerdp/api.h>
25 
26 #include <freerdp/log.h>
27 #define PRIM_TAG FREERDP_TAG("primitives")
28 
29 #ifdef __GNUC__
30 #define PRIM_ALIGN_128 __attribute__((aligned(16)))
31 #else
32 #ifdef _WIN32
33 #define PRIM_ALIGN_128 __declspec(align(16))
34 #endif
35 #endif
36 
37 #if defined(WITH_SSE2)
38 #if defined(_M_IX86) || defined(_M_AMD64) || defined(_M_IA64) || defined(_M_IX86_AMD64)
39 #define SSE2_ENABLED
40 #endif
41 #endif
42 
43 #if defined(WITH_NEON)
44 #if defined(_M_ARM64) || defined(_M_ARM)
45 #define NEON_ENABLED
46 #endif
47 #endif
48 
49 #if defined(SSE2_ENABLED) || defined(NEON_ENABLED) || defined(WITH_OPENCL)
50 #define HAVE_OPTIMIZED_PRIMITIVES 1
51 #endif
52 
53 #if defined(SSE2_ENABLED) || defined(NEON_ENABLED)
54 #define HAVE_CPU_OPTIMIZED_PRIMITIVES 1
55 #endif
56 
57 #if defined(SSE2_ENABLED)
58 /* Use lddqu for unaligned; load for 16-byte aligned. */
59 #define LOAD_SI128(_ptr_) \
60  (((const ULONG_PTR)(_ptr_)&0x0f) ? _mm_lddqu_si128((const __m128i*)(_ptr_)) \
61  : _mm_load_si128((const __m128i*)(_ptr_)))
62 #endif
63 
64 static INLINE BYTE* writePixelBGRA(BYTE* dst, DWORD formatSize, UINT32 format, BYTE R, BYTE G,
65  BYTE B, BYTE A)
66 {
67  WINPR_UNUSED(formatSize);
68  WINPR_UNUSED(format);
69 
70  *dst++ = B;
71  *dst++ = G;
72  *dst++ = R;
73  *dst++ = A;
74  return dst;
75 }
76 
77 static INLINE BYTE* writePixelBGRX(BYTE* dst, DWORD formatSize, UINT32 format, BYTE R, BYTE G,
78  BYTE B, BYTE A)
79 {
80  WINPR_UNUSED(formatSize);
81  WINPR_UNUSED(format);
82  WINPR_UNUSED(A);
83 
84  *dst++ = B;
85  *dst++ = G;
86  *dst++ = R;
87  dst++; /* Do not touch alpha */
88 
89  return dst;
90 }
91 
92 static INLINE BYTE* writePixelRGBA(BYTE* dst, DWORD formatSize, UINT32 format, BYTE R, BYTE G,
93  BYTE B, BYTE A)
94 {
95  WINPR_UNUSED(formatSize);
96  WINPR_UNUSED(format);
97 
98  *dst++ = R;
99  *dst++ = G;
100  *dst++ = B;
101  *dst++ = A;
102  return dst;
103 }
104 
105 static INLINE BYTE* writePixelRGBX(BYTE* dst, DWORD formatSize, UINT32 format, BYTE R, BYTE G,
106  BYTE B, BYTE A)
107 {
108  WINPR_UNUSED(formatSize);
109  WINPR_UNUSED(format);
110  WINPR_UNUSED(A);
111 
112  *dst++ = R;
113  *dst++ = G;
114  *dst++ = B;
115  dst++; /* Do not touch alpha */
116 
117  return dst;
118 }
119 
120 static INLINE BYTE* writePixelABGR(BYTE* dst, DWORD formatSize, UINT32 format, BYTE R, BYTE G,
121  BYTE B, BYTE A)
122 {
123  WINPR_UNUSED(formatSize);
124  WINPR_UNUSED(format);
125 
126  *dst++ = A;
127  *dst++ = B;
128  *dst++ = G;
129  *dst++ = R;
130  return dst;
131 }
132 
133 static INLINE BYTE* writePixelXBGR(BYTE* dst, DWORD formatSize, UINT32 format, BYTE R, BYTE G,
134  BYTE B, BYTE A)
135 {
136  WINPR_UNUSED(formatSize);
137  WINPR_UNUSED(format);
138  WINPR_UNUSED(A);
139 
140  dst++; /* Do not touch alpha */
141  *dst++ = B;
142  *dst++ = G;
143  *dst++ = R;
144  return dst;
145 }
146 
147 static INLINE BYTE* writePixelARGB(BYTE* dst, DWORD formatSize, UINT32 format, BYTE R, BYTE G,
148  BYTE B, BYTE A)
149 {
150  WINPR_UNUSED(formatSize);
151  WINPR_UNUSED(format);
152 
153  *dst++ = A;
154  *dst++ = R;
155  *dst++ = G;
156  *dst++ = B;
157  return dst;
158 }
159 
160 static INLINE BYTE* writePixelXRGB(BYTE* dst, DWORD formatSize, UINT32 format, BYTE R, BYTE G,
161  BYTE B, BYTE A)
162 {
163  WINPR_UNUSED(formatSize);
164  WINPR_UNUSED(format);
165  WINPR_UNUSED(A);
166 
167  dst++; /* Do not touch alpha */
168  *dst++ = R;
169  *dst++ = G;
170  *dst++ = B;
171  return dst;
172 }
173 
174 static INLINE BYTE* writePixelGenericAlpha(BYTE* dst, DWORD formatSize, UINT32 format, BYTE R,
175  BYTE G, BYTE B, BYTE A)
176 {
177  UINT32 color = FreeRDPGetColor(format, R, G, B, A);
178  FreeRDPWriteColor(dst, format, color);
179  return dst + formatSize;
180 }
181 
182 static INLINE BYTE* writePixelGeneric(BYTE* dst, DWORD formatSize, UINT32 format, BYTE R, BYTE G,
183  BYTE B, BYTE A)
184 {
185  UINT32 color = FreeRDPGetColor(format, R, G, B, A);
186  FreeRDPWriteColorIgnoreAlpha(dst, format, color);
187  return dst + formatSize;
188 }
189 
190 typedef BYTE* (*fkt_writePixel)(BYTE*, DWORD, UINT32, BYTE, BYTE, BYTE, BYTE);
191 
192 static INLINE fkt_writePixel getPixelWriteFunction(DWORD format, BOOL useAlpha)
193 {
194  switch (format)
195  {
196  case PIXEL_FORMAT_ARGB32:
197  case PIXEL_FORMAT_XRGB32:
198  return useAlpha ? writePixelARGB : writePixelXRGB;
199 
200  case PIXEL_FORMAT_ABGR32:
201  case PIXEL_FORMAT_XBGR32:
202  return useAlpha ? writePixelABGR : writePixelXBGR;
203 
204  case PIXEL_FORMAT_RGBA32:
205  case PIXEL_FORMAT_RGBX32:
206  return useAlpha ? writePixelRGBA : writePixelRGBX;
207 
208  case PIXEL_FORMAT_BGRA32:
209  case PIXEL_FORMAT_BGRX32:
210  return useAlpha ? writePixelBGRA : writePixelBGRX;
211 
212  default:
213  return useAlpha ? writePixelGenericAlpha : writePixelGeneric;
214  }
215 }
216 
217 static INLINE BYTE CLIP(INT64 X)
218 {
219  if (X > 255L)
220  return 255L;
221 
222  if (X < 0L)
223  return 0L;
224 
225  return (BYTE)X;
226 }
227 
228 static INLINE BYTE CONDITIONAL_CLIP(INT32 in, BYTE original)
229 {
230  BYTE out = CLIP(in);
231  BYTE diff = 0;
232  if (out > original)
233  diff = out - original;
234  else
235  diff = original - out;
236  if (diff < 30)
237  return original;
238  return out;
239 }
240 
246 static INLINE INT32 C(INT32 Y)
247 {
248  return (Y)-0L;
249 }
250 
251 static INLINE INT32 D(INT32 U)
252 {
253  return (U)-128L;
254 }
255 
256 static INLINE INT32 E(INT32 V)
257 {
258  return (V)-128L;
259 }
260 
261 static INLINE BYTE YUV2R(INT32 Y, INT32 U, INT32 V)
262 {
263  const INT32 r = (256L * C(Y) + 0L * D(U) + 403L * E(V));
264  const INT32 r8 = r >> 8L;
265  return CLIP(r8);
266 }
267 
268 static INLINE BYTE YUV2G(INT32 Y, INT32 U, INT32 V)
269 {
270  const INT32 g = (256L * C(Y) - 48L * D(U) - 120L * E(V));
271  const INT32 g8 = g >> 8L;
272  return CLIP(g8);
273 }
274 
275 static INLINE BYTE YUV2B(INT32 Y, INT32 U, INT32 V)
276 {
277  const INT32 b = (256L * C(Y) + 475L * D(U) + 0L * E(V));
278  const INT32 b8 = b >> 8L;
279  return CLIP(b8);
280 }
281 
282 /* Function prototypes for all the init/deinit routines. */
283 FREERDP_LOCAL void primitives_init_copy(primitives_t* WINPR_RESTRICT prims);
284 FREERDP_LOCAL void primitives_init_set(primitives_t* WINPR_RESTRICT prims);
285 FREERDP_LOCAL void primitives_init_add(primitives_t* WINPR_RESTRICT prims);
286 FREERDP_LOCAL void primitives_init_andor(primitives_t* WINPR_RESTRICT prims);
287 FREERDP_LOCAL void primitives_init_shift(primitives_t* WINPR_RESTRICT prims);
288 FREERDP_LOCAL void primitives_init_sign(primitives_t* WINPR_RESTRICT prims);
289 FREERDP_LOCAL void primitives_init_alphaComp(primitives_t* WINPR_RESTRICT prims);
290 FREERDP_LOCAL void primitives_init_colors(primitives_t* WINPR_RESTRICT prims);
291 FREERDP_LOCAL void primitives_init_YCoCg(primitives_t* WINPR_RESTRICT prims);
292 FREERDP_LOCAL void primitives_init_YUV(primitives_t* WINPR_RESTRICT prims);
293 
294 FREERDP_LOCAL void primitives_init_copy_opt(primitives_t* WINPR_RESTRICT prims);
295 FREERDP_LOCAL void primitives_init_set_opt(primitives_t* WINPR_RESTRICT prims);
296 FREERDP_LOCAL void primitives_init_add_opt(primitives_t* WINPR_RESTRICT prims);
297 FREERDP_LOCAL void primitives_init_andor_opt(primitives_t* WINPR_RESTRICT prims);
298 FREERDP_LOCAL void primitives_init_shift_opt(primitives_t* WINPR_RESTRICT prims);
299 FREERDP_LOCAL void primitives_init_sign_opt(primitives_t* WINPR_RESTRICT prims);
300 FREERDP_LOCAL void primitives_init_alphaComp_opt(primitives_t* WINPR_RESTRICT prims);
301 FREERDP_LOCAL void primitives_init_colors_opt(primitives_t* WINPR_RESTRICT prims);
302 FREERDP_LOCAL void primitives_init_YCoCg_opt(primitives_t* WINPR_RESTRICT prims);
303 FREERDP_LOCAL void primitives_init_YUV_opt(primitives_t* WINPR_RESTRICT prims);
304 
305 #if defined(WITH_OPENCL)
306 FREERDP_LOCAL BOOL primitives_init_opencl(primitives_t* WINPR_RESTRICT prims);
307 #endif
308 
309 FREERDP_LOCAL primitives_t* primitives_get_by_type(DWORD type);
310 
311 #endif /* FREERDP_LIB_PRIM_INTERNAL_H */