changeset 95:0430f484641b

Add unscaled blitting functions.
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 02 Oct 2012 18:51:16 +0300
parents 4bbfc0274b29
children 6bf5220fa47e
files Makefile.gen dmblit.c dmblitfunc.h dmlib.h dmscaledblit.h dmunscaledblit.h
diffstat 6 files changed, 420 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile.gen	Tue Oct 02 18:14:44 2012 +0300
+++ b/Makefile.gen	Tue Oct 02 18:51:16 2012 +0300
@@ -222,7 +222,7 @@
 	@echo " CC $+"
 	@$(CC) $(CFLAGS) -c -o $@ $< $(DM_CFLAGS)
 
-$(OBJPATH)dmblit.o: $(DMLIB)dmblit.c $(DMLIB)dmscaledblit.h $(DMLIB)dmblitfunc.h
+$(OBJPATH)dmblit.o: $(DMLIB)dmblit.c $(DMLIB)dmscaledblit.h $(DMLIB)dmunscaledblit.h $(DMLIB)dmblitfunc.h
 	@echo " CC $+"
 	@$(CC) $(CFLAGS) -c -o $@ $< $(DM_CFLAGS)
 
--- a/dmblit.c	Tue Oct 02 18:14:44 2012 +0300
+++ b/dmblit.c	Tue Oct 02 18:51:16 2012 +0300
@@ -15,7 +15,7 @@
 } DMQValue;
 
 
-int dmClipCoord(DMQValue *pv, int v0, int v1, int v2, int clipMin, int clipMax)
+int dmScaledClipCoord(DMQValue *pv, int v0, int v1, int v2, int clipMin, int clipMax)
 {
     DMFixedPoint32 a, b;
 
@@ -69,6 +69,40 @@
 }
 
 
+int dmUnscaledClipCoord(DMQValue *pv, int v0, int v1, int clipMin, int clipMax)
+{
+    // Basic bounds check
+    if (v1 < 1 || v0 + v1 < clipMin || v0 >= clipMax)
+        return -1;
+
+    // Perform clipping
+    if (v0 + v1 >= clipMax)
+    {
+        pv->vadd = v0;
+        pv->v1 = clipMax;
+    }
+    else
+    {
+        pv->vadd = clipMax - v1;
+        pv->v1 = v0 + v1;
+    }
+    
+    if (v0 < clipMin)
+    {
+        pv->voffs = clipMin - v0;
+        pv->v0 = clipMin;
+        pv->vadd -= v0 + clipMin;
+    }
+    else
+    {
+        pv->voffs = 0;
+        pv->v0 = v0;
+    }
+    
+    return 0;
+}
+
+
 #include "dmblitfunc.h"
 
 
@@ -110,6 +144,7 @@
 
 static const int ndmScaledBlitTable = sizeof(dmScaledBlitTable) / sizeof(dmScaledBlitTable[0]);
 
+
 DMScaledBlitFunc dmGetScaledBlitFunc(SDL_PixelFormat *src, SDL_PixelFormat *dst, int mode)
 {
     int isrc, idst;
@@ -134,3 +169,69 @@
 
     return bfunc(src, x0, y0, dwidth, dheight, dst);
 }
