16#include <winpr/sysinfo.h>
18#include <freerdp/config.h>
21#include <freerdp/types.h>
22#include <freerdp/primitives.h>
23#include <freerdp/log.h>
25#include "prim_internal.h"
26#include "prim_avxsse.h"
28#include "../codec/color.h"
30#include <freerdp/codec/color.h>
32#if defined(SSE_AVX_INTRINSICS_ENABLED)
36static inline pstatus_t sse_image_copy_bgr24_bgrx32(BYTE* WINPR_RESTRICT pDstData, UINT32 nDstStep,
37 UINT32 nXDst, UINT32 nYDst, UINT32 nWidth,
39 const BYTE* WINPR_RESTRICT pSrcData,
40 UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
41 int64_t srcVMultiplier, int64_t srcVOffset,
42 int64_t dstVMultiplier, int64_t dstVOffset)
45 const int64_t srcByte = 3;
46 const int64_t dstByte = 4;
48 const __m128i mask = mm_set_epu32(0xFF000000, 0xFF000000, 0xFF000000, 0xFF000000);
49 const __m128i smask = mm_set_epu32(0xff0b0a09, 0xff080706, 0xff050403, 0xff020100);
50 const UINT32 rem = nWidth % 4;
52 const int64_t width = nWidth - rem;
53 for (int64_t y = 0; y < nHeight; y++)
55 const BYTE* WINPR_RESTRICT srcLine =
56 &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset];
57 BYTE* WINPR_RESTRICT dstLine =
58 &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset];
62 for (; x < width; x += 4)
65 WINPR_PACKED_ALIGN_CAST(
const __m128i*, &srcLine[(x + nXSrc) * srcByte]);
66 __m128i* dst = WINPR_PACKED_ALIGN_CAST(__m128i*, &dstLine[(x + nXDst) * dstByte]);
67 const __m128i s0 = LOAD_SI128(src);
68 const __m128i s1 = _mm_shuffle_epi8(s0, smask);
69 const __m128i s2 = LOAD_SI128(dst);
71 __m128i d0 = _mm_blendv_epi8(s1, s2, mask);
75 for (; x < nWidth; x++)
77 const BYTE* src = &srcLine[(x + nXSrc) * srcByte];
78 BYTE* dst = &dstLine[(x + nXDst) * dstByte];
85 return PRIMITIVES_SUCCESS;
88static inline pstatus_t sse_image_copy_bgrx32_bgrx32(BYTE* WINPR_RESTRICT pDstData, UINT32 nDstStep,
89 UINT32 nXDst, UINT32 nYDst, UINT32 nWidth,
91 const BYTE* WINPR_RESTRICT pSrcData,
92 UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
93 int64_t srcVMultiplier, int64_t srcVOffset,
94 int64_t dstVMultiplier, int64_t dstVOffset)
97 const int64_t srcByte = 4;
98 const int64_t dstByte = 4;
100 const __m128i mask = _mm_setr_epi8((
char)0xFF, (
char)0xFF, (
char)0xFF, 0x00, (
char)0xFF,
101 (
char)0xFF, (
char)0xFF, 0x00, (
char)0xFF, (
char)0xFF,
102 (
char)0xFF, 0x00, (
char)0xFF, (
char)0xFF, (
char)0xFF, 0x00);
103 const UINT32 rem = nWidth % 4;
104 const int64_t width = nWidth - rem;
105 for (int64_t y = 0; y < nHeight; y++)
107 const BYTE* WINPR_RESTRICT srcLine =
108 &pSrcData[srcVMultiplier * (y + nYSrc) * nSrcStep + srcVOffset];
109 BYTE* WINPR_RESTRICT dstLine =
110 &pDstData[dstVMultiplier * (y + nYDst) * nDstStep + dstVOffset];
113 for (; x < width; x += 4)
116 WINPR_PACKED_ALIGN_CAST(
const __m128i*, &srcLine[(x + nXSrc) * srcByte]);
117 __m128i* dst = WINPR_PACKED_ALIGN_CAST(__m128i*, &dstLine[(x + nXDst) * dstByte]);
118 const __m128i s0 = LOAD_SI128(src);
119 const __m128i s1 = LOAD_SI128(dst);
120 __m128i d0 = _mm_blendv_epi8(s1, s0, mask);
121 STORE_SI128(dst, d0);
124 for (; x < nWidth; x++)
126 const BYTE* src = &srcLine[(x + nXSrc) * srcByte];
127 BYTE* dst = &dstLine[(x + nXDst) * dstByte];
134 return PRIMITIVES_SUCCESS;
137static pstatus_t sse_image_copy_no_overlap_dst_alpha(
138 BYTE* WINPR_RESTRICT pDstData, DWORD DstFormat, UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
139 UINT32 nWidth, UINT32 nHeight,
const BYTE* WINPR_RESTRICT pSrcData, DWORD SrcFormat,
140 UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
const gdiPalette* WINPR_RESTRICT palette,
141 UINT32 flags, int64_t srcVMultiplier, int64_t srcVOffset, int64_t dstVMultiplier,
144 WINPR_ASSERT(pDstData);
145 WINPR_ASSERT(pSrcData);
149 case PIXEL_FORMAT_BGR24:
152 case PIXEL_FORMAT_BGRX32:
153 case PIXEL_FORMAT_BGRA32:
154 return sse_image_copy_bgr24_bgrx32(
155 pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, pSrcData, nSrcStep,
156 nXSrc, nYSrc, srcVMultiplier, srcVOffset, dstVMultiplier, dstVOffset);
161 case PIXEL_FORMAT_BGRX32:
162 case PIXEL_FORMAT_BGRA32:
165 case PIXEL_FORMAT_BGRX32:
166 case PIXEL_FORMAT_BGRA32:
167 return sse_image_copy_bgrx32_bgrx32(
168 pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, pSrcData, nSrcStep,
169 nXSrc, nYSrc, srcVMultiplier, srcVOffset, dstVMultiplier, dstVOffset);
174 case PIXEL_FORMAT_RGBX32:
175 case PIXEL_FORMAT_RGBA32:
178 case PIXEL_FORMAT_RGBX32:
179 case PIXEL_FORMAT_RGBA32:
180 return sse_image_copy_bgrx32_bgrx32(
181 pDstData, nDstStep, nXDst, nYDst, nWidth, nHeight, pSrcData, nSrcStep,
182 nXSrc, nYSrc, srcVMultiplier, srcVOffset, dstVMultiplier, dstVOffset);
192 return gen->
copy_no_overlap(pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight,
193 pSrcData, SrcFormat, nSrcStep, nXSrc, nYSrc, palette, flags);
196static pstatus_t sse_image_copy_no_overlap(BYTE* WINPR_RESTRICT pDstData, DWORD DstFormat,
197 UINT32 nDstStep, UINT32 nXDst, UINT32 nYDst,
198 UINT32 nWidth, UINT32 nHeight,
199 const BYTE* WINPR_RESTRICT pSrcData, DWORD SrcFormat,
200 UINT32 nSrcStep, UINT32 nXSrc, UINT32 nYSrc,
201 const gdiPalette* WINPR_RESTRICT palette, UINT32 flags)
203 const BOOL vSrcVFlip = (flags & FREERDP_FLIP_VERTICAL) != 0;
204 int64_t srcVOffset = 0;
205 int64_t srcVMultiplier = 1;
206 int64_t dstVOffset = 0;
207 int64_t dstVMultiplier = 1;
209 if ((nWidth == 0) || (nHeight == 0))
210 return PRIMITIVES_SUCCESS;
212 if ((nHeight > INT32_MAX) || (nWidth > INT32_MAX))
215 if (!pDstData || !pSrcData)
219 nDstStep = nWidth * FreeRDPGetBytesPerPixel(DstFormat);
222 nSrcStep = nWidth * FreeRDPGetBytesPerPixel(SrcFormat);
226 srcVOffset = (nHeight - 1ll) * nSrcStep;
230 if (((flags & FREERDP_KEEP_DST_ALPHA) != 0) && FreeRDPColorHasAlpha(DstFormat))
231 return sse_image_copy_no_overlap_dst_alpha(pDstData, DstFormat, nDstStep, nXDst, nYDst,
232 nWidth, nHeight, pSrcData, SrcFormat, nSrcStep,
233 nXSrc, nYSrc, palette, flags, srcVMultiplier,
234 srcVOffset, dstVMultiplier, dstVOffset);
235 else if (FreeRDPAreColorFormatsEqualNoAlpha(SrcFormat, DstFormat))
236 return generic_image_copy_no_overlap_memcpy(pDstData, DstFormat, nDstStep, nXDst, nYDst,
237 nWidth, nHeight, pSrcData, SrcFormat, nSrcStep,
238 nXSrc, nYSrc, palette, srcVMultiplier,
239 srcVOffset, dstVMultiplier, dstVOffset, flags);
243 return gen->
copy_no_overlap(pDstData, DstFormat, nDstStep, nXDst, nYDst, nWidth, nHeight,
244 pSrcData, SrcFormat, nSrcStep, nXSrc, nYSrc, palette, flags);
250void primitives_init_copy_sse41_int(
primitives_t* WINPR_RESTRICT prims)
252#if defined(SSE_AVX_INTRINSICS_ENABLED)
253 WLog_VRB(PRIM_TAG,
"SSE4.1 optimizations");
254 prims->copy_no_overlap = sse_image_copy_no_overlap;
256 WLog_VRB(PRIM_TAG,
"undefined WITH_SIMD or SSE4.1 intrinsics not available");
WINPR_ATTR_NODISCARD fn_copy_no_overlap_t copy_no_overlap