commit 96842fc12394e4a89a66a05f5cf083a5d3441595
Author: Denis Oliver Kropp <dok@cyto.(none)>
Date:   Sun Sep 28 01:05:30 2008 +0200

    [IDirectFBSurface] Added DSBLIT_ROTATE90 and DSBLIT_ROTATE270. Thanks to Young Hoon for original patch!

diff --git a/README b/README
index 95eba3c..e9ab518 100644
--- a/README
+++ b/README
@@ -407,6 +407,7 @@ Thanks to
    Phil Endecott <spam_from_directfb_dev@chezphil.org>
    Brian Austin <brian.austin@cirrus.com>
    Keith Mok <ek9852@gmail.com>
+   Young Hoon <jcybha@hanmail.net>
 
 Special thanks to Ville Syrjala for his great work on the
 Matrox TV-Out support and for his several patches including
diff --git a/include/directfb.h b/include/directfb.h
index 2e7c53e..7df7e1a 100644
--- a/include/directfb.h
+++ b/include/directfb.h
@@ -708,7 +708,9 @@ typedef enum {
                                                 source pixels after premultiplication */
      DSBLIT_INDEX_TRANSLATION  = 0x00000800, /* do fast indexed to indexed translation,
                                                 this flag is mutual exclusive with all others */
+     DSBLIT_ROTATE90           = 0x00002000, /* rotate the image by 90 degree */
      DSBLIT_ROTATE180          = 0x00001000, /* rotate the image by 180 degree */
+     DSBLIT_ROTATE270          = 0x00004000, /* rotate the image by 270 degree */
      DSBLIT_COLORKEY_PROTECT   = 0x00010000, /* make sure written pixels don't match color key (internal only ATM) */
      DSBLIT_SRC_MASK_ALPHA     = 0x00100000, /* modulate source alpha channel with alpha channel from source mask,
                                                 see also IDirectFBSurface::SetSourceMask() */
diff --git a/src/gfx/generic/generic.c b/src/gfx/generic/generic.c
index bb1190b..d2faf49 100644
--- a/src/gfx/generic/generic.c
+++ b/src/gfx/generic/generic.c
@@ -683,6 +683,149 @@ static GenefxFunc Bop_PFI_to_Aop_PFI[DFB_NUM_PIXELFORMATS] = {
      Bop_16_to_Aop,      /* DSPF_BGR555 */
 };
 
+/********************************* Bop_PFI_toR_Aop_PFI *************************/
+
+static void Bop_4_toR_Aop( GenefxState *gfxs )
+{
+     int w = gfxs->length>>1;
+     int Dstep = gfxs->Astep;
+     u8 * S = gfxs->Bop[0];
+     u8 * D = gfxs->Aop[0];
+     while(w--)
+     {
+          *D = *S;
+          D += Dstep;
+          S++;
+     }
+}
+
+static void Bop_8_toR_Aop( GenefxState *gfxs )
+{
+     int w = gfxs->length;
+     int Dstep = gfxs->Astep;
+     u8 * S = gfxs->Bop[0];
+     u8 * D = gfxs->Aop[0];
+     while(w--)
+     {
+          *D = *S;
+          D += Dstep;
+          S++;
+     }
+}
+
+static void Bop_16_toR_Aop( GenefxState *gfxs )
+{
+     int w = gfxs->length;
+     int Dstep = gfxs->Astep;
+     u16 * S = gfxs->Bop[0];
+     u16 * D = gfxs->Aop[0];
+     while(w--)
+     {
+          *D = *S;
+          D += Dstep;
+          S++;
+     }
+}
+
+static void Bop_24_toR_Aop( GenefxState *gfxs )
+{
+     int w = gfxs->length;
+     int Dstep = gfxs->Astep;
+     u8 * S = gfxs->Bop[0];
+     u8 * D = gfxs->Aop[0];
+     while(w--)
+     {
+          D[0] = S[0];
+          D[1] = S[1];
+          D[2] = S[2];
+
+          D += Dstep * 3;
+          S += 3;
+     }
+}
+
+static void Bop_32_toR_Aop( GenefxState *gfxs )
+{
+     int w = gfxs->length;
+     int Dstep = gfxs->Astep;
+     u32 * S = gfxs->Bop[0];
+     u32 * D = gfxs->Aop[0];
+     while(w--)
+     {
+          *D = *S;
+          D += Dstep;
+          S++;
+     }
+}
+
+static void Bop_i420_toR_Aop( GenefxState *gfxs )
+{
+     Bop_8_toR_Aop( gfxs );
+     if (gfxs->AopY & 1) {
+          int w = gfxs->length>>1;
+          int Dstep = gfxs->Astep>>1;
+          u8 * S1 = gfxs->Bop[1];
+          u8 * D1 = gfxs->Aop[1];
+          u8 * S2 = gfxs->Bop[2];
+          u8 * D2 = gfxs->Aop[2];
+          while(w--)
+          {
+               *D1 = *S1++;
+               *D2 = *S2++;
+               D1 += Dstep;
+               D2 += Dstep;
+          }
+     }
+}             
+
+static void Bop_NV_toR_Aop( GenefxState *gfxs )
+{
+     Bop_8_toR_Aop( gfxs );
+     if (gfxs->dst_format == DSPF_NV16 || gfxs->AopY & 1) {
+          int w = gfxs->length&~1;
+          int Dstep = gfxs->Astep;
+          u8 * S = gfxs->Bop[1];
+          u8 * D = gfxs->Aop[1];
+          while(w--)
+          {
+               *D = *S++;
+               D += Dstep;
+          }
+     }
+}
+
+static GenefxFunc Bop_PFI_toR_Aop_PFI[DFB_NUM_PIXELFORMATS] = {
+     Bop_16_toR_Aop,      /* DSPF_ARGB1555 */
+     Bop_16_toR_Aop,      /* DSPF_RGB16 */
+     Bop_24_toR_Aop,      /* DSPF_RGB24 */
+     Bop_32_toR_Aop,      /* DSPF_RGB32 */
+     Bop_32_toR_Aop,      /* DSPF_ARGB */
+     Bop_8_toR_Aop,       /* DSPF_A8 */
+     Bop_16_toR_Aop,      /* DSPF_YUY2 */
+     Bop_8_toR_Aop,       /* DSPF_RGB332 */
+     Bop_16_toR_Aop,      /* DSPF_UYVY */
+     Bop_i420_toR_Aop,    /* DSPF_I420 */
+     Bop_i420_toR_Aop,    /* DSPF_YV12 */
+     Bop_8_toR_Aop,       /* DSPF_LUT8 */
+     Bop_8_toR_Aop,       /* DSPF_ALUT44 */
+     Bop_32_toR_Aop,      /* DSPF_AiRGB */
+     NULL,               /* DSPF_A1 */
+     Bop_NV_toR_Aop,      /* DSPF_NV12 */
+     Bop_NV_toR_Aop,      /* DSPF_NV16 */
+     Bop_16_toR_Aop,      /* DSPF_ARGB2554 */
+     Bop_16_toR_Aop,      /* DSPF_ARGB4444 */
+     Bop_NV_toR_Aop,      /* DSPF_NV21 */
+     Bop_32_toR_Aop,      /* DSPF_AYUV */
+     Bop_4_toR_Aop,       /* DSPF_A4 */
+     Bop_24_toR_Aop,      /* DSPF_ARGB1666 */
+     Bop_24_toR_Aop,      /* DSPF_ARGB6666 */
+     Bop_24_toR_Aop,      /* DSPF_RGB18 */
+     NULL,               /* DSPF_LUT2 */
+     Bop_16_toR_Aop,      /* DSPF_RGB444 */
+     Bop_16_toR_Aop,      /* DSPF_RGB555 */
+     Bop_16_toR_Aop,      /* DSPF_BGR555 */
+};
+
 /********************************* Bop_PFI_Kto_Aop_PFI ************************/
 
 static void Bop_rgb18_Kto_Aop( GenefxState *gfxs )
@@ -1307,8 +1450,10 @@ static GenefxFunc Bop_PFI_Sto_Aop_PFI[DFB_NUM_PIXELFORMATS] = {
      Bop_24_Sto_Aop,          /* DSPF_ARGB1666 */
      Bop_24_Sto_Aop,          /* DSPF_ARGB6666 */
      Bop_24_Sto_Aop,          /* DSPF_RGB18 */
+     NULL,                    /* DSPF_LUT2 */
      Bop_16_Sto_Aop,          /* DSPF_ARGB4444 */
      Bop_16_Sto_Aop,          /* DSPF_ARGB1555 */
+     Bop_16_Sto_Aop,          /* DSPF_ARGB1555 */
 };
 
 /********************************* Bop_PFI_SKto_Aop_PFI ***********************/
@@ -5208,8 +5353,10 @@ static GenefxFunc Bop_a8_set_alphapixel_Aop_PFI[DFB_NUM_PIXELFORMATS] = {
      Bop_a8_set_alphapixel_Aop_argb1666,          /* DSPF_ARGB1666 */
      Bop_a8_set_alphapixel_Aop_argb6666,          /* DSPF_ARGB6666 */
      Bop_a8_set_alphapixel_Aop_rgb18,             /* DSPF_RGB18 */
+     NULL,                                        /* DSPF_LUT2 */
      NULL,                                        /* DSPF_ARGB4444 */
      NULL,                                        /* DSPF_ARGB1555 */
+     NULL,                                        /* DSPF_ARGB1555 */
 };
 
 /************** Bop_a1_set_alphapixel_Aop_PFI *********************************/
@@ -6187,6 +6334,7 @@ static void Bop_argb_blend_alphachannel_src_invsrc_Aop_rgb16( GenefxState *gfxs
 static void Bop_argb_blend_alphachannel_src_invsrc_Aop_rgb32( GenefxState *gfxs )
 {
      int  w = gfxs->length;
+     int Dstep = gfxs->Astep;
      u32 *S = gfxs->Bop[0];
      u32 *D = gfxs->Aop[0];
 
@@ -6198,8 +6346,9 @@ static void Bop_argb_blend_alphachannel_src_invsrc_Aop_rgb32( GenefxState *gfxs
 #define rb (sp32 & 0xff00ff)
 #define g  (sp32 & 0x00ff00)
 
-          *D++ = ((((rb-(dp32 & 0xff00ff))*salpha+((dp32 & 0xff00ff)<<7)) & 0x7f807f80) +
+          *D = ((((rb-(dp32 & 0xff00ff))*salpha+((dp32 & 0xff00ff)<<7)) & 0x7f807f80) +
                   ((( g-(dp32 & 0x00ff00))*salpha+((dp32 & 0x00ff00)<<7)) & 0x007f8000)) >> 7;
+          D += Dstep;
 
 #undef rb
 #undef g
@@ -6319,8 +6468,8 @@ static void Dacc_Alpha_to_YCbCr( GenefxState *gfxs )
 
 /**********************************************************************************************************************/
 
-static void Sop_is_Aop( GenefxState *gfxs ) { gfxs->Sop = gfxs->Aop;}
-static void Sop_is_Bop( GenefxState *gfxs ) { gfxs->Sop = gfxs->Bop;}
+static void Sop_is_Aop( GenefxState *gfxs ) { gfxs->Sop = gfxs->Aop; gfxs->Ostep = gfxs->Astep; }
+static void Sop_is_Bop( GenefxState *gfxs ) { gfxs->Sop = gfxs->Bop; gfxs->Ostep = gfxs->Bstep; }
 
 static void Slut_is_Alut( GenefxState *gfxs ) { gfxs->Slut = gfxs->Alut;}
 static void Slut_is_Blut( GenefxState *gfxs ) { gfxs->Slut = gfxs->Blut;}
@@ -6875,6 +7024,9 @@ bool gAcquire( CardState *state, DFBAccelerationMask accel )
 
      gfxs->need_accumulator = true;
 
+     /* Initialization */
+     gfxs->Astep = gfxs->Bstep = gfxs->Ostep = 1;
+
      switch (accel) {
           case DFXL_FILLRECTANGLE:
           case DFXL_DRAWRECTANGLE:
@@ -7346,6 +7498,10 @@ bool gAcquire( CardState *state, DFBAccelerationMask accel )
                               } else if (state->blittingflags & DSBLIT_DST_COLORKEY) {
                                    gfxs->Dkey = state->dst_colorkey;
                                    *funcs++ = Bop_PFI_toK_Aop_PFI[dst_pfi];
+                              } else if (state->blittingflags & (DSBLIT_ROTATE90  |
+                                                                 DSBLIT_ROTATE180 |
+                                                                 DSBLIT_ROTATE270)) {
+                                   *funcs++ = Bop_PFI_toR_Aop_PFI[dst_pfi];
                               } else
                                    *funcs++ = Bop_PFI_to_Aop_PFI[dst_pfi];
                          }
@@ -7532,6 +7688,12 @@ static inline void Aop_xy( GenefxState *gfxs, int x, int y )
      }
 }
 
+static inline void Aop_crab( GenefxState *gfxs )
+{
+     gfxs->Aop[0] += gfxs->dst_bpp;
+     gfxs->AopY++;
+}
+
 static inline void Aop_next( GenefxState *gfxs )
 {
      int pitch = gfxs->dst_pitch;
@@ -8027,8 +8189,10 @@ void gBlit( CardState *state, DFBRectangle *rect, int dx, int dy )
 
      D_ASSERT( state->clip.x1 <= dx );
      D_ASSERT( state->clip.y1 <= dy );
-     D_ASSERT( state->clip.x2 >= (dx + rect->w - 1) );
-     D_ASSERT( state->clip.y2 >= (dy + rect->h - 1) );
+     D_ASSERT( (state->blittingflags & (DSBLIT_ROTATE90 | DSBLIT_ROTATE270)) || state->clip.x2 >= (dx + rect->w - 1) );
+     D_ASSERT( (state->blittingflags & (DSBLIT_ROTATE90 | DSBLIT_ROTATE270)) || state->clip.y2 >= (dy + rect->h - 1) );
+     D_ASSERT( !(state->blittingflags & (DSBLIT_ROTATE90 | DSBLIT_ROTATE270)) || state->clip.x2 >= (dx + rect->h - 1) );
+     D_ASSERT( !(state->blittingflags & (DSBLIT_ROTATE90 | DSBLIT_ROTATE270)) || state->clip.y2 >= (dy + rect->w - 1) );
 
      CHECK_PIPELINE();
 
@@ -8037,10 +8201,17 @@ void gBlit( CardState *state, DFBRectangle *rect, int dx, int dy )
 
      if (gfxs->src_org[0] == gfxs->dst_org[0] && dy == rect->y && dx > rect->x)
           /* we must blit from right to left */
-          gfxs->Ostep = -1;
+          gfxs->Astep = gfxs->Bstep = -1;
      else
           /* we must blit from left to right*/
-          gfxs->Ostep = 1;
+          gfxs->Astep = gfxs->Bstep = 1;
+     
+     if (state->blittingflags & DSBLIT_ROTATE90)
+          gfxs->Astep *= -gfxs->dst_pitch / gfxs->dst_bpp;
+     else if (state->blittingflags & DSBLIT_ROTATE180)
+          gfxs->Astep *= -1;
+     else if (state->blittingflags & DSBLIT_ROTATE270)
+          gfxs->Astep *= gfxs->dst_pitch / gfxs->dst_bpp;
 
      switch (gfxs->src_format) {
           case DSPF_A4:
@@ -8114,6 +8285,47 @@ void gBlit( CardState *state, DFBRectangle *rect, int dx, int dy )
           }
      }
 
+     if (state->blittingflags & DSBLIT_ROTATE180) {
+          Aop_xy( gfxs, dx + rect->w - 1, dy );
+          Bop_xy( gfxs, rect->x, rect->y + rect->h - 1 );
+          
+          for (h = rect->h; h; h--) {
+               RUN_PIPELINE();
+
+               Aop_next( gfxs );
+               Bop_prev( gfxs );
+          }
+          return;
+     }
+     else if( state->blittingflags & DSBLIT_ROTATE270 )
+     {
+          Aop_xy( gfxs, dx, dy );
+          Bop_xy( gfxs, rect->x, rect->y + rect->h - 1 );
+
+          for( h = rect->h; h; h-- )
+          {
+               RUN_PIPELINE();
+
+               Aop_crab( gfxs );
+               Bop_prev( gfxs );
+          }
+          return;
+     }
+     else if( state->blittingflags & DSBLIT_ROTATE90 )
+     {
+          Aop_xy( gfxs, dx, dy + rect->w - 1 );
+          Bop_xy( gfxs, rect->x, rect->y );
+
+          for( h = rect->h; h; h-- )
+          {
+               RUN_PIPELINE();
+
+               Aop_crab( gfxs );
+               Bop_next( gfxs );
+          }
+          return;
+     }
+
      if (gfxs->src_org[0] == gfxs->dst_org[0] && dy > rect->y &&
          !(state->blittingflags & DSBLIT_DEINTERLACE)) {
           /* we must blit from bottom to top */
diff --git a/src/gfx/generic/generic.h b/src/gfx/generic/generic.h
index 06909fc..6357661 100644
--- a/src/gfx/generic/generic.h
+++ b/src/gfx/generic/generic.h
@@ -99,6 +99,9 @@ struct _GenefxState {
      void *Bop[3];
      u32   Cop;
 
+     int   Astep;
+     int   Bstep;
+
      u8 YCop;
      u8 CbCop;
      u8 CrCop;
diff --git a/src/gfx/generic/template_acc_16.h b/src/gfx/generic/template_acc_16.h
index 853217a..a50e6d5 100644
--- a/src/gfx/generic/template_acc_16.h
+++ b/src/gfx/generic/template_acc_16.h
@@ -74,8 +74,12 @@ static void Sop_PFI_OP_Dacc(Sto)( GenefxState *gfxs )
      int                i     = gfxs->Xphase;
      int                SperD = gfxs->SperD;
      u16               *S     = gfxs->Sop[0];
+     int                Ostep = gfxs->Ostep;
      GenefxAccumulator *D     = gfxs->Dacc;
 
+     if (Ostep != 1)
+          D_UNIMPLEMENTED();
+
      while (l--) {
           u16 s = S[i>>16];
 
@@ -94,9 +98,13 @@ static void Sop_PFI_OP_Dacc(SKto)( GenefxState *gfxs )
      int                i     = gfxs->Xphase;
      int                SperD = gfxs->SperD;
      u16               *S     = gfxs->Sop[0];
+     int                Ostep = gfxs->Ostep;
      GenefxAccumulator *D     = gfxs->Dacc;
      u16                Skey  = gfxs->Skey;
 
+     if (Ostep != 1)
+          D_UNIMPLEMENTED();
+
      while (l--) {
           u16 s = S[i>>16];
 
@@ -117,6 +125,10 @@ static void Sop_PFI_OP_Dacc(to)( GenefxState *gfxs )
      int             w, l = gfxs->length;
      u16               *S = gfxs->Sop[0];
      GenefxAccumulator *D = gfxs->Dacc;
+     int                Ostep = gfxs->Ostep;
+
+     if (Ostep != 1)
+          D_UNIMPLEMENTED();
 
      if ((long)S & 2) {
           u16 s = *S++;
@@ -158,15 +170,17 @@ static void Sop_PFI_OP_Dacc(Kto)( GenefxState *gfxs )
      u16               *S    = gfxs->Sop[0];
      GenefxAccumulator *D    = gfxs->Dacc;
      u16                Skey = gfxs->Skey;
+     int                Ostep = gfxs->Ostep;
 
      while (l--) {
-          u16 s = *S++;
+          u16 s = *S;
 
           if (MASK_RGB( s ) != Skey)
                EXPAND( *D, s );
           else
                D->RGB.a = 0xF000;
 
+          S += Ostep;
           D++;
      }
 }
@@ -178,6 +192,10 @@ static void Sacc_OP_Aop_PFI(to)( GenefxState *gfxs )
      int             w, l = gfxs->length;
      GenefxAccumulator *S = gfxs->Sacc;
      u16               *D = gfxs->Aop[0];
+     int                Dstep = gfxs->Astep;
+
+     if (Dstep != 1)
+          D_UNIMPLEMENTED();
 
      if ((long)D & 2) {
           if (!(S->RGB.a & 0xF000))
@@ -224,6 +242,10 @@ static void Sacc_OP_Aop_PFI(Sto)( GenefxState *gfxs )
      int                SperD = gfxs->SperD;
      GenefxAccumulator *Sacc  = gfxs->Sacc;
      u16               *D     = gfxs->Aop[0];
+     int                Dstep = gfxs->Astep;
+
+     if (Dstep != 1)
+          D_UNIMPLEMENTED();
 
      if ((long)D & 2) {
           GenefxAccumulator *S = Sacc;
@@ -275,13 +297,14 @@ static void Sacc_OP_Aop_PFI(toK)( GenefxState *gfxs )
      GenefxAccumulator *S    = gfxs->Sacc;
      u16               *D    = gfxs->Aop[0];
      u16                Dkey = gfxs->Dkey;
+     int                Dstep = gfxs->Astep;
 
      while (l--) {
           if (!(S->RGB.a & 0xF000) && MASK_RGB( *D ) == Dkey)
                *D = PIXEL( *S );
 
           S++;
-          D++;
+          D += Dstep;
      }
 }
 
@@ -295,6 +318,7 @@ static void Sacc_OP_Aop_PFI(StoK)( GenefxState *gfxs )
      GenefxAccumulator *Sacc  = gfxs->Sacc;
      u16               *D     = gfxs->Aop[0];
      u16                Dkey  = gfxs->Dkey;
+     int                Dstep = gfxs->Astep;
 
      while (l--) {
           GenefxAccumulator *S = &Sacc[i>>16];
@@ -302,7 +326,7 @@ static void Sacc_OP_Aop_PFI(StoK)( GenefxState *gfxs )
           if (!(S->RGB.a & 0xF000) && MASK_RGB( *D ) == Dkey)
                *D = PIXEL( *S );
 
-          D++;
+          D += Dstep;
           i += SperD;
      }
 }
diff --git a/src/gfx/generic/template_acc_32.h b/src/gfx/generic/template_acc_32.h
index 569a135..f0894ca 100644
--- a/src/gfx/generic/template_acc_32.h
+++ b/src/gfx/generic/template_acc_32.h
@@ -69,8 +69,12 @@ static void Sop_PFI_OP_Dacc(Sto)( GenefxState *gfxs )
      int                i     = gfxs->Xphase;
      int                SperD = gfxs->SperD;
      u32               *S     = gfxs->Sop[0];
+     int                Ostep = gfxs->Ostep;
      GenefxAccumulator *D     = gfxs->Dacc;
 
+     if (Ostep != 1)
+          D_UNIMPLEMENTED();
+          
      while (l--) {
           u32 s = S[i>>16];
 
@@ -89,9 +93,13 @@ static void Sop_PFI_OP_Dacc(SKto)( GenefxState *gfxs )
      int                i     = gfxs->Xphase;
      int                SperD = gfxs->SperD;
      u32               *S     = gfxs->Sop[0];
+     int                Ostep = gfxs->Ostep;
      GenefxAccumulator *D     = gfxs->Dacc;
      u32                Skey  = gfxs->Skey;
 
+     if (Ostep != 1)
+          D_UNIMPLEMENTED();
+
      while (l--) {
           u32 s = S[i>>16];
 
@@ -112,12 +120,15 @@ static void Sop_PFI_OP_Dacc(to)( GenefxState *gfxs )
      int                l = gfxs->length;
      u32               *S = gfxs->Sop[0];
      GenefxAccumulator *D = gfxs->Dacc;
+     int                Ostep = gfxs->Ostep;
 
      while (l--) {
-          u32 s = *S++;
+          u32 s = *S;
 
           EXPAND( *D, s );
 
+          S += Ostep;
+
           D++;
      }
 }
@@ -130,15 +141,17 @@ static void Sop_PFI_OP_Dacc(Kto)( GenefxState *gfxs )
      u32               *S    = gfxs->Sop[0];
      GenefxAccumulator *D    = gfxs->Dacc;
      u32                Skey = gfxs->Skey;
+     int                Ostep = gfxs->Ostep;
 
      while (l--) {
-          u32 s = *S++;
+          u32 s = *S;
 
           if ((s & RGB_MASK) != Skey)
                EXPAND( *D, s );
           else
                D->RGB.a = 0xF000;
 
+          S += Ostep;
           D++;
      }
 }
@@ -150,13 +163,14 @@ static void Sacc_OP_Aop_PFI(to)( GenefxState *gfxs )
      int                l = gfxs->length;
      GenefxAccumulator *S = gfxs->Sacc;
      u32               *D = gfxs->Aop[0];
+     int                Dstep = gfxs->Astep;
 
      while (l--) {
           if (!(S->RGB.a & 0xF000))
                *D = PIXEL( *S );
 
           S++;
-          D++;
+          D += Dstep;
      }
 }
 
@@ -169,6 +183,7 @@ static void Sacc_OP_Aop_PFI(Sto)( GenefxState *gfxs )
      int                SperD = gfxs->SperD;
      GenefxAccumulator *Sacc  = gfxs->Sacc;
      u32               *D     = gfxs->Aop[0];
+     int                Dstep = gfxs->Astep;
 
      while (l--) {
           GenefxAccumulator *S = &Sacc[i>>16];
@@ -176,7 +191,7 @@ static void Sacc_OP_Aop_PFI(Sto)( GenefxState *gfxs )
           if (!(S->RGB.a & 0xF000))
                *D = PIXEL( *S );
 
-          D++;
+          D += Dstep;
           i += SperD;
      }
 }
@@ -188,6 +203,7 @@ static void Sacc_OP_Aop_PFI(toK)( GenefxState *gfxs )
      int                l    = gfxs->length;
      GenefxAccumulator *S    = gfxs->Sacc;
      u32               *D    = gfxs->Aop[0];
+     int                Dstep = gfxs->Astep;
      u32                Dkey = gfxs->Dkey;
 
      while (l--) {
@@ -195,7 +211,7 @@ static void Sacc_OP_Aop_PFI(toK)( GenefxState *gfxs )
                *D = PIXEL( *S );
 
           S++;
-          D++;
+          D += Dstep;
      }
 }
 
@@ -208,6 +224,7 @@ static void Sacc_OP_Aop_PFI(StoK)( GenefxState *gfxs )
      int                SperD = gfxs->SperD;
      GenefxAccumulator *Sacc  = gfxs->Sacc;
      u32               *D     = gfxs->Aop[0];
+     int                Dstep = gfxs->Astep;
      u32                Dkey  = gfxs->Dkey;
 
      while (l--) {
@@ -216,7 +233,7 @@ static void Sacc_OP_Aop_PFI(StoK)( GenefxState *gfxs )
           if (!(S->RGB.a & 0xF000) && (*D & RGB_MASK) == Dkey)
                *D = PIXEL( *S );
 
-          D++;
+          D += Dstep;
           i += SperD;
      }
 }
diff --git a/src/gfx/generic/template_colorkey_32.h b/src/gfx/generic/template_colorkey_32.h
index a4d69a1..52227af 100644
--- a/src/gfx/generic/template_colorkey_32.h
+++ b/src/gfx/generic/template_colorkey_32.h
@@ -56,14 +56,15 @@ static void Cop_OP_Aop_PFI(toK)( GenefxState *gfxs )
 static void Bop_PFI_OP_Aop_PFI(Kto)( GenefxState *gfxs )
 {
      int  l     = gfxs->length;
-     int  Ostep = gfxs->Ostep;
+     int  Sstep = gfxs->Bstep;
+     int  Dstep = gfxs->Astep;
      u32 *S     = gfxs->Bop[0];
      u32 *D     = gfxs->Aop[0];
      u32  Skey  = gfxs->Skey;
 
-     if (Ostep < 0) {
+     if (Sstep < 0) {
           S += gfxs->length - 1;
-          D += gfxs->length - 1;
+          D += (gfxs->length - 1) * gfxs->Astep;
      }
 
      while (l--) {
@@ -72,8 +73,8 @@ static void Bop_PFI_OP_Aop_PFI(Kto)( GenefxState *gfxs )
           if ((s & RGB_MASK) != Skey)
                *D = s;
 
-          S += Ostep;
-          D += Ostep;
+          S += Sstep;
+          D += Dstep;
      }
 }
 
@@ -82,22 +83,23 @@ static void Bop_PFI_OP_Aop_PFI(Kto)( GenefxState *gfxs )
 static void Bop_PFI_OP_Aop_PFI(toK)( GenefxState *gfxs )
 {
      int  l     = gfxs->length;
-     int  Ostep = gfxs->Ostep;
+     int  Sstep = gfxs->Bstep;
+     int  Dstep = gfxs->Astep;
      u32 *S     = gfxs->Bop[0];
      u32 *D     = gfxs->Aop[0];
      u32  Dkey  = gfxs->Dkey;
 
-     if (Ostep < 0) {
+     if (Sstep < 0) {
           S += gfxs->length - 1;
-          D += gfxs->length - 1;
+          D += (gfxs->length - 1) * gfxs->Astep;
      }
 
      while (l--) {
           if ((*D & RGB_MASK) == Dkey)
                *D = *S;
 
-          S += Ostep;
-          D += Ostep;
+          S += Sstep;
+          D += Dstep;
      }
 }
 
@@ -106,15 +108,16 @@ static void Bop_PFI_OP_Aop_PFI(toK)( GenefxState *gfxs )
 static void Bop_PFI_OP_Aop_PFI(KtoK)( GenefxState *gfxs )
 {
      int  l     = gfxs->length;
-     int  Ostep = gfxs->Ostep;
+     int  Sstep = gfxs->Bstep;
+     int  Dstep = gfxs->Astep;
      u32 *S     = gfxs->Bop[0];
      u32 *D     = gfxs->Aop[0];
      u32  Skey  = gfxs->Skey;
      u32  Dkey  = gfxs->Dkey;
 
-     if (Ostep < 0) {
+     if (Sstep < 0) {
           S += gfxs->length - 1;
-          D += gfxs->length - 1;
+          D += (gfxs->length - 1) * gfxs->Astep;
      }
 
      while (l--) {
@@ -123,8 +126,8 @@ static void Bop_PFI_OP_Aop_PFI(KtoK)( GenefxState *gfxs )
           if ((s & RGB_MASK) != Skey && (*D & RGB_MASK) == Dkey)
                *D = s;
 
-          S += Ostep;
-          D += Ostep;
+          S += Sstep;
+          D += Dstep;
      }
 }
 
@@ -137,6 +140,7 @@ static void Bop_PFI_OP_Aop_PFI(SKto)( GenefxState *gfxs )
      int  SperD = gfxs->SperD;
      u32 *S     = gfxs->Bop[0];
      u32 *D     = gfxs->Aop[0];
+     int  Dstep = gfxs->Astep;
      u32  Skey  = gfxs->Skey;
 
      while (l--) {
@@ -145,7 +149,7 @@ static void Bop_PFI_OP_Aop_PFI(SKto)( GenefxState *gfxs )
           if ((s & RGB_MASK) != Skey)
                *D = s;
 
-          D++;
+          D += Dstep;
           i += SperD;
      }
 }
@@ -160,12 +164,13 @@ static void Bop_PFI_OP_Aop_PFI(StoK)( GenefxState *gfxs )
      u32 *S     = gfxs->Bop[0];
      u32 *D     = gfxs->Aop[0];
      u32  Dkey  = gfxs->Dkey;
+     int  Dstep = gfxs->Astep;
 
      while (l--) {
           if ((*D & RGB_MASK) != Dkey)
                *D = S[i>>16];
 
-          D++;
+          D += Dstep;
           i += SperD;
      }
 }
@@ -181,6 +186,7 @@ static void Bop_PFI_OP_Aop_PFI(SKtoK)( GenefxState *gfxs )
      u32 *D     = gfxs->Aop[0];
      u32  Skey  = gfxs->Skey;
      u32  Dkey  = gfxs->Dkey;
+     int  Dstep = gfxs->Astep;
 
      while (l--) {
           u32 s = S[i>>16];
@@ -188,7 +194,7 @@ static void Bop_PFI_OP_Aop_PFI(SKtoK)( GenefxState *gfxs )
           if ((s & RGB_MASK) != Skey && (*D & RGB_MASK) == Dkey)
                *D = s;
 
-          D++;
+          D += Dstep;
           i += SperD;
      }
 }
 
commit a42d0243b668376006e673781722bd7f11549857
Author: Denis Oliver Kropp <dok@cyto.(none)>
Date:   Sun Sep 28 01:17:29 2008 +0200

    [graphics] Implement proper clipping for rotated blits of 90, 180 or 270 degree.

diff --git a/src/core/gfxcard.c b/src/core/gfxcard.c
index 8a2fdbf..c8636da 100644
--- a/src/core/gfxcard.c
+++ b/src/core/gfxcard.c
@@ -1641,10 +1641,72 @@ void dfb_gfxcard_filltriangles( const DFBTriangle *tris, int num, CardState *sta
      dfb_state_unlock( state );
 }
 
+static void
+clip_blit_rotated( DFBRectangle *srect, DFBRectangle *drect, const DFBRegion *clip, DFBSurfaceBlittingFlags flags )
+{
+     DFBRegion dest    = DFB_REGION_INIT_FROM_RECTANGLE( drect );
+     DFBRegion clipped = dest;
+
+     if (flags & (DSBLIT_ROTATE90 | DSBLIT_ROTATE270)) {
+          D_ASSERT( srect->w == drect->h );
+          D_ASSERT( srect->h == drect->w );
+     }
+     else {
+          D_ASSERT( srect->w == drect->w );
+          D_ASSERT( srect->h == drect->h );
+     }
+
+     dfb_region_region_intersect( &clipped, clip );
+     dfb_rectangle_from_region( drect, &clipped );
+
+     if (flags & DSBLIT_ROTATE90) {
+          srect->x += dest.y2 - clipped.y2;
+          srect->y += clipped.x1 - dest.x1;
+          srect->w  = drect->h;
+          srect->h  = drect->w;
+
+          D_DEBUG_AT( Core_GraphicsOps, "  => %4d,%4d-%4dx%4d -> %4d,%4d-%4dx%4d (90°)\n",
+                      DFB_RECTANGLE_VALS(srect), DFB_RECTANGLE_VALS(drect) );
+     }
+     else if (flags & DSBLIT_ROTATE180) {
+          srect->x += dest.x2 - clipped.x2;
+          srect->y += dest.y2 - clipped.y2;
+          srect->w  = drect->w;
+          srect->h  = drect->h;
+
+          D_DEBUG_AT( Core_GraphicsOps, "  => %4d,%4d-%4dx%4d -> %4d,%4d-%4dx%4d (180°)\n",
+                      DFB_RECTANGLE_VALS(srect), DFB_RECTANGLE_VALS(drect) );
+     }
+     else if (flags & DSBLIT_ROTATE270) {
+          srect->x += clipped.y1 - dest.y1;
+          srect->y += dest.x2 - clipped.x2;
+          srect->w  = drect->h;
+          srect->h  = drect->w;
+
+          D_DEBUG_AT( Core_GraphicsOps, "  => %4d,%4d-%4dx%4d -> %4d,%4d-%4dx%4d (270°)\n",
+                      DFB_RECTANGLE_VALS(srect), DFB_RECTANGLE_VALS(drect) );
+     }
+     else {
+          srect->x += clipped.x1 - dest.x1;
+          srect->y += clipped.y1 - dest.y1;
+          srect->w  = drect->w;
+          srect->h  = drect->h;
+
+          D_DEBUG_AT( Core_GraphicsOps, "  => %4d,%4d-%4dx%4d -> %4d,%4d-%4dx%4d\n",
+                      DFB_RECTANGLE_VALS(srect), DFB_RECTANGLE_VALS(drect) );
+     }
+}
 
 void dfb_gfxcard_blit( DFBRectangle *rect, int dx, int dy, CardState *state )
 {
-     bool hw = false;
+     bool         hw    = false;
+     DFBRectangle drect = { dx, dy, rect->w, rect->h };
+
+     if (state->blittingflags & (DSBLIT_ROTATE90 | DSBLIT_ROTATE270))
+          D_UTIL_SWAP( drect.w, drect.h );
+
+     D_DEBUG_AT( Core_GraphicsOps, "%s( %4d,%4d-%4dx%4d -> %4d,%4d-%4dx%4d, %p )\n",
+                 __FUNCTION__, DFB_RECTANGLE_VALS(rect), DFB_RECTANGLE_VALS(&drect), state );
 
      D_ASSERT( card != NULL );
      D_ASSERT( card->shared != NULL );
@@ -1658,9 +1720,6 @@ void dfb_gfxcard_blit( DFBRectangle *rect, int dx, int dy, CardState *state )
      D_ASSERT( rect->x + rect->w - 1 < state->source->config.size.w );
      D_ASSERT( rect->y + rect->h - 1 < state->source->config.size.h );
 
-     D_DEBUG_AT( Core_GraphicsOps, "%s( %d,%d - %dx%d -> %d,%d, %p )\n",
-                 __FUNCTION__, DFB_RECTANGLE_VALS(rect), dx, dy, state );
-
      /* The state is locked during graphics operations. */
      dfb_state_lock( state );
 
@@ -1668,7 +1727,8 @@ void dfb_gfxcard_blit( DFBRectangle *rect, int dx, int dy, CardState *state )
      dfb_state_start_drawing( state, card );
 
      if (!(state->render_options & DSRO_MATRIX) &&
-         !dfb_clip_blit_precheck( &state->clip, rect->w, rect->h, dx, dy )) {
+         !dfb_clip_blit_precheck( &state->clip, drect.w, drect.h, drect.x, drect.y ))
+     {
           /* no work at all */
           dfb_state_unlock( state );
           return;
@@ -1679,10 +1739,9 @@ void dfb_gfxcard_blit( DFBRectangle *rect, int dx, int dy, CardState *state )
      {
           if (!D_FLAGS_IS_SET( card->caps.flags, CCF_CLIPPING ) &&
               !D_FLAGS_IS_SET( card->caps.clip, DFXL_BLIT ))
-               dfb_clip_blit( &state->clip, rect, &dx, &dy );
+               clip_blit_rotated( rect, &drect, &state->clip, state->blittingflags );
 
-          hw = card->funcs.Blit( card->driver_data, card->device_data,
-                                 rect, dx, dy );
+          hw = card->funcs.Blit( card->driver_data, card->device_data, rect, drect.x, drect.y );
 
           dfb_gfxcard_state_release( state );
      }
@@ -1716,8 +1775,10 @@ void dfb_gfxcard_blit( DFBRectangle *rect, int dx, int dy, CardState *state )
           }
           else {
                if (gAcquire( state, DFXL_BLIT )) {
-                    dfb_clip_blit( &state->clip, rect, &dx, &dy );
-                    gBlit( state, rect, dx, dy );
+                    clip_blit_rotated( rect, &drect, &state->clip, state->blittingflags );
+
+                    gBlit( state, rect, drect.x, drect.y );
+
                     gRelease( state );
                }
           }
@@ -1986,9 +2047,17 @@ void dfb_gfxcard_stretchblit( DFBRectangle *srect, DFBRectangle *drect,
      D_DEBUG_AT( Core_GraphicsOps, "%s( %d,%d - %dx%d -> %d,%d - %dx%d, %p )\n",
                  __FUNCTION__, DFB_RECTANGLE_VALS(srect), DFB_RECTANGLE_VALS(drect), state );
 
-     if (srect->w == drect->w && srect->h == drect->h) {
-          dfb_gfxcard_blit( srect, drect->x, drect->y, state );
-          return;
+     if (state->blittingflags & (DSBLIT_ROTATE90 | DSBLIT_ROTATE270)) {
+          if (srect->w == drect->h && srect->h == drect->w) {
+               dfb_gfxcard_blit( srect, drect->x, drect->y, state );
+               return;
+          }
+     }
+     else {
+          if (srect->w == drect->w && srect->h == drect->h) {
+               dfb_gfxcard_blit( srect, drect->x, drect->y, state );
+               return;
+          }
      }
 
      /* The state is locked during graphics operations. */
commit 55b46effe7f19ef554ba09517e556105fd21ed74
Author: Denis Oliver Kropp <dok@cyto.(none)>
Date:   Sun Sep 28 00:55:07 2008 +0200

    [util] Added D_UTIL_SWAP(a,b) to exchange values.

diff --git a/lib/direct/util.h b/lib/direct/util.h
index f8b1f00..7d91e48 100644
--- a/lib/direct/util.h
+++ b/lib/direct/util.h
@@ -81,6 +81,11 @@
 
 #define D_ARRAY_SIZE(array)        ((int)(sizeof(array) / sizeof((array)[0])))
 
+#define D_UTIL_SWAP(a,b)                                    \
+     do {                                                   \
+          const typeof(a) x = (a); (a) = (b); (b) = x;      \
+     } while (0)
+
 
 #if __GNUC__ >= 3
 #define D_CONST_FUNC               __attribute__((const))