+
+
+static const DMUnscaledBlitFunc dmUnscaledBlitTable[DMD_NMODES][DMD_NBITDEPTHS][DMD_NBITDEPTHS] =
+{
+    // DMD_NONE
+    {
+        { dmUnscaledBlitSurface8to8           , dmUnscaledBlitSurface8to32 },
+        { NULL                                , dmUnscaledBlitSurface32to32 },
+    },
+    // DMD_TRANSPARENT
+    {
+        { dmUnscaledBlitSurface8to8Transparent, dmUnscaledBlitSurface8to32Transparent },
+        { NULL                                , dmUnscaledBlitSurface32to32Transparent },
+    },
+    // DMD_SATURATE
+    {
+        { dmUnscaledBlitSurface8to8Saturate   , dmUnscaledBlitSurface8to32Saturate },
+        { NULL                                , dmUnscaledBlitSurface32to32Saturate },
+    },
+#if 0
+    // DMD_NONE | DMD_ANTIALIAS
+    {
+        { dmUnscaledBlitSurface8to8Antialias  , dmUnscaledBlitSurface8to32Antialias },
+        { NULL                                , dmUnscaledBlitSurface32to32Antialias },
+    },
+    // DMD_TRANSPARENT | DMD_ANTIALIAS
+    {
+        { dmUnscaledBlitSurface8to8AATransp   , dmUnscaledBlitSurface8to32AATransparent },
+        { NULL                                , dmUnscaledBlitSurface32to32AATransparent },
+    },
+    // DMD_SATURATE | DMD_ANTIALIAS
+    {
+        { dmUnscaledBlitSurface8to8AASaturate , dmUnscaledBlitSurface8to32AASaturate },
+        { NULL                                , dmUnscaledBlitSurface32to32AASaturate },
+    },
+#endif
+};
+
+static const int ndmUnscaledBlitTable = sizeof(dmUnscaledBlitTable) / sizeof(dmUnscaledBlitTable[0]);
+
+
+
+DMUnscaledBlitFunc dmGetUnscaledBlitFunc(SDL_PixelFormat *src, SDL_PixelFormat *dst, int mode)
+{
+    int isrc, idst;
+    if (src == NULL || dst == NULL || mode < 0 || mode >= ndmUnscaledBlitTable)
+        return NULL;
+
+    isrc = dmBitsPerPixel2Index(src->BitsPerPixel);
+    idst = dmBitsPerPixel2Index(dst->BitsPerPixel);
+    if (isrc < 0 || idst < 0)
+        return NULL;
+    
+    return dmUnscaledBlitTable[mode][isrc][idst];
+}
+
+
+int dmUnscaledBlitSurfaceAny(SDL_Surface *src, const int x0, const int y0, SDL_Surface *dst, int mode)
+{
+    DMUnscaledBlitFunc bfunc = dmGetUnscaledBlitFunc(src->format, dst->format, mode);
+    
+    if (bfunc == NULL)
+        return -15;
+
+    return bfunc(src, x0, y0, dst);
+}
--- a/dmblitfunc.h	Tue Oct 02 18:14:44 2012 +0300
+++ b/dmblitfunc.h	Tue Oct 02 18:51:16 2012 +0300
@@ -309,5 +309,237 @@
 #include "dmscaledblit.h"
 
 
+
 // =======================================================================
 // =======================================================================
