# SDL: Add a fast path for ARGB888-\>(A)BGR888 blending with pixel alpha

**URL:** <https://discourse.libsdl.org/t/sdl-add-a-fast-path-for-argb888-a-bgr888-blending-with-pixel-alpha/32923>\
**Category:** SDL Commits\
**Created:** [September 28, 2021, 6:28pm UTC](https://discourse.libsdl.org/t/sdl-add-a-fast-path-for-argb888-a-bgr888-blending-with-pixel-alpha/32923 "2021-09-28T18:28:02Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![SDLPushPostBot](https://discourse.libsdl.org/user_avatar/discourse.libsdl.org/sdlpushpostbot/32/4370_2.png) [@SDLPushPostBot](https://discourse.libsdl.org/u/SDLPushPostBot)\
**Post date:** [September 28, 2021, 6:28pm UTC](https://discourse.libsdl.org/t/sdl-add-a-fast-path-for-argb888-a-bgr888-blending-with-pixel-alpha/32923/1 "2021-09-28T18:28:02Z")

</div>

> <https://github.com/libsdl-org/SDL/commit/c270949b5e9409f0388c5a179f6b65508c01723f>

```diff
From c270949b5e9409f0388c5a179f6b65508c01723f Mon Sep 17 00:00:00 2001
From: Cameron Cawley <[EMAIL REDACTED]>
Date: Tue, 28 Sep 2021 18:07:22 +0100
Subject: [PATCH] Add a fast path for ARGB888->(A)BGR888 blending with pixel
 alpha

---
 src/video/SDL_blit_A.c | 61 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 61 insertions(+)

diff --git a/src/video/SDL_blit_A.c b/src/video/SDL_blit_A.c
index bce6957531..fbd5eaddef 100644
--- a/src/video/SDL_blit_A.c
+++ b/src/video/SDL_blit_A.c
@@ -575,6 +575,61 @@ BlitRGBtoRGBPixelAlpha(SDL_BlitInfo * info)
     }
 }
 
+/* fast ARGB888->(A)BGR888 blending with pixel alpha */
+static void
+BlitRGBtoBGRPixelAlpha(SDL_BlitInfo * info)
+{
+ int width = info->dst_w;
+ int height = info->dst_h;
+ Uint32 *srcp = (Uint32 *) info->src;
+ int srcskip = info->src_skip >> 2;
+ Uint32 *dstp = (Uint32 *) info->dst;
+ int dstskip = info->dst_skip >> 2;
+
+ while (height--) {
+ /* *INDENT-OFF* */
+ DUFFS_LOOP4({
+ Uint32 dalpha;
+ Uint32 d;
+ Uint32 s1;
+ Uint32 d1;
+ Uint32 s = *srcp;
+ Uint32 alpha = s >> 24;
+ /* FIXME: Here we special-case opaque alpha since the
+ compositioning used (>>8 instead of /255) doesn't handle
+ it correctly. Also special-case alpha=0 for speed?
+ Benchmark this! */
+ if (alpha) {
+ /*
+ * take out the middle component (green), and process
+ * the other two in parallel. One multiply less.
+ */
+ s1 = s & 0xff00ff;
+ s1 = (s1 >> 16) | (s1 << 16);
+ s &= 0xff00;
+
+ if (alpha == SDL_ALPHA_OPAQUE) {
+ *dstp = 0xff000000 | s | s1;
+ } else {
+ d = *dstp;
+ dalpha = d >> 24;
+ d1 = d & 0xff00ff;
+ d1 = (d1 + ((s1 - d1) * alpha >> 8)) & 0xff00ff;
+ d &= 0xff00;
+ d = (d + ((s - d) * alpha >> 8)) & 0xff00;
+ dalpha = alpha + (dalpha * (alpha ^ 0xFF) >> 8);
+ *dstp = d1 | d | (dalpha << 24);
+ }
+ }
+ ++srcp;
+ ++dstp;
+ }, width);
+ /* *INDENT-ON* */
+ srcp += srcskip;
+ dstp += dstskip;
+ }
+}
+
 #ifdef __3dNOW__
 /* fast (as in MMX with prefetch) ARGB888->(A)RGB888 blending with pixel alpha */
 static void
@@ -1407,6 +1462,12 @@ SDL_CalculateBlitA(SDL_Surface * surface)
 #endif
                     return BlitRGBtoRGBPixelAlpha;
                 }
+ } else if (sf->Rmask == df->Bmask
+ && sf->Gmask == df->Gmask
+ && sf->Bmask == df->Rmask && sf->BytesPerPixel == 4) {
+ if (sf->Amask == 0xff000000) {
+ return BlitRGBtoBGRPixelAlpha;
+ }
             }
             return BlitNtoNPixelAlpha;
 

```
