SDL_stretch.c
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:7k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /*
  2.     SDL - Simple DirectMedia Layer
  3.     Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga
  4.     This library is free software; you can redistribute it and/or
  5.     modify it under the terms of the GNU Library General Public
  6.     License as published by the Free Software Foundation; either
  7.     version 2 of the License, or (at your option) any later version.
  8.     This library is distributed in the hope that it will be useful,
  9.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11.     Library General Public License for more details.
  12.     You should have received a copy of the GNU Library General Public
  13.     License along with this library; if not, write to the Free
  14.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  15.     Sam Lantinga
  16.     slouken@libsdl.org
  17. */
  18. #ifdef SAVE_RCSID
  19. static char rcsid =
  20.  "@(#) $Id: SDL_stretch.c,v 1.4 2002/04/22 21:38:03 wmay Exp $";
  21. #endif
  22. /* This a stretch blit implementation based on ideas given to me by
  23.    Tomasz Cejner - thanks! :)
  24.    April 27, 2000 - Sam Lantinga
  25. */
  26. #include "SDL_error.h"
  27. #include "SDL_video.h"
  28. #include "SDL_blit.h"
  29. /* This isn't ready for general consumption yet - it should be folded
  30.    into the general blitting mechanism.
  31. */
  32. #if (defined(WIN32) && !defined(_M_ALPHA) && !defined(_WIN32_WCE) && 
  33.      !defined(__WATCOMC__) && !defined(__LCC__) && !defined(__FREEBCC__)) || 
  34.     (defined(i386) && defined(__GNUC__) && defined(USE_ASMBLIT))
  35. #define USE_ASM_STRETCH
  36. #endif
  37. #ifdef USE_ASM_STRETCH
  38. #if defined(WIN32) || defined(i386)
  39. #define PREFIX16 0x66
  40. #define STORE_BYTE 0xAA
  41. #define STORE_WORD 0xAB
  42. #define LOAD_BYTE 0xAC
  43. #define LOAD_WORD 0xAD
  44. #define RETURN 0xC3
  45. #else
  46. #error Need assembly opcodes for this architecture
  47. #endif
  48. #if defined(__ELF__) && defined(__GNUC__)
  49. extern unsigned char _copy_row[4096] __attribute__ ((alias ("copy_row")));
  50. #endif
  51. static unsigned char copy_row[4096];
  52. static int generate_rowbytes(int src_w, int dst_w, int bpp)
  53. {
  54. static struct {
  55. int bpp;
  56. int src_w;
  57. int dst_w;
  58. } last;
  59. int i;
  60. int pos, inc;
  61. unsigned char *eip;
  62. unsigned char load, store;
  63. /* See if we need to regenerate the copy buffer */
  64. if ( (src_w == last.src_w) &&
  65.      (dst_w == last.src_w) && (bpp == last.bpp) ) {
  66. return(0);
  67. }
  68. last.bpp = bpp;
  69. last.src_w = src_w;
  70. last.dst_w = dst_w;
  71. switch (bpp) {
  72.     case 1:
  73. load = LOAD_BYTE;
  74. store = STORE_BYTE;
  75. break;
  76.     case 2:
  77.     case 4:
  78. load = LOAD_WORD;
  79. store = STORE_WORD;
  80. break;
  81.     default:
  82. SDL_SetError("ASM stretch of %d bytes isn't supportedn", bpp);
  83. return(-1);
  84. }
  85. pos = 0x10000;
  86. inc = (src_w << 16) / dst_w;
  87. eip = copy_row;
  88. for ( i=0; i<dst_w; ++i ) {
  89. while ( pos >= 0x10000L ) {
  90. if ( bpp == 2 ) {
  91. *eip++ = PREFIX16;
  92. }
  93. *eip++ = load;
  94. pos -= 0x10000L;
  95. }
  96. if ( bpp == 2 ) {
  97. *eip++ = PREFIX16;
  98. }
  99. *eip++ = store;
  100. pos += inc;
  101. }
  102. *eip++ = RETURN;
  103. /* Verify that we didn't overflow (too late) */
  104. if ( eip > (copy_row+sizeof(copy_row)) ) {
  105. SDL_SetError("Copy buffer overflow");
  106. return(-1);
  107. }
  108. return(0);
  109. }
  110. #else
  111. #define DEFINE_COPY_ROW(name, type)
  112. void name(type *src, int src_w, type *dst, int dst_w)
  113. {
  114. int i;
  115. int pos, inc;
  116. type pixel = 0;
  117. pos = 0x10000;
  118. inc = (src_w << 16) / dst_w;
  119. for ( i=dst_w; i>0; --i ) {
  120. while ( pos >= 0x10000L ) {
  121. pixel = *src++;
  122. pos -= 0x10000L;
  123. }
  124. *dst++ = pixel;
  125. pos += inc;
  126. }
  127. }
  128. DEFINE_COPY_ROW(copy_row1, Uint8)
  129. DEFINE_COPY_ROW(copy_row2, Uint16)
  130. DEFINE_COPY_ROW(copy_row4, Uint32)
  131. #endif /* USE_ASM_STRETCH */
  132. /* The ASM code doesn't handle 24-bpp stretch blits */
  133. void copy_row3(Uint8 *src, int src_w, Uint8 *dst, int dst_w)
  134. {
  135. int i;
  136. int pos, inc;
  137. Uint8 pixel[3];
  138. pos = 0x10000;
  139. inc = (src_w << 16) / dst_w;
  140. for ( i=dst_w; i>0; --i ) {
  141. while ( pos >= 0x10000L ) {
  142. pixel[0] = *src++;
  143. pixel[1] = *src++;
  144. pixel[2] = *src++;
  145. pos -= 0x10000L;
  146. }
  147. *dst++ = pixel[0];
  148. *dst++ = pixel[1];
  149. *dst++ = pixel[2];
  150. pos += inc;
  151. }
  152. }
  153. /* Perform a stretch blit between two surfaces of the same format.
  154.    NOTE:  This function is not safe to call from multiple threads!
  155. */
  156. int SDL_SoftStretch(SDL_Surface *src, SDL_Rect *srcrect,
  157.                     SDL_Surface *dst, SDL_Rect *dstrect)
  158. {
  159. int pos, inc;
  160. int dst_width;
  161. int dst_maxrow;
  162. int src_row, dst_row;
  163. Uint8 *srcp = NULL;
  164. Uint8 *dstp;
  165. SDL_Rect full_src;
  166. SDL_Rect full_dst;
  167. #if defined(USE_ASM_STRETCH) && defined(__GNUC__)
  168. int u1, u2;
  169. #endif
  170. const int bpp = dst->format->BytesPerPixel;
  171. if ( src->format->BitsPerPixel != dst->format->BitsPerPixel ) {
  172. SDL_SetError("Only works with same format surfaces");
  173. return(-1);
  174. }
  175. /* Verify the blit rectangles */
  176. if ( srcrect ) {
  177. if ( (srcrect->x < 0) || (srcrect->y < 0) ||
  178.      ((srcrect->x+srcrect->w) > src->w) ||
  179.      ((srcrect->y+srcrect->h) > src->h) ) {
  180. SDL_SetError("Invalid source blit rectangle");
  181. return(-1);
  182. }
  183. } else {
  184. full_src.x = 0;
  185. full_src.y = 0;
  186. full_src.w = src->w;
  187. full_src.h = src->h;
  188. srcrect = &full_src;
  189. }
  190. if ( dstrect ) {
  191. if ( (dstrect->x < 0) || (dstrect->y < 0) ||
  192.      ((dstrect->x+dstrect->w) > dst->w) ||
  193.      ((dstrect->y+dstrect->h) > dst->h) ) {
  194. SDL_SetError("Invalid destination blit rectangle");
  195. return(-1);
  196. }
  197. } else {
  198. full_dst.x = 0;
  199. full_dst.y = 0;
  200. full_dst.w = dst->w;
  201. full_dst.h = dst->h;
  202. dstrect = &full_dst;
  203. }
  204. /* Set up the data... */
  205. pos = 0x10000;
  206. inc = (srcrect->h << 16) / dstrect->h;
  207. src_row = srcrect->y;
  208. dst_row = dstrect->y;
  209. dst_width = dstrect->w*bpp;
  210. #ifdef USE_ASM_STRETCH
  211. /* Write the opcodes for this stretch */
  212. if ( (bpp != 3) &&
  213.      (generate_rowbytes(srcrect->w, dstrect->w, bpp) < 0) ) {
  214. return(-1);
  215. }
  216. #endif
  217. /* Perform the stretch blit */
  218. for ( dst_maxrow = dst_row+dstrect->h; dst_row<dst_maxrow; ++dst_row ) {
  219. dstp = (Uint8 *)dst->pixels + (dst_row*dst->pitch)
  220.                             + (dstrect->x*bpp);
  221. while ( pos >= 0x10000L ) {
  222. srcp = (Uint8 *)src->pixels + (src_row*src->pitch)
  223.                             + (srcrect->x*bpp);
  224. ++src_row;
  225. pos -= 0x10000L;
  226. }
  227. #ifdef USE_ASM_STRETCH
  228. switch (bpp) {
  229.     case 3:
  230. copy_row3(srcp, srcrect->w, dstp, dstrect->w);
  231. break;
  232.     default:
  233. #ifdef __GNUC__
  234. __asm__ __volatile__ ("
  235. call _copy_row
  236. "
  237. : "=&D" (u1), "=&S" (u2)
  238. : "0" (dstp), "1" (srcp)
  239. : "memory" );
  240. #else
  241. #ifdef WIN32
  242. { void *code = &copy_row;
  243. __asm {
  244. push edi
  245. push esi
  246. mov edi, dstp
  247. mov esi, srcp
  248. call dword ptr code
  249. pop esi
  250. pop edi
  251. }
  252. }
  253. #else
  254. #error Need inline assembly for this compiler
  255. #endif
  256. #endif /* __GNUC__ */
  257. break;
  258. }
  259. #else
  260. switch (bpp) {
  261.     case 1:
  262. copy_row1(srcp, srcrect->w, dstp, dstrect->w);
  263. break;
  264.     case 2:
  265. copy_row2((Uint16 *)srcp, srcrect->w,
  266.           (Uint16 *)dstp, dstrect->w);
  267. break;
  268.     case 3:
  269. copy_row3(srcp, srcrect->w, dstp, dstrect->w);
  270. break;
  271.     case 4:
  272. copy_row4((Uint32 *)srcp, srcrect->w,
  273.           (Uint32 *)dstp, dstrect->w);
  274. break;
  275. }
  276. #endif
  277. pos += inc;
  278. }
  279. return(0);
  280. }