+
+
+
+// =======================================================================
+// DMD_NONE
+// =======================================================================
+
+#define DM_BLITFUNC_NAME dmUnscaledBlitSurface8to8
+#define DM_BLITFUNC_SRC_BYTES 1
+#define DM_BLITFUNC_DST_BYTES 1
+#define DM_BLITFUNC_SRC_TYPE Uint8
+#define DM_BLITFUNC_DST_TYPE Uint8
+
+#define DM_BLITFUNC_INNER *dp++ = sp[xv];
+
+#include "dmunscaledblit.h"
+
+// -----------------------------------------------------------------------
+
+#define DM_BLITFUNC_NAME dmUnscaledBlitSurface8to32
+#define DM_BLITFUNC_SRC_BYTES 1
+#define DM_BLITFUNC_DST_BYTES 4
+#define DM_BLITFUNC_SRC_TYPE Uint8
+#define DM_BLITFUNC_DST_TYPE Uint32
+
+#define DM_BLITFUNC_VARS const Uint32 *pal;
+#define DM_BLITFUNC_INIT \
+    if (src->format->palette == NULL || src->format->palette->ncolors < 256) return -2;	\
+    pal = (Uint32 *) src->format->palette->colors;
+
+#define DM_BLITFUNC_INNER *dp++ = pal[sp[xv]];
+
+#include "dmunscaledblit.h"
+
+// -----------------------------------------------------------------------
+
+#define DM_BLITFUNC_NAME dmUnscaledBlitSurface32to32
+#define DM_BLITFUNC_SRC_BYTES 4
+#define DM_BLITFUNC_DST_BYTES 4
+#define DM_BLITFUNC_SRC_TYPE Uint32
+#define DM_BLITFUNC_DST_TYPE Uint32
+#define DM_BLITFUNC_INIT
+#define DM_BLITFUNC_INNER *dp++ = sp[xv];
+
+#include "dmunscaledblit.h"
+
+
+// =======================================================================
+// DMD_TRANSPARENT
+// =======================================================================
+
+#define DM_BLITFUNC_NAME dmUnscaledBlitSurface8to8Transparent
+#define DM_BLITFUNC_SRC_BYTES 1
+#define DM_BLITFUNC_DST_BYTES 1
+#define DM_BLITFUNC_SRC_TYPE Uint8
+#define DM_BLITFUNC_DST_TYPE Uint8
+
+#define DM_BLITFUNC_INNER \
+    *dp = sp[xv] ? sp[xv] : *dp; dp++;
+
+#include "dmunscaledblit.h"
+
+// -----------------------------------------------------------------------
+
+#define DM_BLITFUNC_NAME dmUnscaledBlitSurface8to32Transparent
+#define DM_BLITFUNC_SRC_BYTES 1
+#define DM_BLITFUNC_DST_BYTES 4
+#define DM_BLITFUNC_SRC_TYPE Uint8
+#define DM_BLITFUNC_DST_TYPE DMRGBA32
+#define DM_BLITFUNC_VARS const DMRGBA32 *pal;
+#define DM_BLITFUNC_INIT \
+    if (src->format->palette == NULL || src->format->palette->ncolors < 256) return -2;	\
+    pal = (DMRGBA32 *) src->format->palette->colors;
+
+#define DM_BLITFUNC_INNER \
+    const DMRGBA32 q = pal[sp[xv]]; \
+    dp->r += ((q.r - dp->r) * q.a) >> 8; \
+    dp->g += ((q.g - dp->g) * q.a) >> 8; \
+    dp->b += ((q.b - dp->b) * q.a) >> 8; \
+    dp->a  = q.a; \
+    dp++;
+
+#include "dmunscaledblit.h"
+
+
+// -----------------------------------------------------------------------
+
+#define DM_BLITFUNC_NAME dmUnscaledBlitSurface32to32Transparent
+#define DM_BLITFUNC_SRC_BYTES 4
+#define DM_BLITFUNC_DST_BYTES 4
+
+#ifdef DM_USE_SIMD
+#define DM_BLITFUNC_VARS \
+    const Uint32 qpdmask =       0xff000000; \
+    const Uint64 qpdrm   = 0xff00ff00ff00ffULL;
+    
+#define DM_BLITFUNC_SRC_TYPE Uint32
+#define DM_BLITFUNC_DST_TYPE Uint32
+#define DM_BLITFUNC_INNER				\
+    asm(					\
+        "movd        %2,     %%mm1\n"		\
+        \
+        "movd        %3,     %%mm2\n"		\
+        "movq        %%mm1,  %%mm5\n"		\
+        "pand        %%mm2,  %%mm5\n"		\
+        "psrlw       $8,     %%mm5\n"		\
+        "punpcklwd   %%mm5,  %%mm5\n"		\
+        "punpckhwd   %%mm5,  %%mm5\n"		\
+        \
+        "pxor        %%mm2,  %%mm2\n"		\
+        "movd        %1,     %%mm3\n"		\
+        "punpcklbw   %%mm2,  %%mm1\n"		\
+        "punpcklbw   %%mm2,  %%mm3\n"		\
+        \
+        "psubw       %%mm3,  %%mm1\n"		\
+        "pmullw      %%mm5,  %%mm1\n"		\
+        "psraw       $8,     %%mm1\n"		\
+        "paddw       %%mm3,  %%mm1\n"		\
+        "pand        %4,     %%mm1\n"		\
+        "packuswb    %%mm2,  %%mm1\n"		\
+        "movd        %%mm1,  %0\n"		\
+        : "=m" (*dp)				\
+        : "m" (*dp), "m" (sp[xv]), "m" (qpdmask), "m" (qpdrm)	\
+        : "memory", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5" ); dp++;
+
+#define DM_BLITFUNC_FINISH asm("emms\n");
+
+#else
+
+#define DM_BLITFUNC_SRC_TYPE DMRGBA32
+#define DM_BLITFUNC_DST_TYPE DMRGBA32
+#define DM_BLITFUNC_INNER \
+    const DMRGBA32 q = sp[xv]; \
+    dp->r += ((q.r - dp->r) * q.a) >> 8; \
+    dp->g += ((q.g - dp->g) * q.a) >> 8; \
+    dp->b += ((q.b - dp->b) * q.a) >> 8; \
+    dp->a  = q.a; \
+    dp++;
+#endif
+
+#include "dmunscaledblit.h"
+
+
+// =======================================================================
+// DMD_SATURATE
+// =======================================================================
+
+#define DM_BLITFUNC_NAME dmUnscaledBlitSurface8to8Saturate
+#define DM_BLITFUNC_SRC_BYTES 1
+#define DM_BLITFUNC_DST_BYTES 1
+#define DM_BLITFUNC_SRC_TYPE Uint8
+#define DM_BLITFUNC_DST_TYPE Uint8
+#define DM_BLITFUNC_INNER \
+    const int q = sp[xv] + *dp; \
+    *(dp++) = q < 256 ? q : 255;
+
+#include "dmunscaledblit.h"
+
+// -----------------------------------------------------------------------
+
+#define DM_BLITFUNC_NAME dmUnscaledBlitSurface8to32Saturate
+#define DM_BLITFUNC_SRC_BYTES 1
+#define DM_BLITFUNC_DST_BYTES 4
+#define DM_BLITFUNC_SRC_TYPE Uint8
+#define DM_BLITFUNC_DST_TYPE DMRGBA32
+#define DM_BLITFUNC_VARS const DMRGBA32 *pal;
+#define DM_BLITFUNC_INIT \
+    if (src->format->palette == NULL || src->format->palette->ncolors < 256) return -2;	\
+    pal = (DMRGBA32 *) src->format->palette->colors;
+
+#ifdef DM_USE_SIMD
+#define DM_BLITFUNC_INNER				\
+    asm("movd        %2,     %%mm1\n"		\
+        "movd        %1,     %%mm2\n"		\
+        "paddusb     %%mm2,  %%mm1\n"		\
+        "movd        %%mm1,  %0\n"		\
+        : "=m" (*dp)				\
+        : "m" (*dp), "m" (pal[sp[xv]])	\
+        : "memory", "%mm1", "%mm2" ); dp++;
+
+#define DM_BLITFUNC_FINISH asm("emms\n");
+#else
+#define DM_BLITFUNC_INNER \
+    const DMRGBA32 q = pal[sp[xv]]; \
+    const int qr = dp->r + q.r, qg = dp->g + q.g, qb = dp->b + q.b; \
+    dp->r = qr < 256 ? qr : 255; \
+    dp->g = qg < 256 ? qg : 255; \
+    dp->b = qb < 256 ? qb : 255; \
+    dp->a = q.a; \
+    dp++;
+#endif
+
+#include "dmunscaledblit.h"
+
+// -----------------------------------------------------------------------
+
+#define DM_BLITFUNC_NAME dmUnscaledBlitSurface32to32Saturate
+#define DM_BLITFUNC_SRC_BYTES 4
+#define DM_BLITFUNC_DST_BYTES 4
+#define DM_BLITFUNC_INIT
+
+#ifdef DM_USE_SIMD
+#define DM_BLITFUNC_SRC_TYPE Uint32
+#define DM_BLITFUNC_DST_TYPE Uint32
+#define DM_BLITFUNC_INNER				\
+    asm("movd        %2,     %%mm1\n"		\
+        "movd        %1,     %%mm2\n"		\
+        "paddusb     %%mm2,  %%mm1\n"		\
+        "movd        %%mm1,  %0\n"		\
+        : "=m" (*dp)				\
+        : "m" (*dp), "m" (sp[xv])	\
+        : "memory", "%mm1", "%mm2" ); dp++;
+
+#define DM_BLITFUNC_FINISH asm("emms\n");
+#else
+#define DM_BLITFUNC_SRC_TYPE DMRGBA32
+#define DM_BLITFUNC_DST_TYPE DMRGBA32
+#define DM_BLITFUNC_INNER \
+    const DMRGBA32 q = sp[xv]; \
+    const int qr = dp->r + q.r, qg = dp->g + q.g, qb = dp->b + q.b; \
+    dp->r = qr < 256 ? qr : 255; \
+    dp->g = qg < 256 ? qg : 255; \
+    dp->b = qb < 256 ? qb : 255; \
+    dp->a = q.a; \
+    dp++;
+#endif
+
+#include "dmunscaledblit.h"
+
+
+// =======================================================================
--- a/dmlib.h	Tue Oct 02 18:14:44 2012 +0300
+++ b/dmlib.h	Tue Oct 02 18:51:16 2012 +0300
@@ -225,7 +225,8 @@
 int        dmDrawLineAny(SDL_Surface *src, int x0, int y0, int x1, int y1, const Uint32 color, int mode);
 #endif
 
-/* Scaled blitting functions
+
+/* Various blitting functions
  */
 #ifdef DM_GFX_BLITS
 typedef int (*DMScaledBlitFunc)(SDL_Surface *src, const int x0, const int y0, const int dwidth, const int dheight, SDL_Surface *dst);
@@ -235,8 +236,15 @@
 
 int dmScaledBlitSurface32to32TransparentX(SDL_Surface *src, const int x0, const int y0, const int dwidth, const int dheight, SDL_Surface *dst);
 int dmScaledBlitSurface32to32TransparentGA(SDL_Surface *src, const int x0, const int y0, const int dwidth, const int dheight, SDL_Surface *dst, Uint32 alpha);
+
+
+typedef int (*DMUnscaledBlitFunc)(SDL_Surface *src, const int x0, const int y0, SDL_Surface *dst);
+
+DMUnscaledBlitFunc dmGetUnscaledBlitFunc(SDL_PixelFormat *src, SDL_PixelFormat *dst, int mode);
+int dmUnscaledBlitSurfaceAny(SDL_Surface *src, const int x0, const int y0, SDL_Surface *dst, int mode);
 #endif
 
+
 /* Misc functions
  */
 #ifdef DM_GFX_MISC
--- a/dmscaledblit.h	Tue Oct 02 18:14:44 2012 +0300
+++ b/dmscaledblit.h	Tue Oct 02 18:51:16 2012 +0300
@@ -23,10 +23,10 @@
 #endif
     
     // Clip coordinates
-    if (dmClipCoord(&xr, x0, src->w, dwidth, 
+    if (dmScaledClipCoord(&xr, x0, src->w, dwidth, 
         dst->clip_rect.x, dst->clip_rect.x + dst->clip_rect.w)
         ||
-        dmClipCoord(&yr, y0, src->h, dheight,
+        dmScaledClipCoord(&yr, y0, src->h, dheight,
         dst->clip_rect.y, dst->clip_rect.y + dst->clip_rect.h))
         return -1;
 
@@ -42,7 +42,7 @@
     FP_MUL_R(dx, dx, xr.vdelta);
 
     // Take pitch into account
-    const int xadd = xr.vadd - dst->clip_rect.w + dst->clip_rect.x + (dst->pitch / DM_BLITFUNC_DST_BYTES);
+    const int dstadd = xr.vadd - dst->clip_rect.w + dst->clip_rect.x + (dst->pitch / DM_BLITFUNC_DST_BYTES);
 
     // Blit scaled
     DM_BLITFUNC_DST_TYPE * dp = ((DM_BLITFUNC_DST_TYPE *) dst->pixels) + (yr.v0 * dst->pitch) / DM_BLITFUNC_DST_BYTES + xr.v0;
@@ -61,7 +61,7 @@
             FP_ADD(xv, xr.vdelta);
         }
         FP_ADD(yv, yr.vdelta);
-        dp += xadd;
+        dp += dstadd;
     }
 
 #ifdef DM_BLITFUNC_FINISH
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmunscaledblit.h	Tue Oct 02 18:51:16 2012 +0300
@@ -0,0 +1,72 @@
+/*
+ * DMLib
+ * -- Unscaled sprite / surface blitting function template
+ * Programmed and designed by Matti 'ccr' Hamalainen
+ * (C) Copyright 2012 Tecnic Software productions (TNSP)
+ */
+
+int DM_BLITFUNC_NAME (SDL_Surface *src,
+    const int x0, const int y0,
+    SDL_Surface *dst
+#ifdef DM_BLITFUNC_ARGS
+    DM_BLITFUNC_ARGS
+#endif
+    )
+{
+    int yc;
+    DMQValue xr, yr;
+#ifdef DM_BLITFUNC_VARS
+    DM_BLITFUNC_VARS
+#endif
+    
+    // Clip coordinates
+    if (dmUnscaledClipCoord(&xr, x0, src->w,
+        dst->clip_rect.x, dst->clip_rect.x + dst->clip_rect.w)
+        ||
+        dmUnscaledClipCoord(&yr, y0, src->h,
+        dst->clip_rect.y, dst->clip_rect.y + dst->clip_rect.h))
+        return -1;
+
+#ifdef DM_BLITFUNC_INIT
+    DM_BLITFUNC_INIT
+#endif
+    const int srcadd = src->pitch / DM_BLITFUNC_SRC_BYTES;
+    const int dstadd = xr.vadd - dst->clip_rect.w + dst->clip_rect.x + (dst->pitch / DM_BLITFUNC_DST_BYTES);
+
+    DM_BLITFUNC_SRC_TYPE * sp = ((DM_BLITFUNC_SRC_TYPE *) src->pixels) + (yr.voffs * src->pitch) / DM_BLITFUNC_SRC_BYTES;
+    DM_BLITFUNC_DST_TYPE * dp = ((DM_BLITFUNC_DST_TYPE *) dst->pixels) + (yr.v0 * dst->pitch) / DM_BLITFUNC_DST_BYTES + xr.v0;
+
+    for (yc = yr.v0; yc < yr.v1; yc++)
+    {
+        int xv, xc;
+
+#ifdef DM_BLITFUNC_INNER_INIT
+        DM_BLITFUNC_INNER_INIT
+#endif
+
+        for (xv = xr.voffs, xc = xr.v0; xc < xr.v1; xc++, xv++)
+        {
+            DM_BLITFUNC_INNER
+        }
+        sp += srcadd;
+        dp += dstadd;
+    }
+
+#ifdef DM_BLITFUNC_FINISH
+    DM_BLITFUNC_FINISH
+#endif
+    return 0;
+}
+
+
+#undef DM_BLITFUNC_NAME
+#undef DM_BLITFUNC_ARGS
+#undef DM_BLITFUNC_SRC_BYTES
+#undef DM_BLITFUNC_DST_BYTES
+#undef DM_BLITFUNC_SRC_TYPE
+#undef DM_BLITFUNC_DST_TYPE
+#undef DM_BLITFUNC_VARS
+#undef DM_BLITFUNC_INIT
+#undef DM_BLITFUNC_INNER_INIT
+#undef DM_BLITFUNC_INNER
+#undef DM_BLITFUNC_FINISH