Page MenuHomePhabricator (Chris)

No OneTemporary

Authored By
Unknown
Size
35 KB
Referenced Files
None
Subscribers
None
diff --git a/util/sdl/stretch/SDL_stretch.h b/util/sdl/stretch/SDL_stretch.h
new file mode 100644
index 00000000..24f0b981
--- /dev/null
+++ b/util/sdl/stretch/SDL_stretch.h
@@ -0,0 +1,85 @@
+/*
+ SDL_stretch - Stretch Functions For The Simple DirectMedia Layer
+ Copyright (C) 2003 Guido Draheim
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Guido Draheim, guidod@gmx.de
+*/
+
+#ifndef _SDL_stretch_h
+#define _SDL_stretch_h
+
+#include <SDL_video.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef DECLSPEC
+#define DECLSPEC
+#endif
+
+/** Perform a stretch blit between two surfaces of the same format.
+ * NOTE: This function is not safe to call from multiple threads!
+ *
+ * This function will stretch a srcrect smoothly to the full area of
+ * the dst surface. If no srcrect is given then the full area of the
+ * src surface is stretched smoothly to the full dst surface. The
+ * dstrect is ignored always.
+ *
+ * This function will also watch for a clip rectangle on the src
+ * surface. This may speed up handling in your programs by creating
+ * a larger src surface with an associated viewframe, and the srcrect
+ * argument needs not be recomputed.
+ */
+extern DECLSPEC int
+SDL_StretchSurfaceRect(SDL_Surface *src, SDL_Rect *srcrect,
+ SDL_Surface *dst, SDL_Rect *dstrect);
+/** Perform a stretch blit between two surfaces of the same format.
+ * NOTE: This function is not safe to call from multiple threads!
+ *
+ * This function will stretch a srcrect smoothly to the full area of
+ * the dst surface. If no srcrect is given then the full area of the
+ * src surface is stretched smoothly to the full dst surface. The
+ * dstrect is ignored always.
+ *
+ * Remember that this is the inverse meaning, the main SDL lib will
+ * ignore the srcrect and only watch for the dstrect if any.
+ */
+extern DECLSPEC int
+SDL_StretchSurfaceBlit(SDL_Surface *src, SDL_Rect *srcrect,
+ SDL_Surface *dst, SDL_Rect *dstrect);
+/**
+ * This function will stretch to 150%. This is not only a fast function
+ * but it is also safe to call from multiple threads. If the srcrect
+ * is given then only that rect is copied. Otherwise the full src
+ * surface is copied to the full dst surface. The dstrect is ignored.
+ */
+extern DECLSPEC int
+SDL_StretchSurface_23(SDL_Surface *src, SDL_Rect *srcrect,
+ SDL_Surface *dst, SDL_Rect *dstrect);
+
+/**
+ * return some informative information.
+ */
+extern DECLSPEC char*
+SDL_StretchInfo(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/util/sdl/stretch/SDL_stretchasm.h b/util/sdl/stretch/SDL_stretchasm.h
new file mode 100644
index 00000000..d2441456
--- /dev/null
+++ b/util/sdl/stretch/SDL_stretchasm.h
@@ -0,0 +1,102 @@
+/*
+ SDL_stretch - Stretch Functions For The Simple DirectMedia Layer
+ Copyright (C) 2003 Guido Draheim
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Guido Draheim, guidod@gmx.de
+*/
+
+#ifndef _SDL_STRETCHASM_IMPLEMENTATION_
+#define _SDL_STRETCHASM_IMPLEMENTATION_
+
+/* development header - do not use */
+
+#if (defined(WIN32) && !defined(_M_ALPHA) && !defined(_WIN32_WCE))
+#define SDL_STRETCH_I386
+#define SDL_STRETCH_MASM
+#define SDL_STRETCH_USE_ASM
+#endif
+
+#if defined(__i386__) && defined(__GNUC__)
+#define SDL_STRETCH_I386
+#define SDL_STRETCH_GAS
+#define SDL_STRETCH_USE_ASM
+#endif
+
+#if defined(__x86_64__) && defined(__GNUC__)
+#define SDL_STRETCH_X86_64
+#define SDL_STRETCH_GAS
+#define SDL_STRETCH_USE_ASM
+#endif
+
+#if defined SDL_STRETCH_I386 && defined SDL_STRETCH_MASM
+#define SDL_STRETCH_CALL(code, srcp, dstp) \
+__asm {\
+ push edi ;\
+ push esi ;\
+ mov edi, dstp ;\
+ mov esi, srcp ;\
+ call dword ptr code ;\
+ pop esi ;\
+ pop edi ;\
+}
+#endif
+
+#if defined SDL_STRETCH_X86_64 && defined SDL_STRETCH_MASM
+#define SDL_STRETCH_CALL(code, srcp, dstp) \
+__asm {\
+ push rdi ;\
+ push rsi ;\
+ mov rdi, dstp ;\
+ mov rsi, srcp ;\
+ call qword ptr code ;\
+ pop rsi ;\
+ pop rdi ;\
+}
+#endif
+
+#if defined SDL_STRETCH_I386 && defined SDL_STRETCH_GAS
+#define SDL_STRETCH_CALL(code, srcp, dstp) \
+__asm__ __volatile__ ("call *%%eax" \
+ :: "S" (dstp), "D" (srcp), "a" (code));
+#endif
+
+#if defined SDL_STRETCH_X86_64 && defined SDL_STRETCH_GAS
+#define SDL_STRETCH_CALL(code, srcp, dstp) \
+__asm__ __volatile__ ("call *%%rax" \
+ :: "S" (dstp), "D" (srcp), "a" (code));
+#endif
+
+#if defined USE_ASM_STRETCH && ! defined SDL_STRETCH_USE_ASM
+#define SDL_STRETCH_USE_ASM 1
+#endif
+
+#if defined SDL_STRETCH_DISABLE_ASM
+#undef SDL_STRETCH_USE_ASM
+#undef SDL_STRETCH_CALL
+#endif
+
+#if defined SDL_STRETCH_USE_INTERPRETED_CODE
+#undef SDL_STRETCH_CALL
+#endif
+
+#if defined SDL_STRETCH_I386 || defined WIN32 || !defined SDL_STRETCH_CALL
+#define SDL_STRETCH_DATA_EXECUTABLE
+#else
+#define SDL_STRETCH_DATA_NOEXEC
+#endif
+
+#endif
diff --git a/util/sdl/stretch/SDL_stretchcode.h b/util/sdl/stretch/SDL_stretchcode.h
new file mode 100644
index 00000000..f8d06c3d
--- /dev/null
+++ b/util/sdl/stretch/SDL_stretchcode.h
@@ -0,0 +1,103 @@
+/*
+ SDL_stretch - Stretch Functions For The Simple DirectMedia Layer
+ Copyright (C) 2003 Guido Draheim
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Guido Draheim, guidod@gmx.de
+*/
+
+#ifndef _SDL_STRETCHCODE_IMPLEMENTATION_
+#define _SDL_STRETCHCODE_IMPLEMENTATION_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* development header - do not use */
+
+#define SDL_STRETCHCODE_BUFFERSIZE 8192
+
+/**
+ * TheRowStretchCode is a shared buffer between Stretch-routines that
+ * use no extra buffer-argument. You should call SDL_SetRowStretchCode
+ * to fill this internal buffer and set a "call"-operation for your target
+ * cpu to execute this static buffer. That is done for effiency
+ * as the RowStretch is often called in a tight loop for each Row
+ * in a rectengular stretch and it is best to not use a variable
+ * argument with an indirect call or a function call that would
+ * build up a callframe and release that callframe later.
+ *
+ * If you do not need that effiency, use PutRowStretchCode and RunRowStretchCode
+ * which are also good in a multithreading environment. To allocate a new buffer
+ * for usage with Put/Run you can use the NewRowStretchCode routine which is
+ * also used on NX machines (e.g. AMD64) where the data segment is set to be
+ * not-executable (in that case it will allocate from heap and use mprotect).
+ * if the argument is 0 then a buffer of the default size is allocated. If the
+ * buffer allocation (or mprotect) fails it will return NULL and SDL_SetError.
+ */
+extern unsigned char* SDL_GetRowStretchCode(void);
+
+/** => SDL_GetRowStretchCode */
+extern unsigned char* SDL_NewRowStretchCode(unsigned size);
+
+/**
+ * The SetRowStretchCode is a wrapper around PutRowStretchCode that
+ * uses the Adress and Size of the shared SDL_TheRowStretchCode buffer.
+ * The PutRowStretchCode will fill the given buffer with an assembler
+ * stream that should be called with SDL_RunRowStretchCode. The
+ * assembler stream is usually faster as all the scale decisions are
+ * done in advance of the execution. This helps when a RunCode is
+ * done multiple times with the same src_w/dst_w/bpp pair. All the
+ * pixel-get and pixel-set calls are unrolled in that buffer. Therefore,
+ * the buffer should be big enough - as a rule of thumb use a buffer
+ * of size (src_w+dst_w)*5
+ *
+ * If PutCode or SetCode fails, a NULL is returned and SDL_SetError.
+ * Otherwise, the start adress of the machine code buffer is returned,
+ * which is also the input argument of PutCode and RunCode.
+ */
+unsigned char* SDL_SetRowStretchCode(int src_w, int dst_w, int bpp);
+/** => SDL_SetRowStretchCode */
+unsigned char* SDL_PutRowStretchCode(unsigned char* buffer, int buflen,
+ int src_w, int dst_w, int bpp);
+/** => SDL_SetRowStretchCode */
+void SDL_RunRowStretchCode(unsigned char* buffer,
+ unsigned char* src,
+ unsigned char* dst);
+
+/** => SDL_SetRowStretchCode
+ * If SDL_SetRowStretchCode fails, this function must be used instead.
+ * This function and its cousins are singular routines that work in
+ * a tight loop to scale a single row. The number specifies the
+ * byte-width of each pixel (it is not a bit-width!).
+ */
+void SDL_StretchRow1(Uint8 *src, int src_w, Uint8 *dst, int dst_w);
+/** => SDL_SetRowStretchCode */
+void SDL_StretchRow2(Uint16 *src, int src_w, Uint16 *dst, int dst_w);
+/** => SDL_SetRowStretchCode */
+void SDL_StretchRow3(Uint8 *src, int src_w, Uint8 *dst, int dst_w);
+/** => SDL_SetRowStretchCode */
+void SDL_StretchRow4(Uint32 *src, int src_w, Uint32 *dst, int dst_w);
+
+/**
+ * return some informative information.
+ */
+extern char* SDL_StretchRowInfo(void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/util/sdl/stretch/SDL_stretchtest.hh b/util/sdl/stretch/SDL_stretchtest.hh
new file mode 100644
index 00000000..07800a0b
--- /dev/null
+++ b/util/sdl/stretch/SDL_stretchtest.hh
@@ -0,0 +1,42 @@
+/*
+ SDL_stretch - Stretch Functions For The Simple DirectMedia Layer
+ Copyright (C) 2003 Guido Draheim
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Guido Draheim, guidod@gmx.de
+*/
+
+#ifndef _SDL_stretch_test_h
+#define _SDL_stretch_test_h
+
+#include "SDL_video.h"
+#ifndef _SDL_video_h
+#include <SDL/SDL_video.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int SDL_StretchSurfaceRectTo(SDL_Surface *src, SDL_Rect *srcrect,
+ SDL_Surface *dst, SDL_Rect *dstrect);
+extern int SDL_StretchSurfaceBlitTo(SDL_Surface *src, SDL_Rect *srcrect,
+ SDL_Surface *dst, SDL_Rect *dstrect);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/util/sdl/stretch/config.h b/util/sdl/stretch/config.h
new file mode 100644
index 00000000..3f811f54
--- /dev/null
+++ b/util/sdl/stretch/config.h
@@ -0,0 +1,60 @@
+/* src/config.h. Generated from config.h.in by configure. */
+/* src/config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+ */
+#define LT_OBJDIR ".libs/"
+
+/* Name of package */
+#define PACKAGE "SDL_stretch"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT ""
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME ""
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING ""
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION ""
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Version number of package */
+#define VERSION "0.3.1"
diff --git a/util/sdl/stretch/sdlscreen.c b/util/sdl/stretch/sdlscreen.c
new file mode 100644
index 00000000..a1df98fe
--- /dev/null
+++ b/util/sdl/stretch/sdlscreen.c
@@ -0,0 +1,376 @@
+/*
+ SDL_stretch - Stretch Functions For The Simple DirectMedia Layer
+ Copyright (C) 2003 Guido Draheim
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Guido Draheim, guidod@gmx.de
+*/
+
+/* these will fill the target surface completely */
+
+/****************************************************
+ *
+ * WARNING: these routines are not used anymore.
+ * (they will not be part of the normal library)
+ *
+ ****************************************************
+ */
+
+#ifdef SAVE_RCSID
+static char rcsid =
+ "@(#) $Id: sdstretch.c $";
+#endif
+
+#include "SDL/SDL_error.h"
+#include "SDL/SDL_video.h"
+#include "SDL_stretch.h"
+#include "SDL_stretchcode.h"
+#include "SDL_stretchasm.h"
+#include "SDL_stretchtest.hh"
+
+#define PRERUN 0
+
+
+/* Perform a stretch blit between two surfaces of the same format.
+ NOTE: This function is not safe to call from multiple threads!
+*/
+int SDL_StretchSurfaceBlitTo(SDL_Surface *src, SDL_Rect *srcrect,
+ SDL_Surface *dst, SDL_Rect *dstrect)
+{
+ int i = 0;
+ int src_row, dst_row;
+ SDL_Rect full_src;
+ /* SDL_Rect full_dst; */
+# if defined SDL_STRETCH_USE_ASM
+ unsigned char* code = 0;
+# endif
+ const int bpp = dst->format->BytesPerPixel;
+ auto int dest_w = srcrect->w * dst->w / src->w;
+ auto int dest_x = srcrect->x * dst->w / src->w;
+
+ if ( src->format->BitsPerPixel != dst->format->BitsPerPixel ) {
+ SDL_SetError("Only works with same format surfaces");
+ return(-1);
+ }
+
+ /* Verify the blit rectangles */
+ if ( srcrect ) {
+ if ( (srcrect->x < 0) || (srcrect->y < 0) ||
+ ((srcrect->x+srcrect->w) > src->w) ||
+ ((srcrect->y+srcrect->h) > src->h) ) {
+ SDL_SetError("Invalid source blit rectangle");
+ return(-1);
+ }
+ } else {
+ full_src.x = 0;
+ full_src.y = 0;
+ full_src.w = src->w;
+ full_src.h = src->h;
+ srcrect = &full_src;
+ }
+
+# ifdef SDL_STRETCH_USE_ASM
+ /* Write the opcodes for this stretch */
+ /* if ( (bpp != 3) */
+ code = SDL_SetRowStretchCode(srcrect->w, dest_w, bpp);
+# endif
+
+
+ if (PRERUN) /* let the compiler do the dead-code removal */
+ { /* Pre-Run the stretch blit (the invisible lines) */
+ src_row = 0;
+ dst_row = 0;
+ while (1)
+ {
+ if (src_row >= srcrect->y) break;
+ dst_row++; i += src->h;
+ if (i < dst->h) continue;
+ do { i -= dst->h; src_row++; } while (i >= dst->h);
+ }
+ }else
+ { /* or compute the resulting dst_row and i-fraction directly: */
+ src_row = srcrect->y;
+ dst_row = ((src_row * dst->h)+(src->h-1)) / src->h;
+ i = (dst_row * src->h - src_row * dst->h ) % dst->h;
+ if (i < 0) i += dst->h;
+ }
+
+ if (dstrect) { /*returnvalue*/
+ dstrect->y = dst_row;
+ dstrect->x = dest_x;
+ dstrect->w = dest_w;
+ }
+
+
+ while (src_row < srcrect->y + srcrect->h)
+ {
+ Uint8 *srcp, *dstp;
+ srcp = (Uint8 *)src->pixels + (src_row*src->pitch)
+ + (srcrect->x*bpp);
+ draw:
+ dstp = (Uint8 *)dst->pixels + (dst_row*dst->pitch)
+ + (dest_x*bpp);
+# ifdef SDL_STRETCH_USE_ASM
+ if (code)
+ {
+# if defined SDL_STRETCH_CALL
+ SDL_STRETCH_CALL(code, srcp, dstp);
+# else
+ SDL_RunRowStretchCode(code, srcp, dstp);
+# endif
+ }else
+# endif /*USE_ASM*/
+ {
+ switch (bpp) {
+ case 1:
+ SDL_StretchRow1(srcp, srcrect->w, dstp, dest_w);
+ break;
+ case 2:
+ SDL_StretchRow2((Uint16 *)srcp, srcrect->w,
+ (Uint16 *)dstp, dest_w);
+ break;
+ case 3:
+ SDL_StretchRow3(srcp, srcrect->w, dstp, dest_w);
+ break;
+ case 4:
+ SDL_StretchRow4((Uint32 *)srcp, srcrect->w,
+ (Uint32 *)dstp, dest_w);
+ break;
+ }
+ }
+
+ dst_row++; i += src->h;
+ if (dst_row == dst->h) break; /*oops*/
+ if (i < dst->h) goto draw; /* draw the line again */
+ do { i -= dst->h; src_row++; } while (i >= dst->h);
+ }
+
+ if (dstrect) dstrect->h = dst_row - dstrect->y; /*returnvalue*/
+
+ return(0);
+}
+
+/* ------------------------------------------------------------------------ */
+
+#define OPTIMIZED 1
+
+#if defined SDL_STRETCH_USE_ASM && defined OPTIMIZED
+static int SDL_StretchFastBlitTo(
+ unsigned char* code,
+ int dst_row, int src_row,
+ SDL_Surface* dst, SDL_Surface* src,
+ SDL_Rect* rect, SDL_Rect* clip, int dest_x, int i)
+{
+ const int bpp = src->format->BytesPerPixel;
+ Uint8 *srcp = (Uint8 *)src->pixels + (src_row*src->pitch) + (rect->x*bpp);
+ Uint8 *srcE = (Uint8 *)src->pixels + ((rect->y + rect->h)
+ *src->pitch) + (rect->x*bpp);
+ Uint8 *dstp = (Uint8 *)dst->pixels + (dst_row*dst->pitch) + (dest_x*bpp);
+// Uint8* dstE = (Uint8 *)dst->pixels + (dst->h*dst->pitch) + (dest_x*bpp);
+
+ while (srcp < srcE)
+ {
+ draws:
+# if defined SDL_STRETCH_CALL
+ SDL_STRETCH_CALL(code, srcp, dstp)
+# else
+ SDL_RunRowStretchCode(code, srcp, dstp);
+# endif
+ dstp += dst->pitch; i += clip->h;
+ // if (dstp == dstE) break; /*oops*/
+ if (i < dst->h) goto draws; /* draw the line again */
+ do { i -= dst->h; srcp += src->pitch; } while (i >= dst->h);
+ }
+ return dst_row;
+}
+#endif
+
+#define DEBUGSIZES 0
+#define DEBUGSIZES_ (src->h != dst->h)
+
+/* Perform a stretch blit between two surfaces of the same format.
+ NOTE: This function is not safe to call from multiple threads!
+*/
+int SDL_StretchSurfaceRectTo(SDL_Surface *src, SDL_Rect *srcrect,
+ SDL_Surface *dst, SDL_Rect *dstrect)
+{
+ int i = 0;
+ int src_row, dst_row;
+ int dest_x, dest_w;
+ SDL_Rect rect;
+ SDL_Rect clip;
+# if defined SDL_STRETCH_USE_ASM
+ unsigned char* code = 0;
+# endif
+ const int bpp = src->format->BytesPerPixel;
+
+ if ( src->format->BitsPerPixel != dst->format->BitsPerPixel ) {
+ SDL_SetError("Only works with same format surfaces");
+ return(-1);
+ }
+
+ /* Verify the blit rectangles */
+ if ( srcrect ) {
+ rect = *srcrect;
+#if 0
+ clip.x = clip.y = 0; clip.h = src->h; clip.w = src->w;
+#else
+ clip = src->clip_rect;
+
+ if (rect.x > clip.x + clip.w ||
+ rect.x + rect.w < clip.x ||
+ rect.y > clip.y + clip.h ||
+ rect.y + rect.h < clip.y) return 1;
+ if (rect.x < clip.x) { rect.w -= clip.x-rect.x; rect.x = clip.x; }
+ if (rect.w > clip.x + clip.w - rect.x)
+ rect.w = clip.x + clip.w - rect.x;
+ if (rect.y < clip.y) { rect.h -= clip.y-rect.y; rect.y = clip.y; }
+ if (rect.h > clip.y + clip.h - rect.y)
+ rect.h = clip.y + clip.h - rect.y;
+#endif
+ if (! rect.h || !rect.w) return 1;
+ } else {
+ rect.x = 0;
+ rect.y = 0;
+ rect.w = src->w;
+ rect.h = src->h;
+ clip = rect;
+ }
+
+ if (DEBUGSIZES)
+ fprintf (stderr, "[%i/%i][%i+%i/%i+%i][%i+%i/%i+%i]\n",
+ src->w,src->h,
+ clip.x,clip.w,clip.y,clip.h,
+ rect.x,rect.w,rect.y,rect.h);
+
+ dest_w = rect.w * dst->w / clip.w;
+ dest_x = (rect.x-clip.x) * dst->w / clip.w;
+
+# ifdef SDL_STRETCH_USE_ASM
+ /* Write the opcodes for this stretch */
+ /* if ( (bpp != 3) */
+ code = SDL_SetRowStretchCode(rect.w, dest_w, bpp);
+# endif
+
+ if (PRERUN) /* let the compiler do the dead-code removal */
+ { /* Pre-Run the stretch blit (the invisible lines) */
+ src_row = clip.y;
+ dst_row = 0;
+ while (1)
+ {
+ if (src_row >= rect.y) break;
+ dst_row++; i += clip.h;
+ if (i < dst->h) continue;
+ do { i -= dst->h; src_row++; } while (i >= dst->h);
+ }
+ }else
+ { /* or compute the resulting dst_row and i-fraction directly: */
+ src_row = rect.y - clip.y;
+ dst_row = ((src_row * dst->h)+(clip.h-1)) / clip.h;
+ i = (dst_row * clip.h - src_row * dst->h ) % dst->h;
+ if (i < 0) i += dst->h;
+ }
+
+ if (dstrect) {
+ dstrect->y = dst_row;
+ dstrect->x = dest_x;
+ dstrect->w = dest_w;
+ }
+
+ if (DEBUGSIZES)
+ fprintf (stderr, "[%i/%i][%i+%i/%i+%i][%i+%i/%i+%i]"
+ " -> [%i/%i][%i+%i/%i+?]\n",
+ src->w,src->h,
+ clip.x,clip.w,clip.y,clip.h,
+ rect.x,rect.w,rect.y,rect.h,
+ dst->w,dst->h,
+ dest_x,dest_w,dst_row);
+
+# ifdef SDL_STRETCH_USE_ASM
+ if (code)
+ {
+# ifdef OPTIMIZED
+ dst_row = SDL_StretchFastBlitTo(code, dst_row, src_row, dst, src, &rect, &clip, dest_x,i);
+# else
+ while (src_row < rect.y + rect.h)
+ {
+ Uint8 *srcp, *dstp;
+ srcp = (Uint8 *)src->pixels + (src_row*src->pitch)
+ + (rect.x*bpp);
+ draws:
+ dstp = (Uint8 *)dst->pixels + (dst_row*dst->pitch)
+ + (dest_x*bpp);
+# ifdef SDL_STRETCH_CALL
+ SDL_STRETCH_CALL(code, srcp, dstp);
+# else
+ SDL_RunRowStretchCode(code, srcp, dstp);
+# endif
+ dst_row++; i += clip.h;
+ if (dst_row == dst->h) break; /*oops*/
+ if (i < dst->h) goto draws; /* draw the line again */
+ do { i -= dst->h; src_row++; } while (i >= dst->h);
+ }
+# endif
+ }else
+# endif /*USE_ASM*/
+ {
+ while (src_row < rect.y + rect.h)
+ {
+ Uint8 *srcp, *dstp;
+ srcp = (Uint8 *)src->pixels + (src_row*src->pitch)
+ + (rect.x*bpp);
+ draw:
+ dstp = (Uint8 *)dst->pixels + (dst_row*dst->pitch)
+ + (dest_x*bpp);
+
+ if (DEBUGSIZES) fprintf(stderr, ".");
+ switch (bpp) {
+ case 1:
+ SDL_StretchRow1(srcp, rect.w, dstp, dest_w);
+ break;
+ case 2:
+ SDL_StretchRow2((Uint16 *)srcp, rect.w,
+ (Uint16 *)dstp, dest_w);
+ break;
+ case 3:
+ SDL_StretchRow3(srcp, rect.w, dstp, dest_w);
+ break;
+ case 4:
+ SDL_StretchRow4((Uint32 *)srcp, rect.w,
+ (Uint32 *)dstp, dest_w);
+ break;
+ }
+
+ dst_row++; i += clip.h;
+ if (dst_row == dst->h) break; /*oops*/
+ if (i < dst->h) goto draw; /* draw the line again */
+ do { i -= dst->h; src_row++; } while (i >= dst->h);
+ }
+ }
+
+ if (dstrect) dstrect->h = dst_row - dstrect->y; /*returnvalue*/
+
+ if (DEBUGSIZES)
+ fprintf (stderr, "[%i/%i][%i+%i/%i+%i][%i+%i/%i+%i]"
+ " -> [%i/%i][%i+%i/?..%i]\n",
+ src->w,src->h,
+ clip.x,clip.w,clip.y,clip.h,
+ rect.x,rect.w,rect.y,rect.h,
+ dst->w,dst->h,
+ dest_x,dest_w,dst_row);
+
+ return(0);
+}
diff --git a/util/sdl/stretch/sdlstretch.c b/util/sdl/stretch/sdlstretch.c
new file mode 100644
index 00000000..5701691a
--- /dev/null
+++ b/util/sdl/stretch/sdlstretch.c
@@ -0,0 +1,382 @@
+/*
+ SDL_stretch - Stretch Functions For The Simple DirectMedia Layer
+ Copyright (C) 2003 Guido Draheim
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Guido Draheim, guidod@gmx.de
+*/
+
+#ifdef SAVE_RCSID
+static char rcsid =
+ "@(#) $Id: sdstretch.c $";
+#endif
+
+#include "SDL/SDL_error.h"
+#include "SDL/SDL_video.h"
+#include "SDL_stretch.h"
+#include "SDL_stretchcode.h"
+#include "SDL_stretchasm.h"
+
+#define PRERUN 0
+
+
+/* Perform a stretch blit between two surfaces of the same format.
+ NOTE: This function is not safe to call from multiple threads!
+*/
+int SDL_StretchSurfaceBlit(SDL_Surface *src, SDL_Rect *srcrect,
+ SDL_Surface *dst, SDL_Rect *dstrect)
+{
+ int i = 0;
+ int src_row, dst_row;
+ SDL_Rect rect;
+# if defined SDL_STRETCH_USE_ASM
+ unsigned char* code = 0;
+# endif
+ const int bpp = dst->format->BytesPerPixel;
+ auto int dest_w;
+ auto int dest_x;
+
+ if ( src->format->BitsPerPixel != dst->format->BitsPerPixel ) {
+ SDL_SetError("Only works with same format surfaces");
+ return(-1);
+ }
+
+ /* Verify the blit rectangles */
+ if ( srcrect ) {
+ if ( (srcrect->x < 0) || (srcrect->y < 0) ||
+ ((srcrect->x+srcrect->w) > src->w) ||
+ ((srcrect->y+srcrect->h) > src->h) ) {
+ SDL_SetError("Invalid source blit rectangle");
+ return(-1);
+ }
+ } else {
+ rect.x = 0;
+ rect.y = 0;
+ rect.w = src->w;
+ rect.h = src->h;
+ srcrect = &rect;
+ }
+
+ dest_w = srcrect->w * dst->w / src->w;
+ dest_x = srcrect->x * dst->w / src->w;
+
+# ifdef SDL_STRETCH_USE_ASM
+ /* Write the opcodes for this stretch */
+ /* if ( (bpp != 3) */
+ code = SDL_SetRowStretchCode(srcrect->w, dest_w, bpp);
+# endif
+
+
+ if (PRERUN) /* let the compiler do the dead-code removal */
+ { /* Pre-Run the stretch blit (the invisible lines) */
+ src_row = 0;
+ dst_row = 0;
+ while (1)
+ {
+ if (src_row >= srcrect->y) break;
+ dst_row++; i += src->h;
+ if (i < dst->h) continue;
+ do { i -= dst->h; src_row++; } while (i >= dst->h);
+ }
+ }else
+ { /* or compute the resulting dst_row and i-fraction directly: */
+ src_row = srcrect->y;
+ dst_row = ((src_row * dst->h)+(src->h-1)) / src->h;
+ i = (dst_row * src->h - src_row * dst->h ) % dst->h;
+ if (i < 0) i += dst->h;
+ }
+
+ if (dstrect) { /*returnvalue*/
+ dstrect->y = dst_row;
+ dstrect->x = dest_x;
+ dstrect->w = dest_w;
+ }
+
+
+ while (src_row < srcrect->y + srcrect->h)
+ {
+ Uint8 *srcp, *dstp;
+ srcp = (Uint8 *)src->pixels
+ + (src_row*src->pitch)
+ + (srcrect->x*bpp);
+ draw:
+ dstp = (Uint8 *)dst->pixels
+ + (dst_row*dst->pitch)
+ + (dest_x*bpp);
+# ifdef SDL_STRETCH_USE_ASM
+ if (code)
+ {
+# ifdef SDL_STRETCH_CALL
+ SDL_STRETCH_CALL(code, srcp, dstp);
+# else
+ SDL_RunRowStretchCode(code, srcp, dstp);
+# endif
+ }else
+# endif /*USE_ASM*/
+ {
+ switch (bpp) {
+ case 1:
+ SDL_StretchRow1(srcp, srcrect->w, dstp, dest_w);
+ break;
+ case 2:
+ SDL_StretchRow2((Uint16 *)srcp, srcrect->w,
+ (Uint16 *)dstp, dest_w);
+ break;
+ case 3:
+ SDL_StretchRow3(srcp, srcrect->w, dstp, dest_w);
+ break;
+ case 4:
+ SDL_StretchRow4((Uint32 *)srcp, srcrect->w,
+ (Uint32 *)dstp, dest_w);
+ break;
+ }
+ }
+
+ dst_row++; i += src->h;
+ if (dst_row == dst->h) break; /*oops*/
+ if (i < dst->h) goto draw; /* draw the line again */
+ do { i -= dst->h; src_row++; } while (i >= dst->h);
+ }
+
+ if (dstrect) dstrect->h = dst_row - dstrect->y; /*returnvalue*/
+
+ return(0);
+}
+
+/* ------------------------------------------------------------------------ */
+
+#define OPTIMIZED 1
+
+#if defined SDL_STRETCH_USE_ASM && defined OPTIMIZED
+static int SDL_StretchFastBlit(unsigned char* code,
+ int dst_row, int src_row,
+ SDL_Surface* dst, SDL_Surface* src,
+ SDL_Rect* rect, SDL_Rect* clip, int dest_x, int i)
+{
+ const int bpp = src->format->BytesPerPixel;
+ Uint8 *srcp = (Uint8 *)src->pixels
+ + (src_row*src->pitch)
+ + (rect->x*bpp);
+ Uint8 *srcE = (Uint8 *)src->pixels
+ + ((rect->y + rect->h) * src->pitch)
+ + (rect->x*bpp);
+ Uint8 *dstp = (Uint8 *)dst->pixels
+ + (dst_row*dst->pitch)
+ + (dest_x*bpp);
+// Uint8* dstE = (Uint8 *)dst->pixels + (dst->h*dst->pitch) + (dest_x*bpp);
+
+ while (srcp < srcE)
+ {
+ draws:
+# ifdef SDL_STRETCH_CALL
+ SDL_STRETCH_CALL(code, srcp, dstp);
+# else
+ SDL_RunRowStretchCode(code, srcp, dstp);
+# endif
+ dstp += dst->pitch; i += clip->h;
+ // if (dstp == dstE) break; /*oops*/
+ if (i < dst->h) goto draws; /* draw the line again */
+ do { i -= dst->h; srcp += src->pitch; } while (i >= dst->h);
+ }
+ return dst_row;
+}
+#endif
+
+#define DEBUGSIZES 0
+#define DEBUGSIZES_ (src->h != dst->h)
+
+/* Perform a stretch blit between two surfaces of the same format.
+ NOTE: This function is not safe to call from multiple threads!
+*/
+int SDL_StretchSurfaceRect(SDL_Surface *src, SDL_Rect *srcrect,
+ SDL_Surface *dst, SDL_Rect *dstrect)
+{
+ int i = 0;
+ int src_row, dst_row;
+ int dest_x, dest_w;
+ SDL_Rect rect;
+ SDL_Rect clip;
+# if defined SDL_STRETCH_USE_ASM
+ unsigned char* code = 0;
+# endif
+ const int bpp = src->format->BytesPerPixel;
+
+ if ( src->format->BitsPerPixel != dst->format->BitsPerPixel ) {
+ SDL_SetError("Only works with same format surfaces");
+ return(-1);
+ }
+
+ /* Verify the blit rectangles */
+ if ( srcrect ) {
+ rect = *srcrect;
+#if 0
+ clip.x = clip.y = 0; clip.h = src->h; clip.w = src->w;
+#else
+ clip = src->clip_rect;
+
+ if (rect.x > clip.x + clip.w ||
+ rect.x + rect.w < clip.x ||
+ rect.y > clip.y + clip.h ||
+ rect.y + rect.h < clip.y) return 1;
+ if (rect.x < clip.x) { rect.w -= clip.x-rect.x; rect.x = clip.x; }
+ if (rect.w > clip.x + clip.w - rect.x)
+ rect.w = clip.x + clip.w - rect.x;
+ if (rect.y < clip.y) { rect.h -= clip.y-rect.y; rect.y = clip.y; }
+ if (rect.h > clip.y + clip.h - rect.y)
+ rect.h = clip.y + clip.h - rect.y;
+#endif
+ if (! rect.h || !rect.w) return 1;
+ } else {
+ rect.x = 0;
+ rect.y = 0;
+ rect.w = src->w;
+ rect.h = src->h;
+ clip = rect;
+ }
+
+ if (DEBUGSIZES)
+ fprintf (stderr, "[%i/%i][%i+%i/%i+%i][%i+%i/%i+%i]\n",
+ src->w,src->h,
+ clip.x,clip.w,clip.y,clip.h,
+ rect.x,rect.w,rect.y,rect.h);
+
+ dest_w = rect.w * dst->w / clip.w;
+ dest_x = (rect.x-clip.x) * dst->w / clip.w;
+
+# ifdef SDL_STRETCH_USE_ASM
+ /* Write the opcodes for this stretch */
+ /* if ( (bpp != 3) */
+ code = SDL_SetRowStretchCode(rect.w, dest_w, bpp);
+# endif
+
+ if (PRERUN) /* let the compiler do the dead-code removal */
+ { /* Pre-Run the stretch blit (the invisible lines) */
+ src_row = clip.y;
+ dst_row = 0;
+ while (1)
+ {
+ if (src_row >= rect.y) break;
+ dst_row++; i += clip.h;
+ if (i < dst->h) continue;
+ do { i -= dst->h; src_row++; } while (i >= dst->h);
+ }
+ }else
+ { /* or compute the resulting dst_row and i-fraction directly: */
+ src_row = rect.y - clip.y;
+ dst_row = ((src_row * dst->h)+(clip.h-1)) / clip.h;
+ i = (dst_row * clip.h - src_row * dst->h ) % dst->h;
+ if (i < 0) i += dst->h;
+ }
+
+ if (dstrect) {
+ dstrect->y = dst_row;
+ dstrect->x = dest_x;
+ dstrect->w = dest_w;
+ }
+
+ if (DEBUGSIZES)
+ fprintf (stderr, "[%i/%i][%i+%i/%i+%i][%i+%i/%i+%i]"
+ " -> [%i/%i][%i+%i/%i+?]\n",
+ src->w,src->h,
+ clip.x,clip.w,clip.y,clip.h,
+ rect.x,rect.w,rect.y,rect.h,
+ dst->w,dst->h,
+ dest_x,dest_w,dst_row);
+
+#ifdef SDL_STRETCH_USE_ASM
+ if (code)
+ {
+# ifdef OPTIMIZED
+ dst_row = SDL_StretchFastBlit(code, dst_row, src_row, dst, src, &rect, &clip, dest_x,i);
+# else
+ while (src_row < rect.y + rect.h)
+ {
+ Uint8 *srcp, *dstp;
+ srcp = (Uint8 *)src->pixels
+ + (src_row*src->pitch)
+ + (rect.x*bpp);
+ draws:
+ dstp = (Uint8 *)dst->pixels
+ + (dst_row*dst->pitch)
+ + (dest_x*bpp);
+
+# ifdef SDL_STRETCH_CALL
+ SDL_STRETCH_CALL(code, srcp, dstp);
+# else
+ SDL_RunRowStretchCode(code, srcp, dstp);
+# endif
+ dst_row++; i += clip.h;
+ if (dst_row == dst->h) break; /*oops*/
+ if (i < dst->h) goto draws; /* draw the line again */
+ do { i -= dst->h; src_row++; } while (i >= dst->h);
+ }
+# endif
+ }else
+# endif /*USE_ASM*/
+ {
+ while (src_row < rect.y + rect.h)
+ {
+ Uint8 *srcp, *dstp;
+ srcp = (Uint8 *)src->pixels
+ + (src_row*src->pitch)
+ + (rect.x*bpp);
+ draw:
+ dstp = (Uint8 *)dst->pixels
+ + (dst_row*dst->pitch)
+ + (dest_x*bpp);
+
+ if (DEBUGSIZES) fprintf(stderr, ".");
+ switch (bpp) {
+ case 1:
+ SDL_StretchRow1(srcp, rect.w, dstp, dest_w);
+ break;
+ case 2:
+ SDL_StretchRow2((Uint16 *)srcp, rect.w,
+ (Uint16 *)dstp, dest_w);
+ break;
+ case 3:
+ SDL_StretchRow3(srcp, rect.w, dstp, dest_w);
+ break;
+ case 4:
+ SDL_StretchRow4((Uint32 *)srcp, rect.w,
+ (Uint32 *)dstp, dest_w);
+ break;
+ }
+
+ dst_row++; i += clip.h;
+ if (dst_row == dst->h) break; /*oops*/
+ if (i < dst->h) goto draw; /* draw the line again */
+ do { i -= dst->h; src_row++; } while (i >= dst->h);
+ }
+ }
+
+ if (dstrect) dstrect->h = dst_row - dstrect->y; /*returnvalue*/
+
+ if (DEBUGSIZES)
+ fprintf (stderr, "[%i/%i][%i+%i/%i+%i][%i+%i/%i+%i]"
+ " -> [%i/%i][%i+%i/?..%i]\n",
+ src->w,src->h,
+ clip.x,clip.w,clip.y,clip.h,
+ rect.x,rect.w,rect.y,rect.h,
+ dst->w,dst->h,
+ dest_x,dest_w,dst_row);
+
+ return(0);
+}
+
+char* SDL_StretchInfo(void) {
+ return SDL_StretchRowInfo();
+}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Jun 11, 1:09 PM (3 w, 4 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
69178
Default Alt Text
(35 KB)

Event Timeline