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

流媒体/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_blit.c,v 1.4 2002/04/22 21:38:03 wmay Exp $";
  21. #endif
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include "SDL_error.h"
  26. #include "SDL_video.h"
  27. #include "SDL_sysvideo.h"
  28. #include "SDL_blit.h"
  29. #include "SDL_RLEaccel_c.h"
  30. #include "SDL_pixels_c.h"
  31. #include "SDL_memops.h"
  32. /* The general purpose software blit routine */
  33. static int SDL_SoftBlit(SDL_Surface *src, SDL_Rect *srcrect,
  34. SDL_Surface *dst, SDL_Rect *dstrect)
  35. {
  36. int okay;
  37. int src_locked;
  38. int dst_locked;
  39. /* Everything is okay at the beginning...  */
  40. okay = 1;
  41. /* Lock the destination if it's in hardware */
  42. dst_locked = 0;
  43. if ( dst->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT) ) {
  44. SDL_VideoDevice *video = current_video;
  45. SDL_VideoDevice *this  = current_video;
  46. if ( video->LockHWSurface(this, dst) < 0 ) {
  47. okay = 0;
  48. } else {
  49. dst_locked = 1;
  50. }
  51. }
  52. /* Lock the source if it's in hardware */
  53. src_locked = 0;
  54. if ( src->flags & (SDL_HWSURFACE|SDL_ASYNCBLIT) ) {
  55. SDL_VideoDevice *video = current_video;
  56. SDL_VideoDevice *this  = current_video;
  57. if ( video->LockHWSurface(this, src) < 0 ) {
  58. okay = 0;
  59. } else {
  60. src_locked = 1;
  61. }
  62. }
  63. /* Unencode the destination if it's RLE encoded */
  64. if ( dst->flags & SDL_RLEACCEL ) {
  65. SDL_UnRLESurface(dst, 1);
  66. dst->flags |= SDL_RLEACCEL; /* save accel'd state */
  67. }
  68. /* Set up source and destination buffer pointers, and BLIT! */
  69. if ( okay  && srcrect->w && srcrect->h ) {
  70. SDL_BlitInfo info;
  71. SDL_loblit RunBlit;
  72. /* Set up the blit information */
  73. info.s_pixels = (Uint8 *)src->pixels + src->offset +
  74. (Uint16)srcrect->y*src->pitch +
  75. (Uint16)srcrect->x*src->format->BytesPerPixel;
  76. info.s_width = srcrect->w;
  77. info.s_height = srcrect->h;
  78. info.s_skip=src->pitch-info.s_width*src->format->BytesPerPixel;
  79. info.d_pixels = (Uint8 *)dst->pixels + dst->offset +
  80. (Uint16)dstrect->y*dst->pitch +
  81. (Uint16)dstrect->x*dst->format->BytesPerPixel;
  82. info.d_width = dstrect->w;
  83. info.d_height = dstrect->h;
  84. info.d_skip=dst->pitch-info.d_width*dst->format->BytesPerPixel;
  85. info.aux_data = src->map->sw_data->aux_data;
  86. info.src = src->format;
  87. info.table = src->map->table;
  88. info.dst = dst->format;
  89. RunBlit = src->map->sw_data->blit;
  90. /* Run the actual software blit */
  91. RunBlit(&info);
  92. }
  93. /* Re-encode the destination if it's RLE encoded */
  94. if ( dst->flags & SDL_RLEACCEL ) {
  95.         dst->flags &= ~SDL_RLEACCEL; /* stop lying */
  96. SDL_RLESurface(dst);
  97. }
  98. /* We need to unlock the surfaces if they're locked */
  99. if ( dst_locked ) {
  100. SDL_VideoDevice *video = current_video;
  101. SDL_VideoDevice *this  = current_video;
  102. video->UnlockHWSurface(this, dst);
  103. }
  104. if ( src_locked ) {
  105. SDL_VideoDevice *video = current_video;
  106. SDL_VideoDevice *this  = current_video;
  107. video->UnlockHWSurface(this, src);
  108. }
  109. /* Blit is done! */
  110. return(okay ? 0 : -1);
  111. }
  112. static void SDL_BlitCopy(SDL_BlitInfo *info)
  113. {
  114. Uint8 *src, *dst;
  115. int w, h;
  116. int srcskip, dstskip;
  117. w = info->d_width*info->dst->BytesPerPixel;
  118. h = info->d_height;
  119. src = info->s_pixels;
  120. dst = info->d_pixels;
  121. srcskip = w+info->s_skip;
  122. dstskip = w+info->d_skip;
  123. while ( h-- ) {
  124. SDL_memcpy(dst, src, w);
  125. src += srcskip;
  126. dst += dstskip;
  127. }
  128. }
  129. static void SDL_BlitCopyOverlap(SDL_BlitInfo *info)
  130. {
  131. Uint8 *src, *dst;
  132. int w, h;
  133. int srcskip, dstskip;
  134. w = info->d_width*info->dst->BytesPerPixel;
  135. h = info->d_height;
  136. src = info->s_pixels;
  137. dst = info->d_pixels;
  138. srcskip = w+info->s_skip;
  139. dstskip = w+info->d_skip;
  140. if ( dst < src ) {
  141. while ( h-- ) {
  142. SDL_memcpy(dst, src, w);
  143. src += srcskip;
  144. dst += dstskip;
  145. }
  146. } else {
  147. src += ((h-1) * srcskip);
  148. dst += ((h-1) * dstskip);
  149. while ( h-- ) {
  150. SDL_revcpy(dst, src, w);
  151. src -= srcskip;
  152. dst -= dstskip;
  153. }
  154. }
  155. }
  156. /* Figure out which of many blit routines to set up on a surface */
  157. int SDL_CalculateBlit(SDL_Surface *surface)
  158. {
  159. int blit_index;
  160. /* Clean everything out to start */
  161. if ( (surface->flags & SDL_RLEACCEL) == SDL_RLEACCEL ) {
  162. SDL_UnRLESurface(surface, 1);
  163. }
  164. surface->map->sw_blit = NULL;
  165. /* Figure out if an accelerated hardware blit is possible */
  166. surface->flags &= ~SDL_HWACCEL;
  167. if ( surface->map->identity ) {
  168. int hw_blit_ok;
  169. if ( (surface->flags & SDL_HWSURFACE) == SDL_HWSURFACE ) {
  170. /* We only support accelerated blitting to hardware */
  171. if ( surface->map->dst->flags & SDL_HWSURFACE ) {
  172. hw_blit_ok = current_video->info.blit_hw;
  173. } else {
  174. hw_blit_ok = 0;
  175. }
  176. if (hw_blit_ok && (surface->flags & SDL_SRCCOLORKEY)) {
  177. hw_blit_ok = current_video->info.blit_hw_CC;
  178. }
  179. if ( hw_blit_ok && (surface->flags & SDL_SRCALPHA) ) {
  180. hw_blit_ok = current_video->info.blit_hw_A;
  181. }
  182. } else {
  183. /* We only support accelerated blitting to hardware */
  184. if ( surface->map->dst->flags & SDL_HWSURFACE ) {
  185. hw_blit_ok = current_video->info.blit_sw;
  186. } else {
  187. hw_blit_ok = 0;
  188. }
  189. if (hw_blit_ok && (surface->flags & SDL_SRCCOLORKEY)) {
  190. hw_blit_ok = current_video->info.blit_sw_CC;
  191. }
  192. if ( hw_blit_ok && (surface->flags & SDL_SRCALPHA) ) {
  193. hw_blit_ok = current_video->info.blit_sw_A;
  194. }
  195. }
  196. if ( hw_blit_ok ) {
  197. SDL_VideoDevice *video = current_video;
  198. SDL_VideoDevice *this  = current_video;
  199. video->CheckHWBlit(this, surface, surface->map->dst);
  200. }
  201. }
  202. /* Get the blit function index, based on surface mode */
  203. /* { 0 = nothing, 1 = colorkey, 2 = alpha, 3 = colorkey+alpha } */
  204. blit_index = 0;
  205. blit_index |= (!!(surface->flags & SDL_SRCCOLORKEY))      << 0;
  206. if ( surface->flags & SDL_SRCALPHA
  207.      && (surface->format->alpha != SDL_ALPHA_OPAQUE
  208.  || surface->format->Amask) ) {
  209.         blit_index |= 2;
  210. }
  211. /* Check for special "identity" case -- copy blit */
  212. if ( surface->map->identity && blit_index == 0 ) {
  213.         surface->map->sw_data->blit = SDL_BlitCopy;
  214. /* Handle overlapping blits on the same surface */
  215. if ( surface == surface->map->dst ) {
  216.         surface->map->sw_data->blit = SDL_BlitCopyOverlap;
  217. }
  218. } else {
  219. if ( surface->format->BitsPerPixel < 8 ) {
  220. surface->map->sw_data->blit =
  221.     SDL_CalculateBlit0(surface, blit_index);
  222. } else {
  223. switch ( surface->format->BytesPerPixel ) {
  224.     case 1:
  225. surface->map->sw_data->blit =
  226.     SDL_CalculateBlit1(surface, blit_index);
  227. break;
  228.     case 2:
  229.     case 3:
  230.     case 4:
  231. surface->map->sw_data->blit =
  232.     SDL_CalculateBlitN(surface, blit_index);
  233. break;
  234.     default:
  235. surface->map->sw_data->blit = NULL;
  236. break;
  237. }
  238. }
  239. }
  240. /* Make sure we have a blit function */
  241. if ( surface->map->sw_data->blit == NULL ) {
  242. SDL_InvalidateMap(surface->map);
  243. SDL_SetError("Blit combination not supported");
  244. return(-1);
  245. }
  246. /* Choose software blitting function */
  247. if(surface->flags & SDL_RLEACCELOK
  248.    && (surface->flags & SDL_HWACCEL) != SDL_HWACCEL) {
  249.         if(surface->map->identity
  250.    && (blit_index == 1
  251.        || (blit_index == 3 && !surface->format->Amask))) {
  252.         if ( SDL_RLESurface(surface) == 0 )
  253.         surface->map->sw_blit = SDL_RLEBlit;
  254. } else if(blit_index == 2 && surface->format->Amask) {
  255.         if ( SDL_RLESurface(surface) == 0 )
  256.         surface->map->sw_blit = SDL_RLEAlphaBlit;
  257. }
  258. }
  259. if ( surface->map->sw_blit == NULL ) {
  260. surface->map->sw_blit = SDL_SoftBlit;
  261. }
  262. return(0);
  263. }